Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <bcc/BPF.h>
#include <iostream>
#include <signal.h>
#include <string>
#define COUNTER_STRUCT \
struct counter { \
uint64_t pad; \
uint64_t counter; \
} __attribute__((packed, aligned(8)));
#define Q(x) #x
#define QUOTE(x) Q(x)
const std::string BPF_PROGRAM = std::string(QUOTE(COUNTER_STRUCT)) + R"(
BPF_ARRAY(counter, struct counter, 1);
int handler(struct xdp_md *ctx) {
int key = 0;
// lookup without using bpf_sping_lock
struct counter *c = counter.lookup(&key);
if (c) {
u32 h2, h1;
h1 = c->counter & 0xffffffff;
h2 = c->counter >> 32;
if (h2 != 2*h1) {
bpf_trace_printk("Partial updated detected!\n");
}
}
return XDP_PASS;
}
)";
volatile int stop = 0;
void handle_sigint(int sig) {
stop = 1;
}
int main(void) {
ebpf::StatusTuple res(0);
ebpf::BPF bpf;
int fd;
res = bpf.init(BPF_PROGRAM);
if (res.code()) {
std::cout << "error compiling program" << std::endl;
return 1;
}
res = bpf.load_func("handler", BPF_PROG_TYPE_XDP, fd);
if (res.code() != 0) {
std::cout << "failed to load XDP program: " << res.msg() << std::endl;
return -1;
}
int attach_flags = 1U << 1; // SKB mode
if (bpf_attach_xdp("veth1", fd, attach_flags) < 0) {
std::cout << "failed to attach XDP program to port: " << std::endl;
return -1;
}
signal(SIGINT, handle_sigint);
COUNTER_STRUCT
uint32_t h1 = 0, h2 = 0;
struct counter counter = {0, 0};
while (!stop) {
auto t = bpf.get_array_table<struct counter>("counter");
counter.counter = (uint64_t) h2 << 32 | h1;
// update without using bpf_spin_lock
t.update_value(0, counter);
h1++;
h2 = 2*h1;
}
cleanup:
std::cout << "bye" << std::endl;
if (bpf_attach_xdp("veth1", -1, attach_flags) < 0) {
std::cout << "failed to detach XDP program to port: " << std::endl;
return -1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment