xskxceiver.c (17f1034dd76d7465d4c0948c5280c6fc64ee0542) | xskxceiver.c (f540d44e05cf2f324697ba375235da2d7c92743c) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2020 Intel Corporation. */ 3 4/* 5 * Some functions in this program are taken from 6 * Linux kernel samples/bpf/xdpsock* and modified 7 * for use. 8 * --- 35 unchanged lines hidden (view full) --- 44 * f. bpf_link resource persistence 45 * Configure sockets at indexes 0 and 1, run a traffic on queue ids 0, 46 * then remove xsk sockets from queue 0 on both veth interfaces and 47 * finally run a traffic on queues ids 1 48 * g. unaligned mode 49 * h. tests for invalid and corner case Tx descriptors so that the correct ones 50 * are discarded and let through, respectively. 51 * i. 2K frame size tests | 1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2020 Intel Corporation. */ 3 4/* 5 * Some functions in this program are taken from 6 * Linux kernel samples/bpf/xdpsock* and modified 7 * for use. 8 * --- 35 unchanged lines hidden (view full) --- 44 * f. bpf_link resource persistence 45 * Configure sockets at indexes 0 and 1, run a traffic on queue ids 0, 46 * then remove xsk sockets from queue 0 on both veth interfaces and 47 * finally run a traffic on queues ids 1 48 * g. unaligned mode 49 * h. tests for invalid and corner case Tx descriptors so that the correct ones 50 * are discarded and let through, respectively. 51 * i. 2K frame size tests |
52 * j. If multi-buffer is supported, send 9k packets divided into 3 frames |
|
52 * 53 * Total tests: 12 54 * 55 * Flow: 56 * ----- 57 * - Single process spawns two threads: Tx and Rx 58 * - Each of these two threads attach to a veth interface 59 * - Each thread creates one AF_XDP socket connected to a unique umem for each --- 12 unchanged lines hidden (view full) --- 72#include <assert.h> 73#include <fcntl.h> 74#include <errno.h> 75#include <getopt.h> 76#include <asm/barrier.h> 77#include <linux/if_link.h> 78#include <linux/if_ether.h> 79#include <linux/mman.h> | 53 * 54 * Total tests: 12 55 * 56 * Flow: 57 * ----- 58 * - Single process spawns two threads: Tx and Rx 59 * - Each of these two threads attach to a veth interface 60 * - Each thread creates one AF_XDP socket connected to a unique umem for each --- 12 unchanged lines hidden (view full) --- 73#include <assert.h> 74#include <fcntl.h> 75#include <errno.h> 76#include <getopt.h> 77#include <asm/barrier.h> 78#include <linux/if_link.h> 79#include <linux/if_ether.h> 80#include <linux/mman.h> |
81#include <linux/netdev.h> |
|
80#include <arpa/inet.h> 81#include <net/if.h> 82#include <locale.h> 83#include <poll.h> 84#include <pthread.h> 85#include <signal.h> 86#include <stdio.h> 87#include <stdlib.h> --- 160 unchanged lines hidden (view full) --- 248 struct xsk_ring_prod *txr; 249 250 xsk->umem = umem; 251 cfg.rx_size = xsk->rxqsize; 252 cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 253 cfg.bind_flags = ifobject->bind_flags; 254 if (shared) 255 cfg.bind_flags |= XDP_SHARED_UMEM; | 82#include <arpa/inet.h> 83#include <net/if.h> 84#include <locale.h> 85#include <poll.h> 86#include <pthread.h> 87#include <signal.h> 88#include <stdio.h> 89#include <stdlib.h> --- 160 unchanged lines hidden (view full) --- 250 struct xsk_ring_prod *txr; 251 252 xsk->umem = umem; 253 cfg.rx_size = xsk->rxqsize; 254 cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 255 cfg.bind_flags = ifobject->bind_flags; 256 if (shared) 257 cfg.bind_flags |= XDP_SHARED_UMEM; |
258 if (ifobject->pkt_stream && ifobject->mtu > MAX_ETH_PKT_SIZE) 259 cfg.bind_flags |= XDP_USE_SG; |
|
256 257 txr = ifobject->tx_on ? &xsk->tx : NULL; 258 rxr = ifobject->rx_on ? &xsk->rx : NULL; 259 return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg); 260} 261 262static bool ifobj_zc_avail(struct ifobject *ifobject) 263{ --- 146 unchanged lines hidden (view full) --- 410 } 411 412 test->ifobj_tx = ifobj_tx; 413 test->ifobj_rx = ifobj_rx; 414 test->current_step = 0; 415 test->total_steps = 1; 416 test->nb_sockets = 1; 417 test->fail = false; | 260 261 txr = ifobject->tx_on ? &xsk->tx : NULL; 262 rxr = ifobject->rx_on ? &xsk->rx : NULL; 263 return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg); 264} 265 266static bool ifobj_zc_avail(struct ifobject *ifobject) 267{ --- 146 unchanged lines hidden (view full) --- 414 } 415 416 test->ifobj_tx = ifobj_tx; 417 test->ifobj_rx = ifobj_rx; 418 test->current_step = 0; 419 test->total_steps = 1; 420 test->nb_sockets = 1; 421 test->fail = false; |
422 test->mtu = MAX_ETH_PKT_SIZE; |
|
418 test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog; 419 test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk; 420 test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog; 421 test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk; 422} 423 424static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, 425 struct ifobject *ifobj_rx, enum test_mode mode) --- 37 unchanged lines hidden (view full) --- 463 struct bpf_map *xskmap_tx) 464{ 465 test->xdp_prog_rx = xdp_prog_rx; 466 test->xdp_prog_tx = xdp_prog_tx; 467 test->xskmap_rx = xskmap_rx; 468 test->xskmap_tx = xskmap_tx; 469} 470 | 423 test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog; 424 test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk; 425 test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog; 426 test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk; 427} 428 429static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, 430 struct ifobject *ifobj_rx, enum test_mode mode) --- 37 unchanged lines hidden (view full) --- 468 struct bpf_map *xskmap_tx) 469{ 470 test->xdp_prog_rx = xdp_prog_rx; 471 test->xdp_prog_tx = xdp_prog_tx; 472 test->xskmap_rx = xskmap_rx; 473 test->xskmap_tx = xskmap_tx; 474} 475 |
476static int test_spec_set_mtu(struct test_spec *test, int mtu) 477{ 478 int err; 479 480 if (test->ifobj_rx->mtu != mtu) { 481 err = xsk_set_mtu(test->ifobj_rx->ifindex, mtu); 482 if (err) 483 return err; 484 test->ifobj_rx->mtu = mtu; 485 } 486 if (test->ifobj_tx->mtu != mtu) { 487 err = xsk_set_mtu(test->ifobj_tx->ifindex, mtu); 488 if (err) 489 return err; 490 test->ifobj_tx->mtu = mtu; 491 } 492 493 return 0; 494} 495 |
|
471static void pkt_stream_reset(struct pkt_stream *pkt_stream) 472{ 473 if (pkt_stream) 474 pkt_stream->current_pkt_nb = 0; 475} 476 477static struct pkt *pkt_stream_get_next_tx_pkt(struct pkt_stream *pkt_stream) 478{ --- 1032 unchanged lines hidden (view full) --- 1511 if (xdp_prog_changed_tx(test)) 1512 xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode); 1513} 1514 1515static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1, 1516 struct ifobject *ifobj2) 1517{ 1518 pthread_t t0, t1; | 496static void pkt_stream_reset(struct pkt_stream *pkt_stream) 497{ 498 if (pkt_stream) 499 pkt_stream->current_pkt_nb = 0; 500} 501 502static struct pkt *pkt_stream_get_next_tx_pkt(struct pkt_stream *pkt_stream) 503{ --- 1032 unchanged lines hidden (view full) --- 1536 if (xdp_prog_changed_tx(test)) 1537 xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode); 1538} 1539 1540static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1, 1541 struct ifobject *ifobj2) 1542{ 1543 pthread_t t0, t1; |
1544 int err; |
|
1519 | 1545 |
1546 if (test->mtu > MAX_ETH_PKT_SIZE) { 1547 if (test->mode == TEST_MODE_ZC && (!ifobj1->multi_buff_zc_supp || 1548 (ifobj2 && !ifobj2->multi_buff_zc_supp))) { 1549 ksft_test_result_skip("Multi buffer for zero-copy not supported.\n"); 1550 return TEST_SKIP; 1551 } 1552 if (test->mode != TEST_MODE_ZC && (!ifobj1->multi_buff_supp || 1553 (ifobj2 && !ifobj2->multi_buff_supp))) { 1554 ksft_test_result_skip("Multi buffer not supported.\n"); 1555 return TEST_SKIP; 1556 } 1557 } 1558 err = test_spec_set_mtu(test, test->mtu); 1559 if (err) { 1560 ksft_print_msg("Error, could not set mtu.\n"); 1561 exit_with_error(err); 1562 } 1563 |
|
1520 if (ifobj2) { 1521 if (pthread_barrier_init(&barr, NULL, 2)) 1522 exit_with_error(errno); 1523 pkt_stream_reset(ifobj2->pkt_stream); 1524 } 1525 1526 test->current_step++; 1527 pkt_stream_reset(ifobj1->pkt_stream); --- 192 unchanged lines hidden (view full) --- 1720static int testapp_single_pkt(struct test_spec *test) 1721{ 1722 struct pkt pkts[] = {{0, MIN_PKT_SIZE, 0, true}}; 1723 1724 pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts)); 1725 return testapp_validate_traffic(test); 1726} 1727 | 1564 if (ifobj2) { 1565 if (pthread_barrier_init(&barr, NULL, 2)) 1566 exit_with_error(errno); 1567 pkt_stream_reset(ifobj2->pkt_stream); 1568 } 1569 1570 test->current_step++; 1571 pkt_stream_reset(ifobj1->pkt_stream); --- 192 unchanged lines hidden (view full) --- 1764static int testapp_single_pkt(struct test_spec *test) 1765{ 1766 struct pkt pkts[] = {{0, MIN_PKT_SIZE, 0, true}}; 1767 1768 pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts)); 1769 return testapp_validate_traffic(test); 1770} 1771 |
1772static int testapp_multi_buffer(struct test_spec *test) 1773{ 1774 test_spec_set_name(test, "RUN_TO_COMPLETION_9K_PACKETS"); 1775 test->mtu = MAX_ETH_JUMBO_SIZE; 1776 pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE); 1777 1778 return testapp_validate_traffic(test); 1779} 1780 |
|
1728static int testapp_invalid_desc(struct test_spec *test) 1729{ 1730 struct xsk_umem_info *umem = test->ifobj_tx->umem; 1731 u64 umem_size = umem->num_frames * umem->frame_size; 1732 struct pkt pkts[] = { 1733 /* Zero packet address allowed */ 1734 {0, MIN_PKT_SIZE, 0, true}, 1735 /* Allowed packet */ --- 117 unchanged lines hidden (view full) --- 1853 mmap_sz = ceil_u64(mmap_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE; 1854 munmap(bufs, mmap_sz); 1855 return true; 1856} 1857 1858static void init_iface(struct ifobject *ifobj, const char *dst_mac, const char *src_mac, 1859 thread_func_t func_ptr) 1860{ | 1781static int testapp_invalid_desc(struct test_spec *test) 1782{ 1783 struct xsk_umem_info *umem = test->ifobj_tx->umem; 1784 u64 umem_size = umem->num_frames * umem->frame_size; 1785 struct pkt pkts[] = { 1786 /* Zero packet address allowed */ 1787 {0, MIN_PKT_SIZE, 0, true}, 1788 /* Allowed packet */ --- 117 unchanged lines hidden (view full) --- 1906 mmap_sz = ceil_u64(mmap_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE; 1907 munmap(bufs, mmap_sz); 1908 return true; 1909} 1910 1911static void init_iface(struct ifobject *ifobj, const char *dst_mac, const char *src_mac, 1912 thread_func_t func_ptr) 1913{ |
1914 LIBBPF_OPTS(bpf_xdp_query_opts, query_opts); |
|
1861 int err; 1862 1863 memcpy(ifobj->dst_mac, dst_mac, ETH_ALEN); 1864 memcpy(ifobj->src_mac, src_mac, ETH_ALEN); 1865 1866 ifobj->func_ptr = func_ptr; 1867 1868 err = xsk_load_xdp_programs(ifobj); 1869 if (err) { 1870 printf("Error loading XDP program\n"); 1871 exit_with_error(err); 1872 } 1873 1874 if (hugepages_present()) 1875 ifobj->unaligned_supp = true; | 1915 int err; 1916 1917 memcpy(ifobj->dst_mac, dst_mac, ETH_ALEN); 1918 memcpy(ifobj->src_mac, src_mac, ETH_ALEN); 1919 1920 ifobj->func_ptr = func_ptr; 1921 1922 err = xsk_load_xdp_programs(ifobj); 1923 if (err) { 1924 printf("Error loading XDP program\n"); 1925 exit_with_error(err); 1926 } 1927 1928 if (hugepages_present()) 1929 ifobj->unaligned_supp = true; |
1930 1931 err = bpf_xdp_query(ifobj->ifindex, XDP_FLAGS_DRV_MODE, &query_opts); 1932 if (err) { 1933 ksft_print_msg("Error querrying XDP capabilities\n"); 1934 exit_with_error(-err); 1935 } 1936 if (query_opts.feature_flags & NETDEV_XDP_ACT_RX_SG) 1937 ifobj->multi_buff_supp = true; 1938 if (query_opts.feature_flags & NETDEV_XDP_ACT_XSK_ZEROCOPY) 1939 if (query_opts.xdp_zc_max_segs > 1) 1940 ifobj->multi_buff_zc_supp = true; |
|
1876} 1877 1878static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_type type) 1879{ 1880 int ret = TEST_SKIP; 1881 1882 switch (type) { 1883 case TEST_TYPE_STATS_RX_DROPPED: --- 16 unchanged lines hidden (view full) --- 1900 break; 1901 case TEST_TYPE_BPF_RES: 1902 ret = testapp_bpf_res(test); 1903 break; 1904 case TEST_TYPE_RUN_TO_COMPLETION: 1905 test_spec_set_name(test, "RUN_TO_COMPLETION"); 1906 ret = testapp_validate_traffic(test); 1907 break; | 1941} 1942 1943static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_type type) 1944{ 1945 int ret = TEST_SKIP; 1946 1947 switch (type) { 1948 case TEST_TYPE_STATS_RX_DROPPED: --- 16 unchanged lines hidden (view full) --- 1965 break; 1966 case TEST_TYPE_BPF_RES: 1967 ret = testapp_bpf_res(test); 1968 break; 1969 case TEST_TYPE_RUN_TO_COMPLETION: 1970 test_spec_set_name(test, "RUN_TO_COMPLETION"); 1971 ret = testapp_validate_traffic(test); 1972 break; |
1973 case TEST_TYPE_RUN_TO_COMPLETION_MB: 1974 ret = testapp_multi_buffer(test); 1975 break; |
|
1908 case TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT: 1909 test_spec_set_name(test, "RUN_TO_COMPLETION_SINGLE_PKT"); 1910 ret = testapp_single_pkt(test); 1911 break; 1912 case TEST_TYPE_RUN_TO_COMPLETION_2K_FRAME: 1913 test_spec_set_name(test, "RUN_TO_COMPLETION_2K_FRAME_SIZE"); 1914 test->ifobj_tx->umem->frame_size = 2048; 1915 test->ifobj_rx->umem->frame_size = 2048; --- 211 unchanged lines hidden --- | 1976 case TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT: 1977 test_spec_set_name(test, "RUN_TO_COMPLETION_SINGLE_PKT"); 1978 ret = testapp_single_pkt(test); 1979 break; 1980 case TEST_TYPE_RUN_TO_COMPLETION_2K_FRAME: 1981 test_spec_set_name(test, "RUN_TO_COMPLETION_2K_FRAME_SIZE"); 1982 test->ifobj_tx->umem->frame_size = 2048; 1983 test->ifobj_rx->umem->frame_size = 2048; --- 211 unchanged lines hidden --- |