summaryrefslogtreecommitdiffstats
path: root/lib/bpf_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bpf_glue.c')
-rw-r--r--lib/bpf_glue.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/bpf_glue.c b/lib/bpf_glue.c
new file mode 100644
index 0000000..88a2475
--- /dev/null
+++ b/lib/bpf_glue.c
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * bpf_glue.c: BPF code to call both legacy and libbpf code
+ * Authors: Hangbin Liu <haliu@redhat.com>
+ *
+ */
+#include <sys/syscall.h>
+#include <limits.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "bpf_util.h"
+#ifdef HAVE_LIBBPF
+#include <bpf/bpf.h>
+#endif
+
+int bpf(int cmd, union bpf_attr *attr, unsigned int size)
+{
+#ifdef __NR_bpf
+ return syscall(__NR_bpf, cmd, attr, size);
+#else
+ fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int bpf_program_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
+{
+#ifdef HAVE_LIBBPF
+ return bpf_prog_attach(prog_fd, target_fd, type, 0);
+#else
+ return bpf_prog_attach_fd(prog_fd, target_fd, type);
+#endif
+}
+
+#ifdef HAVE_LIBBPF
+static const char *_libbpf_compile_version = LIBBPF_VERSION;
+static char _libbpf_version[10] = {};
+
+const char *get_libbpf_version(void)
+{
+ /* Start by copying compile-time version into buffer so we have a
+ * fallback value in case we are dynamically linked, or can't find a
+ * version in /proc/self/maps below.
+ */
+ strncpy(_libbpf_version, _libbpf_compile_version,
+ sizeof(_libbpf_version)-1);
+#ifdef LIBBPF_DYNAMIC
+ char buf[PATH_MAX], *s;
+ bool found = false;
+ FILE *fp;
+
+ /* When dynamically linking against libbpf, we can't be sure that the
+ * version we discovered at compile time is actually the one we are
+ * using at runtime. This can lead to hard-to-debug errors, so we try to
+ * discover the correct version at runtime.
+ *
+ * The simple solution to this would be if libbpf itself exported a
+ * version in its API. But since it doesn't, we work around this by
+ * parsing the mappings of the binary at runtime, looking for the full
+ * filename of libbpf.so and using that.
+ */
+ fp = fopen("/proc/self/maps", "r");
+ if (fp == NULL)
+ goto out;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if ((s = strstr(buf, "libbpf.so.")) != NULL) {
+ strncpy(_libbpf_version, s+10, sizeof(_libbpf_version)-1);
+ strtok(_libbpf_version, "\n");
+ found = true;
+ break;
+ }
+ }
+
+ fclose(fp);
+out:
+ if (!found)
+ fprintf(stderr, "Couldn't find runtime libbpf version - falling back to compile-time value!\n");
+#endif /* LIBBPF_DYNAMIC */
+
+ _libbpf_version[sizeof(_libbpf_version)-1] = '\0';
+ return _libbpf_version;
+}
+#else
+const char *get_libbpf_version(void)
+{
+ return NULL;
+}
+#endif /* HAVE_LIBBPF */