From a746871f0dd6ac4f5158f7b9fc713d5d06e65db4 Mon Sep 17 00:00:00 2001 From: Nimrod Oren Date: Tue, 5 Nov 2024 16:33:52 +0200 Subject: [PATCH 1/2] xdp-bench: Update load-mode documentation Update the documentation to reflect the changes made in pull request #409 (d7edea3). Signed-off-by: Nimrod Oren --- xdp-bench/README.org | 21 +++++++++------------ xdp-bench/xdp-bench.8 | 27 ++++++++++++--------------- xdp-bench/xdp-bench.c | 2 +- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/xdp-bench/README.org b/xdp-bench/README.org index 1e24709c..a2f69290 100644 --- a/xdp-bench/README.org +++ b/xdp-bench/README.org @@ -78,13 +78,12 @@ flushing it back out if writing). The default for this option is =no-touch=. ** -l, --load-mode -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with =-p parse-ip=). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: #+begin_src sh dpa - Use traditional Direct Packet Access from the XDP program - load-bytes - Use the xdp_load_bytes() helper function to load the data + load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions #+end_src This can be used to benchmark the various packet access modes supported by the @@ -154,13 +153,12 @@ following actions are available: The default for this option is =no-touch=. ** -l, --load-mode -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with =-p parse-ip=). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: #+begin_src sh dpa - Use traditional Direct Packet Access from the XDP program - load-bytes - Use the xdp_load_bytes() helper function to load the data + load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions #+end_src This can be used to benchmark the various packet access modes supported by the @@ -234,13 +232,12 @@ allows this function to be turned off. The default for this option is =swap-macs=. ** -l, --load-mode -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with =-p parse-ip=). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: #+begin_src sh dpa - Use traditional Direct Packet Access from the XDP program - load-bytes - Use the xdp_load_bytes() helper function to load the data + load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions #+end_src This can be used to benchmark the various packet access modes supported by the diff --git a/xdp-bench/xdp-bench.8 b/xdp-bench/xdp-bench.8 index 01263bab..20b6b5a9 100644 --- a/xdp-bench/xdp-bench.8 +++ b/xdp-bench/xdp-bench.8 @@ -92,14 +92,13 @@ The default for this option is \fIno\-touch\fP. .SS "-l, --load-mode " .PP -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with \fI\-p parse\-ip\fP). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: .RS .nf -\fCdpa - Use traditional Direct Packet Access from the XDP program -load-bytes - Use the xdp_load_bytes() helper function to load the data +\fCdpa - Use traditional Direct Packet Access from the XDP program +load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions \fP .fi .RE @@ -191,14 +190,13 @@ The default for this option is \fIno\-touch\fP. .SS "-l, --load-mode " .PP -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with \fI\-p parse\-ip\fP). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: .RS .nf -\fCdpa - Use traditional Direct Packet Access from the XDP program -load-bytes - Use the xdp_load_bytes() helper function to load the data +\fCdpa - Use traditional Direct Packet Access from the XDP program +load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions \fP .fi .RE @@ -295,14 +293,13 @@ The default for this option is \fIswap\-macs\fP. .SS "-l, --load-mode " .PP -Specify which mechanism xdp-bench should use to load the packet data when -parsing the IP header (used with \fI\-p parse\-ip\fP). The following modes are -available: +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: .RS .nf -\fCdpa - Use traditional Direct Packet Access from the XDP program -load-bytes - Use the xdp_load_bytes() helper function to load the data +\fCdpa - Use traditional Direct Packet Access from the XDP program +load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions \fP .fi .RE diff --git a/xdp-bench/xdp-bench.c b/xdp-bench/xdp-bench.c index ce3457c3..cab7cbf2 100644 --- a/xdp-bench/xdp-bench.c +++ b/xdp-bench/xdp-bench.c @@ -82,7 +82,7 @@ struct prog_option basic_options[] = { .short_opt = 'l', .metavar = "", .typearg = basic_load_modes, - .help = "How to load data when parsing IP header (with -p parse-ip; default dpa)"), + .help = "How to load (and store) data; default dpa"), DEFINE_OPTION("rxq-stats", OPT_BOOL, struct basic_opts, rxq_stats, .short_opt = 'r', .help = "Collect per-RXQ drop statistics"), From 3b199c0c185d4603406e6324ca5783b157c0e492 Mon Sep 17 00:00:00 2001 From: Nimrod Oren Date: Tue, 5 Nov 2024 16:45:43 +0200 Subject: [PATCH 2/2] xdp-bench: Introduce xdp_redirect_basic_load_bytes_prog This commit introduces xdp_redirect_basic_load_bytes_prog to xdp-bench. This program uses the bpf_xdp_load_bytes and bpf_xdp_store_bytes helpers for packet data access. In contrast, xdp_redirect_basic_prog uses direct packet access. The program that will be attached is determined by the --load-mode flag. Signed-off-by: Nimrod Oren --- xdp-bench/README.org | 14 +++++++++++++ xdp-bench/tests/test-xdp-bench.sh | 12 ++++++++++- xdp-bench/xdp-bench.8 | 20 ++++++++++++++++++ xdp-bench/xdp-bench.c | 5 +++++ xdp-bench/xdp-bench.h | 1 + xdp-bench/xdp_redirect_basic.bpf.c | 33 +++++++++++++++++++++++++++++- xdp-bench/xdp_redirect_basic.c | 9 +++++++- 7 files changed, 91 insertions(+), 3 deletions(-) diff --git a/xdp-bench/README.org b/xdp-bench/README.org index a2f69290..fe63190e 100644 --- a/xdp-bench/README.org +++ b/xdp-bench/README.org @@ -290,6 +290,20 @@ be redirect to the output interface ==. The supported options are: +** -l, --load-mode +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: + +#+begin_src sh + dpa - Use traditional Direct Packet Access from the XDP program + load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions +#+end_src + +This can be used to benchmark the various packet access modes supported by the +kernel. + +The default for this option is =dpa=. + ** -i, --interval Set the polling interval for collecting all statistics and displaying them to the output. The unit of interval is in seconds. diff --git a/xdp-bench/tests/test-xdp-bench.sh b/xdp-bench/tests/test-xdp-bench.sh index 171d5d1a..b759e736 100644 --- a/xdp-bench/tests/test-xdp-bench.sh +++ b/xdp-bench/tests/test-xdp-bench.sh @@ -35,10 +35,20 @@ test_xdp_load_bytes() export XDP_SAMPLE_IMMEDIATE_EXIT=1 for action in drop pass tx; do - check_run $XDP_BENCH $action $NS -p parse-ip -l load-bytes -vv + check_run $XDP_BENCH $action $NS -l load-bytes -vv check_run $XDP_BENCH $action $NS -p read-data -l load-bytes -vv + check_run $XDP_BENCH $action $NS -p parse-ip -l load-bytes -vv check_run $XDP_BENCH $action $NS -p swap-macs -l load-bytes -vv + check_run $XDP_BENCH $action $NS -m skb -l load-bytes -vv + check_run $XDP_BENCH $action $NS -e -l load-bytes -vv done + + check_run ip link add dev btest0 type veth peer name btest1 + check_run $XDP_BENCH redirect btest0 btest1 -l load-bytes -vv + check_run $XDP_BENCH redirect btest0 btest1 -s -l load-bytes -vv + check_run $XDP_BENCH redirect btest0 btest1 -m skb -l load-bytes -vv + check_run $XDP_BENCH redirect btest0 btest1 -e -l load-bytes -vv + ip link del dev btest0 } test_rxq_stats() diff --git a/xdp-bench/xdp-bench.8 b/xdp-bench/xdp-bench.8 index 20b6b5a9..15926c94 100644 --- a/xdp-bench/xdp-bench.8 +++ b/xdp-bench/xdp-bench.8 @@ -368,6 +368,26 @@ be redirect to the output interface \fI\fP. .PP The supported options are: +.SS "-l, --load-mode " +.PP +Specify which mechanism xdp-bench should use to load (and store) the packet data. +The following modes are available: + +.RS +.nf +\fCdpa - Use traditional Direct Packet Access from the XDP program +load-bytes - Use the xdp_load_bytes() and xdp_store_bytes() helper functions +\fP +.fi +.RE + +.PP +This can be used to benchmark the various packet access modes supported by the +kernel. + +.PP +The default for this option is \fIdpa\fP. + .SS "-i, --interval " .PP Set the polling interval for collecting all statistics and displaying them to diff --git a/xdp-bench/xdp-bench.c b/xdp-bench/xdp-bench.c index cab7cbf2..715fffcd 100644 --- a/xdp-bench/xdp-bench.c +++ b/xdp-bench/xdp-bench.c @@ -107,6 +107,11 @@ struct prog_option basic_options[] = { }; struct prog_option redirect_basic_options[] = { + DEFINE_OPTION("load-mode", OPT_ENUM, struct redirect_opts, load_mode, + .short_opt = 'l', + .metavar = "", + .typearg = basic_load_modes, + .help = "How to load (and store) data; default dpa"), DEFINE_OPTION("interval", OPT_U32, struct redirect_opts, interval, .short_opt = 'i', .metavar = "", diff --git a/xdp-bench/xdp-bench.h b/xdp-bench/xdp-bench.h index b8a12585..a5cf60aa 100644 --- a/xdp-bench/xdp-bench.h +++ b/xdp-bench/xdp-bench.h @@ -43,6 +43,7 @@ struct redirect_opts { bool extended; __u32 interval; enum xdp_attach_mode mode; + enum basic_load_mode load_mode; struct iface iface_in; struct iface iface_out; }; diff --git a/xdp-bench/xdp_redirect_basic.bpf.c b/xdp-bench/xdp_redirect_basic.bpf.c index ca2af1f8..dc3d920b 100644 --- a/xdp-bench/xdp_redirect_basic.bpf.c +++ b/xdp-bench/xdp_redirect_basic.bpf.c @@ -16,10 +16,15 @@ #include #include +#ifndef HAVE_LIBBPF_BPF_PROGRAM__TYPE +static long (*bpf_xdp_load_bytes)(struct xdp_md *xdp_md, __u32 offset, void *buf, __u32 len) = (void *) 189; +static long (*bpf_xdp_store_bytes)(struct xdp_md *xdp_md, __u32 offset, void *buf, __u32 len) = (void *) 190; +#endif + const volatile int ifindex_out; SEC("xdp") -int xdp_redirect_basic_prog(struct xdp_md *ctx) +int xdp_redirect_prog(struct xdp_md *ctx) { void *data_end = (void *)(long)ctx->data_end; void *data = (void *)(long)ctx->data; @@ -41,4 +46,30 @@ int xdp_redirect_basic_prog(struct xdp_md *ctx) return bpf_redirect(ifindex_out, 0); } +SEC("xdp") +int xdp_redirect_load_bytes_prog(struct xdp_md *ctx) +{ + __u32 key = bpf_get_smp_processor_id(); + int err, offset = 0; + struct datarec *rec; + struct ethhdr eth; + + err = bpf_xdp_load_bytes(ctx, offset, ð, sizeof(eth)); + if (err) + return err; + + rec = bpf_map_lookup_elem(&rx_cnt, &key); + if (!rec) + return XDP_PASS; + NO_TEAR_INC(rec->processed); + + swap_src_dst_mac(ð); + + err = bpf_xdp_store_bytes(ctx, offset, ð, sizeof(eth)); + if (err) + return err; + + return bpf_redirect(ifindex_out, 0); +} + char _license[] SEC("license") = "GPL"; diff --git a/xdp-bench/xdp_redirect_basic.c b/xdp-bench/xdp_redirect_basic.c index 4ffa2cad..ee6c1801 100644 --- a/xdp-bench/xdp_redirect_basic.c +++ b/xdp-bench/xdp_redirect_basic.c @@ -39,6 +39,7 @@ int do_redirect_basic(const void *cfg, __unused const char *pin_root_path) struct xdp_program *xdp_prog = NULL, *dummy_prog = NULL; DECLARE_LIBBPF_OPTS(xdp_program_opts, opts); + struct bpf_program *prog = NULL; struct xdp_redirect_basic *skel; char str[2 * IF_NAMESIZE + 1]; int ret = EXIT_FAIL_OPTION; @@ -73,8 +74,14 @@ int do_redirect_basic(const void *cfg, __unused const char *pin_root_path) skel->rodata->to_match[0] = opt->iface_out.ifindex; skel->rodata->ifindex_out = opt->iface_out.ifindex; + /* Make sure we only load the one XDP program we are interested in */ + while ((prog = bpf_object__next_program(skel->obj, prog)) != NULL) + if (bpf_program__type(prog) == BPF_PROG_TYPE_XDP && + bpf_program__expected_attach_type(prog) == BPF_XDP) + bpf_program__set_autoload(prog, false); + opts.obj = skel->obj; - opts.prog_name = bpf_program__name(skel->progs.xdp_redirect_basic_prog); + opts.prog_name = (opt->load_mode == BASIC_LOAD_BYTES) ? "xdp_redirect_load_bytes_prog" : "xdp_redirect_prog"; xdp_prog = xdp_program__create(&opts); if (!xdp_prog) { ret = -errno;