]> ruderich.org/simon Gitweb - bpf/xdp-example.git/commitdiff
Initial commit master
authorSimon Ruderich <simon@ruderich.org>
Sun, 15 Nov 2020 07:43:22 +0000 (08:43 +0100)
committerSimon Ruderich <simon@ruderich.org>
Sun, 15 Nov 2020 07:43:22 +0000 (08:43 +0100)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.adoc [new file with mode: 0644]
example.bpf.c [new file with mode: 0644]
example.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d4218fb
--- /dev/null
@@ -0,0 +1,4 @@
+/example
+/example.bpf.o
+/example.skel.h
+/vmlinux.h
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..db9abd1
--- /dev/null
@@ -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 (file)
index 0000000..70e9113
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (LGPL-2.1-or-later OR BSD-2-Clause)
+
+#include "vmlinux.h"
+
+#include <bpf/bpf_helpers.h>
+
+
+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 (file)
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 <net/if.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <bpf/bpf.h>
+/* XDP_FLAGS_SKB_MODE */
+#include <linux/if_link.h>
+
+#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 <iface>\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;
+}