Skip to content

Commit

Permalink
Merge pull request iovisor#1644 from iovisor/yhs_dev
Browse files Browse the repository at this point in the history
add an example of accessing an externally created map in C++
  • Loading branch information
4ast committed Mar 22, 2018
2 parents 57bbd87 + 914a78f commit ad99e0e
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
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;
}

0 comments on commit ad99e0e

Please sign in to comment.