Re: [PATCH bpf-next v2 15/15] selftests/xsk: automatically switch XDP programs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 10, 2023 at 12:57 PM Maciej Fijalkowski
<maciej.fijalkowski@xxxxxxxxx> wrote:
>
> On Wed, Jan 04, 2023 at 01:17:44PM +0100, Magnus Karlsson wrote:
> > From: Magnus Karlsson <magnus.karlsson@xxxxxxxxx>
> >
> > Implement automatic switching of XDP programs and execution modes if
> > needed by a test. This makes it much simpler to write a test as it
> > only has to say what XDP program it needs if it is not the default
> > one. This also makes it possible to remove the initial explicit
> > attachment of the XDP program as well as the explicit mode switch in
> > the code. These are now handled by the same code that just checks if a
> > switch is necessary, so no special cases are needed.
> >
> > The default XDP program for all tests is one that sends all packets to
> > the AF_XDP socket. If you need another one, please use the new
> > function test_spec_set_xdp_prog() to specify what XDP programs and
> > maps to use for this test.
> >
> > Signed-off-by: Magnus Karlsson <magnus.karlsson@xxxxxxxxx>
> > ---
> >  tools/testing/selftests/bpf/xsk.c        |  14 +++
> >  tools/testing/selftests/bpf/xsk.h        |   1 +
> >  tools/testing/selftests/bpf/xskxceiver.c | 137 ++++++++++++-----------
> >  tools/testing/selftests/bpf/xskxceiver.h |   7 +-
> >  4 files changed, 91 insertions(+), 68 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/xsk.c b/tools/testing/selftests/bpf/xsk.c
> > index dc6b47280ec4..d9d44a29c7cc 100644
> > --- a/tools/testing/selftests/bpf/xsk.c
> > +++ b/tools/testing/selftests/bpf/xsk.c
> > @@ -267,6 +267,20 @@ int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area,
> >       return err;
> >  }
> >
> > +bool xsk_is_in_drv_mode(u32 ifindex)
> > +{
> > +     LIBBPF_OPTS(bpf_xdp_query_opts, opts);
> > +     int ret;
> > +
> > +     ret = bpf_xdp_query(ifindex, XDP_FLAGS_DRV_MODE, &opts);
> > +     if (ret) {
> > +             printf("DRV mode query returned error %s\n", strerror(errno));
> > +             return false;
> > +     }
> > +
> > +     return opts.attach_mode == XDP_ATTACHED_DRV;
> > +}
>
> How about making this function more generic since you're adding this to a
> "lib" file? you could take on input the mode that you are expecting the
> prog being loaded on. Not sure if there will be any future use case for
> this, maybe if we would have a support for running a standalone test, not
> the whole test suite. I am sort of bothered that things are hard coded in
> a way that we expect DRV tests to follow the SKB ones.
>
> That's only a rant though :)

Sounds like a good idea. Will give it a shot.

