From: Simon Ruderich Date: Sun, 15 Nov 2020 07:43:22 +0000 (+0100) Subject: Initial commit X-Git-Url: https://ruderich.org/simon/gitweb/?a=commitdiff_plain;p=bpf%2Fxdp-example.git Initial commit --- f699c0f19e570840775eba9ff8a006871be667e6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4218fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/example +/example.bpf.o +/example.skel.h +/vmlinux.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8778a8f --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +CLANG = clang +CFLAGS = -g -O2 -Wall -Wextra + +PROGS = example + + +all: $(PROGS) + +clean: + rm -f $(PROGS) + rm -f vmlinux.h *.bpf.o *.skel.h + + +vmlinux.h: + bpftool btf dump file /sys/kernel/btf/vmlinux format c > $@ + +%.bpf.o: %.bpf.c vmlinux.h + $(CLANG) $(CFLAGS) -target bpf -c $< + +%.skel.h: %.bpf.o + bpftool gen skeleton $< > $@ + +$(PROGS): %: %.c %.skel.h + $(CC) $(CFLAGS) -o $@ $< -lbpf + +.PHONY: all clean + +.DELETE_ON_ERROR: +.SECONDARY: diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..db9abd1 --- /dev/null +++ b/README.adoc @@ -0,0 +1,9 @@ +README +====== + +Minimal XDP example code licensed under LGPL-2.1-or-later and BSD-2-Clause, +see https://ruderich.org/simon/notes/xdp-minimal-example for details. + + $ make vmlinux.h + $ make + $ ./example eth0 diff --git a/example.bpf.c b/example.bpf.c new file mode 100644 index 0000000..70e9113 --- /dev/null +++ b/example.bpf.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (LGPL-2.1-or-later OR BSD-2-Clause) + +#include "vmlinux.h" + +#include + + +SEC("xdp") +int xdp_prog(struct xdp_md *ctx) { + (void)ctx; + return XDP_PASS; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/example.c b/example.c new file mode 100644 index 0000000..f333587 --- /dev/null +++ b/example.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (LGPL-2.1-or-later OR BSD-2-Clause) + +#include +#include +#include +#include + +#include +/* XDP_FLAGS_SKB_MODE */ +#include + +#include "example.skel.h" + + +static int libbpf_print(enum libbpf_print_level level, const char *format, va_list args) { + if (level == LIBBPF_DEBUG) { + return 0; + } + return vfprintf(stderr, format, args); +} + + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + const char *iface = argv[1]; + unsigned int ifindex = if_nametoindex(iface); + if (!ifindex) { + perror("failed to resolve iface to ifindex"); + return EXIT_FAILURE; + } + + struct rlimit rlim = { + .rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY, + }; + if (setrlimit(RLIMIT_MEMLOCK, &rlim)) { + perror("failed to increase RLIMIT_MEMLOCK"); + return EXIT_FAILURE; + } + + libbpf_set_print(libbpf_print); + + int err; + struct example_bpf *obj; + + obj = example_bpf__open(); + if (!obj) { + fprintf(stderr, "failed to open BPF object\n"); + return EXIT_FAILURE; + } + err = example_bpf__load(obj); + if (err) { + fprintf(stderr, "failed to load BPF object: %d\n", err); + goto cleanup; + } + + /* + * Use "xdpgeneric" mode; less performance but supported by all drivers + */ + int flags = XDP_FLAGS_SKB_MODE; + int fd = bpf_program__fd(obj->progs.xdp_prog); + + /* Attach BPF to network interface */ + err = bpf_set_link_xdp_fd(ifindex, fd, flags); + if (err) { + fprintf(stderr, "failed to attach BPF to iface %s (%d): %d\n", + iface, ifindex, err); + goto cleanup; + } + + // XXX: replace with actual code, e.g. loop to get data from BPF + sleep(10); + + /* Remove BPF from network interface */ + fd = -1; + err = bpf_set_link_xdp_fd(ifindex, fd, flags); + if (err) { + fprintf(stderr, "failed to detach BPF from iface %s (%d): %d\n", + iface, ifindex, err); + goto cleanup; + } + +cleanup: + example_bpf__destroy(obj); + + if (err) { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +}