You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.8 KiB
135 lines
3.8 KiB
/*
|
|
* UseExternalMap shows how to access an external map through
|
|
* C++ interface. The external map could be a pinned map.
|
|
* This example simulates the pinned map through a locally
|
|
* created map by calling libbpf bpf_create_map.
|
|
*
|
|
* Copyright (c) Facebook, Inc.
|
|
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <iostream>
|
|
|
|
#include "BPF.h"
|
|
|
|
// Used by C++ get hash_table
|
|
struct sched_switch_info {
|
|
int prev_pid;
|
|
int next_pid;
|
|
char prev_comm[16];
|
|
char next_comm[16];
|
|
};
|
|
|
|
#define CHECK(condition, msg) \
|
|
({ \
|
|
if (condition) { \
|
|
std::cerr << msg << std::endl; \
|
|
return 1; \
|
|
} \
|
|
})
|
|
|
|
const std::string BPF_PROGRAM = R"(
|
|
#include <linux/sched.h>
|
|
|
|
struct sched_switch_info {
|
|
int prev_pid;
|
|
int next_pid;
|
|
char prev_comm[16];
|
|
char next_comm[16];
|
|
};
|
|
|
|
BPF_TABLE("extern", u32, u32, control, 1);
|
|
BPF_HASH(counts, struct sched_switch_info, u32);
|
|
int on_sched_switch(struct tracepoint__sched__sched_switch *args) {
|
|
struct sched_switch_info key = {};
|
|
u32 zero = 0, *val;
|
|
|
|
/* only do something when control is on */
|
|
val = control.lookup(&zero);
|
|
if (!val || *val == 0)
|
|
return 0;
|
|
|
|
/* record sched_switch info in counts table */
|
|
key.prev_pid = args->prev_pid;
|
|
key.next_pid = args->next_pid;
|
|
__builtin_memcpy(&key.prev_comm, args->prev_comm, 16);
|
|
__builtin_memcpy(&key.next_comm, args->next_comm, 16);
|
|
val = counts.lookup_or_init(&key, &zero);
|
|
(*val)++;
|
|
|
|
return 0;
|
|
}
|
|
)";
|
|
|
|
static void print_counts(ebpf::BPF *bpfp, std::string msg) {
|
|
auto counts_table_hdl =
|
|
bpfp->get_hash_table<struct sched_switch_info, uint32_t>("counts");
|
|
printf("%s\n", msg.c_str());
|
|
printf("%-8s %-16s %-8s %-16s %-4s\n", "PREV_PID", "PREV_COMM",
|
|
"CURR_PID", "CURR_COMM", "CNT");
|
|
for (auto it : counts_table_hdl.get_table_offline()) {
|
|
printf("%-8d (%-16s) ==> %-8d (%-16s): %-4d\n", it.first.prev_pid,
|
|
it.first.prev_comm, it.first.next_pid, it.first.next_comm,
|
|
it.second);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
int ctrl_map_fd;
|
|
uint32_t val;
|
|
|
|
// create a map through bpf_create_map, bcc knows nothing about this map.
|
|
ctrl_map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, "control", sizeof(uint32_t),
|
|
sizeof(uint32_t), 1, 0);
|
|
CHECK(ctrl_map_fd < 0, "bpf_create_map failure");
|
|
|
|
// populate control map into TableStorage
|
|
std::unique_ptr<ebpf::TableStorage> local_ts =
|
|
ebpf::createSharedTableStorage();
|
|
ebpf::Path global_path({"control"});
|
|
ebpf::TableDesc table_desc("control", ebpf::FileDesc(ctrl_map_fd),
|
|
BPF_MAP_TYPE_ARRAY, sizeof(uint32_t),
|
|
sizeof(uint32_t), 1, 0);
|
|
local_ts->Insert(global_path, std::move(table_desc));
|
|
|
|
// constructor with the pre-populated table storage
|
|
ebpf::BPF bpf(0, &*local_ts);
|
|
auto res = bpf.init(BPF_PROGRAM);
|
|
CHECK(res.code(), res.msg());
|
|
|
|
// attach to the tracepoint sched:sched_switch
|
|
res = bpf.attach_tracepoint("sched:sched_switch", "on_sched_switch");
|
|
CHECK(res.code(), res.msg());
|
|
|
|
// wait for some scheduling events
|
|
sleep(1);
|
|
|
|
auto control_table_hdl = bpf.get_array_table<uint32_t>("control");
|
|
res = control_table_hdl.get_value(0, val);
|
|
CHECK(res.code() || val != 0, res.msg());
|
|
|
|
// we should not see any events here
|
|
print_counts(&bpf, "events with control off:");
|
|
|
|
printf("\n");
|
|
|
|
// change the control to on so bpf program starts to count events
|
|
val = 1;
|
|
res = control_table_hdl.update_value(0, val);
|
|
CHECK(res.code(), res.msg());
|
|
|
|
// verify we get the control on back
|
|
val = 0;
|
|
res = control_table_hdl.get_value(0, val);
|
|
CHECK(res.code() || val != 1, res.msg());
|
|
|
|
// wait for some scheduling events
|
|
sleep(1);
|
|
|
|
// we should see a bunch of events here
|
|
print_counts(&bpf, "events with control on:");
|
|
|
|
return 0;
|
|
}
|