summaryrefslogtreecommitdiffstats
path: root/xdp-bench/xdp-bench.c
diff options
context:
space:
mode:
Diffstat (limited to 'xdp-bench/xdp-bench.c')
-rw-r--r--xdp-bench/xdp-bench.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/xdp-bench/xdp-bench.c b/xdp-bench/xdp-bench.c
new file mode 100644
index 0000000..4a09514
--- /dev/null
+++ b/xdp-bench/xdp-bench.c
@@ -0,0 +1,275 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "xdp-bench.h"
+#include "params.h"
+
+#define PROG_NAME "xdp-bench"
+
+int do_help(__unused const void *cfg, __unused const char *pin_root_path)
+{
+ fprintf(stderr,
+ "Usage: xdp-bench COMMAND [options]\n"
+ "\n"
+ "COMMAND can be one of:\n"
+ " drop - Drop all packets on an interface\n"
+ " pass - Pass all packets to the network stack\n"
+ " tx - Transmit packets back out on an interface (hairpin forwarding)\n"
+ " redirect - XDP redirect using the bpf_redirect() helper\n"
+ " redirect-cpu - XDP CPU redirect using BPF_MAP_TYPE_CPUMAP\n"
+ " redirect-map - XDP redirect using BPF_MAP_TYPE_DEVMAP\n"
+ " redirect-multi - XDP multi-redirect using BPF_MAP_TYPE_DEVMAP and the BPF_F_BROADCAST flag\n"
+ " help - show this help message\n"
+ "\n"
+ "Use 'xdp-bench COMMAND --help' to see options for each command\n");
+ return -1;
+}
+
+
+struct enum_val xdp_modes[] = {
+ {"native", XDP_MODE_NATIVE},
+ {"skb", XDP_MODE_SKB},
+ {NULL, 0}
+};
+
+struct enum_val basic_program_modes[] = {
+ {"no-touch", BASIC_NO_TOUCH},
+ {"read-data", BASIC_READ_DATA},
+ {"swap-macs", BASIC_SWAP_MACS},
+ {NULL, 0}
+};
+
+struct enum_val cpumap_remote_actions[] = {
+ {"disabled", ACTION_DISABLED},
+ {"drop", ACTION_DROP},
+ {"pass", ACTION_PASS},
+ {"redirect", ACTION_REDIRECT},
+ {NULL, 0}
+};
+
+struct enum_val cpumap_program_modes[] = {
+ {"no-touch", CPUMAP_NO_TOUCH},
+ {"touch", CPUMAP_TOUCH_DATA},
+ {"round-robin", CPUMAP_CPU_ROUND_ROBIN},
+ {"l4-proto", CPUMAP_CPU_L4_PROTO},
+ {"l4-filter", CPUMAP_CPU_L4_PROTO_FILTER},
+ {"l4-hash", CPUMAP_CPU_L4_HASH},
+ {NULL, 0}
+};
+
+
+struct prog_option basic_options[] = {
+ DEFINE_OPTION("program-mode", OPT_ENUM, struct basic_opts, program_mode,
+ .short_opt = 'p',
+ .metavar = "<mode>",
+ .typearg = basic_program_modes,
+ .help = "Action to take before dropping packet."),
+ DEFINE_OPTION("rxq-stats", OPT_BOOL, struct basic_opts, rxq_stats,
+ .short_opt = 'r',
+ .help = "Collect per-RXQ drop statistics"),
+ DEFINE_OPTION("interval", OPT_U32, struct basic_opts, interval,
+ .short_opt = 'i',
+ .metavar = "<seconds>",
+ .help = "Polling interval (default 2)"),
+ DEFINE_OPTION("extended", OPT_BOOL, struct basic_opts, extended,
+ .short_opt = 'e',
+ .help = "Start running in extended output mode (C^\\ to toggle)"),
+ DEFINE_OPTION("xdp-mode", OPT_ENUM, struct basic_opts, mode,
+ .short_opt = 'm',
+ .typearg = xdp_modes,
+ .metavar = "<mode>",
+ .help = "Load XDP program in <mode>; default native"),
+ DEFINE_OPTION("dev", OPT_IFNAME, struct basic_opts, iface_in,
+ .positional = true,
+ .metavar = "<ifname>",
+ .required = true,
+ .help = "Load on device <ifname>"),
+ END_OPTIONS
+};
+
+struct prog_option redirect_basic_options[] = {
+ DEFINE_OPTION("interval", OPT_U32, struct redirect_opts, interval,
+ .short_opt = 'i',
+ .metavar = "<seconds>",
+ .help = "Polling interval (default 2)"),
+ DEFINE_OPTION("stats", OPT_BOOL, struct redirect_opts, stats,
+ .short_opt = 's',
+ .help = "Enable statistics for transmitted packets (not just errors)"),
+ DEFINE_OPTION("extended", OPT_BOOL, struct redirect_opts, extended,
+ .short_opt = 'e',
+ .help = "Start running in extended output mode (C^\\ to toggle)"),
+ DEFINE_OPTION("mode", OPT_ENUM, struct redirect_opts, mode,
+ .short_opt = 'm',
+ .typearg = xdp_modes,
+ .metavar = "<mode>",
+ .help = "Load XDP program in <mode>; default native"),
+ DEFINE_OPTION("dev_in", OPT_IFNAME, struct redirect_opts, iface_in,
+ .positional = true,
+ .metavar = "<ifname_in>",
+ .required = true,
+ .help = "Redirect from device <ifname>"),
+ DEFINE_OPTION("dev_out", OPT_IFNAME, struct redirect_opts, iface_out,
+ .positional = true,
+ .metavar = "<ifname_out>",
+ .required = true,
+ .help = "Redirect to device <ifname>"),
+ END_OPTIONS
+};
+
+struct prog_option redirect_cpumap_options[] = {
+ DEFINE_OPTION("cpu", OPT_U32_MULTI, struct cpumap_opts, cpus,
+ .short_opt = 'c',
+ .metavar = "<cpu>",
+ .required = true,
+ .help = "Insert CPU <cpu> into CPUMAP (can be specified multiple times)"),
+ DEFINE_OPTION("dev", OPT_IFNAME, struct cpumap_opts, iface_in,
+ .positional = true,
+ .metavar = "<ifname>",
+ .required = true,
+ .help = "Run on <ifname>"),
+ DEFINE_OPTION("program-mode", OPT_ENUM, struct cpumap_opts, program_mode,
+ .short_opt = 'p',
+ .metavar = "<mode>",
+ .typearg = cpumap_program_modes,
+ .help = "Redirect to CPUs using <mode>. Default l4-hash."),
+ DEFINE_OPTION("remote-action", OPT_ENUM, struct cpumap_opts, remote_action,
+ .short_opt = 'r',
+ .metavar = "<action>",
+ .typearg = cpumap_remote_actions,
+ .help = "Perform <action> on the remote CPU. Default disabled."),
+ DEFINE_OPTION("redirect-device", OPT_IFNAME, struct cpumap_opts, redir_iface,
+ .short_opt = 'D',
+ .metavar = "<ifname>",
+ .help = "Redirect packets to <ifname> on remote CPU (when --remote-action is 'redirect')"),
+ DEFINE_OPTION("qsize", OPT_U32, struct cpumap_opts, qsize,
+ .short_opt = 'q',
+ .metavar = "<packets>",
+ .help = "CPUMAP queue size (default 2048)"),
+ DEFINE_OPTION("stress-mode", OPT_BOOL, struct cpumap_opts, stress_mode,
+ .short_opt = 'x',
+ .help = "Stress the kernel CPUMAP setup and teardown code while running"),
+ DEFINE_OPTION("interval", OPT_U32, struct cpumap_opts, interval,
+ .short_opt = 'i',
+ .metavar = "<seconds>",
+ .help = "Polling interval (default 2)"),
+ DEFINE_OPTION("stats", OPT_BOOL, struct cpumap_opts, stats,
+ .short_opt = 's',
+ .help = "Enable statistics for transmitted packets (not just errors)"),
+ DEFINE_OPTION("extended", OPT_BOOL, struct basic_opts, extended,
+ .short_opt = 'e',
+ .help = "Start running in extended output mode (C^\\ to toggle)"),
+ DEFINE_OPTION("xdp-mode", OPT_ENUM, struct cpumap_opts, mode,
+ .short_opt = 'm',
+ .typearg = xdp_modes,
+ .metavar = "<mode>",
+ .help = "Load XDP program in <mode>; default native"),
+ END_OPTIONS
+};
+
+struct prog_option redirect_devmap_options[] = {
+ DEFINE_OPTION("load-egress", OPT_BOOL, struct devmap_opts, load_egress,
+ .short_opt = 'X',
+ .help = "Load an egress program into the devmap"),
+ DEFINE_OPTION("interval", OPT_U32, struct devmap_opts, interval,
+ .short_opt = 'i',
+ .metavar = "<seconds>",
+ .help = "Polling interval (default 2)"),
+ DEFINE_OPTION("stats", OPT_BOOL, struct devmap_opts, stats,
+ .short_opt = 's',
+ .help = "Enable statistics for transmitted packets (not just errors)"),
+ DEFINE_OPTION("extended", OPT_BOOL, struct devmap_opts, extended,
+ .short_opt = 'e',
+ .help = "Start running in extended output mode (C^\\ to toggle)"),
+ DEFINE_OPTION("mode", OPT_ENUM, struct devmap_opts, mode,
+ .short_opt = 'm',
+ .typearg = xdp_modes,
+ .metavar = "<mode>",
+ .help = "Load XDP program in <mode>; default native"),
+ DEFINE_OPTION("dev_in", OPT_IFNAME, struct devmap_opts, iface_in,
+ .positional = true,
+ .metavar = "<ifname_in>",
+ .required = true,
+ .help = "Redirect from device <ifname>"),
+ DEFINE_OPTION("dev_out", OPT_IFNAME, struct devmap_opts, iface_out,
+ .positional = true,
+ .metavar = "<ifname_out>",
+ .required = true,
+ .help = "Redirect to device <ifname>"),
+ END_OPTIONS
+};
+
+struct prog_option redirect_devmap_multi_options[] = {
+ DEFINE_OPTION("load-egress", OPT_BOOL, struct devmap_multi_opts, load_egress,
+ .short_opt = 'X',
+ .help = "Load an egress program into the devmap"),
+ DEFINE_OPTION("interval", OPT_U32, struct devmap_multi_opts, interval,
+ .short_opt = 'i',
+ .metavar = "<seconds>",
+ .help = "Polling interval (default 2)"),
+ DEFINE_OPTION("stats", OPT_BOOL, struct devmap_multi_opts, stats,
+ .short_opt = 's',
+ .help = "Enable statistics for transmitted packets (not just errors)"),
+ DEFINE_OPTION("extended", OPT_BOOL, struct devmap_multi_opts, extended,
+ .short_opt = 'e',
+ .help = "Start running in extended output mode (C^\\ to toggle)"),
+ DEFINE_OPTION("mode", OPT_ENUM, struct devmap_multi_opts, mode,
+ .short_opt = 'm',
+ .typearg = xdp_modes,
+ .metavar = "<mode>",
+ .help = "Load XDP program in <mode>; default native"),
+ DEFINE_OPTION("devs", OPT_IFNAME_MULTI, struct devmap_multi_opts, ifaces,
+ .positional = true,
+ .metavar = "<ifname...>",
+ .min_num = 2,
+ .max_num = MAX_IFACE_NUM,
+ .required = true,
+ .help = "Redirect from and to devices <ifname...>"),
+ END_OPTIONS
+};
+
+static const struct prog_command cmds[] = {
+ { .name = "drop",
+ .func = do_drop,
+ .options = basic_options,
+ .default_cfg = &defaults_drop,
+ .doc = "Drop all packets on an interface" },
+ { .name = "pass",
+ .func = do_pass,
+ .options = basic_options,
+ .default_cfg = &defaults_pass,
+ .doc = "Pass all packets to the network stack" },
+ { .name = "tx",
+ .func = do_tx,
+ .options = basic_options,
+ .default_cfg = &defaults_tx,
+ .doc = "Transmit packets back out an interface (hairpin forwarding)" },
+ DEFINE_COMMAND_NAME("redirect", redirect_basic,
+ "XDP redirect using the bpf_redirect() helper"),
+ DEFINE_COMMAND_NAME("redirect-cpu", redirect_cpumap,
+ "XDP CPU redirect using BPF_MAP_TYPE_CPUMAP"),
+ DEFINE_COMMAND_NAME("redirect-map", redirect_devmap,
+ "XDP redirect using BPF_MAP_TYPE_DEVMAP"),
+ DEFINE_COMMAND_NAME(
+ "redirect-multi", redirect_devmap_multi,
+ "XDP multi-redirect using BPF_MAP_TYPE_DEVMAP and the BPF_F_BROADCAST flag"),
+ { .name = "help", .func = do_help, .no_cfg = true },
+ END_COMMANDS
+};
+
+union all_opts {
+ struct basic_opts basic;
+ struct cpumap_opts cpumap;
+ struct devmap_opts devmap;
+ struct devmap_multi_opts devmap_multi;
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ return dispatch_commands(argv[1], argc - 1, argv + 1, cmds,
+ sizeof(union all_opts), PROG_NAME, false);
+
+ return do_help(NULL, NULL);
+}