summaryrefslogtreecommitdiffstats
path: root/xdp-bench/xdp_basic.c
diff options
context:
space:
mode:
Diffstat (limited to 'xdp-bench/xdp_basic.c')
-rw-r--r--xdp-bench/xdp_basic.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/xdp-bench/xdp_basic.c b/xdp-bench/xdp_basic.c
new file mode 100644
index 0000000..f748c2b
--- /dev/null
+++ b/xdp-bench/xdp_basic.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2016 John Fastabend <john.r.fastabend@intel.com>
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <net/if.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <bpf/bpf.h>
+#include <stdbool.h>
+#include <linux/bpf.h>
+#include <bpf/libbpf.h>
+#include <sys/resource.h>
+#include <linux/if_link.h>
+#include <xdp/libxdp.h>
+
+#include "logging.h"
+
+#include "xdp-bench.h"
+#include "xdp_sample.h"
+#include "xdp_basic.skel.h"
+
+static int mask = SAMPLE_RX_CNT | SAMPLE_EXCEPTION_CNT;
+
+DEFINE_SAMPLE_INIT(xdp_basic);
+
+const struct basic_opts defaults_drop = { .mode = XDP_MODE_NATIVE,
+ .interval = 2 };
+const struct basic_opts defaults_pass = { .mode = XDP_MODE_NATIVE,
+ .interval = 2 };
+const struct basic_opts defaults_tx = { .mode = XDP_MODE_NATIVE,
+ .interval = 2,
+ .program_mode = BASIC_SWAP_MACS };
+
+static int do_basic(const struct basic_opts *opt, enum xdp_action action)
+{
+ DECLARE_LIBBPF_OPTS(xdp_program_opts, opts);
+ struct xdp_program *xdp_prog = NULL;
+ int ret = EXIT_FAIL_OPTION;
+ struct xdp_basic *skel;
+
+ if (opt->extended)
+ sample_switch_mode();
+
+ skel = xdp_basic__open();
+ if (!skel) {
+ pr_warn("Failed to xdp_basic__open: %s\n", strerror(errno));
+ ret = EXIT_FAIL_BPF;
+ goto end;
+ }
+
+ ret = sample_init_pre_load(skel, opt->iface_in.ifname);
+ if (ret < 0) {
+ pr_warn("Failed to sample_init_pre_load: %s\n", strerror(-ret));
+ ret = EXIT_FAIL_BPF;
+ goto end_destroy;
+ }
+
+ skel->rodata->action = action;
+ if (action == XDP_DROP)
+ mask |= SAMPLE_DROP_OK;
+
+ if (opt->program_mode >= BASIC_READ_DATA)
+ skel->rodata->read_data = true;
+ if (opt->program_mode >= BASIC_SWAP_MACS)
+ skel->rodata->swap_macs = true;
+ if (opt->rxq_stats) {
+ skel->rodata->rxq_stats = true;
+ mask |= SAMPLE_RXQ_STATS;
+ }
+
+ opts.obj = skel->obj;
+ opts.prog_name = bpf_program__name(skel->progs.xdp_basic_prog);
+ xdp_prog = xdp_program__create(&opts);
+ if (!xdp_prog) {
+ ret = -errno;
+ pr_warn("Couldn't open XDP program: %s\n",
+ strerror(-ret));
+ goto end_destroy;
+ }
+
+ ret = xdp_program__attach(xdp_prog, opt->iface_in.ifindex, opt->mode, 0);
+ if (ret < 0) {
+ pr_warn("Failed to attach XDP program: %s\n", strerror(-ret));
+ ret = EXIT_FAIL_BPF;
+ goto end_destroy;
+ }
+
+ ret = sample_init(skel, mask, 0, 0);
+ if (ret < 0) {
+ pr_warn("Failed to initialize sample: %s\n", strerror(-ret));
+ ret = EXIT_FAIL;
+ goto end_detach;
+ }
+
+ ret = EXIT_FAIL;
+
+ pr_info("%s packets on %s (ifindex %d; driver %s)\n",
+ action == XDP_DROP ? "Dropping" : "Hairpinning (XDP_TX)",
+ opt->iface_in.ifname, opt->iface_in.ifindex, get_driver_name(opt->iface_in.ifindex));
+
+ ret = sample_run(opt->interval, NULL, NULL);
+ if (ret < 0) {
+ pr_warn("Failed during sample run: %s\n", strerror(-ret));
+ ret = EXIT_FAIL;
+ goto end_detach;
+ }
+ ret = EXIT_OK;
+end_detach:
+ xdp_program__detach(xdp_prog, opt->iface_in.ifindex, opt->mode, 0);
+end_destroy:
+ xdp_basic__destroy(skel);
+end:
+ sample_teardown();
+ return ret;
+}
+
+int do_drop(const void *cfg, __unused const char *pin_root_path)
+{
+ const struct basic_opts *opt = cfg;
+
+ return do_basic(opt, XDP_DROP);
+}
+
+int do_pass(const void *cfg, __unused const char *pin_root_path)
+{
+ const struct basic_opts *opt = cfg;
+
+ return do_basic(opt, XDP_PASS);
+}
+
+int do_tx(const void *cfg, __unused const char *pin_root_path)
+{
+ const struct basic_opts *opt = cfg;
+
+ return do_basic(opt, XDP_TX);
+}