No functional changes (in theory): convert libxsk-generated program bytecode to the C code to better illustrate kfunc metadata (see next patch in the series). There is also a bunch of unrelated changes, ignore them for the sake of demo: - stats.rx_dopped == 2048 vs 2047 ? - buggy ksft_print_msg calls - test is limited only to TEST_MODE_DRV+TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT Cc: Martin KaFai Lau <martin.lau@xxxxxxxxx> Cc: Jakub Kicinski <kuba@xxxxxxxxxx> Cc: Willem de Bruijn <willemb@xxxxxxxxxx> Cc: Jesper Dangaard Brouer <brouer@xxxxxxxxxx> Cc: Anatoly Burakov <anatoly.burakov@xxxxxxxxx> Cc: Alexander Lobakin <alexandr.lobakin@xxxxxxxxx> Cc: Magnus Karlsson <magnus.karlsson@xxxxxxxxx> Cc: Maryam Tahhan <mtahhan@xxxxxxxxxx> Cc: xdp-hints@xxxxxxxxxxxxxxx Cc: netdev@xxxxxxxxxxxxxxx Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> --- tools/testing/selftests/bpf/Makefile | 1 + .../testing/selftests/bpf/progs/xskxceiver.c | 21 ++++ tools/testing/selftests/bpf/xskxceiver.c | 98 +++++++++++++++---- tools/testing/selftests/bpf/xskxceiver.h | 5 +- 4 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/xskxceiver.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 79edef1dbda4..3cab2e1b0e74 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -378,6 +378,7 @@ linked_maps.skel.h-deps := linked_maps1.bpf.o linked_maps2.bpf.o test_subskeleton.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o test_subskeleton.bpf.o test_subskeleton_lib.skel.h-deps := test_subskeleton_lib2.bpf.o test_subskeleton_lib.bpf.o test_usdt.skel.h-deps := test_usdt.bpf.o test_usdt_multispec.bpf.o +xskxceiver-deps := xskxceiver.bpf.o LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) diff --git a/tools/testing/selftests/bpf/progs/xskxceiver.c b/tools/testing/selftests/bpf/progs/xskxceiver.c new file mode 100644 index 000000000000..b135daddad3a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/xskxceiver.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/bpf.h> + +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_endian.h> + +struct { + __uint(type, BPF_MAP_TYPE_XSKMAP); + __uint(max_entries, 4); + __type(key, __u32); + __type(value, __u32); +} xsk SEC(".maps"); + +SEC("xdp") +int rx(struct xdp_md *ctx) +{ + return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS); +} + +char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c index 681a5db80dae..066bd691db13 100644 --- a/tools/testing/selftests/bpf/xskxceiver.c +++ b/tools/testing/selftests/bpf/xskxceiver.c @@ -399,6 +399,58 @@ static void usage(const char *prog) ksft_print_msg(str, prog); } +static void bpf_update_xsk_map(struct ifobject *ifobject, __u32 queue_id) +{ + int map_fd; + int sock_fd; + int ret; + + map_fd = bpf_map__fd(ifobject->bpf_obj->maps.xsk); + sock_fd = xsk_socket__fd(ifobject->xsk->xsk); + + (void)bpf_map_delete_elem(map_fd, &queue_id); + ret = bpf_map_update_elem(map_fd, &queue_id, &sock_fd, 0); + if (ret) + exit_with_error(-ret); +} + +static int bpf_attach(struct ifobject *ifobject) +{ + __u32 prog_id = 0; + + bpf_xdp_query_id(ifobject->ifindex, ifobject->xdp_flags, &prog_id); + if (prog_id) + return 0; + + int ret = bpf_xdp_attach(ifobject->ifindex, + bpf_program__fd(ifobject->bpf_obj->progs.rx), + ifobject->xdp_flags, NULL); + if (ret < 0) { + if (errno != EEXIST && errno != EBUSY) { + exit_with_error(errno); + } + } + + bpf_update_xsk_map(ifobject, 0); + + return 0; +} + +static void bpf_detach(struct ifobject *ifobject) +{ + int my_ns = open("/proc/self/ns/net", O_RDONLY); + + /* Make sure we're in the right namespace when detaching. + * Relevant only for TEST_TYPE_BIDI. + */ + if (ifobject->ns_fd > 0) + setns(ifobject->ns_fd, 0); + + bpf_xdp_detach(ifobject->ifindex, ifobject->xdp_flags, NULL); + + setns(my_ns, 0); +} + static int switch_namespace(const char *nsname) { char fqns[26] = "/var/run/netns/"; @@ -1141,9 +1193,10 @@ static int validate_rx_dropped(struct ifobject *ifobject) if (err) return TEST_FAILURE; - if (stats.rx_dropped == ifobject->pkt_stream->nb_pkts / 2) + if (stats.rx_dropped == ifobject->pkt_stream->nb_pkts / 2 - 1) return TEST_PASS; + printf("%lld != %d\n", stats.rx_dropped, ifobject->pkt_stream->nb_pkts / 2 - 1); return TEST_FAILURE; } @@ -1239,7 +1292,6 @@ static void thread_common_ops_tx(struct test_spec *test, struct ifobject *ifobje { xsk_configure_socket(test, ifobject, test->ifobj_rx->umem, true); ifobject->xsk = &ifobject->xsk_arr[0]; - ifobject->xsk_map_fd = test->ifobj_rx->xsk_map_fd; memcpy(ifobject->umem, test->ifobj_rx->umem, sizeof(struct xsk_umem_info)); } @@ -1284,6 +1336,14 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject) ifobject->ns_fd = switch_namespace(ifobject->nsname); + ifindex = if_nametoindex(ifobject->ifname); + if (!ifindex) + exit_with_error(errno); + + ifobject->bpf_obj = xskxceiver__open_and_load(); + if (libbpf_get_error(ifobject->bpf_obj)) + exit_with_error(libbpf_get_error(ifobject->bpf_obj)); + if (ifobject->umem->unaligned_mode) mmap_flags |= MAP_HUGETLB; @@ -1307,11 +1367,8 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject) if (!ifobject->rx_on) return; - ifindex = if_nametoindex(ifobject->ifname); - if (!ifindex) - exit_with_error(errno); - - ret = xsk_setup_xdp_prog_xsk(ifobject->xsk->xsk, &ifobject->xsk_map_fd); + ifobject->ifindex = ifindex; + ret = bpf_attach(ifobject); if (ret) exit_with_error(-ret); @@ -1321,19 +1378,17 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject) if (ifobject->xdp_flags & XDP_FLAGS_SKB_MODE) { if (opts.attach_mode != XDP_ATTACHED_SKB) { - ksft_print_msg("ERROR: [%s] XDP prog not in SKB mode\n"); + ksft_print_msg("ERROR: XDP prog not in SKB mode\n"); exit_with_error(-EINVAL); } } else if (ifobject->xdp_flags & XDP_FLAGS_DRV_MODE) { if (opts.attach_mode != XDP_ATTACHED_DRV) { - ksft_print_msg("ERROR: [%s] XDP prog not in DRV mode\n"); + ksft_print_msg("ERROR: XDP prog not in DRV mode\n"); exit_with_error(-EINVAL); } } - ret = xsk_socket__update_xskmap(ifobject->xsk->xsk, ifobject->xsk_map_fd); - if (ret) - exit_with_error(-ret); + bpf_update_xsk_map(ifobject, 0); } static void *worker_testapp_validate_tx(void *arg) @@ -1372,8 +1427,7 @@ static void *worker_testapp_validate_rx(void *arg) if (test->current_step == 1) { thread_common_ops(test, ifobject); } else { - bpf_map_delete_elem(ifobject->xsk_map_fd, &id); - xsk_socket__update_xskmap(ifobject->xsk->xsk, ifobject->xsk_map_fd); + bpf_update_xsk_map(ifobject, id); } fds.fd = xsk_socket__fd(ifobject->xsk->xsk); @@ -1481,6 +1535,8 @@ static int testapp_validate_traffic(struct test_spec *test) if (test->total_steps == test->current_step || test->fail) { xsk_socket__delete(ifobj_tx->xsk->xsk); xsk_socket__delete(ifobj_rx->xsk->xsk); + bpf_detach(ifobj_tx); + bpf_detach(ifobj_rx); testapp_clean_xsk_umem(ifobj_rx); if (!ifobj_tx->shared_umem) testapp_clean_xsk_umem(ifobj_tx); @@ -1531,16 +1587,12 @@ static void testapp_bidi(struct test_spec *test) static void swap_xsk_resources(struct ifobject *ifobj_tx, struct ifobject *ifobj_rx) { - int ret; - xsk_socket__delete(ifobj_tx->xsk->xsk); xsk_socket__delete(ifobj_rx->xsk->xsk); ifobj_tx->xsk = &ifobj_tx->xsk_arr[1]; ifobj_rx->xsk = &ifobj_rx->xsk_arr[1]; - ret = xsk_socket__update_xskmap(ifobj_rx->xsk->xsk, ifobj_rx->xsk_map_fd); - if (ret) - exit_with_error(-ret); + bpf_update_xsk_map(ifobj_tx, 0); } static void testapp_bpf_res(struct test_spec *test) @@ -1635,6 +1687,8 @@ static bool testapp_unaligned(struct test_spec *test) { if (!hugepages_present(test->ifobj_tx)) { ksft_test_result_skip("No 2M huge pages present.\n"); + bpf_detach(test->ifobj_tx); + bpf_detach(test->ifobj_rx); return false; } @@ -1947,10 +2001,16 @@ int main(int argc, char **argv) for (i = 0; i < modes; i++) for (j = 0; j < TEST_TYPE_MAX; j++) { + if (j != TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT) continue; // XXX + if (i != TEST_MODE_DRV) continue; // XXX + test_spec_init(&test, ifobj_tx, ifobj_rx, i); run_pkt_test(&test, i, j); usleep(USLEEP_MAX); + xskxceiver__destroy(ifobj_tx->bpf_obj); + xskxceiver__destroy(ifobj_rx->bpf_obj); + if (test.fail) failed_tests++; } diff --git a/tools/testing/selftests/bpf/xskxceiver.h b/tools/testing/selftests/bpf/xskxceiver.h index edb76d2def9f..c27dcbdb030f 100644 --- a/tools/testing/selftests/bpf/xskxceiver.h +++ b/tools/testing/selftests/bpf/xskxceiver.h @@ -5,6 +5,8 @@ #ifndef XSKXCEIVER_H_ #define XSKXCEIVER_H_ +#include "xskxceiver.skel.h" + #ifndef SOL_XDP #define SOL_XDP 283 #endif @@ -134,6 +136,7 @@ typedef void *(*thread_func_t)(void *arg); struct ifobject { char ifname[MAX_INTERFACE_NAME_CHARS]; char nsname[MAX_INTERFACES_NAMESPACE_CHARS]; + struct xskxceiver *bpf_obj; struct xsk_socket_info *xsk; struct xsk_socket_info *xsk_arr; struct xsk_umem_info *umem; @@ -141,7 +144,7 @@ struct ifobject { validation_func_t validation_func; struct pkt_stream *pkt_stream; int ns_fd; - int xsk_map_fd; + int ifindex; u32 dst_ip; u32 src_ip; u32 xdp_flags; -- 2.38.1.273.g43a17bfeac-goog