> > +
> >  int xsk_attach_xdp_program(struct bpf_program *prog, int ifindex, u32 xdp_flags)
> >  {
> >       int prog_fd;
> > diff --git a/tools/testing/selftests/bpf/xsk.h b/tools/testing/selftests/bpf/xsk.h
> > index 5624d31b8db7..3cb9d69589b8 100644
> > --- a/tools/testing/selftests/bpf/xsk.h
> > +++ b/tools/testing/selftests/bpf/xsk.h
> > @@ -201,6 +201,7 @@ int xsk_attach_xdp_program(struct bpf_program *prog, int ifindex, u32 xdp_flags)
> >  void xsk_detach_xdp_program(int ifindex, u32 xdp_flags);
> >  int xsk_update_xskmap(struct bpf_map *map, struct xsk_socket *xsk);
> >  void xsk_clear_xskmap(struct bpf_map *map);
> > +bool xsk_is_in_drv_mode(u32 ifindex);
> >
> >  struct xsk_socket_config {
> >       __u32 rx_size;
> > diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c
> > index 66863504c76a..9af0f8240a59 100644
> > --- a/tools/testing/selftests/bpf/xskxceiver.c
> > +++ b/tools/testing/selftests/bpf/xskxceiver.c
> > @@ -96,6 +96,8 @@
> >  #include <time.h>
> >  #include <unistd.h>
> >  #include <stdatomic.h>
> > +
> > +#include "xsk_xdp_progs.skel.h"
> >  #include "xsk.h"
> >  #include "xskxceiver.h"
> >  #include <bpf/bpf.h>
> > @@ -356,7 +358,6 @@ static bool ifobj_zc_avail(struct ifobject *ifobject)
> >       xsk = calloc(1, sizeof(struct xsk_socket_info));
> >       if (!xsk)
> >               goto out;
> > -     ifobject->xdp_flags = XDP_FLAGS_DRV_MODE;
> >       ifobject->bind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;
> >       ifobject->rx_on = true;
> >       xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
> > @@ -493,6 +494,10 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
> >       test->total_steps = 1;
> >       test->nb_sockets = 1;
> >       test->fail = false;
> > +     test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog;
> > +     test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk;
> > +     test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog;
> > +     test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk;
>
> Is this needed for Tx side? I believe at this point shared_netdev is set,
> no? Or is this just a default state.

This is the default state. shared_netdev could be either false or true
here. Though shared_netdev is fixed for the execution of the test
suite, shared_umem might change in the future as we add tests for that
too.

> >  }
> >
> >  static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
> > @@ -532,6 +537,16 @@ static void test_spec_set_name(struct test_spec *test, const char *name)
> >       strncpy(test->name, name, MAX_TEST_NAME_SIZE);
> >  }
> >
> > +static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx,
> > +                                struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx,
> > +                                struct bpf_map *xskmap_tx)
>
>
> Nit:
>
> static void
> test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx,
>                       struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx,
>                       struct bpf_map *xskmap_tx)
>
> > +{
> > +     test->xdp_prog_rx = xdp_prog_rx;
> > +     test->xdp_prog_tx = xdp_prog_tx;
> > +     test->xskmap_rx = xskmap_rx;
> > +     test->xskmap_tx = xskmap_tx;
> > +}
> > +
> >  static void pkt_stream_reset(struct pkt_stream *pkt_stream)
> >  {
> >       if (pkt_stream)
> > @@ -1356,6 +1371,47 @@ static void handler(int signum)
> >       pthread_exit(NULL);
> >  }
> >
> > +static bool xdp_prog_changed(struct test_spec *test, struct ifobject *ifobj)
> > +{
> > +     return ifobj->xdp_prog != test->xdp_prog_rx || ifobj->mode != test->mode;
> > +}
> > +
> > +static void xsk_reattach_xdp(struct ifobject *ifobj, struct bpf_program *xdp_prog,
> > +                          struct bpf_map *xskmap, enum test_mode mode)
> > +{
> > +     int err;
> > +
> > +     xsk_detach_xdp_program(ifobj->ifindex, mode_to_xdp_flags(ifobj->mode));
> > +     err = xsk_attach_xdp_program(xdp_prog, ifobj->ifindex, mode_to_xdp_flags(mode));
> > +     if (err) {
> > +             printf("Error attaching XDP program\n");
> > +             exit_with_error(-err);
> > +     }
> > +
> > +     if (ifobj->mode != mode && (mode == TEST_MODE_DRV || mode == TEST_MODE_ZC))
> > +             if (!xsk_is_in_drv_mode(ifobj->ifindex)) {
> > +                     ksft_print_msg("ERROR: XDP prog not in DRV mode\n");
> > +                     exit_with_error(EINVAL);
> > +             }
> > +
> > +     ifobj->xdp_prog = xdp_prog;
> > +     ifobj->xskmap = xskmap;
> > +     ifobj->mode = mode;
> > +}
> > +
> > +static void xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_rx,
> > +                              struct ifobject *ifobj_tx)
> > +{
> > +     if (xdp_prog_changed(test, ifobj_rx))
> > +             xsk_reattach_xdp(ifobj_rx, test->xdp_prog_rx, test->xskmap_rx, test->mode);
> > +
> > +     if (!ifobj_tx || ifobj_tx->shared_umem)
> > +             return;
> > +
> > +     if (xdp_prog_changed(test, ifobj_tx))
> > +             xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode);
> > +}
> > +
> >  static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1,
> >                                     struct ifobject *ifobj2)
> >  {
> > @@ -1403,7 +1459,11 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i
> >
> >  static int testapp_validate_traffic(struct test_spec *test)
> >  {
> > -     return __testapp_validate_traffic(test, test->ifobj_rx, test->ifobj_tx);
> > +     struct ifobject *ifobj_rx = test->ifobj_rx;
> > +     struct ifobject *ifobj_tx = test->ifobj_tx;
> > +
> > +     xsk_attach_xdp_progs(test, ifobj_rx, ifobj_tx);
> > +     return __testapp_validate_traffic(test, ifobj_rx, ifobj_tx);
> >  }
> >
> >  static int testapp_validate_traffic_single_thread(struct test_spec *test, struct ifobject *ifobj)
> > @@ -1446,7 +1506,7 @@ static void testapp_bidi(struct test_spec *test)
> >
> >       print_verbose("Switching Tx/Rx vectors\n");
> >       swap_directions(&test->ifobj_rx, &test->ifobj_tx);
> > -     testapp_validate_traffic(test);
> > +     __testapp_validate_traffic(test, test->ifobj_rx, test->ifobj_tx);
> >
> >       swap_directions(&test->ifobj_rx, &test->ifobj_tx);
> >  }
> > @@ -1615,29 +1675,15 @@ static void testapp_invalid_desc(struct test_spec *test)
> >
> >  static void testapp_xdp_drop(struct test_spec *test)
> >  {
> > -     struct ifobject *ifobj = test->ifobj_rx;
> > -     int err;
> > +     struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
> > +     struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
> >
> >       test_spec_set_name(test, "XDP_DROP_HALF");
> > -     xsk_detach_xdp_program(ifobj->ifindex, ifobj->xdp_flags);
> > -     err = xsk_attach_xdp_program(ifobj->xdp_progs->progs.xsk_xdp_drop, ifobj->ifindex,
> > -                                  ifobj->xdp_flags);
> > -     if (err) {
> > -             printf("Error attaching XDP_DROP program\n");
> > -             test->fail = true;
> > -             return;
> > -     }
> > +     test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_drop, skel_tx->progs.xsk_xdp_drop,
> > +                            skel_rx->maps.xsk, skel_tx->maps.xsk);
> >
> >       pkt_stream_receive_half(test);
> >       testapp_validate_traffic(test);
> > -
> > -     xsk_detach_xdp_program(ifobj->ifindex, ifobj->xdp_flags);
> > -     err = xsk_attach_xdp_program(ifobj->xdp_progs->progs.xsk_def_prog, ifobj->ifindex,
> > -                                  ifobj->xdp_flags);
> > -     if (err) {
> > -             printf("Error restoring default XDP program\n");
> > -             exit_with_error(-err);
> > -     }
> >  }
> >
> >  static void testapp_poll_txq_tmout(struct test_spec *test)
> > @@ -1674,7 +1720,7 @@ static void xsk_unload_xdp_programs(struct ifobject *ifobj)
> >
> >  static void init_iface(struct ifobject *ifobj, const char *dst_mac, const char *src_mac,
> >                      const char *dst_ip, const char *src_ip, const u16 dst_port,
> > -                    const u16 src_port, thread_func_t func_ptr, bool load_xdp)
> > +                    const u16 src_port, thread_func_t func_ptr)
> >  {
> >       struct in_addr ip;
> >       int err;
> > @@ -1693,23 +1739,11 @@ static void init_iface(struct ifobject *ifobj, const char *dst_mac, const char *
> >
> >       ifobj->func_ptr = func_ptr;
> >
> > -     if (!load_xdp)
> > -             return;
> > -
> >       err = xsk_load_xdp_programs(ifobj);
> >       if (err) {
> >               printf("Error loading XDP program\n");
> >               exit_with_error(err);
> >       }
> > -
> > -     ifobj->xdp_flags = mode_to_xdp_flags(TEST_MODE_SKB);
> > -     err = xsk_attach_xdp_program(ifobj->xdp_progs->progs.xsk_def_prog, ifobj->ifindex,
> > -                                  ifobj->xdp_flags);
> > -     if (err) {
> > -             printf("Error attaching XDP program\n");
> > -             exit_with_error(-err);
> > -     }
> > -     ifobj->xskmap = ifobj->xdp_progs->maps.xsk;
> >  }
> >
> >  static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_type type)
> > @@ -1871,31 +1905,6 @@ static bool is_xdp_supported(int ifindex)
> >       return true;
> >  }
> >
> > -static void change_to_drv_mode(struct ifobject *ifobj)
> > -{
> > -     LIBBPF_OPTS(bpf_xdp_query_opts, opts);
> > -     int ret;
> > -
> > -     xsk_detach_xdp_program(ifobj->ifindex, ifobj->xdp_flags);
> > -     ifobj->xdp_flags = XDP_FLAGS_DRV_MODE;
> > -     ret = xsk_attach_xdp_program(ifobj->xdp_progs->progs.xsk_def_prog, ifobj->ifindex,
> > -                                  ifobj->xdp_flags);
> > -     if (ret) {
> > -             ksft_print_msg("Error attaching XDP program\n");
> > -             exit_with_error(-ret);
> > -     }
> > -     ifobj->xskmap = ifobj->xdp_progs->maps.xsk;
> > -
> > -     ret = bpf_xdp_query(ifobj->ifindex, XDP_FLAGS_DRV_MODE, &opts);
> > -     if (ret)
> > -             exit_with_error(errno);
> > -
> > -     if (opts.attach_mode != XDP_ATTACHED_DRV) {
> > -             ksft_print_msg("ERROR: XDP prog not in DRV mode\n");
> > -             exit_with_error(EINVAL);
> > -     }
> > -}
> > -
> >  int main(int argc, char **argv)
> >  {
> >       struct pkt_stream *rx_pkt_stream_default;
> > @@ -1936,9 +1945,9 @@ int main(int argc, char **argv)
> >       }
> >
> >       init_iface(ifobj_rx, MAC1, MAC2, IP1, IP2, UDP_PORT1, UDP_PORT2,
> > -                worker_testapp_validate_rx, true);
> > +                worker_testapp_validate_rx);
> >       init_iface(ifobj_tx, MAC2, MAC1, IP2, IP1, UDP_PORT2, UDP_PORT1,
> > -                worker_testapp_validate_tx, !shared_netdev);
> > +                worker_testapp_validate_tx);
> >
> >       test_spec_init(&test, ifobj_tx, ifobj_rx, 0);
> >       tx_pkt_stream_default = pkt_stream_generate(ifobj_tx->umem, DEFAULT_PKT_CNT, PKT_SIZE);
> > @@ -1951,12 +1960,6 @@ int main(int argc, char **argv)
> >       ksft_set_plan(modes * TEST_TYPE_MAX);
> >
> >       for (i = 0; i < modes; i++) {
> > -             if (i == TEST_MODE_DRV) {
> > -                     change_to_drv_mode(ifobj_rx);
> > -                     if (!shared_netdev)
> > -                             change_to_drv_mode(ifobj_tx);
> > -             }
> > -
> >               for (j = 0; j < TEST_TYPE_MAX; j++) {
> >                       test_spec_init(&test, ifobj_tx, ifobj_rx, i);
> >                       run_pkt_test(&test, i, j);
> > diff --git a/tools/testing/selftests/bpf/xskxceiver.h b/tools/testing/selftests/bpf/xskxceiver.h
> > index a4daa5134fc0..3e8ec7d8ec32 100644
> > --- a/tools/testing/selftests/bpf/xskxceiver.h
> > +++ b/tools/testing/selftests/bpf/xskxceiver.h
> > @@ -143,10 +143,11 @@ struct ifobject {
> >       struct pkt_stream *pkt_stream;
> >       struct xsk_xdp_progs *xdp_progs;
> >       struct bpf_map *xskmap;
> > +     struct bpf_program *xdp_prog;
> > +     enum test_mode mode;
> >       int ifindex;
> >       u32 dst_ip;
> >       u32 src_ip;
> > -     u32 xdp_flags;
> >       u32 bind_flags;
> >       u16 src_port;
> >       u16 dst_port;
> > @@ -166,6 +167,10 @@ struct test_spec {
> >       struct ifobject *ifobj_rx;
> >       struct pkt_stream *tx_pkt_stream_default;
> >       struct pkt_stream *rx_pkt_stream_default;
> > +     struct bpf_program *xdp_prog_rx;
> > +     struct bpf_program *xdp_prog_tx;
> > +     struct bpf_map *xskmap_rx;
> > +     struct bpf_map *xskmap_tx;
> >       u16 total_steps;
> >       u16 current_step;
> >       u16 nb_sockets;
> > --
> > 2.34.1
> >



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux