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 ---