Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/xsk: Add support for zero copy testing

Introduce new mode to xdpxceiver responsible for testing AF_XDP zero
copy support of driver that serves underlying physical device. When
setting up test suite, determine whether driver has ZC support or not by
trying to bind XSK ZC socket to the interface. If it succeeded,
interpret it as ZC support being in place and do softirq and busy poll
tests for zero copy mode.

Note that Rx dropped tests are skipped since ZC path is not touching
rx_dropped stat at all.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Magnus Karlsson <magnus.karlsson@intel.com>
Link: https://lore.kernel.org/bpf/20220901114813.16275-7-maciej.fijalkowski@intel.com

authored by

Maciej Fijalkowski and committed by
Daniel Borkmann
fe2ad08e c29fe883

+74 -4
+72 -4
tools/testing/selftests/bpf/xskxceiver.c
··· 124 124 } 125 125 126 126 #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__) 127 - 128 - #define mode_string(test) (test)->ifobj_tx->xdp_flags & XDP_FLAGS_SKB_MODE ? "SKB" : "DRV" 129 127 #define busy_poll_string(test) (test)->ifobj_tx->busy_poll ? "BUSY-POLL " : "" 128 + static char *mode_string(struct test_spec *test) 129 + { 130 + switch (test->mode) { 131 + case TEST_MODE_SKB: 132 + return "SKB"; 133 + case TEST_MODE_DRV: 134 + return "DRV"; 135 + case TEST_MODE_ZC: 136 + return "ZC"; 137 + default: 138 + return "BOGUS"; 139 + } 140 + } 130 141 131 142 static void report_failure(struct test_spec *test) 132 143 { ··· 333 322 return xsk_socket__create(&xsk->xsk, ifobject->ifname, 0, umem->umem, rxr, txr, &cfg); 334 323 } 335 324 325 + static bool ifobj_zc_avail(struct ifobject *ifobject) 326 + { 327 + size_t umem_sz = DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE; 328 + int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; 329 + struct xsk_socket_info *xsk; 330 + struct xsk_umem_info *umem; 331 + bool zc_avail = false; 332 + void *bufs; 333 + int ret; 334 + 335 + bufs = mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); 336 + if (bufs == MAP_FAILED) 337 + exit_with_error(errno); 338 + 339 + umem = calloc(1, sizeof(struct xsk_umem_info)); 340 + if (!umem) { 341 + munmap(bufs, umem_sz); 342 + exit_with_error(-ENOMEM); 343 + } 344 + umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE; 345 + ret = xsk_configure_umem(umem, bufs, umem_sz); 346 + if (ret) 347 + exit_with_error(-ret); 348 + 349 + xsk = calloc(1, sizeof(struct xsk_socket_info)); 350 + if (!xsk) 351 + goto out; 352 + ifobject->xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; 353 + ifobject->xdp_flags |= XDP_FLAGS_DRV_MODE; 354 + ifobject->bind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY; 355 + ifobject->rx_on = true; 356 + xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS; 357 + ret = __xsk_configure_socket(xsk, umem, ifobject, false); 358 + if (!ret) 359 + zc_avail = true; 360 + 361 + xsk_socket__delete(xsk->xsk); 362 + free(xsk); 363 + out: 364 + munmap(umem->buffer, umem_sz); 365 + xsk_umem__delete(umem->umem); 366 + free(umem); 367 + return zc_avail; 368 + } 369 + 336 370 static struct option long_options[] = { 337 371 {"interface", required_argument, 0, 'i'}, 338 372 {"busy-poll", no_argument, 0, 'b'}, ··· 544 488 else 545 489 ifobj->xdp_flags |= XDP_FLAGS_DRV_MODE; 546 490 547 - ifobj->bind_flags = XDP_USE_NEED_WAKEUP | XDP_COPY; 491 + ifobj->bind_flags = XDP_USE_NEED_WAKEUP; 492 + if (mode == TEST_MODE_ZC) 493 + ifobj->bind_flags |= XDP_ZEROCOPY; 494 + else 495 + ifobj->bind_flags |= XDP_COPY; 548 496 } 549 497 498 + test->mode = mode; 550 499 __test_spec_init(test, ifobj_tx, ifobj_rx); 551 500 } 552 501 ··· 1725 1664 { 1726 1665 switch (type) { 1727 1666 case TEST_TYPE_STATS_RX_DROPPED: 1667 + if (mode == TEST_MODE_ZC) { 1668 + ksft_test_result_skip("Can not run RX_DROPPED test for ZC mode\n"); 1669 + return; 1670 + } 1728 1671 testapp_stats_rx_dropped(test); 1729 1672 break; 1730 1673 case TEST_TYPE_STATS_TX_INVALID_DESCS: ··· 1925 1860 init_iface(ifobj_rx, MAC2, MAC1, IP2, IP1, UDP_PORT2, UDP_PORT1, 1926 1861 worker_testapp_validate_rx); 1927 1862 1928 - if (is_xdp_supported(ifobj_tx)) 1863 + if (is_xdp_supported(ifobj_tx)) { 1929 1864 modes++; 1865 + if (ifobj_zc_avail(ifobj_tx)) 1866 + modes++; 1867 + } 1930 1868 1931 1869 test_spec_init(&test, ifobj_tx, ifobj_rx, 0); 1932 1870 tx_pkt_stream_default = pkt_stream_generate(ifobj_tx->umem, DEFAULT_PKT_CNT, PKT_SIZE);
+2
tools/testing/selftests/bpf/xskxceiver.h
··· 62 62 enum test_mode { 63 63 TEST_MODE_SKB, 64 64 TEST_MODE_DRV, 65 + TEST_MODE_ZC, 65 66 TEST_MODE_MAX 66 67 }; 67 68 ··· 168 167 u16 current_step; 169 168 u16 nb_sockets; 170 169 bool fail; 170 + enum test_mode mode; 171 171 char name[MAX_TEST_NAME_SIZE]; 172 172 }; 173 173