Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add an example of accessing an externally created map in C++ #1644

Merged
merged 1 commit into from
Mar 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
add an example of accessing an externally created map in C++
Some application may need to access a pinned map which is not
created by bcc. This example shows how to incorporate such
maps with C++ APIs.

Basically, the application needs to create a TableStorage and
pre-populate it with pinned map before calling BPF constructor.
The bpf program defines this pinned map as an "extern" map.

Signed-off-by: Yonghong Song <[email protected]>
  • Loading branch information
yonghong-song committed Mar 22, 2018
commit 914a78f6255cb1d0280757f19277f8a14b5ee2e9
4 changes: 4 additions & 0 deletions examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ target_link_libraries(LLCStat bcc-static)
add_executable(FollyRequestContextSwitch FollyRequestContextSwitch.cc)
target_link_libraries(FollyRequestContextSwitch bcc-static)

add_executable(UseExternalMap UseExternalMap.cc)
target_link_libraries(UseExternalMap bcc-static)

if(INSTALL_CPP_EXAMPLES)
install (TARGETS HelloWorld DESTINATION share/bcc/examples/cpp)
install (TARGETS CPUDistribution DESTINATION share/bcc/examples/cpp)
Expand All @@ -35,4 +38,5 @@ if(INSTALL_CPP_EXAMPLES)
install (TARGETS RandomRead DESTINATION share/bcc/examples/cpp)
install (TARGETS LLCStat DESTINATION share/bcc/examples/cpp)
install (TARGETS FollyRequestContextSwitch DESTINATION share/bcc/examples/cpp)
install (TARGETS UseExternalMap DESTINATION share/bcc/examples/cpp)
endif(INSTALL_CPP_EXAMPLES)
134 changes: 134 additions & 0 deletions examples/cpp/UseExternalMap.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* 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;
}