xref: /aosp_15_r20/external/bcc/examples/cpp/UseExternalMap.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * UseExternalMap shows how to access an external map through
3*387f9dfdSAndroid Build Coastguard Worker  * C++ interface. The external map could be a pinned map.
4*387f9dfdSAndroid Build Coastguard Worker  * This example simulates the pinned map through a locally
5*387f9dfdSAndroid Build Coastguard Worker  * created map by calling libbpf bcc_create_map.
6*387f9dfdSAndroid Build Coastguard Worker  *
7*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
8*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
9*387f9dfdSAndroid Build Coastguard Worker  */
10*387f9dfdSAndroid Build Coastguard Worker 
11*387f9dfdSAndroid Build Coastguard Worker #include <stdint.h>
12*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
15*387f9dfdSAndroid Build Coastguard Worker 
16*387f9dfdSAndroid Build Coastguard Worker // Used by C++ get hash_table
17*387f9dfdSAndroid Build Coastguard Worker struct sched_switch_info {
18*387f9dfdSAndroid Build Coastguard Worker   int prev_pid;
19*387f9dfdSAndroid Build Coastguard Worker   int next_pid;
20*387f9dfdSAndroid Build Coastguard Worker   char prev_comm[16];
21*387f9dfdSAndroid Build Coastguard Worker   char next_comm[16];
22*387f9dfdSAndroid Build Coastguard Worker };
23*387f9dfdSAndroid Build Coastguard Worker 
24*387f9dfdSAndroid Build Coastguard Worker #define CHECK(condition, msg)        \
25*387f9dfdSAndroid Build Coastguard Worker   ({                                 \
26*387f9dfdSAndroid Build Coastguard Worker     if (condition) {                 \
27*387f9dfdSAndroid Build Coastguard Worker       std::cerr << msg << std::endl; \
28*387f9dfdSAndroid Build Coastguard Worker       return 1;                      \
29*387f9dfdSAndroid Build Coastguard Worker     }                                \
30*387f9dfdSAndroid Build Coastguard Worker   })
31*387f9dfdSAndroid Build Coastguard Worker 
32*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
33*387f9dfdSAndroid Build Coastguard Worker #include <linux/sched.h>
34*387f9dfdSAndroid Build Coastguard Worker 
35*387f9dfdSAndroid Build Coastguard Worker struct sched_switch_info {
36*387f9dfdSAndroid Build Coastguard Worker   int prev_pid;
37*387f9dfdSAndroid Build Coastguard Worker   int next_pid;
38*387f9dfdSAndroid Build Coastguard Worker   char prev_comm[16];
39*387f9dfdSAndroid Build Coastguard Worker   char next_comm[16];
40*387f9dfdSAndroid Build Coastguard Worker };
41*387f9dfdSAndroid Build Coastguard Worker 
42*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("extern", u32, u32, control, 1);
43*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(counts, struct sched_switch_info, u32);
44*387f9dfdSAndroid Build Coastguard Worker int on_sched_switch(struct tracepoint__sched__sched_switch *args) {
45*387f9dfdSAndroid Build Coastguard Worker   struct sched_switch_info key = {};
46*387f9dfdSAndroid Build Coastguard Worker   u32 zero = 0, *val;
47*387f9dfdSAndroid Build Coastguard Worker 
48*387f9dfdSAndroid Build Coastguard Worker   /* only do something when control is on */
49*387f9dfdSAndroid Build Coastguard Worker   val = control.lookup(&zero);
50*387f9dfdSAndroid Build Coastguard Worker   if (!val || *val == 0)
51*387f9dfdSAndroid Build Coastguard Worker     return 0;
52*387f9dfdSAndroid Build Coastguard Worker 
53*387f9dfdSAndroid Build Coastguard Worker   /* record sched_switch info in counts table */
54*387f9dfdSAndroid Build Coastguard Worker   key.prev_pid = args->prev_pid;
55*387f9dfdSAndroid Build Coastguard Worker   key.next_pid = args->next_pid;
56*387f9dfdSAndroid Build Coastguard Worker   __builtin_memcpy(&key.prev_comm, args->prev_comm, 16);
57*387f9dfdSAndroid Build Coastguard Worker   __builtin_memcpy(&key.next_comm, args->next_comm, 16);
58*387f9dfdSAndroid Build Coastguard Worker   val = counts.lookup_or_try_init(&key, &zero);
59*387f9dfdSAndroid Build Coastguard Worker   if (val) {
60*387f9dfdSAndroid Build Coastguard Worker     (*val)++;
61*387f9dfdSAndroid Build Coastguard Worker   }
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker   return 0;
64*387f9dfdSAndroid Build Coastguard Worker }
65*387f9dfdSAndroid Build Coastguard Worker )";
66*387f9dfdSAndroid Build Coastguard Worker 
print_counts(ebpf::BPF * bpfp,std::string msg)67*387f9dfdSAndroid Build Coastguard Worker static void print_counts(ebpf::BPF *bpfp, std::string msg) {
68*387f9dfdSAndroid Build Coastguard Worker   auto counts_table_hdl =
69*387f9dfdSAndroid Build Coastguard Worker       bpfp->get_hash_table<struct sched_switch_info, uint32_t>("counts");
70*387f9dfdSAndroid Build Coastguard Worker   printf("%s\n", msg.c_str());
71*387f9dfdSAndroid Build Coastguard Worker   printf("%-8s  %-16s      %-8s  %-16s   %-4s\n", "PREV_PID", "PREV_COMM",
72*387f9dfdSAndroid Build Coastguard Worker          "CURR_PID", "CURR_COMM", "CNT");
73*387f9dfdSAndroid Build Coastguard Worker   for (auto it : counts_table_hdl.get_table_offline()) {
74*387f9dfdSAndroid Build Coastguard Worker     printf("%-8d (%-16s) ==> %-8d (%-16s): %-4d\n", it.first.prev_pid,
75*387f9dfdSAndroid Build Coastguard Worker            it.first.prev_comm, it.first.next_pid, it.first.next_comm,
76*387f9dfdSAndroid Build Coastguard Worker            it.second);
77*387f9dfdSAndroid Build Coastguard Worker   }
78*387f9dfdSAndroid Build Coastguard Worker }
79*387f9dfdSAndroid Build Coastguard Worker 
main()80*387f9dfdSAndroid Build Coastguard Worker int main() {
81*387f9dfdSAndroid Build Coastguard Worker   int ctrl_map_fd;
82*387f9dfdSAndroid Build Coastguard Worker   uint32_t val;
83*387f9dfdSAndroid Build Coastguard Worker 
84*387f9dfdSAndroid Build Coastguard Worker   // create a map through bcc_create_map, bcc knows nothing about this map.
85*387f9dfdSAndroid Build Coastguard Worker   ctrl_map_fd = bcc_create_map(BPF_MAP_TYPE_ARRAY, "control", sizeof(uint32_t),
86*387f9dfdSAndroid Build Coastguard Worker                                sizeof(uint32_t), 1, 0);
87*387f9dfdSAndroid Build Coastguard Worker   CHECK(ctrl_map_fd < 0, "bcc_create_map failure");
88*387f9dfdSAndroid Build Coastguard Worker 
89*387f9dfdSAndroid Build Coastguard Worker   // populate control map into TableStorage
90*387f9dfdSAndroid Build Coastguard Worker   std::unique_ptr<ebpf::TableStorage> local_ts =
91*387f9dfdSAndroid Build Coastguard Worker       ebpf::createSharedTableStorage();
92*387f9dfdSAndroid Build Coastguard Worker   ebpf::Path global_path({"control"});
93*387f9dfdSAndroid Build Coastguard Worker   ebpf::TableDesc table_desc("control", ebpf::FileDesc(ctrl_map_fd),
94*387f9dfdSAndroid Build Coastguard Worker                              BPF_MAP_TYPE_ARRAY, sizeof(uint32_t),
95*387f9dfdSAndroid Build Coastguard Worker                              sizeof(uint32_t), 1, 0);
96*387f9dfdSAndroid Build Coastguard Worker   local_ts->Insert(global_path, std::move(table_desc));
97*387f9dfdSAndroid Build Coastguard Worker 
98*387f9dfdSAndroid Build Coastguard Worker   // constructor with the pre-populated table storage
99*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf(0, &*local_ts);
100*387f9dfdSAndroid Build Coastguard Worker   auto res = bpf.init(BPF_PROGRAM);
101*387f9dfdSAndroid Build Coastguard Worker   CHECK(res.code(), res.msg());
102*387f9dfdSAndroid Build Coastguard Worker 
103*387f9dfdSAndroid Build Coastguard Worker   // attach to the tracepoint sched:sched_switch
104*387f9dfdSAndroid Build Coastguard Worker   res = bpf.attach_tracepoint("sched:sched_switch", "on_sched_switch");
105*387f9dfdSAndroid Build Coastguard Worker   CHECK(res.code(), res.msg());
106*387f9dfdSAndroid Build Coastguard Worker 
107*387f9dfdSAndroid Build Coastguard Worker   // wait for some scheduling events
108*387f9dfdSAndroid Build Coastguard Worker   sleep(1);
109*387f9dfdSAndroid Build Coastguard Worker 
110*387f9dfdSAndroid Build Coastguard Worker   auto control_table_hdl = bpf.get_array_table<uint32_t>("control");
111*387f9dfdSAndroid Build Coastguard Worker   res = control_table_hdl.get_value(0, val);
112*387f9dfdSAndroid Build Coastguard Worker   CHECK(res.code() || val != 0, res.msg());
113*387f9dfdSAndroid Build Coastguard Worker 
114*387f9dfdSAndroid Build Coastguard Worker   // we should not see any events here
115*387f9dfdSAndroid Build Coastguard Worker   print_counts(&bpf, "events with control off:");
116*387f9dfdSAndroid Build Coastguard Worker 
117*387f9dfdSAndroid Build Coastguard Worker   printf("\n");
118*387f9dfdSAndroid Build Coastguard Worker 
119*387f9dfdSAndroid Build Coastguard Worker   // change the control to on so bpf program starts to count events
120*387f9dfdSAndroid Build Coastguard Worker   val = 1;
121*387f9dfdSAndroid Build Coastguard Worker   res = control_table_hdl.update_value(0, val);
122*387f9dfdSAndroid Build Coastguard Worker   CHECK(res.code(), res.msg());
123*387f9dfdSAndroid Build Coastguard Worker 
124*387f9dfdSAndroid Build Coastguard Worker   // verify we get the control on back
125*387f9dfdSAndroid Build Coastguard Worker   val = 0;
126*387f9dfdSAndroid Build Coastguard Worker   res = control_table_hdl.get_value(0, val);
127*387f9dfdSAndroid Build Coastguard Worker   CHECK(res.code() || val != 1, res.msg());
128*387f9dfdSAndroid Build Coastguard Worker 
129*387f9dfdSAndroid Build Coastguard Worker   // wait for some scheduling events
130*387f9dfdSAndroid Build Coastguard Worker   sleep(1);
131*387f9dfdSAndroid Build Coastguard Worker 
132*387f9dfdSAndroid Build Coastguard Worker   // we should see a bunch of events here
133*387f9dfdSAndroid Build Coastguard Worker   print_counts(&bpf, "events with control on:");
134*387f9dfdSAndroid Build Coastguard Worker 
135*387f9dfdSAndroid Build Coastguard Worker   return 0;
136*387f9dfdSAndroid Build Coastguard Worker }
137