1*d1aec26fSBastien Curutchet (eBPF Foundation) // SPDX-License-Identifier: GPL-2.0 2*d1aec26fSBastien Curutchet (eBPF Foundation) #include <bpf/bpf.h> 3*d1aec26fSBastien Curutchet (eBPF Foundation) #include <errno.h> 4*d1aec26fSBastien Curutchet (eBPF Foundation) #include <linux/bitmap.h> 5*d1aec26fSBastien Curutchet (eBPF Foundation) #include <linux/if_link.h> 6*d1aec26fSBastien Curutchet (eBPF Foundation) #include <linux/mman.h> 7*d1aec26fSBastien Curutchet (eBPF Foundation) #include <linux/netdev.h> 8*d1aec26fSBastien Curutchet (eBPF Foundation) #include <poll.h> 9*d1aec26fSBastien Curutchet (eBPF Foundation) #include <pthread.h> 10*d1aec26fSBastien Curutchet (eBPF Foundation) #include <signal.h> 11*d1aec26fSBastien Curutchet (eBPF Foundation) #include <string.h> 12*d1aec26fSBastien Curutchet (eBPF Foundation) #include <sys/mman.h> 13*d1aec26fSBastien Curutchet (eBPF Foundation) #include <sys/socket.h> 14*d1aec26fSBastien Curutchet (eBPF Foundation) #include <sys/time.h> 15*d1aec26fSBastien Curutchet (eBPF Foundation) #include <unistd.h> 16*d1aec26fSBastien Curutchet (eBPF Foundation) 17*d1aec26fSBastien Curutchet (eBPF Foundation) #include "network_helpers.h" 18*d1aec26fSBastien Curutchet (eBPF Foundation) #include "test_xsk.h" 19*d1aec26fSBastien Curutchet (eBPF Foundation) #include "xsk_xdp_common.h" 20*d1aec26fSBastien Curutchet (eBPF Foundation) #include "xsk_xdp_progs.skel.h" 21*d1aec26fSBastien Curutchet (eBPF Foundation) 22*d1aec26fSBastien Curutchet (eBPF Foundation) #define DEFAULT_BATCH_SIZE 64 23*d1aec26fSBastien Curutchet (eBPF Foundation) #define MIN_PKT_SIZE 64 24*d1aec26fSBastien Curutchet (eBPF Foundation) #define MAX_ETH_JUMBO_SIZE 9000 25*d1aec26fSBastien Curutchet (eBPF Foundation) #define MAX_INTERFACES 2 26*d1aec26fSBastien Curutchet (eBPF Foundation) #define MAX_TEARDOWN_ITER 10 27*d1aec26fSBastien Curutchet (eBPF Foundation) #define MAX_TX_BUDGET_DEFAULT 32 28*d1aec26fSBastien Curutchet (eBPF Foundation) #define PKT_DUMP_NB_TO_PRINT 16 29*d1aec26fSBastien Curutchet (eBPF Foundation) /* Just to align the data in the packet */ 30*d1aec26fSBastien Curutchet (eBPF Foundation) #define PKT_HDR_SIZE (sizeof(struct ethhdr) + 2) 31*d1aec26fSBastien Curutchet (eBPF Foundation) #define POLL_TMOUT 1000 32*d1aec26fSBastien Curutchet (eBPF Foundation) #define THREAD_TMOUT 3 33*d1aec26fSBastien Curutchet (eBPF Foundation) #define UMEM_HEADROOM_TEST_SIZE 128 34*d1aec26fSBastien Curutchet (eBPF Foundation) #define XSK_DESC__INVALID_OPTION (0xffff) 35*d1aec26fSBastien Curutchet (eBPF Foundation) #define XSK_UMEM__INVALID_FRAME_SIZE (MAX_ETH_JUMBO_SIZE + 1) 36*d1aec26fSBastien Curutchet (eBPF Foundation) #define XSK_UMEM__LARGE_FRAME_SIZE (3 * 1024) 37*d1aec26fSBastien Curutchet (eBPF Foundation) #define XSK_UMEM__MAX_FRAME_SIZE (4 * 1024) 38*d1aec26fSBastien Curutchet (eBPF Foundation) 39*d1aec26fSBastien Curutchet (eBPF Foundation) static const u8 g_mac[ETH_ALEN] = {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; 40*d1aec26fSBastien Curutchet (eBPF Foundation) 41*d1aec26fSBastien Curutchet (eBPF Foundation) bool opt_verbose; 42*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_barrier_t barr; 43*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER; 44*d1aec26fSBastien Curutchet (eBPF Foundation) 45*d1aec26fSBastien Curutchet (eBPF Foundation) int pkts_in_flight; 46*d1aec26fSBastien Curutchet (eBPF Foundation) 47*d1aec26fSBastien Curutchet (eBPF Foundation) /* The payload is a word consisting of a packet sequence number in the upper 48*d1aec26fSBastien Curutchet (eBPF Foundation) * 16-bits and a intra packet data sequence number in the lower 16 bits. So the 3rd packet's 49*d1aec26fSBastien Curutchet (eBPF Foundation) * 5th word of data will contain the number (2<<16) | 4 as they are numbered from 0. 50*d1aec26fSBastien Curutchet (eBPF Foundation) */ 51*d1aec26fSBastien Curutchet (eBPF Foundation) static void write_payload(void *dest, u32 pkt_nb, u32 start, u32 size) 52*d1aec26fSBastien Curutchet (eBPF Foundation) { 53*d1aec26fSBastien Curutchet (eBPF Foundation) u32 *ptr = (u32 *)dest, i; 54*d1aec26fSBastien Curutchet (eBPF Foundation) 55*d1aec26fSBastien Curutchet (eBPF Foundation) start /= sizeof(*ptr); 56*d1aec26fSBastien Curutchet (eBPF Foundation) size /= sizeof(*ptr); 57*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < size; i++) 58*d1aec26fSBastien Curutchet (eBPF Foundation) ptr[i] = htonl(pkt_nb << 16 | (i + start)); 59*d1aec26fSBastien Curutchet (eBPF Foundation) } 60*d1aec26fSBastien Curutchet (eBPF Foundation) 61*d1aec26fSBastien Curutchet (eBPF Foundation) static void gen_eth_hdr(struct xsk_socket_info *xsk, struct ethhdr *eth_hdr) 62*d1aec26fSBastien Curutchet (eBPF Foundation) { 63*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(eth_hdr->h_dest, xsk->dst_mac, ETH_ALEN); 64*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(eth_hdr->h_source, xsk->src_mac, ETH_ALEN); 65*d1aec26fSBastien Curutchet (eBPF Foundation) eth_hdr->h_proto = htons(ETH_P_LOOPBACK); 66*d1aec26fSBastien Curutchet (eBPF Foundation) } 67*d1aec26fSBastien Curutchet (eBPF Foundation) 68*d1aec26fSBastien Curutchet (eBPF Foundation) static bool is_umem_valid(struct ifobject *ifobj) 69*d1aec26fSBastien Curutchet (eBPF Foundation) { 70*d1aec26fSBastien Curutchet (eBPF Foundation) return !!ifobj->umem->umem; 71*d1aec26fSBastien Curutchet (eBPF Foundation) } 72*d1aec26fSBastien Curutchet (eBPF Foundation) 73*d1aec26fSBastien Curutchet (eBPF Foundation) static u32 mode_to_xdp_flags(enum test_mode mode) 74*d1aec26fSBastien Curutchet (eBPF Foundation) { 75*d1aec26fSBastien Curutchet (eBPF Foundation) return (mode == TEST_MODE_SKB) ? XDP_FLAGS_SKB_MODE : XDP_FLAGS_DRV_MODE; 76*d1aec26fSBastien Curutchet (eBPF Foundation) } 77*d1aec26fSBastien Curutchet (eBPF Foundation) 78*d1aec26fSBastien Curutchet (eBPF Foundation) static u64 umem_size(struct xsk_umem_info *umem) 79*d1aec26fSBastien Curutchet (eBPF Foundation) { 80*d1aec26fSBastien Curutchet (eBPF Foundation) return umem->num_frames * umem->frame_size; 81*d1aec26fSBastien Curutchet (eBPF Foundation) } 82*d1aec26fSBastien Curutchet (eBPF Foundation) 83*d1aec26fSBastien Curutchet (eBPF Foundation) int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void *buffer, 84*d1aec26fSBastien Curutchet (eBPF Foundation) u64 size) 85*d1aec26fSBastien Curutchet (eBPF Foundation) { 86*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_config cfg = { 87*d1aec26fSBastien Curutchet (eBPF Foundation) .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS, 88*d1aec26fSBastien Curutchet (eBPF Foundation) .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS, 89*d1aec26fSBastien Curutchet (eBPF Foundation) .frame_size = umem->frame_size, 90*d1aec26fSBastien Curutchet (eBPF Foundation) .frame_headroom = umem->frame_headroom, 91*d1aec26fSBastien Curutchet (eBPF Foundation) .flags = XSK_UMEM__DEFAULT_FLAGS 92*d1aec26fSBastien Curutchet (eBPF Foundation) }; 93*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 94*d1aec26fSBastien Curutchet (eBPF Foundation) 95*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->fill_size) 96*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.fill_size = umem->fill_size; 97*d1aec26fSBastien Curutchet (eBPF Foundation) 98*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->comp_size) 99*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.comp_size = umem->comp_size; 100*d1aec26fSBastien Curutchet (eBPF Foundation) 101*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->unaligned_mode) 102*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG; 103*d1aec26fSBastien Curutchet (eBPF Foundation) 104*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_umem__create(&umem->umem, buffer, size, 105*d1aec26fSBastien Curutchet (eBPF Foundation) &umem->fq, &umem->cq, &cfg); 106*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 107*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 108*d1aec26fSBastien Curutchet (eBPF Foundation) 109*d1aec26fSBastien Curutchet (eBPF Foundation) umem->buffer = buffer; 110*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->shared_umem && ifobj->rx_on) { 111*d1aec26fSBastien Curutchet (eBPF Foundation) umem->base_addr = umem_size(umem); 112*d1aec26fSBastien Curutchet (eBPF Foundation) umem->next_buffer = umem_size(umem); 113*d1aec26fSBastien Curutchet (eBPF Foundation) } 114*d1aec26fSBastien Curutchet (eBPF Foundation) 115*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 116*d1aec26fSBastien Curutchet (eBPF Foundation) } 117*d1aec26fSBastien Curutchet (eBPF Foundation) 118*d1aec26fSBastien Curutchet (eBPF Foundation) static u64 umem_alloc_buffer(struct xsk_umem_info *umem) 119*d1aec26fSBastien Curutchet (eBPF Foundation) { 120*d1aec26fSBastien Curutchet (eBPF Foundation) u64 addr; 121*d1aec26fSBastien Curutchet (eBPF Foundation) 122*d1aec26fSBastien Curutchet (eBPF Foundation) addr = umem->next_buffer; 123*d1aec26fSBastien Curutchet (eBPF Foundation) umem->next_buffer += umem->frame_size; 124*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->next_buffer >= umem->base_addr + umem_size(umem)) 125*d1aec26fSBastien Curutchet (eBPF Foundation) umem->next_buffer = umem->base_addr; 126*d1aec26fSBastien Curutchet (eBPF Foundation) 127*d1aec26fSBastien Curutchet (eBPF Foundation) return addr; 128*d1aec26fSBastien Curutchet (eBPF Foundation) } 129*d1aec26fSBastien Curutchet (eBPF Foundation) 130*d1aec26fSBastien Curutchet (eBPF Foundation) static void umem_reset_alloc(struct xsk_umem_info *umem) 131*d1aec26fSBastien Curutchet (eBPF Foundation) { 132*d1aec26fSBastien Curutchet (eBPF Foundation) umem->next_buffer = 0; 133*d1aec26fSBastien Curutchet (eBPF Foundation) } 134*d1aec26fSBastien Curutchet (eBPF Foundation) 135*d1aec26fSBastien Curutchet (eBPF Foundation) static int enable_busy_poll(struct xsk_socket_info *xsk) 136*d1aec26fSBastien Curutchet (eBPF Foundation) { 137*d1aec26fSBastien Curutchet (eBPF Foundation) int sock_opt; 138*d1aec26fSBastien Curutchet (eBPF Foundation) 139*d1aec26fSBastien Curutchet (eBPF Foundation) sock_opt = 1; 140*d1aec26fSBastien Curutchet (eBPF Foundation) if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_PREFER_BUSY_POLL, 141*d1aec26fSBastien Curutchet (eBPF Foundation) (void *)&sock_opt, sizeof(sock_opt)) < 0) 142*d1aec26fSBastien Curutchet (eBPF Foundation) return -errno; 143*d1aec26fSBastien Curutchet (eBPF Foundation) 144*d1aec26fSBastien Curutchet (eBPF Foundation) sock_opt = 20; 145*d1aec26fSBastien Curutchet (eBPF Foundation) if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL, 146*d1aec26fSBastien Curutchet (eBPF Foundation) (void *)&sock_opt, sizeof(sock_opt)) < 0) 147*d1aec26fSBastien Curutchet (eBPF Foundation) return -errno; 148*d1aec26fSBastien Curutchet (eBPF Foundation) 149*d1aec26fSBastien Curutchet (eBPF Foundation) sock_opt = xsk->batch_size; 150*d1aec26fSBastien Curutchet (eBPF Foundation) if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL_BUDGET, 151*d1aec26fSBastien Curutchet (eBPF Foundation) (void *)&sock_opt, sizeof(sock_opt)) < 0) 152*d1aec26fSBastien Curutchet (eBPF Foundation) return -errno; 153*d1aec26fSBastien Curutchet (eBPF Foundation) 154*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 155*d1aec26fSBastien Curutchet (eBPF Foundation) } 156*d1aec26fSBastien Curutchet (eBPF Foundation) 157*d1aec26fSBastien Curutchet (eBPF Foundation) int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, 158*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobject, bool shared) 159*d1aec26fSBastien Curutchet (eBPF Foundation) { 160*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket_config cfg = {}; 161*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_ring_cons *rxr; 162*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_ring_prod *txr; 163*d1aec26fSBastien Curutchet (eBPF Foundation) 164*d1aec26fSBastien Curutchet (eBPF Foundation) xsk->umem = umem; 165*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.rx_size = xsk->rxqsize; 166*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 167*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.bind_flags = ifobject->bind_flags; 168*d1aec26fSBastien Curutchet (eBPF Foundation) if (shared) 169*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.bind_flags |= XDP_SHARED_UMEM; 170*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobject->mtu > MAX_ETH_PKT_SIZE) 171*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.bind_flags |= XDP_USE_SG; 172*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->comp_size) 173*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.tx_size = umem->comp_size; 174*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->fill_size) 175*d1aec26fSBastien Curutchet (eBPF Foundation) cfg.rx_size = umem->fill_size; 176*d1aec26fSBastien Curutchet (eBPF Foundation) 177*d1aec26fSBastien Curutchet (eBPF Foundation) txr = ifobject->tx_on ? &xsk->tx : NULL; 178*d1aec26fSBastien Curutchet (eBPF Foundation) rxr = ifobject->rx_on ? &xsk->rx : NULL; 179*d1aec26fSBastien Curutchet (eBPF Foundation) return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg); 180*d1aec26fSBastien Curutchet (eBPF Foundation) } 181*d1aec26fSBastien Curutchet (eBPF Foundation) 182*d1aec26fSBastien Curutchet (eBPF Foundation) #define MAX_SKB_FRAGS_PATH "/proc/sys/net/core/max_skb_frags" 183*d1aec26fSBastien Curutchet (eBPF Foundation) static unsigned int get_max_skb_frags(void) 184*d1aec26fSBastien Curutchet (eBPF Foundation) { 185*d1aec26fSBastien Curutchet (eBPF Foundation) unsigned int max_skb_frags = 0; 186*d1aec26fSBastien Curutchet (eBPF Foundation) FILE *file; 187*d1aec26fSBastien Curutchet (eBPF Foundation) 188*d1aec26fSBastien Curutchet (eBPF Foundation) file = fopen(MAX_SKB_FRAGS_PATH, "r"); 189*d1aec26fSBastien Curutchet (eBPF Foundation) if (!file) { 190*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error opening %s\n", MAX_SKB_FRAGS_PATH); 191*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 192*d1aec26fSBastien Curutchet (eBPF Foundation) } 193*d1aec26fSBastien Curutchet (eBPF Foundation) 194*d1aec26fSBastien Curutchet (eBPF Foundation) if (fscanf(file, "%u", &max_skb_frags) != 1) 195*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error reading %s\n", MAX_SKB_FRAGS_PATH); 196*d1aec26fSBastien Curutchet (eBPF Foundation) 197*d1aec26fSBastien Curutchet (eBPF Foundation) fclose(file); 198*d1aec26fSBastien Curutchet (eBPF Foundation) return max_skb_frags; 199*d1aec26fSBastien Curutchet (eBPF Foundation) } 200*d1aec26fSBastien Curutchet (eBPF Foundation) 201*d1aec26fSBastien Curutchet (eBPF Foundation) static int set_ring_size(struct ifobject *ifobj) 202*d1aec26fSBastien Curutchet (eBPF Foundation) { 203*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 204*d1aec26fSBastien Curutchet (eBPF Foundation) u32 ctr = 0; 205*d1aec26fSBastien Curutchet (eBPF Foundation) 206*d1aec26fSBastien Curutchet (eBPF Foundation) while (ctr++ < SOCK_RECONF_CTR) { 207*d1aec26fSBastien Curutchet (eBPF Foundation) ret = set_hw_ring_size(ifobj->ifname, &ifobj->ring); 208*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ret) 209*d1aec26fSBastien Curutchet (eBPF Foundation) break; 210*d1aec26fSBastien Curutchet (eBPF Foundation) 211*d1aec26fSBastien Curutchet (eBPF Foundation) /* Retry if it fails */ 212*d1aec26fSBastien Curutchet (eBPF Foundation) if (ctr >= SOCK_RECONF_CTR || errno != EBUSY) 213*d1aec26fSBastien Curutchet (eBPF Foundation) return -errno; 214*d1aec26fSBastien Curutchet (eBPF Foundation) 215*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(USLEEP_MAX); 216*d1aec26fSBastien Curutchet (eBPF Foundation) } 217*d1aec26fSBastien Curutchet (eBPF Foundation) 218*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 219*d1aec26fSBastien Curutchet (eBPF Foundation) } 220*d1aec26fSBastien Curutchet (eBPF Foundation) 221*d1aec26fSBastien Curutchet (eBPF Foundation) int hw_ring_size_reset(struct ifobject *ifobj) 222*d1aec26fSBastien Curutchet (eBPF Foundation) { 223*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->ring.tx_pending = ifobj->set_ring.default_tx; 224*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->ring.rx_pending = ifobj->set_ring.default_rx; 225*d1aec26fSBastien Curutchet (eBPF Foundation) return set_ring_size(ifobj); 226*d1aec26fSBastien Curutchet (eBPF Foundation) } 227*d1aec26fSBastien Curutchet (eBPF Foundation) 228*d1aec26fSBastien Curutchet (eBPF Foundation) static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, 229*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj_rx) 230*d1aec26fSBastien Curutchet (eBPF Foundation) { 231*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i, j; 232*d1aec26fSBastien Curutchet (eBPF Foundation) 233*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < MAX_INTERFACES; i++) { 234*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx; 235*d1aec26fSBastien Curutchet (eBPF Foundation) 236*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk = &ifobj->xsk_arr[0]; 237*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->use_poll = false; 238*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->use_fill_ring = true; 239*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->release_rx = true; 240*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->validation_func = NULL; 241*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->use_metadata = false; 242*d1aec26fSBastien Curutchet (eBPF Foundation) 243*d1aec26fSBastien Curutchet (eBPF Foundation) if (i == 0) { 244*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->rx_on = false; 245*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->tx_on = true; 246*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 247*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->rx_on = true; 248*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->tx_on = false; 249*d1aec26fSBastien Curutchet (eBPF Foundation) } 250*d1aec26fSBastien Curutchet (eBPF Foundation) 251*d1aec26fSBastien Curutchet (eBPF Foundation) memset(ifobj->umem, 0, sizeof(*ifobj->umem)); 252*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->umem->num_frames = DEFAULT_UMEM_BUFFERS; 253*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE; 254*d1aec26fSBastien Curutchet (eBPF Foundation) 255*d1aec26fSBastien Curutchet (eBPF Foundation) for (j = 0; j < MAX_SOCKETS; j++) { 256*d1aec26fSBastien Curutchet (eBPF Foundation) memset(&ifobj->xsk_arr[j], 0, sizeof(ifobj->xsk_arr[j])); 257*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS; 258*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].batch_size = DEFAULT_BATCH_SIZE; 259*d1aec26fSBastien Curutchet (eBPF Foundation) if (i == 0) 260*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].pkt_stream = test->tx_pkt_stream_default; 261*d1aec26fSBastien Curutchet (eBPF Foundation) else 262*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].pkt_stream = test->rx_pkt_stream_default; 263*d1aec26fSBastien Curutchet (eBPF Foundation) 264*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(ifobj->xsk_arr[j].src_mac, g_mac, ETH_ALEN); 265*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(ifobj->xsk_arr[j].dst_mac, g_mac, ETH_ALEN); 266*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].src_mac[5] += ((j * 2) + 0); 267*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr[j].dst_mac[5] += ((j * 2) + 1); 268*d1aec26fSBastien Curutchet (eBPF Foundation) } 269*d1aec26fSBastien Curutchet (eBPF Foundation) } 270*d1aec26fSBastien Curutchet (eBPF Foundation) 271*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj_tx->hw_ring_size_supp) 272*d1aec26fSBastien Curutchet (eBPF Foundation) hw_ring_size_reset(ifobj_tx); 273*d1aec26fSBastien Curutchet (eBPF Foundation) 274*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx = ifobj_tx; 275*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx = ifobj_rx; 276*d1aec26fSBastien Curutchet (eBPF Foundation) test->current_step = 0; 277*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 1; 278*d1aec26fSBastien Curutchet (eBPF Foundation) test->nb_sockets = 1; 279*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = false; 280*d1aec26fSBastien Curutchet (eBPF Foundation) test->set_ring = false; 281*d1aec26fSBastien Curutchet (eBPF Foundation) test->adjust_tail = false; 282*d1aec26fSBastien Curutchet (eBPF Foundation) test->adjust_tail_support = false; 283*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_PKT_SIZE; 284*d1aec26fSBastien Curutchet (eBPF Foundation) test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog; 285*d1aec26fSBastien Curutchet (eBPF Foundation) test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk; 286*d1aec26fSBastien Curutchet (eBPF Foundation) test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog; 287*d1aec26fSBastien Curutchet (eBPF Foundation) test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk; 288*d1aec26fSBastien Curutchet (eBPF Foundation) } 289*d1aec26fSBastien Curutchet (eBPF Foundation) 290*d1aec26fSBastien Curutchet (eBPF Foundation) void test_init(struct test_spec *test, struct ifobject *ifobj_tx, 291*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj_rx, enum test_mode mode, 292*d1aec26fSBastien Curutchet (eBPF Foundation) const struct test_spec *test_to_run) 293*d1aec26fSBastien Curutchet (eBPF Foundation) { 294*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *tx_pkt_stream; 295*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *rx_pkt_stream; 296*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 297*d1aec26fSBastien Curutchet (eBPF Foundation) 298*d1aec26fSBastien Curutchet (eBPF Foundation) tx_pkt_stream = test->tx_pkt_stream_default; 299*d1aec26fSBastien Curutchet (eBPF Foundation) rx_pkt_stream = test->rx_pkt_stream_default; 300*d1aec26fSBastien Curutchet (eBPF Foundation) memset(test, 0, sizeof(*test)); 301*d1aec26fSBastien Curutchet (eBPF Foundation) test->tx_pkt_stream_default = tx_pkt_stream; 302*d1aec26fSBastien Curutchet (eBPF Foundation) test->rx_pkt_stream_default = rx_pkt_stream; 303*d1aec26fSBastien Curutchet (eBPF Foundation) 304*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < MAX_INTERFACES; i++) { 305*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx; 306*d1aec26fSBastien Curutchet (eBPF Foundation) 307*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->bind_flags = XDP_USE_NEED_WAKEUP; 308*d1aec26fSBastien Curutchet (eBPF Foundation) if (mode == TEST_MODE_ZC) 309*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->bind_flags |= XDP_ZEROCOPY; 310*d1aec26fSBastien Curutchet (eBPF Foundation) else 311*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->bind_flags |= XDP_COPY; 312*d1aec26fSBastien Curutchet (eBPF Foundation) } 313*d1aec26fSBastien Curutchet (eBPF Foundation) 314*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(test->name, test_to_run->name, MAX_TEST_NAME_SIZE); 315*d1aec26fSBastien Curutchet (eBPF Foundation) test->test_func = test_to_run->test_func; 316*d1aec26fSBastien Curutchet (eBPF Foundation) test->mode = mode; 317*d1aec26fSBastien Curutchet (eBPF Foundation) __test_spec_init(test, ifobj_tx, ifobj_rx); 318*d1aec26fSBastien Curutchet (eBPF Foundation) } 319*d1aec26fSBastien Curutchet (eBPF Foundation) 320*d1aec26fSBastien Curutchet (eBPF Foundation) static void test_spec_reset(struct test_spec *test) 321*d1aec26fSBastien Curutchet (eBPF Foundation) { 322*d1aec26fSBastien Curutchet (eBPF Foundation) __test_spec_init(test, test->ifobj_tx, test->ifobj_rx); 323*d1aec26fSBastien Curutchet (eBPF Foundation) } 324*d1aec26fSBastien Curutchet (eBPF Foundation) 325*d1aec26fSBastien Curutchet (eBPF Foundation) static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx, 326*d1aec26fSBastien Curutchet (eBPF Foundation) struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx, 327*d1aec26fSBastien Curutchet (eBPF Foundation) struct bpf_map *xskmap_tx) 328*d1aec26fSBastien Curutchet (eBPF Foundation) { 329*d1aec26fSBastien Curutchet (eBPF Foundation) test->xdp_prog_rx = xdp_prog_rx; 330*d1aec26fSBastien Curutchet (eBPF Foundation) test->xdp_prog_tx = xdp_prog_tx; 331*d1aec26fSBastien Curutchet (eBPF Foundation) test->xskmap_rx = xskmap_rx; 332*d1aec26fSBastien Curutchet (eBPF Foundation) test->xskmap_tx = xskmap_tx; 333*d1aec26fSBastien Curutchet (eBPF Foundation) } 334*d1aec26fSBastien Curutchet (eBPF Foundation) 335*d1aec26fSBastien Curutchet (eBPF Foundation) static int test_spec_set_mtu(struct test_spec *test, int mtu) 336*d1aec26fSBastien Curutchet (eBPF Foundation) { 337*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 338*d1aec26fSBastien Curutchet (eBPF Foundation) 339*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_rx->mtu != mtu) { 340*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_set_mtu(test->ifobj_rx->ifindex, mtu); 341*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 342*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 343*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->mtu = mtu; 344*d1aec26fSBastien Curutchet (eBPF Foundation) } 345*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_tx->mtu != mtu) { 346*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_set_mtu(test->ifobj_tx->ifindex, mtu); 347*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 348*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 349*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->mtu = mtu; 350*d1aec26fSBastien Curutchet (eBPF Foundation) } 351*d1aec26fSBastien Curutchet (eBPF Foundation) 352*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 353*d1aec26fSBastien Curutchet (eBPF Foundation) } 354*d1aec26fSBastien Curutchet (eBPF Foundation) 355*d1aec26fSBastien Curutchet (eBPF Foundation) void pkt_stream_reset(struct pkt_stream *pkt_stream) 356*d1aec26fSBastien Curutchet (eBPF Foundation) { 357*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream) { 358*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->current_pkt_nb = 0; 359*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_rx_pkts = 0; 360*d1aec26fSBastien Curutchet (eBPF Foundation) } 361*d1aec26fSBastien Curutchet (eBPF Foundation) } 362*d1aec26fSBastien Curutchet (eBPF Foundation) 363*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt *pkt_stream_get_next_tx_pkt(struct pkt_stream *pkt_stream) 364*d1aec26fSBastien Curutchet (eBPF Foundation) { 365*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream->current_pkt_nb >= pkt_stream->nb_pkts) 366*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 367*d1aec26fSBastien Curutchet (eBPF Foundation) 368*d1aec26fSBastien Curutchet (eBPF Foundation) return &pkt_stream->pkts[pkt_stream->current_pkt_nb++]; 369*d1aec26fSBastien Curutchet (eBPF Foundation) } 370*d1aec26fSBastien Curutchet (eBPF Foundation) 371*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt *pkt_stream_get_next_rx_pkt(struct pkt_stream *pkt_stream, u32 *pkts_sent) 372*d1aec26fSBastien Curutchet (eBPF Foundation) { 373*d1aec26fSBastien Curutchet (eBPF Foundation) while (pkt_stream->current_pkt_nb < pkt_stream->nb_pkts) { 374*d1aec26fSBastien Curutchet (eBPF Foundation) (*pkts_sent)++; 375*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream->pkts[pkt_stream->current_pkt_nb].valid) 376*d1aec26fSBastien Curutchet (eBPF Foundation) return &pkt_stream->pkts[pkt_stream->current_pkt_nb++]; 377*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->current_pkt_nb++; 378*d1aec26fSBastien Curutchet (eBPF Foundation) } 379*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 380*d1aec26fSBastien Curutchet (eBPF Foundation) } 381*d1aec26fSBastien Curutchet (eBPF Foundation) 382*d1aec26fSBastien Curutchet (eBPF Foundation) void pkt_stream_delete(struct pkt_stream *pkt_stream) 383*d1aec26fSBastien Curutchet (eBPF Foundation) { 384*d1aec26fSBastien Curutchet (eBPF Foundation) free(pkt_stream->pkts); 385*d1aec26fSBastien Curutchet (eBPF Foundation) free(pkt_stream); 386*d1aec26fSBastien Curutchet (eBPF Foundation) } 387*d1aec26fSBastien Curutchet (eBPF Foundation) 388*d1aec26fSBastien Curutchet (eBPF Foundation) void pkt_stream_restore_default(struct test_spec *test) 389*d1aec26fSBastien Curutchet (eBPF Foundation) { 390*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *tx_pkt_stream = test->ifobj_tx->xsk->pkt_stream; 391*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *rx_pkt_stream = test->ifobj_rx->xsk->pkt_stream; 392*d1aec26fSBastien Curutchet (eBPF Foundation) 393*d1aec26fSBastien Curutchet (eBPF Foundation) if (tx_pkt_stream != test->tx_pkt_stream_default) { 394*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_delete(test->ifobj_tx->xsk->pkt_stream); 395*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->pkt_stream = test->tx_pkt_stream_default; 396*d1aec26fSBastien Curutchet (eBPF Foundation) } 397*d1aec26fSBastien Curutchet (eBPF Foundation) 398*d1aec26fSBastien Curutchet (eBPF Foundation) if (rx_pkt_stream != test->rx_pkt_stream_default) { 399*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_delete(test->ifobj_rx->xsk->pkt_stream); 400*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->pkt_stream = test->rx_pkt_stream_default; 401*d1aec26fSBastien Curutchet (eBPF Foundation) } 402*d1aec26fSBastien Curutchet (eBPF Foundation) } 403*d1aec26fSBastien Curutchet (eBPF Foundation) 404*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt_stream *__pkt_stream_alloc(u32 nb_pkts) 405*d1aec26fSBastien Curutchet (eBPF Foundation) { 406*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 407*d1aec26fSBastien Curutchet (eBPF Foundation) 408*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = calloc(1, sizeof(*pkt_stream)); 409*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 410*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 411*d1aec26fSBastien Curutchet (eBPF Foundation) 412*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->pkts = calloc(nb_pkts, sizeof(*pkt_stream->pkts)); 413*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream->pkts) { 414*d1aec26fSBastien Curutchet (eBPF Foundation) free(pkt_stream); 415*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 416*d1aec26fSBastien Curutchet (eBPF Foundation) } 417*d1aec26fSBastien Curutchet (eBPF Foundation) 418*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_pkts = nb_pkts; 419*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt_stream; 420*d1aec26fSBastien Curutchet (eBPF Foundation) } 421*d1aec26fSBastien Curutchet (eBPF Foundation) 422*d1aec26fSBastien Curutchet (eBPF Foundation) static u32 pkt_nb_frags(u32 frame_size, struct pkt_stream *pkt_stream, struct pkt *pkt) 423*d1aec26fSBastien Curutchet (eBPF Foundation) { 424*d1aec26fSBastien Curutchet (eBPF Foundation) u32 nb_frags = 1, next_frag; 425*d1aec26fSBastien Curutchet (eBPF Foundation) 426*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt) 427*d1aec26fSBastien Curutchet (eBPF Foundation) return 1; 428*d1aec26fSBastien Curutchet (eBPF Foundation) 429*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream->verbatim) { 430*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt->valid || !pkt->len) 431*d1aec26fSBastien Curutchet (eBPF Foundation) return 1; 432*d1aec26fSBastien Curutchet (eBPF Foundation) return ceil_u32(pkt->len, frame_size); 433*d1aec26fSBastien Curutchet (eBPF Foundation) } 434*d1aec26fSBastien Curutchet (eBPF Foundation) 435*d1aec26fSBastien Curutchet (eBPF Foundation) /* Search for the end of the packet in verbatim mode */ 436*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_continues(pkt->options)) 437*d1aec26fSBastien Curutchet (eBPF Foundation) return nb_frags; 438*d1aec26fSBastien Curutchet (eBPF Foundation) 439*d1aec26fSBastien Curutchet (eBPF Foundation) next_frag = pkt_stream->current_pkt_nb; 440*d1aec26fSBastien Curutchet (eBPF Foundation) pkt++; 441*d1aec26fSBastien Curutchet (eBPF Foundation) while (next_frag++ < pkt_stream->nb_pkts) { 442*d1aec26fSBastien Curutchet (eBPF Foundation) nb_frags++; 443*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_continues(pkt->options) || !pkt->valid) 444*d1aec26fSBastien Curutchet (eBPF Foundation) break; 445*d1aec26fSBastien Curutchet (eBPF Foundation) pkt++; 446*d1aec26fSBastien Curutchet (eBPF Foundation) } 447*d1aec26fSBastien Curutchet (eBPF Foundation) return nb_frags; 448*d1aec26fSBastien Curutchet (eBPF Foundation) } 449*d1aec26fSBastien Curutchet (eBPF Foundation) 450*d1aec26fSBastien Curutchet (eBPF Foundation) static bool set_pkt_valid(int offset, u32 len) 451*d1aec26fSBastien Curutchet (eBPF Foundation) { 452*d1aec26fSBastien Curutchet (eBPF Foundation) return len <= MAX_ETH_JUMBO_SIZE; 453*d1aec26fSBastien Curutchet (eBPF Foundation) } 454*d1aec26fSBastien Curutchet (eBPF Foundation) 455*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_set(struct pkt_stream *pkt_stream, struct pkt *pkt, int offset, u32 len) 456*d1aec26fSBastien Curutchet (eBPF Foundation) { 457*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->offset = offset; 458*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->len = len; 459*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->valid = set_pkt_valid(offset, len); 460*d1aec26fSBastien Curutchet (eBPF Foundation) } 461*d1aec26fSBastien Curutchet (eBPF Foundation) 462*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_stream_pkt_set(struct pkt_stream *pkt_stream, struct pkt *pkt, int offset, u32 len) 463*d1aec26fSBastien Curutchet (eBPF Foundation) { 464*d1aec26fSBastien Curutchet (eBPF Foundation) bool prev_pkt_valid = pkt->valid; 465*d1aec26fSBastien Curutchet (eBPF Foundation) 466*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_set(pkt_stream, pkt, offset, len); 467*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_valid_entries += pkt->valid - prev_pkt_valid; 468*d1aec26fSBastien Curutchet (eBPF Foundation) } 469*d1aec26fSBastien Curutchet (eBPF Foundation) 470*d1aec26fSBastien Curutchet (eBPF Foundation) static u32 pkt_get_buffer_len(struct xsk_umem_info *umem, u32 len) 471*d1aec26fSBastien Curutchet (eBPF Foundation) { 472*d1aec26fSBastien Curutchet (eBPF Foundation) return ceil_u32(len, umem->frame_size) * umem->frame_size; 473*d1aec26fSBastien Curutchet (eBPF Foundation) } 474*d1aec26fSBastien Curutchet (eBPF Foundation) 475*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt_stream *__pkt_stream_generate(u32 nb_pkts, u32 pkt_len, u32 nb_start, u32 nb_off) 476*d1aec26fSBastien Curutchet (eBPF Foundation) { 477*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 478*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 479*d1aec26fSBastien Curutchet (eBPF Foundation) 480*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_alloc(nb_pkts); 481*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 482*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 483*d1aec26fSBastien Curutchet (eBPF Foundation) 484*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_pkts = nb_pkts; 485*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->max_pkt_len = pkt_len; 486*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < nb_pkts; i++) { 487*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkt = &pkt_stream->pkts[i]; 488*d1aec26fSBastien Curutchet (eBPF Foundation) 489*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_pkt_set(pkt_stream, pkt, 0, pkt_len); 490*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->pkt_nb = nb_start + i * nb_off; 491*d1aec26fSBastien Curutchet (eBPF Foundation) } 492*d1aec26fSBastien Curutchet (eBPF Foundation) 493*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt_stream; 494*d1aec26fSBastien Curutchet (eBPF Foundation) } 495*d1aec26fSBastien Curutchet (eBPF Foundation) 496*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream_generate(u32 nb_pkts, u32 pkt_len) 497*d1aec26fSBastien Curutchet (eBPF Foundation) { 498*d1aec26fSBastien Curutchet (eBPF Foundation) return __pkt_stream_generate(nb_pkts, pkt_len, 0, 1); 499*d1aec26fSBastien Curutchet (eBPF Foundation) } 500*d1aec26fSBastien Curutchet (eBPF Foundation) 501*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt_stream *pkt_stream_clone(struct pkt_stream *pkt_stream) 502*d1aec26fSBastien Curutchet (eBPF Foundation) { 503*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt_stream_generate(pkt_stream->nb_pkts, pkt_stream->pkts[0].len); 504*d1aec26fSBastien Curutchet (eBPF Foundation) } 505*d1aec26fSBastien Curutchet (eBPF Foundation) 506*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_replace_ifobject(struct ifobject *ifobj, u32 nb_pkts, u32 pkt_len) 507*d1aec26fSBastien Curutchet (eBPF Foundation) { 508*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk->pkt_stream = pkt_stream_generate(nb_pkts, pkt_len); 509*d1aec26fSBastien Curutchet (eBPF Foundation) 510*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj->xsk->pkt_stream) 511*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 512*d1aec26fSBastien Curutchet (eBPF Foundation) 513*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 514*d1aec26fSBastien Curutchet (eBPF Foundation) } 515*d1aec26fSBastien Curutchet (eBPF Foundation) 516*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_replace(struct test_spec *test, u32 nb_pkts, u32 pkt_len) 517*d1aec26fSBastien Curutchet (eBPF Foundation) { 518*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 519*d1aec26fSBastien Curutchet (eBPF Foundation) 520*d1aec26fSBastien Curutchet (eBPF Foundation) ret = pkt_stream_replace_ifobject(test->ifobj_tx, nb_pkts, pkt_len); 521*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 522*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 523*d1aec26fSBastien Curutchet (eBPF Foundation) 524*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt_stream_replace_ifobject(test->ifobj_rx, nb_pkts, pkt_len); 525*d1aec26fSBastien Curutchet (eBPF Foundation) } 526*d1aec26fSBastien Curutchet (eBPF Foundation) 527*d1aec26fSBastien Curutchet (eBPF Foundation) static int __pkt_stream_replace_half(struct ifobject *ifobj, u32 pkt_len, 528*d1aec26fSBastien Curutchet (eBPF Foundation) int offset) 529*d1aec26fSBastien Curutchet (eBPF Foundation) { 530*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 531*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 532*d1aec26fSBastien Curutchet (eBPF Foundation) 533*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = pkt_stream_clone(ifobj->xsk->pkt_stream); 534*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 535*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 536*d1aec26fSBastien Curutchet (eBPF Foundation) 537*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 1; i < ifobj->xsk->pkt_stream->nb_pkts; i += 2) 538*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_pkt_set(pkt_stream, &pkt_stream->pkts[i], offset, pkt_len); 539*d1aec26fSBastien Curutchet (eBPF Foundation) 540*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk->pkt_stream = pkt_stream; 541*d1aec26fSBastien Curutchet (eBPF Foundation) 542*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 543*d1aec26fSBastien Curutchet (eBPF Foundation) } 544*d1aec26fSBastien Curutchet (eBPF Foundation) 545*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_replace_half(struct test_spec *test, u32 pkt_len, int offset) 546*d1aec26fSBastien Curutchet (eBPF Foundation) { 547*d1aec26fSBastien Curutchet (eBPF Foundation) int ret = __pkt_stream_replace_half(test->ifobj_tx, pkt_len, offset); 548*d1aec26fSBastien Curutchet (eBPF Foundation) 549*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 550*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 551*d1aec26fSBastien Curutchet (eBPF Foundation) 552*d1aec26fSBastien Curutchet (eBPF Foundation) return __pkt_stream_replace_half(test->ifobj_rx, pkt_len, offset); 553*d1aec26fSBastien Curutchet (eBPF Foundation) } 554*d1aec26fSBastien Curutchet (eBPF Foundation) 555*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_receive_half(struct test_spec *test) 556*d1aec26fSBastien Curutchet (eBPF Foundation) { 557*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream = test->ifobj_tx->xsk->pkt_stream; 558*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 559*d1aec26fSBastien Curutchet (eBPF Foundation) 560*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_rx->xsk->pkt_stream != test->rx_pkt_stream_default) 561*d1aec26fSBastien Curutchet (eBPF Foundation) /* Packet stream has already been replaced so we have to release this one. 562*d1aec26fSBastien Curutchet (eBPF Foundation) * The newly created one will be freed by the restore_default() at the 563*d1aec26fSBastien Curutchet (eBPF Foundation) * end of the test 564*d1aec26fSBastien Curutchet (eBPF Foundation) */ 565*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_delete(test->ifobj_rx->xsk->pkt_stream); 566*d1aec26fSBastien Curutchet (eBPF Foundation) 567*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(pkt_stream->nb_pkts, 568*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->pkts[0].len); 569*d1aec26fSBastien Curutchet (eBPF Foundation) if (!test->ifobj_rx->xsk->pkt_stream) 570*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 571*d1aec26fSBastien Curutchet (eBPF Foundation) 572*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = test->ifobj_rx->xsk->pkt_stream; 573*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 1; i < pkt_stream->nb_pkts; i += 2) 574*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->pkts[i].valid = false; 575*d1aec26fSBastien Curutchet (eBPF Foundation) 576*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_valid_entries /= 2; 577*d1aec26fSBastien Curutchet (eBPF Foundation) 578*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 579*d1aec26fSBastien Curutchet (eBPF Foundation) } 580*d1aec26fSBastien Curutchet (eBPF Foundation) 581*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_even_odd_sequence(struct test_spec *test) 582*d1aec26fSBastien Curutchet (eBPF Foundation) { 583*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 584*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 585*d1aec26fSBastien Curutchet (eBPF Foundation) 586*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) { 587*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = test->ifobj_tx->xsk_arr[i].pkt_stream; 588*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2, 589*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->pkts[0].len, i, 2); 590*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 591*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 592*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk_arr[i].pkt_stream = pkt_stream; 593*d1aec26fSBastien Curutchet (eBPF Foundation) 594*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = test->ifobj_rx->xsk_arr[i].pkt_stream; 595*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2, 596*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->pkts[0].len, i, 2); 597*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 598*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 599*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk_arr[i].pkt_stream = pkt_stream; 600*d1aec26fSBastien Curutchet (eBPF Foundation) } 601*d1aec26fSBastien Curutchet (eBPF Foundation) 602*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 603*d1aec26fSBastien Curutchet (eBPF Foundation) } 604*d1aec26fSBastien Curutchet (eBPF Foundation) 605*d1aec26fSBastien Curutchet (eBPF Foundation) static void release_even_odd_sequence(struct test_spec *test) 606*d1aec26fSBastien Curutchet (eBPF Foundation) { 607*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *later_free_tx = test->ifobj_tx->xsk->pkt_stream; 608*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *later_free_rx = test->ifobj_rx->xsk->pkt_stream; 609*d1aec26fSBastien Curutchet (eBPF Foundation) int i; 610*d1aec26fSBastien Curutchet (eBPF Foundation) 611*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) { 612*d1aec26fSBastien Curutchet (eBPF Foundation) /* later_free_{rx/tx} will be freed by restore_default() */ 613*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_tx->xsk_arr[i].pkt_stream != later_free_tx) 614*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_delete(test->ifobj_tx->xsk_arr[i].pkt_stream); 615*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_rx->xsk_arr[i].pkt_stream != later_free_rx) 616*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_delete(test->ifobj_rx->xsk_arr[i].pkt_stream); 617*d1aec26fSBastien Curutchet (eBPF Foundation) } 618*d1aec26fSBastien Curutchet (eBPF Foundation) 619*d1aec26fSBastien Curutchet (eBPF Foundation) } 620*d1aec26fSBastien Curutchet (eBPF Foundation) 621*d1aec26fSBastien Curutchet (eBPF Foundation) static u64 pkt_get_addr(struct pkt *pkt, struct xsk_umem_info *umem) 622*d1aec26fSBastien Curutchet (eBPF Foundation) { 623*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt->valid) 624*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt->offset; 625*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt->offset + umem_alloc_buffer(umem); 626*d1aec26fSBastien Curutchet (eBPF Foundation) } 627*d1aec26fSBastien Curutchet (eBPF Foundation) 628*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_stream_cancel(struct pkt_stream *pkt_stream) 629*d1aec26fSBastien Curutchet (eBPF Foundation) { 630*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->current_pkt_nb--; 631*d1aec26fSBastien Curutchet (eBPF Foundation) } 632*d1aec26fSBastien Curutchet (eBPF Foundation) 633*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_generate(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, u64 addr, u32 len, 634*d1aec26fSBastien Curutchet (eBPF Foundation) u32 pkt_nb, u32 bytes_written) 635*d1aec26fSBastien Curutchet (eBPF Foundation) { 636*d1aec26fSBastien Curutchet (eBPF Foundation) void *data = xsk_umem__get_data(umem->buffer, addr); 637*d1aec26fSBastien Curutchet (eBPF Foundation) 638*d1aec26fSBastien Curutchet (eBPF Foundation) if (len < MIN_PKT_SIZE) 639*d1aec26fSBastien Curutchet (eBPF Foundation) return; 640*d1aec26fSBastien Curutchet (eBPF Foundation) 641*d1aec26fSBastien Curutchet (eBPF Foundation) if (!bytes_written) { 642*d1aec26fSBastien Curutchet (eBPF Foundation) gen_eth_hdr(xsk, data); 643*d1aec26fSBastien Curutchet (eBPF Foundation) 644*d1aec26fSBastien Curutchet (eBPF Foundation) len -= PKT_HDR_SIZE; 645*d1aec26fSBastien Curutchet (eBPF Foundation) data += PKT_HDR_SIZE; 646*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 647*d1aec26fSBastien Curutchet (eBPF Foundation) bytes_written -= PKT_HDR_SIZE; 648*d1aec26fSBastien Curutchet (eBPF Foundation) } 649*d1aec26fSBastien Curutchet (eBPF Foundation) 650*d1aec26fSBastien Curutchet (eBPF Foundation) write_payload(data, pkt_nb, bytes_written, len); 651*d1aec26fSBastien Curutchet (eBPF Foundation) } 652*d1aec26fSBastien Curutchet (eBPF Foundation) 653*d1aec26fSBastien Curutchet (eBPF Foundation) static struct pkt_stream *__pkt_stream_generate_custom(struct ifobject *ifobj, struct pkt *frames, 654*d1aec26fSBastien Curutchet (eBPF Foundation) u32 nb_frames, bool verbatim) 655*d1aec26fSBastien Curutchet (eBPF Foundation) { 656*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i, len = 0, pkt_nb = 0, payload = 0; 657*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 658*d1aec26fSBastien Curutchet (eBPF Foundation) 659*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_alloc(nb_frames); 660*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 661*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 662*d1aec26fSBastien Curutchet (eBPF Foundation) 663*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < nb_frames; i++) { 664*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkt = &pkt_stream->pkts[pkt_nb]; 665*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *frame = &frames[i]; 666*d1aec26fSBastien Curutchet (eBPF Foundation) 667*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->offset = frame->offset; 668*d1aec26fSBastien Curutchet (eBPF Foundation) if (verbatim) { 669*d1aec26fSBastien Curutchet (eBPF Foundation) *pkt = *frame; 670*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->pkt_nb = payload; 671*d1aec26fSBastien Curutchet (eBPF Foundation) if (!frame->valid || !pkt_continues(frame->options)) 672*d1aec26fSBastien Curutchet (eBPF Foundation) payload++; 673*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 674*d1aec26fSBastien Curutchet (eBPF Foundation) if (frame->valid) 675*d1aec26fSBastien Curutchet (eBPF Foundation) len += frame->len; 676*d1aec26fSBastien Curutchet (eBPF Foundation) if (frame->valid && pkt_continues(frame->options)) 677*d1aec26fSBastien Curutchet (eBPF Foundation) continue; 678*d1aec26fSBastien Curutchet (eBPF Foundation) 679*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->pkt_nb = pkt_nb; 680*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->len = len; 681*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->valid = frame->valid; 682*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->options = 0; 683*d1aec26fSBastien Curutchet (eBPF Foundation) 684*d1aec26fSBastien Curutchet (eBPF Foundation) len = 0; 685*d1aec26fSBastien Curutchet (eBPF Foundation) } 686*d1aec26fSBastien Curutchet (eBPF Foundation) 687*d1aec26fSBastien Curutchet (eBPF Foundation) print_verbose("offset: %d len: %u valid: %u options: %u pkt_nb: %u\n", 688*d1aec26fSBastien Curutchet (eBPF Foundation) pkt->offset, pkt->len, pkt->valid, pkt->options, pkt->pkt_nb); 689*d1aec26fSBastien Curutchet (eBPF Foundation) 690*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt->valid && pkt->len > pkt_stream->max_pkt_len) 691*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->max_pkt_len = pkt->len; 692*d1aec26fSBastien Curutchet (eBPF Foundation) 693*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt->valid) 694*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_valid_entries++; 695*d1aec26fSBastien Curutchet (eBPF Foundation) 696*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_nb++; 697*d1aec26fSBastien Curutchet (eBPF Foundation) } 698*d1aec26fSBastien Curutchet (eBPF Foundation) 699*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_pkts = pkt_nb; 700*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->verbatim = verbatim; 701*d1aec26fSBastien Curutchet (eBPF Foundation) return pkt_stream; 702*d1aec26fSBastien Curutchet (eBPF Foundation) } 703*d1aec26fSBastien Curutchet (eBPF Foundation) 704*d1aec26fSBastien Curutchet (eBPF Foundation) static int pkt_stream_generate_custom(struct test_spec *test, struct pkt *pkts, u32 nb_pkts) 705*d1aec26fSBastien Curutchet (eBPF Foundation) { 706*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 707*d1aec26fSBastien Curutchet (eBPF Foundation) 708*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_generate_custom(test->ifobj_tx, pkts, nb_pkts, true); 709*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 710*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 711*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->pkt_stream = pkt_stream; 712*d1aec26fSBastien Curutchet (eBPF Foundation) 713*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = __pkt_stream_generate_custom(test->ifobj_rx, pkts, nb_pkts, false); 714*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) 715*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOMEM; 716*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->pkt_stream = pkt_stream; 717*d1aec26fSBastien Curutchet (eBPF Foundation) 718*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 719*d1aec26fSBastien Curutchet (eBPF Foundation) } 720*d1aec26fSBastien Curutchet (eBPF Foundation) 721*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_print_data(u32 *data, u32 cnt) 722*d1aec26fSBastien Curutchet (eBPF Foundation) { 723*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 724*d1aec26fSBastien Curutchet (eBPF Foundation) 725*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < cnt; i++) { 726*d1aec26fSBastien Curutchet (eBPF Foundation) u32 seqnum, pkt_nb; 727*d1aec26fSBastien Curutchet (eBPF Foundation) 728*d1aec26fSBastien Curutchet (eBPF Foundation) seqnum = ntohl(*data) & 0xffff; 729*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_nb = ntohl(*data) >> 16; 730*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("%u:%u ", pkt_nb, seqnum); 731*d1aec26fSBastien Curutchet (eBPF Foundation) data++; 732*d1aec26fSBastien Curutchet (eBPF Foundation) } 733*d1aec26fSBastien Curutchet (eBPF Foundation) } 734*d1aec26fSBastien Curutchet (eBPF Foundation) 735*d1aec26fSBastien Curutchet (eBPF Foundation) static void pkt_dump(void *pkt, u32 len, bool eth_header) 736*d1aec26fSBastien Curutchet (eBPF Foundation) { 737*d1aec26fSBastien Curutchet (eBPF Foundation) struct ethhdr *ethhdr = pkt; 738*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i, *data; 739*d1aec26fSBastien Curutchet (eBPF Foundation) 740*d1aec26fSBastien Curutchet (eBPF Foundation) if (eth_header) { 741*d1aec26fSBastien Curutchet (eBPF Foundation) /*extract L2 frame */ 742*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("DEBUG>> L2: dst mac: "); 743*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < ETH_ALEN; i++) 744*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("%02X", ethhdr->h_dest[i]); 745*d1aec26fSBastien Curutchet (eBPF Foundation) 746*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("\nDEBUG>> L2: src mac: "); 747*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < ETH_ALEN; i++) 748*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("%02X", ethhdr->h_source[i]); 749*d1aec26fSBastien Curutchet (eBPF Foundation) 750*d1aec26fSBastien Curutchet (eBPF Foundation) data = pkt + PKT_HDR_SIZE; 751*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 752*d1aec26fSBastien Curutchet (eBPF Foundation) data = pkt; 753*d1aec26fSBastien Curutchet (eBPF Foundation) } 754*d1aec26fSBastien Curutchet (eBPF Foundation) 755*d1aec26fSBastien Curutchet (eBPF Foundation) /*extract L5 frame */ 756*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("\nDEBUG>> L5: seqnum: "); 757*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_print_data(data, PKT_DUMP_NB_TO_PRINT); 758*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("...."); 759*d1aec26fSBastien Curutchet (eBPF Foundation) if (len > PKT_DUMP_NB_TO_PRINT * sizeof(u32)) { 760*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("\n.... "); 761*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_print_data(data + len / sizeof(u32) - PKT_DUMP_NB_TO_PRINT, 762*d1aec26fSBastien Curutchet (eBPF Foundation) PKT_DUMP_NB_TO_PRINT); 763*d1aec26fSBastien Curutchet (eBPF Foundation) } 764*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("\n---------------------------------------\n"); 765*d1aec26fSBastien Curutchet (eBPF Foundation) } 766*d1aec26fSBastien Curutchet (eBPF Foundation) 767*d1aec26fSBastien Curutchet (eBPF Foundation) static bool is_offset_correct(struct xsk_umem_info *umem, struct pkt *pkt, u64 addr) 768*d1aec26fSBastien Curutchet (eBPF Foundation) { 769*d1aec26fSBastien Curutchet (eBPF Foundation) u32 headroom = umem->unaligned_mode ? 0 : umem->frame_headroom; 770*d1aec26fSBastien Curutchet (eBPF Foundation) u32 offset = addr % umem->frame_size, expected_offset; 771*d1aec26fSBastien Curutchet (eBPF Foundation) int pkt_offset = pkt->valid ? pkt->offset : 0; 772*d1aec26fSBastien Curutchet (eBPF Foundation) 773*d1aec26fSBastien Curutchet (eBPF Foundation) if (!umem->unaligned_mode) 774*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_offset = 0; 775*d1aec26fSBastien Curutchet (eBPF Foundation) 776*d1aec26fSBastien Curutchet (eBPF Foundation) expected_offset = (pkt_offset + headroom + XDP_PACKET_HEADROOM) % umem->frame_size; 777*d1aec26fSBastien Curutchet (eBPF Foundation) 778*d1aec26fSBastien Curutchet (eBPF Foundation) if (offset == expected_offset) 779*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 780*d1aec26fSBastien Curutchet (eBPF Foundation) 781*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected [%u], got [%u]\n", __func__, expected_offset, offset); 782*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 783*d1aec26fSBastien Curutchet (eBPF Foundation) } 784*d1aec26fSBastien Curutchet (eBPF Foundation) 785*d1aec26fSBastien Curutchet (eBPF Foundation) static bool is_metadata_correct(struct pkt *pkt, void *buffer, u64 addr) 786*d1aec26fSBastien Curutchet (eBPF Foundation) { 787*d1aec26fSBastien Curutchet (eBPF Foundation) void *data = xsk_umem__get_data(buffer, addr); 788*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_info *meta = data - sizeof(struct xdp_info); 789*d1aec26fSBastien Curutchet (eBPF Foundation) 790*d1aec26fSBastien Curutchet (eBPF Foundation) if (meta->count != pkt->pkt_nb) { 791*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%llu]\n", 792*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, pkt->pkt_nb, 793*d1aec26fSBastien Curutchet (eBPF Foundation) (unsigned long long)meta->count); 794*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 795*d1aec26fSBastien Curutchet (eBPF Foundation) } 796*d1aec26fSBastien Curutchet (eBPF Foundation) 797*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 798*d1aec26fSBastien Curutchet (eBPF Foundation) } 799*d1aec26fSBastien Curutchet (eBPF Foundation) 800*d1aec26fSBastien Curutchet (eBPF Foundation) static int is_adjust_tail_supported(struct xsk_xdp_progs *skel_rx, bool *supported) 801*d1aec26fSBastien Curutchet (eBPF Foundation) { 802*d1aec26fSBastien Curutchet (eBPF Foundation) struct bpf_map *data_map; 803*d1aec26fSBastien Curutchet (eBPF Foundation) int adjust_value = 0; 804*d1aec26fSBastien Curutchet (eBPF Foundation) int key = 0; 805*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 806*d1aec26fSBastien Curutchet (eBPF Foundation) 807*d1aec26fSBastien Curutchet (eBPF Foundation) data_map = bpf_object__find_map_by_name(skel_rx->obj, "xsk_xdp_.bss"); 808*d1aec26fSBastien Curutchet (eBPF Foundation) if (!data_map || !bpf_map__is_internal(data_map)) { 809*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error: could not find bss section of XDP program\n"); 810*d1aec26fSBastien Curutchet (eBPF Foundation) return -EINVAL; 811*d1aec26fSBastien Curutchet (eBPF Foundation) } 812*d1aec26fSBastien Curutchet (eBPF Foundation) 813*d1aec26fSBastien Curutchet (eBPF Foundation) ret = bpf_map_lookup_elem(bpf_map__fd(data_map), &key, &adjust_value); 814*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) { 815*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error: bpf_map_lookup_elem failed with error %d\n", ret); 816*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 817*d1aec26fSBastien Curutchet (eBPF Foundation) } 818*d1aec26fSBastien Curutchet (eBPF Foundation) 819*d1aec26fSBastien Curutchet (eBPF Foundation) /* Set the 'adjust_value' variable to -EOPNOTSUPP in the XDP program if the adjust_tail 820*d1aec26fSBastien Curutchet (eBPF Foundation) * helper is not supported. Skip the adjust_tail test case in this scenario. 821*d1aec26fSBastien Curutchet (eBPF Foundation) */ 822*d1aec26fSBastien Curutchet (eBPF Foundation) *supported = adjust_value != -EOPNOTSUPP; 823*d1aec26fSBastien Curutchet (eBPF Foundation) 824*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 825*d1aec26fSBastien Curutchet (eBPF Foundation) } 826*d1aec26fSBastien Curutchet (eBPF Foundation) 827*d1aec26fSBastien Curutchet (eBPF Foundation) static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u32 expected_pkt_nb, 828*d1aec26fSBastien Curutchet (eBPF Foundation) u32 bytes_processed) 829*d1aec26fSBastien Curutchet (eBPF Foundation) { 830*d1aec26fSBastien Curutchet (eBPF Foundation) u32 seqnum, pkt_nb, *pkt_data, words_to_end, expected_seqnum; 831*d1aec26fSBastien Curutchet (eBPF Foundation) void *data = xsk_umem__get_data(umem->buffer, addr); 832*d1aec26fSBastien Curutchet (eBPF Foundation) 833*d1aec26fSBastien Curutchet (eBPF Foundation) addr -= umem->base_addr; 834*d1aec26fSBastien Curutchet (eBPF Foundation) 835*d1aec26fSBastien Curutchet (eBPF Foundation) if (addr >= umem->num_frames * umem->frame_size || 836*d1aec26fSBastien Curutchet (eBPF Foundation) addr + len > umem->num_frames * umem->frame_size) { 837*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Frag invalid addr: %llx len: %u\n", 838*d1aec26fSBastien Curutchet (eBPF Foundation) (unsigned long long)addr, len); 839*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 840*d1aec26fSBastien Curutchet (eBPF Foundation) } 841*d1aec26fSBastien Curutchet (eBPF Foundation) if (!umem->unaligned_mode && addr % umem->frame_size + len > umem->frame_size) { 842*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Frag crosses frame boundary addr: %llx len: %u\n", 843*d1aec26fSBastien Curutchet (eBPF Foundation) (unsigned long long)addr, len); 844*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 845*d1aec26fSBastien Curutchet (eBPF Foundation) } 846*d1aec26fSBastien Curutchet (eBPF Foundation) 847*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_data = data; 848*d1aec26fSBastien Curutchet (eBPF Foundation) if (!bytes_processed) { 849*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_data += PKT_HDR_SIZE / sizeof(*pkt_data); 850*d1aec26fSBastien Curutchet (eBPF Foundation) len -= PKT_HDR_SIZE; 851*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 852*d1aec26fSBastien Curutchet (eBPF Foundation) bytes_processed -= PKT_HDR_SIZE; 853*d1aec26fSBastien Curutchet (eBPF Foundation) } 854*d1aec26fSBastien Curutchet (eBPF Foundation) 855*d1aec26fSBastien Curutchet (eBPF Foundation) expected_seqnum = bytes_processed / sizeof(*pkt_data); 856*d1aec26fSBastien Curutchet (eBPF Foundation) seqnum = ntohl(*pkt_data) & 0xffff; 857*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_nb = ntohl(*pkt_data) >> 16; 858*d1aec26fSBastien Curutchet (eBPF Foundation) 859*d1aec26fSBastien Curutchet (eBPF Foundation) if (expected_pkt_nb != pkt_nb) { 860*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected pkt_nb [%u], got pkt_nb [%u]\n", 861*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, expected_pkt_nb, pkt_nb); 862*d1aec26fSBastien Curutchet (eBPF Foundation) goto error; 863*d1aec26fSBastien Curutchet (eBPF Foundation) } 864*d1aec26fSBastien Curutchet (eBPF Foundation) if (expected_seqnum != seqnum) { 865*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected seqnum at start [%u], got seqnum [%u]\n", 866*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, expected_seqnum, seqnum); 867*d1aec26fSBastien Curutchet (eBPF Foundation) goto error; 868*d1aec26fSBastien Curutchet (eBPF Foundation) } 869*d1aec26fSBastien Curutchet (eBPF Foundation) 870*d1aec26fSBastien Curutchet (eBPF Foundation) words_to_end = len / sizeof(*pkt_data) - 1; 871*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_data += words_to_end; 872*d1aec26fSBastien Curutchet (eBPF Foundation) seqnum = ntohl(*pkt_data) & 0xffff; 873*d1aec26fSBastien Curutchet (eBPF Foundation) expected_seqnum += words_to_end; 874*d1aec26fSBastien Curutchet (eBPF Foundation) if (expected_seqnum != seqnum) { 875*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected seqnum at end [%u], got seqnum [%u]\n", 876*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, expected_seqnum, seqnum); 877*d1aec26fSBastien Curutchet (eBPF Foundation) goto error; 878*d1aec26fSBastien Curutchet (eBPF Foundation) } 879*d1aec26fSBastien Curutchet (eBPF Foundation) 880*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 881*d1aec26fSBastien Curutchet (eBPF Foundation) 882*d1aec26fSBastien Curutchet (eBPF Foundation) error: 883*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_dump(data, len, !bytes_processed); 884*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 885*d1aec26fSBastien Curutchet (eBPF Foundation) } 886*d1aec26fSBastien Curutchet (eBPF Foundation) 887*d1aec26fSBastien Curutchet (eBPF Foundation) static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len) 888*d1aec26fSBastien Curutchet (eBPF Foundation) { 889*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt->len != len) { 890*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] expected packet length [%d], got length [%d]\n", 891*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, pkt->len, len); 892*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_dump(xsk_umem__get_data(buffer, addr), len, true); 893*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 894*d1aec26fSBastien Curutchet (eBPF Foundation) } 895*d1aec26fSBastien Curutchet (eBPF Foundation) 896*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 897*d1aec26fSBastien Curutchet (eBPF Foundation) } 898*d1aec26fSBastien Curutchet (eBPF Foundation) 899*d1aec26fSBastien Curutchet (eBPF Foundation) static u32 load_value(u32 *counter) 900*d1aec26fSBastien Curutchet (eBPF Foundation) { 901*d1aec26fSBastien Curutchet (eBPF Foundation) return __atomic_load_n(counter, __ATOMIC_ACQUIRE); 902*d1aec26fSBastien Curutchet (eBPF Foundation) } 903*d1aec26fSBastien Curutchet (eBPF Foundation) 904*d1aec26fSBastien Curutchet (eBPF Foundation) static bool kick_tx_with_check(struct xsk_socket_info *xsk, int *ret) 905*d1aec26fSBastien Curutchet (eBPF Foundation) { 906*d1aec26fSBastien Curutchet (eBPF Foundation) u32 max_budget = MAX_TX_BUDGET_DEFAULT; 907*d1aec26fSBastien Curutchet (eBPF Foundation) u32 cons, ready_to_send; 908*d1aec26fSBastien Curutchet (eBPF Foundation) int delta; 909*d1aec26fSBastien Curutchet (eBPF Foundation) 910*d1aec26fSBastien Curutchet (eBPF Foundation) cons = load_value(xsk->tx.consumer); 911*d1aec26fSBastien Curutchet (eBPF Foundation) ready_to_send = load_value(xsk->tx.producer) - cons; 912*d1aec26fSBastien Curutchet (eBPF Foundation) *ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); 913*d1aec26fSBastien Curutchet (eBPF Foundation) 914*d1aec26fSBastien Curutchet (eBPF Foundation) delta = load_value(xsk->tx.consumer) - cons; 915*d1aec26fSBastien Curutchet (eBPF Foundation) /* By default, xsk should consume exact @max_budget descs at one 916*d1aec26fSBastien Curutchet (eBPF Foundation) * send in this case where hitting the max budget limit in while 917*d1aec26fSBastien Curutchet (eBPF Foundation) * loop is triggered in __xsk_generic_xmit(). Please make sure that 918*d1aec26fSBastien Curutchet (eBPF Foundation) * the number of descs to be sent is larger than @max_budget, or 919*d1aec26fSBastien Curutchet (eBPF Foundation) * else the tx.consumer will be updated in xskq_cons_peek_desc() 920*d1aec26fSBastien Curutchet (eBPF Foundation) * in time which hides the issue we try to verify. 921*d1aec26fSBastien Curutchet (eBPF Foundation) */ 922*d1aec26fSBastien Curutchet (eBPF Foundation) if (ready_to_send > max_budget && delta != max_budget) 923*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 924*d1aec26fSBastien Curutchet (eBPF Foundation) 925*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 926*d1aec26fSBastien Curutchet (eBPF Foundation) } 927*d1aec26fSBastien Curutchet (eBPF Foundation) 928*d1aec26fSBastien Curutchet (eBPF Foundation) int kick_tx(struct xsk_socket_info *xsk) 929*d1aec26fSBastien Curutchet (eBPF Foundation) { 930*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 931*d1aec26fSBastien Curutchet (eBPF Foundation) 932*d1aec26fSBastien Curutchet (eBPF Foundation) if (xsk->check_consumer) { 933*d1aec26fSBastien Curutchet (eBPF Foundation) if (!kick_tx_with_check(xsk, &ret)) 934*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 935*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 936*d1aec26fSBastien Curutchet (eBPF Foundation) ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); 937*d1aec26fSBastien Curutchet (eBPF Foundation) } 938*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret >= 0) 939*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 940*d1aec26fSBastien Curutchet (eBPF Foundation) if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) { 941*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(100); 942*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 943*d1aec26fSBastien Curutchet (eBPF Foundation) } 944*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 945*d1aec26fSBastien Curutchet (eBPF Foundation) } 946*d1aec26fSBastien Curutchet (eBPF Foundation) 947*d1aec26fSBastien Curutchet (eBPF Foundation) int kick_rx(struct xsk_socket_info *xsk) 948*d1aec26fSBastien Curutchet (eBPF Foundation) { 949*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 950*d1aec26fSBastien Curutchet (eBPF Foundation) 951*d1aec26fSBastien Curutchet (eBPF Foundation) ret = recvfrom(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, NULL); 952*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret < 0) 953*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 954*d1aec26fSBastien Curutchet (eBPF Foundation) 955*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 956*d1aec26fSBastien Curutchet (eBPF Foundation) } 957*d1aec26fSBastien Curutchet (eBPF Foundation) 958*d1aec26fSBastien Curutchet (eBPF Foundation) static int complete_pkts(struct xsk_socket_info *xsk, int batch_size) 959*d1aec26fSBastien Curutchet (eBPF Foundation) { 960*d1aec26fSBastien Curutchet (eBPF Foundation) unsigned int rcvd; 961*d1aec26fSBastien Curutchet (eBPF Foundation) u32 idx; 962*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 963*d1aec26fSBastien Curutchet (eBPF Foundation) 964*d1aec26fSBastien Curutchet (eBPF Foundation) if (xsk_ring_prod__needs_wakeup(&xsk->tx)) { 965*d1aec26fSBastien Curutchet (eBPF Foundation) ret = kick_tx(xsk); 966*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 967*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 968*d1aec26fSBastien Curutchet (eBPF Foundation) } 969*d1aec26fSBastien Curutchet (eBPF Foundation) 970*d1aec26fSBastien Curutchet (eBPF Foundation) rcvd = xsk_ring_cons__peek(&xsk->umem->cq, batch_size, &idx); 971*d1aec26fSBastien Curutchet (eBPF Foundation) if (rcvd) { 972*d1aec26fSBastien Curutchet (eBPF Foundation) if (rcvd > xsk->outstanding_tx) { 973*d1aec26fSBastien Curutchet (eBPF Foundation) u64 addr = *xsk_ring_cons__comp_addr(&xsk->umem->cq, idx + rcvd - 1); 974*d1aec26fSBastien Curutchet (eBPF Foundation) 975*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] Too many packets completed\n", __func__); 976*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Last completion address: %llx\n", 977*d1aec26fSBastien Curutchet (eBPF Foundation) (unsigned long long)addr); 978*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 979*d1aec26fSBastien Curutchet (eBPF Foundation) } 980*d1aec26fSBastien Curutchet (eBPF Foundation) 981*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_cons__release(&xsk->umem->cq, rcvd); 982*d1aec26fSBastien Curutchet (eBPF Foundation) xsk->outstanding_tx -= rcvd; 983*d1aec26fSBastien Curutchet (eBPF Foundation) } 984*d1aec26fSBastien Curutchet (eBPF Foundation) 985*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 986*d1aec26fSBastien Curutchet (eBPF Foundation) } 987*d1aec26fSBastien Curutchet (eBPF Foundation) 988*d1aec26fSBastien Curutchet (eBPF Foundation) static int __receive_pkts(struct test_spec *test, struct xsk_socket_info *xsk) 989*d1aec26fSBastien Curutchet (eBPF Foundation) { 990*d1aec26fSBastien Curutchet (eBPF Foundation) u32 frags_processed = 0, nb_frags = 0, pkt_len = 0; 991*d1aec26fSBastien Curutchet (eBPF Foundation) u32 idx_rx = 0, idx_fq = 0, rcvd, pkts_sent = 0; 992*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream = xsk->pkt_stream; 993*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj = test->ifobj_rx; 994*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_info *umem = xsk->umem; 995*d1aec26fSBastien Curutchet (eBPF Foundation) struct pollfd fds = { }; 996*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkt; 997*d1aec26fSBastien Curutchet (eBPF Foundation) u64 first_addr = 0; 998*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 999*d1aec26fSBastien Curutchet (eBPF Foundation) 1000*d1aec26fSBastien Curutchet (eBPF Foundation) fds.fd = xsk_socket__fd(xsk->xsk); 1001*d1aec26fSBastien Curutchet (eBPF Foundation) fds.events = POLLIN; 1002*d1aec26fSBastien Curutchet (eBPF Foundation) 1003*d1aec26fSBastien Curutchet (eBPF Foundation) ret = kick_rx(xsk); 1004*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1005*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1006*d1aec26fSBastien Curutchet (eBPF Foundation) 1007*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->use_poll) { 1008*d1aec26fSBastien Curutchet (eBPF Foundation) ret = poll(&fds, 1, POLL_TMOUT); 1009*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret < 0) 1010*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1011*d1aec26fSBastien Curutchet (eBPF Foundation) 1012*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ret) { 1013*d1aec26fSBastien Curutchet (eBPF Foundation) if (!is_umem_valid(test->ifobj_tx)) 1014*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1015*d1aec26fSBastien Curutchet (eBPF Foundation) 1016*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Poll timed out\n", __func__); 1017*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1018*d1aec26fSBastien Curutchet (eBPF Foundation) } 1019*d1aec26fSBastien Curutchet (eBPF Foundation) 1020*d1aec26fSBastien Curutchet (eBPF Foundation) if (!(fds.revents & POLLIN)) 1021*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1022*d1aec26fSBastien Curutchet (eBPF Foundation) } 1023*d1aec26fSBastien Curutchet (eBPF Foundation) 1024*d1aec26fSBastien Curutchet (eBPF Foundation) rcvd = xsk_ring_cons__peek(&xsk->rx, xsk->batch_size, &idx_rx); 1025*d1aec26fSBastien Curutchet (eBPF Foundation) if (!rcvd) 1026*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1027*d1aec26fSBastien Curutchet (eBPF Foundation) 1028*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->use_fill_ring) { 1029*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq); 1030*d1aec26fSBastien Curutchet (eBPF Foundation) while (ret != rcvd) { 1031*d1aec26fSBastien Curutchet (eBPF Foundation) if (xsk_ring_prod__needs_wakeup(&umem->fq)) { 1032*d1aec26fSBastien Curutchet (eBPF Foundation) ret = poll(&fds, 1, POLL_TMOUT); 1033*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret < 0) 1034*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1035*d1aec26fSBastien Curutchet (eBPF Foundation) } 1036*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq); 1037*d1aec26fSBastien Curutchet (eBPF Foundation) } 1038*d1aec26fSBastien Curutchet (eBPF Foundation) } 1039*d1aec26fSBastien Curutchet (eBPF Foundation) 1040*d1aec26fSBastien Curutchet (eBPF Foundation) while (frags_processed < rcvd) { 1041*d1aec26fSBastien Curutchet (eBPF Foundation) const struct xdp_desc *desc = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++); 1042*d1aec26fSBastien Curutchet (eBPF Foundation) u64 addr = desc->addr, orig; 1043*d1aec26fSBastien Curutchet (eBPF Foundation) 1044*d1aec26fSBastien Curutchet (eBPF Foundation) orig = xsk_umem__extract_addr(addr); 1045*d1aec26fSBastien Curutchet (eBPF Foundation) addr = xsk_umem__add_offset_to_addr(addr); 1046*d1aec26fSBastien Curutchet (eBPF Foundation) 1047*d1aec26fSBastien Curutchet (eBPF Foundation) if (!nb_frags) { 1048*d1aec26fSBastien Curutchet (eBPF Foundation) pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &pkts_sent); 1049*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt) { 1050*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] received too many packets addr: %lx len %u\n", 1051*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, addr, desc->len); 1052*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1053*d1aec26fSBastien Curutchet (eBPF Foundation) } 1054*d1aec26fSBastien Curutchet (eBPF Foundation) } 1055*d1aec26fSBastien Curutchet (eBPF Foundation) 1056*d1aec26fSBastien Curutchet (eBPF Foundation) print_verbose("Rx: addr: %lx len: %u options: %u pkt_nb: %u valid: %u\n", 1057*d1aec26fSBastien Curutchet (eBPF Foundation) addr, desc->len, desc->options, pkt->pkt_nb, pkt->valid); 1058*d1aec26fSBastien Curutchet (eBPF Foundation) 1059*d1aec26fSBastien Curutchet (eBPF Foundation) if (!is_frag_valid(umem, addr, desc->len, pkt->pkt_nb, pkt_len) || 1060*d1aec26fSBastien Curutchet (eBPF Foundation) !is_offset_correct(umem, pkt, addr) || (ifobj->use_metadata && 1061*d1aec26fSBastien Curutchet (eBPF Foundation) !is_metadata_correct(pkt, umem->buffer, addr))) 1062*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1063*d1aec26fSBastien Curutchet (eBPF Foundation) 1064*d1aec26fSBastien Curutchet (eBPF Foundation) if (!nb_frags++) 1065*d1aec26fSBastien Curutchet (eBPF Foundation) first_addr = addr; 1066*d1aec26fSBastien Curutchet (eBPF Foundation) frags_processed++; 1067*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_len += desc->len; 1068*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->use_fill_ring) 1069*d1aec26fSBastien Curutchet (eBPF Foundation) *xsk_ring_prod__fill_addr(&umem->fq, idx_fq++) = orig; 1070*d1aec26fSBastien Curutchet (eBPF Foundation) 1071*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_continues(desc->options)) 1072*d1aec26fSBastien Curutchet (eBPF Foundation) continue; 1073*d1aec26fSBastien Curutchet (eBPF Foundation) 1074*d1aec26fSBastien Curutchet (eBPF Foundation) /* The complete packet has been received */ 1075*d1aec26fSBastien Curutchet (eBPF Foundation) if (!is_pkt_valid(pkt, umem->buffer, first_addr, pkt_len) || 1076*d1aec26fSBastien Curutchet (eBPF Foundation) !is_offset_correct(umem, pkt, addr)) 1077*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1078*d1aec26fSBastien Curutchet (eBPF Foundation) 1079*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream->nb_rx_pkts++; 1080*d1aec26fSBastien Curutchet (eBPF Foundation) nb_frags = 0; 1081*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_len = 0; 1082*d1aec26fSBastien Curutchet (eBPF Foundation) } 1083*d1aec26fSBastien Curutchet (eBPF Foundation) 1084*d1aec26fSBastien Curutchet (eBPF Foundation) if (nb_frags) { 1085*d1aec26fSBastien Curutchet (eBPF Foundation) /* In the middle of a packet. Start over from beginning of packet. */ 1086*d1aec26fSBastien Curutchet (eBPF Foundation) idx_rx -= nb_frags; 1087*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_cons__cancel(&xsk->rx, nb_frags); 1088*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->use_fill_ring) { 1089*d1aec26fSBastien Curutchet (eBPF Foundation) idx_fq -= nb_frags; 1090*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__cancel(&umem->fq, nb_frags); 1091*d1aec26fSBastien Curutchet (eBPF Foundation) } 1092*d1aec26fSBastien Curutchet (eBPF Foundation) frags_processed -= nb_frags; 1093*d1aec26fSBastien Curutchet (eBPF Foundation) } 1094*d1aec26fSBastien Curutchet (eBPF Foundation) 1095*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->use_fill_ring) 1096*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__submit(&umem->fq, frags_processed); 1097*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->release_rx) 1098*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_cons__release(&xsk->rx, frags_processed); 1099*d1aec26fSBastien Curutchet (eBPF Foundation) 1100*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_mutex_lock(&pacing_mutex); 1101*d1aec26fSBastien Curutchet (eBPF Foundation) pkts_in_flight -= pkts_sent; 1102*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_mutex_unlock(&pacing_mutex); 1103*d1aec26fSBastien Curutchet (eBPF Foundation) pkts_sent = 0; 1104*d1aec26fSBastien Curutchet (eBPF Foundation) 1105*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1106*d1aec26fSBastien Curutchet (eBPF Foundation) } 1107*d1aec26fSBastien Curutchet (eBPF Foundation) 1108*d1aec26fSBastien Curutchet (eBPF Foundation) bool all_packets_received(struct test_spec *test, struct xsk_socket_info *xsk, u32 sock_num, 1109*d1aec26fSBastien Curutchet (eBPF Foundation) unsigned long *bitmap) 1110*d1aec26fSBastien Curutchet (eBPF Foundation) { 1111*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream = xsk->pkt_stream; 1112*d1aec26fSBastien Curutchet (eBPF Foundation) 1113*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream) { 1114*d1aec26fSBastien Curutchet (eBPF Foundation) __set_bit(sock_num, bitmap); 1115*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 1116*d1aec26fSBastien Curutchet (eBPF Foundation) } 1117*d1aec26fSBastien Curutchet (eBPF Foundation) 1118*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream->nb_rx_pkts == pkt_stream->nb_valid_entries) { 1119*d1aec26fSBastien Curutchet (eBPF Foundation) __set_bit(sock_num, bitmap); 1120*d1aec26fSBastien Curutchet (eBPF Foundation) if (bitmap_full(bitmap, test->nb_sockets)) 1121*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 1122*d1aec26fSBastien Curutchet (eBPF Foundation) } 1123*d1aec26fSBastien Curutchet (eBPF Foundation) 1124*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 1125*d1aec26fSBastien Curutchet (eBPF Foundation) } 1126*d1aec26fSBastien Curutchet (eBPF Foundation) 1127*d1aec26fSBastien Curutchet (eBPF Foundation) static int receive_pkts(struct test_spec *test) 1128*d1aec26fSBastien Curutchet (eBPF Foundation) { 1129*d1aec26fSBastien Curutchet (eBPF Foundation) struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0}; 1130*d1aec26fSBastien Curutchet (eBPF Foundation) DECLARE_BITMAP(bitmap, test->nb_sockets); 1131*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket_info *xsk; 1132*d1aec26fSBastien Curutchet (eBPF Foundation) u32 sock_num = 0; 1133*d1aec26fSBastien Curutchet (eBPF Foundation) int res, ret; 1134*d1aec26fSBastien Curutchet (eBPF Foundation) 1135*d1aec26fSBastien Curutchet (eBPF Foundation) bitmap_zero(bitmap, test->nb_sockets); 1136*d1aec26fSBastien Curutchet (eBPF Foundation) 1137*d1aec26fSBastien Curutchet (eBPF Foundation) ret = gettimeofday(&tv_now, NULL); 1138*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1139*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1140*d1aec26fSBastien Curutchet (eBPF Foundation) 1141*d1aec26fSBastien Curutchet (eBPF Foundation) timeradd(&tv_now, &tv_timeout, &tv_end); 1142*d1aec26fSBastien Curutchet (eBPF Foundation) 1143*d1aec26fSBastien Curutchet (eBPF Foundation) while (1) { 1144*d1aec26fSBastien Curutchet (eBPF Foundation) xsk = &test->ifobj_rx->xsk_arr[sock_num]; 1145*d1aec26fSBastien Curutchet (eBPF Foundation) 1146*d1aec26fSBastien Curutchet (eBPF Foundation) if ((all_packets_received(test, xsk, sock_num, bitmap))) 1147*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1148*d1aec26fSBastien Curutchet (eBPF Foundation) 1149*d1aec26fSBastien Curutchet (eBPF Foundation) res = __receive_pkts(test, xsk); 1150*d1aec26fSBastien Curutchet (eBPF Foundation) if (!(res == TEST_PASS || res == TEST_CONTINUE)) 1151*d1aec26fSBastien Curutchet (eBPF Foundation) return res; 1152*d1aec26fSBastien Curutchet (eBPF Foundation) 1153*d1aec26fSBastien Curutchet (eBPF Foundation) ret = gettimeofday(&tv_now, NULL); 1154*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1155*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1156*d1aec26fSBastien Curutchet (eBPF Foundation) 1157*d1aec26fSBastien Curutchet (eBPF Foundation) if (timercmp(&tv_now, &tv_end, >)) { 1158*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Receive loop timed out\n", __func__); 1159*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1160*d1aec26fSBastien Curutchet (eBPF Foundation) } 1161*d1aec26fSBastien Curutchet (eBPF Foundation) sock_num = (sock_num + 1) % test->nb_sockets; 1162*d1aec26fSBastien Curutchet (eBPF Foundation) } 1163*d1aec26fSBastien Curutchet (eBPF Foundation) 1164*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1165*d1aec26fSBastien Curutchet (eBPF Foundation) } 1166*d1aec26fSBastien Curutchet (eBPF Foundation) 1167*d1aec26fSBastien Curutchet (eBPF Foundation) static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, bool timeout) 1168*d1aec26fSBastien Curutchet (eBPF Foundation) { 1169*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i, idx = 0, valid_pkts = 0, valid_frags = 0, buffer_len; 1170*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream = xsk->pkt_stream; 1171*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_info *umem = ifobject->umem; 1172*d1aec26fSBastien Curutchet (eBPF Foundation) bool use_poll = ifobject->use_poll; 1173*d1aec26fSBastien Curutchet (eBPF Foundation) struct pollfd fds = { }; 1174*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 1175*d1aec26fSBastien Curutchet (eBPF Foundation) 1176*d1aec26fSBastien Curutchet (eBPF Foundation) buffer_len = pkt_get_buffer_len(umem, pkt_stream->max_pkt_len); 1177*d1aec26fSBastien Curutchet (eBPF Foundation) /* pkts_in_flight might be negative if many invalid packets are sent */ 1178*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkts_in_flight >= (int)((umem_size(umem) - xsk->batch_size * buffer_len) / 1179*d1aec26fSBastien Curutchet (eBPF Foundation) buffer_len)) { 1180*d1aec26fSBastien Curutchet (eBPF Foundation) ret = kick_tx(xsk); 1181*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1182*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1183*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1184*d1aec26fSBastien Curutchet (eBPF Foundation) } 1185*d1aec26fSBastien Curutchet (eBPF Foundation) 1186*d1aec26fSBastien Curutchet (eBPF Foundation) fds.fd = xsk_socket__fd(xsk->xsk); 1187*d1aec26fSBastien Curutchet (eBPF Foundation) fds.events = POLLOUT; 1188*d1aec26fSBastien Curutchet (eBPF Foundation) 1189*d1aec26fSBastien Curutchet (eBPF Foundation) while (xsk_ring_prod__reserve(&xsk->tx, xsk->batch_size, &idx) < xsk->batch_size) { 1190*d1aec26fSBastien Curutchet (eBPF Foundation) if (use_poll) { 1191*d1aec26fSBastien Curutchet (eBPF Foundation) ret = poll(&fds, 1, POLL_TMOUT); 1192*d1aec26fSBastien Curutchet (eBPF Foundation) if (timeout) { 1193*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret < 0) { 1194*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Poll error %d\n", 1195*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, errno); 1196*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1197*d1aec26fSBastien Curutchet (eBPF Foundation) } 1198*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret == 0) 1199*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1200*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1201*d1aec26fSBastien Curutchet (eBPF Foundation) } 1202*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret <= 0) { 1203*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Poll error %d\n", 1204*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, errno); 1205*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1206*d1aec26fSBastien Curutchet (eBPF Foundation) } 1207*d1aec26fSBastien Curutchet (eBPF Foundation) } 1208*d1aec26fSBastien Curutchet (eBPF Foundation) 1209*d1aec26fSBastien Curutchet (eBPF Foundation) complete_pkts(xsk, xsk->batch_size); 1210*d1aec26fSBastien Curutchet (eBPF Foundation) } 1211*d1aec26fSBastien Curutchet (eBPF Foundation) 1212*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < xsk->batch_size; i++) { 1213*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkt = pkt_stream_get_next_tx_pkt(pkt_stream); 1214*d1aec26fSBastien Curutchet (eBPF Foundation) u32 nb_frags_left, nb_frags, bytes_written = 0; 1215*d1aec26fSBastien Curutchet (eBPF Foundation) 1216*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt) 1217*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1218*d1aec26fSBastien Curutchet (eBPF Foundation) 1219*d1aec26fSBastien Curutchet (eBPF Foundation) nb_frags = pkt_nb_frags(umem->frame_size, pkt_stream, pkt); 1220*d1aec26fSBastien Curutchet (eBPF Foundation) if (nb_frags > xsk->batch_size - i) { 1221*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_cancel(pkt_stream); 1222*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__cancel(&xsk->tx, xsk->batch_size - i); 1223*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1224*d1aec26fSBastien Curutchet (eBPF Foundation) } 1225*d1aec26fSBastien Curutchet (eBPF Foundation) nb_frags_left = nb_frags; 1226*d1aec26fSBastien Curutchet (eBPF Foundation) 1227*d1aec26fSBastien Curutchet (eBPF Foundation) while (nb_frags_left--) { 1228*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i); 1229*d1aec26fSBastien Curutchet (eBPF Foundation) 1230*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->addr = pkt_get_addr(pkt, ifobject->umem); 1231*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream->verbatim) { 1232*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->len = pkt->len; 1233*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->options = pkt->options; 1234*d1aec26fSBastien Curutchet (eBPF Foundation) } else if (nb_frags_left) { 1235*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->len = umem->frame_size; 1236*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->options = XDP_PKT_CONTD; 1237*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1238*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->len = pkt->len - bytes_written; 1239*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->options = 0; 1240*d1aec26fSBastien Curutchet (eBPF Foundation) } 1241*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt->valid) 1242*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_generate(xsk, umem, tx_desc->addr, tx_desc->len, pkt->pkt_nb, 1243*d1aec26fSBastien Curutchet (eBPF Foundation) bytes_written); 1244*d1aec26fSBastien Curutchet (eBPF Foundation) bytes_written += tx_desc->len; 1245*d1aec26fSBastien Curutchet (eBPF Foundation) 1246*d1aec26fSBastien Curutchet (eBPF Foundation) print_verbose("Tx addr: %llx len: %u options: %u pkt_nb: %u\n", 1247*d1aec26fSBastien Curutchet (eBPF Foundation) tx_desc->addr, tx_desc->len, tx_desc->options, pkt->pkt_nb); 1248*d1aec26fSBastien Curutchet (eBPF Foundation) 1249*d1aec26fSBastien Curutchet (eBPF Foundation) if (nb_frags_left) { 1250*d1aec26fSBastien Curutchet (eBPF Foundation) i++; 1251*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream->verbatim) 1252*d1aec26fSBastien Curutchet (eBPF Foundation) pkt = pkt_stream_get_next_tx_pkt(pkt_stream); 1253*d1aec26fSBastien Curutchet (eBPF Foundation) } 1254*d1aec26fSBastien Curutchet (eBPF Foundation) } 1255*d1aec26fSBastien Curutchet (eBPF Foundation) 1256*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt && pkt->valid) { 1257*d1aec26fSBastien Curutchet (eBPF Foundation) valid_pkts++; 1258*d1aec26fSBastien Curutchet (eBPF Foundation) valid_frags += nb_frags; 1259*d1aec26fSBastien Curutchet (eBPF Foundation) } 1260*d1aec26fSBastien Curutchet (eBPF Foundation) } 1261*d1aec26fSBastien Curutchet (eBPF Foundation) 1262*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_mutex_lock(&pacing_mutex); 1263*d1aec26fSBastien Curutchet (eBPF Foundation) pkts_in_flight += valid_pkts; 1264*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_mutex_unlock(&pacing_mutex); 1265*d1aec26fSBastien Curutchet (eBPF Foundation) 1266*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__submit(&xsk->tx, i); 1267*d1aec26fSBastien Curutchet (eBPF Foundation) xsk->outstanding_tx += valid_frags; 1268*d1aec26fSBastien Curutchet (eBPF Foundation) 1269*d1aec26fSBastien Curutchet (eBPF Foundation) if (use_poll) { 1270*d1aec26fSBastien Curutchet (eBPF Foundation) ret = poll(&fds, 1, POLL_TMOUT); 1271*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret <= 0) { 1272*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret == 0 && timeout) 1273*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1274*d1aec26fSBastien Curutchet (eBPF Foundation) 1275*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Poll error %d\n", __func__, ret); 1276*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1277*d1aec26fSBastien Curutchet (eBPF Foundation) } 1278*d1aec26fSBastien Curutchet (eBPF Foundation) } 1279*d1aec26fSBastien Curutchet (eBPF Foundation) 1280*d1aec26fSBastien Curutchet (eBPF Foundation) if (!timeout) { 1281*d1aec26fSBastien Curutchet (eBPF Foundation) if (complete_pkts(xsk, i)) 1282*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1283*d1aec26fSBastien Curutchet (eBPF Foundation) 1284*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(10); 1285*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1286*d1aec26fSBastien Curutchet (eBPF Foundation) } 1287*d1aec26fSBastien Curutchet (eBPF Foundation) 1288*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_CONTINUE; 1289*d1aec26fSBastien Curutchet (eBPF Foundation) } 1290*d1aec26fSBastien Curutchet (eBPF Foundation) 1291*d1aec26fSBastien Curutchet (eBPF Foundation) static int wait_for_tx_completion(struct xsk_socket_info *xsk) 1292*d1aec26fSBastien Curutchet (eBPF Foundation) { 1293*d1aec26fSBastien Curutchet (eBPF Foundation) struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0}; 1294*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 1295*d1aec26fSBastien Curutchet (eBPF Foundation) 1296*d1aec26fSBastien Curutchet (eBPF Foundation) ret = gettimeofday(&tv_now, NULL); 1297*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1298*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1299*d1aec26fSBastien Curutchet (eBPF Foundation) timeradd(&tv_now, &tv_timeout, &tv_end); 1300*d1aec26fSBastien Curutchet (eBPF Foundation) 1301*d1aec26fSBastien Curutchet (eBPF Foundation) while (xsk->outstanding_tx) { 1302*d1aec26fSBastien Curutchet (eBPF Foundation) ret = gettimeofday(&tv_now, NULL); 1303*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1304*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1305*d1aec26fSBastien Curutchet (eBPF Foundation) if (timercmp(&tv_now, &tv_end, >)) { 1306*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: [%s] Transmission loop timed out\n", __func__); 1307*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1308*d1aec26fSBastien Curutchet (eBPF Foundation) } 1309*d1aec26fSBastien Curutchet (eBPF Foundation) 1310*d1aec26fSBastien Curutchet (eBPF Foundation) complete_pkts(xsk, xsk->batch_size); 1311*d1aec26fSBastien Curutchet (eBPF Foundation) } 1312*d1aec26fSBastien Curutchet (eBPF Foundation) 1313*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1314*d1aec26fSBastien Curutchet (eBPF Foundation) } 1315*d1aec26fSBastien Curutchet (eBPF Foundation) 1316*d1aec26fSBastien Curutchet (eBPF Foundation) bool all_packets_sent(struct test_spec *test, unsigned long *bitmap) 1317*d1aec26fSBastien Curutchet (eBPF Foundation) { 1318*d1aec26fSBastien Curutchet (eBPF Foundation) return bitmap_full(bitmap, test->nb_sockets); 1319*d1aec26fSBastien Curutchet (eBPF Foundation) } 1320*d1aec26fSBastien Curutchet (eBPF Foundation) 1321*d1aec26fSBastien Curutchet (eBPF Foundation) static int send_pkts(struct test_spec *test, struct ifobject *ifobject) 1322*d1aec26fSBastien Curutchet (eBPF Foundation) { 1323*d1aec26fSBastien Curutchet (eBPF Foundation) bool timeout = !is_umem_valid(test->ifobj_rx); 1324*d1aec26fSBastien Curutchet (eBPF Foundation) DECLARE_BITMAP(bitmap, test->nb_sockets); 1325*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i, ret; 1326*d1aec26fSBastien Curutchet (eBPF Foundation) 1327*d1aec26fSBastien Curutchet (eBPF Foundation) bitmap_zero(bitmap, test->nb_sockets); 1328*d1aec26fSBastien Curutchet (eBPF Foundation) 1329*d1aec26fSBastien Curutchet (eBPF Foundation) while (!(all_packets_sent(test, bitmap))) { 1330*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) { 1331*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt_stream *pkt_stream; 1332*d1aec26fSBastien Curutchet (eBPF Foundation) 1333*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream = ifobject->xsk_arr[i].pkt_stream; 1334*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt_stream || pkt_stream->current_pkt_nb >= pkt_stream->nb_pkts) { 1335*d1aec26fSBastien Curutchet (eBPF Foundation) __set_bit(i, bitmap); 1336*d1aec26fSBastien Curutchet (eBPF Foundation) continue; 1337*d1aec26fSBastien Curutchet (eBPF Foundation) } 1338*d1aec26fSBastien Curutchet (eBPF Foundation) ret = __send_pkts(ifobject, &ifobject->xsk_arr[i], timeout); 1339*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret == TEST_CONTINUE && !test->fail) 1340*d1aec26fSBastien Curutchet (eBPF Foundation) continue; 1341*d1aec26fSBastien Curutchet (eBPF Foundation) 1342*d1aec26fSBastien Curutchet (eBPF Foundation) if ((ret || test->fail) && !timeout) 1343*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1344*d1aec26fSBastien Curutchet (eBPF Foundation) 1345*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret == TEST_PASS && timeout) 1346*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1347*d1aec26fSBastien Curutchet (eBPF Foundation) 1348*d1aec26fSBastien Curutchet (eBPF Foundation) ret = wait_for_tx_completion(&ifobject->xsk_arr[i]); 1349*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1350*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1351*d1aec26fSBastien Curutchet (eBPF Foundation) } 1352*d1aec26fSBastien Curutchet (eBPF Foundation) } 1353*d1aec26fSBastien Curutchet (eBPF Foundation) 1354*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1355*d1aec26fSBastien Curutchet (eBPF Foundation) } 1356*d1aec26fSBastien Curutchet (eBPF Foundation) 1357*d1aec26fSBastien Curutchet (eBPF Foundation) static int get_xsk_stats(struct xsk_socket *xsk, struct xdp_statistics *stats) 1358*d1aec26fSBastien Curutchet (eBPF Foundation) { 1359*d1aec26fSBastien Curutchet (eBPF Foundation) int fd = xsk_socket__fd(xsk), err; 1360*d1aec26fSBastien Curutchet (eBPF Foundation) socklen_t optlen, expected_len; 1361*d1aec26fSBastien Curutchet (eBPF Foundation) 1362*d1aec26fSBastien Curutchet (eBPF Foundation) optlen = sizeof(*stats); 1363*d1aec26fSBastien Curutchet (eBPF Foundation) err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, stats, &optlen); 1364*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1365*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n", 1366*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, -err, strerror(-err)); 1367*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1368*d1aec26fSBastien Curutchet (eBPF Foundation) } 1369*d1aec26fSBastien Curutchet (eBPF Foundation) 1370*d1aec26fSBastien Curutchet (eBPF Foundation) expected_len = sizeof(struct xdp_statistics); 1371*d1aec26fSBastien Curutchet (eBPF Foundation) if (optlen != expected_len) { 1372*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] getsockopt optlen error. Expected: %u got: %u\n", 1373*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, expected_len, optlen); 1374*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1375*d1aec26fSBastien Curutchet (eBPF Foundation) } 1376*d1aec26fSBastien Curutchet (eBPF Foundation) 1377*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1378*d1aec26fSBastien Curutchet (eBPF Foundation) } 1379*d1aec26fSBastien Curutchet (eBPF Foundation) 1380*d1aec26fSBastien Curutchet (eBPF Foundation) static int validate_rx_dropped(struct ifobject *ifobject) 1381*d1aec26fSBastien Curutchet (eBPF Foundation) { 1382*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket *xsk = ifobject->xsk->xsk; 1383*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_statistics stats; 1384*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1385*d1aec26fSBastien Curutchet (eBPF Foundation) 1386*d1aec26fSBastien Curutchet (eBPF Foundation) err = kick_rx(ifobject->xsk); 1387*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1388*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1389*d1aec26fSBastien Curutchet (eBPF Foundation) 1390*d1aec26fSBastien Curutchet (eBPF Foundation) err = get_xsk_stats(xsk, &stats); 1391*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1392*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1393*d1aec26fSBastien Curutchet (eBPF Foundation) 1394*d1aec26fSBastien Curutchet (eBPF Foundation) /* The receiver calls getsockopt after receiving the last (valid) 1395*d1aec26fSBastien Curutchet (eBPF Foundation) * packet which is not the final packet sent in this test (valid and 1396*d1aec26fSBastien Curutchet (eBPF Foundation) * invalid packets are sent in alternating fashion with the final 1397*d1aec26fSBastien Curutchet (eBPF Foundation) * packet being invalid). Since the last packet may or may not have 1398*d1aec26fSBastien Curutchet (eBPF Foundation) * been dropped already, both outcomes must be allowed. 1399*d1aec26fSBastien Curutchet (eBPF Foundation) */ 1400*d1aec26fSBastien Curutchet (eBPF Foundation) if (stats.rx_dropped == ifobject->xsk->pkt_stream->nb_pkts / 2 || 1401*d1aec26fSBastien Curutchet (eBPF Foundation) stats.rx_dropped == ifobject->xsk->pkt_stream->nb_pkts / 2 - 1) 1402*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1403*d1aec26fSBastien Curutchet (eBPF Foundation) 1404*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1405*d1aec26fSBastien Curutchet (eBPF Foundation) } 1406*d1aec26fSBastien Curutchet (eBPF Foundation) 1407*d1aec26fSBastien Curutchet (eBPF Foundation) static int validate_rx_full(struct ifobject *ifobject) 1408*d1aec26fSBastien Curutchet (eBPF Foundation) { 1409*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket *xsk = ifobject->xsk->xsk; 1410*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_statistics stats; 1411*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1412*d1aec26fSBastien Curutchet (eBPF Foundation) 1413*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(1000); 1414*d1aec26fSBastien Curutchet (eBPF Foundation) err = kick_rx(ifobject->xsk); 1415*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1416*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1417*d1aec26fSBastien Curutchet (eBPF Foundation) 1418*d1aec26fSBastien Curutchet (eBPF Foundation) err = get_xsk_stats(xsk, &stats); 1419*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1420*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1421*d1aec26fSBastien Curutchet (eBPF Foundation) 1422*d1aec26fSBastien Curutchet (eBPF Foundation) if (stats.rx_ring_full) 1423*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1424*d1aec26fSBastien Curutchet (eBPF Foundation) 1425*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1426*d1aec26fSBastien Curutchet (eBPF Foundation) } 1427*d1aec26fSBastien Curutchet (eBPF Foundation) 1428*d1aec26fSBastien Curutchet (eBPF Foundation) static int validate_fill_empty(struct ifobject *ifobject) 1429*d1aec26fSBastien Curutchet (eBPF Foundation) { 1430*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket *xsk = ifobject->xsk->xsk; 1431*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_statistics stats; 1432*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1433*d1aec26fSBastien Curutchet (eBPF Foundation) 1434*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(1000); 1435*d1aec26fSBastien Curutchet (eBPF Foundation) err = kick_rx(ifobject->xsk); 1436*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1437*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1438*d1aec26fSBastien Curutchet (eBPF Foundation) 1439*d1aec26fSBastien Curutchet (eBPF Foundation) err = get_xsk_stats(xsk, &stats); 1440*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1441*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1442*d1aec26fSBastien Curutchet (eBPF Foundation) 1443*d1aec26fSBastien Curutchet (eBPF Foundation) if (stats.rx_fill_ring_empty_descs) 1444*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1445*d1aec26fSBastien Curutchet (eBPF Foundation) 1446*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1447*d1aec26fSBastien Curutchet (eBPF Foundation) } 1448*d1aec26fSBastien Curutchet (eBPF Foundation) 1449*d1aec26fSBastien Curutchet (eBPF Foundation) static int validate_tx_invalid_descs(struct ifobject *ifobject) 1450*d1aec26fSBastien Curutchet (eBPF Foundation) { 1451*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_socket *xsk = ifobject->xsk->xsk; 1452*d1aec26fSBastien Curutchet (eBPF Foundation) int fd = xsk_socket__fd(xsk); 1453*d1aec26fSBastien Curutchet (eBPF Foundation) struct xdp_statistics stats; 1454*d1aec26fSBastien Curutchet (eBPF Foundation) socklen_t optlen; 1455*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1456*d1aec26fSBastien Curutchet (eBPF Foundation) 1457*d1aec26fSBastien Curutchet (eBPF Foundation) optlen = sizeof(stats); 1458*d1aec26fSBastien Curutchet (eBPF Foundation) err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen); 1459*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1460*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n", 1461*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, -err, strerror(-err)); 1462*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1463*d1aec26fSBastien Curutchet (eBPF Foundation) } 1464*d1aec26fSBastien Curutchet (eBPF Foundation) 1465*d1aec26fSBastien Curutchet (eBPF Foundation) if (stats.tx_invalid_descs != ifobject->xsk->pkt_stream->nb_pkts / 2) { 1466*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("[%s] tx_invalid_descs incorrect. Got [%llu] expected [%u]\n", 1467*d1aec26fSBastien Curutchet (eBPF Foundation) __func__, 1468*d1aec26fSBastien Curutchet (eBPF Foundation) (unsigned long long)stats.tx_invalid_descs, 1469*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->xsk->pkt_stream->nb_pkts); 1470*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1471*d1aec26fSBastien Curutchet (eBPF Foundation) } 1472*d1aec26fSBastien Curutchet (eBPF Foundation) 1473*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1474*d1aec26fSBastien Curutchet (eBPF Foundation) } 1475*d1aec26fSBastien Curutchet (eBPF Foundation) 1476*d1aec26fSBastien Curutchet (eBPF Foundation) static int xsk_configure(struct test_spec *test, struct ifobject *ifobject, 1477*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_info *umem, bool tx) 1478*d1aec26fSBastien Curutchet (eBPF Foundation) { 1479*d1aec26fSBastien Curutchet (eBPF Foundation) int i, ret; 1480*d1aec26fSBastien Curutchet (eBPF Foundation) 1481*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) { 1482*d1aec26fSBastien Curutchet (eBPF Foundation) bool shared = (ifobject->shared_umem && tx) ? true : !!i; 1483*d1aec26fSBastien Curutchet (eBPF Foundation) u32 ctr = 0; 1484*d1aec26fSBastien Curutchet (eBPF Foundation) 1485*d1aec26fSBastien Curutchet (eBPF Foundation) while (ctr++ < SOCK_RECONF_CTR) { 1486*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_configure_socket(&ifobject->xsk_arr[i], umem, 1487*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject, shared); 1488*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ret) 1489*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1490*d1aec26fSBastien Curutchet (eBPF Foundation) 1491*d1aec26fSBastien Curutchet (eBPF Foundation) /* Retry if it fails as xsk_socket__create() is asynchronous */ 1492*d1aec26fSBastien Curutchet (eBPF Foundation) if (ctr >= SOCK_RECONF_CTR) 1493*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1494*d1aec26fSBastien Curutchet (eBPF Foundation) usleep(USLEEP_MAX); 1495*d1aec26fSBastien Curutchet (eBPF Foundation) } 1496*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobject->busy_poll) { 1497*d1aec26fSBastien Curutchet (eBPF Foundation) ret = enable_busy_poll(&ifobject->xsk_arr[i]); 1498*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1499*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1500*d1aec26fSBastien Curutchet (eBPF Foundation) } 1501*d1aec26fSBastien Curutchet (eBPF Foundation) } 1502*d1aec26fSBastien Curutchet (eBPF Foundation) 1503*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1504*d1aec26fSBastien Curutchet (eBPF Foundation) } 1505*d1aec26fSBastien Curutchet (eBPF Foundation) 1506*d1aec26fSBastien Curutchet (eBPF Foundation) static int thread_common_ops_tx(struct test_spec *test, struct ifobject *ifobject) 1507*d1aec26fSBastien Curutchet (eBPF Foundation) { 1508*d1aec26fSBastien Curutchet (eBPF Foundation) int ret = xsk_configure(test, ifobject, test->ifobj_rx->umem, true); 1509*d1aec26fSBastien Curutchet (eBPF Foundation) 1510*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1511*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1512*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->xsk = &ifobject->xsk_arr[0]; 1513*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->xskmap = test->ifobj_rx->xskmap; 1514*d1aec26fSBastien Curutchet (eBPF Foundation) memcpy(ifobject->umem, test->ifobj_rx->umem, sizeof(struct xsk_umem_info)); 1515*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->umem->base_addr = 0; 1516*d1aec26fSBastien Curutchet (eBPF Foundation) 1517*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1518*d1aec26fSBastien Curutchet (eBPF Foundation) } 1519*d1aec26fSBastien Curutchet (eBPF Foundation) 1520*d1aec26fSBastien Curutchet (eBPF Foundation) static int xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_stream *pkt_stream, 1521*d1aec26fSBastien Curutchet (eBPF Foundation) bool fill_up) 1522*d1aec26fSBastien Curutchet (eBPF Foundation) { 1523*d1aec26fSBastien Curutchet (eBPF Foundation) u32 rx_frame_size = umem->frame_size - XDP_PACKET_HEADROOM; 1524*d1aec26fSBastien Curutchet (eBPF Foundation) u32 idx = 0, filled = 0, buffers_to_fill, nb_pkts; 1525*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 1526*d1aec26fSBastien Curutchet (eBPF Foundation) 1527*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->num_frames < XSK_RING_PROD__DEFAULT_NUM_DESCS) 1528*d1aec26fSBastien Curutchet (eBPF Foundation) buffers_to_fill = umem->num_frames; 1529*d1aec26fSBastien Curutchet (eBPF Foundation) else 1530*d1aec26fSBastien Curutchet (eBPF Foundation) buffers_to_fill = umem->fill_size; 1531*d1aec26fSBastien Curutchet (eBPF Foundation) 1532*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_ring_prod__reserve(&umem->fq, buffers_to_fill, &idx); 1533*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret != buffers_to_fill) 1534*d1aec26fSBastien Curutchet (eBPF Foundation) return -ENOSPC; 1535*d1aec26fSBastien Curutchet (eBPF Foundation) 1536*d1aec26fSBastien Curutchet (eBPF Foundation) while (filled < buffers_to_fill) { 1537*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &nb_pkts); 1538*d1aec26fSBastien Curutchet (eBPF Foundation) u64 addr; 1539*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 1540*d1aec26fSBastien Curutchet (eBPF Foundation) 1541*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < pkt_nb_frags(rx_frame_size, pkt_stream, pkt); i++) { 1542*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkt) { 1543*d1aec26fSBastien Curutchet (eBPF Foundation) if (!fill_up) 1544*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1545*d1aec26fSBastien Curutchet (eBPF Foundation) addr = filled * umem->frame_size + umem->base_addr; 1546*d1aec26fSBastien Curutchet (eBPF Foundation) } else if (pkt->offset >= 0) { 1547*d1aec26fSBastien Curutchet (eBPF Foundation) addr = pkt->offset % umem->frame_size + umem_alloc_buffer(umem); 1548*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1549*d1aec26fSBastien Curutchet (eBPF Foundation) addr = pkt->offset + umem_alloc_buffer(umem); 1550*d1aec26fSBastien Curutchet (eBPF Foundation) } 1551*d1aec26fSBastien Curutchet (eBPF Foundation) 1552*d1aec26fSBastien Curutchet (eBPF Foundation) *xsk_ring_prod__fill_addr(&umem->fq, idx++) = addr; 1553*d1aec26fSBastien Curutchet (eBPF Foundation) if (++filled >= buffers_to_fill) 1554*d1aec26fSBastien Curutchet (eBPF Foundation) break; 1555*d1aec26fSBastien Curutchet (eBPF Foundation) } 1556*d1aec26fSBastien Curutchet (eBPF Foundation) } 1557*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__submit(&umem->fq, filled); 1558*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_ring_prod__cancel(&umem->fq, buffers_to_fill - filled); 1559*d1aec26fSBastien Curutchet (eBPF Foundation) 1560*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_reset(pkt_stream); 1561*d1aec26fSBastien Curutchet (eBPF Foundation) umem_reset_alloc(umem); 1562*d1aec26fSBastien Curutchet (eBPF Foundation) 1563*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1564*d1aec26fSBastien Curutchet (eBPF Foundation) } 1565*d1aec26fSBastien Curutchet (eBPF Foundation) 1566*d1aec26fSBastien Curutchet (eBPF Foundation) static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject) 1567*d1aec26fSBastien Curutchet (eBPF Foundation) { 1568*d1aec26fSBastien Curutchet (eBPF Foundation) LIBBPF_OPTS(bpf_xdp_query_opts, opts); 1569*d1aec26fSBastien Curutchet (eBPF Foundation) int mmap_flags; 1570*d1aec26fSBastien Curutchet (eBPF Foundation) u64 umem_sz; 1571*d1aec26fSBastien Curutchet (eBPF Foundation) void *bufs; 1572*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 1573*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 1574*d1aec26fSBastien Curutchet (eBPF Foundation) 1575*d1aec26fSBastien Curutchet (eBPF Foundation) umem_sz = ifobject->umem->num_frames * ifobject->umem->frame_size; 1576*d1aec26fSBastien Curutchet (eBPF Foundation) mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; 1577*d1aec26fSBastien Curutchet (eBPF Foundation) 1578*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobject->umem->unaligned_mode) 1579*d1aec26fSBastien Curutchet (eBPF Foundation) mmap_flags |= MAP_HUGETLB | MAP_HUGE_2MB; 1580*d1aec26fSBastien Curutchet (eBPF Foundation) 1581*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobject->shared_umem) 1582*d1aec26fSBastien Curutchet (eBPF Foundation) umem_sz *= 2; 1583*d1aec26fSBastien Curutchet (eBPF Foundation) 1584*d1aec26fSBastien Curutchet (eBPF Foundation) bufs = mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); 1585*d1aec26fSBastien Curutchet (eBPF Foundation) if (bufs == MAP_FAILED) 1586*d1aec26fSBastien Curutchet (eBPF Foundation) return -errno; 1587*d1aec26fSBastien Curutchet (eBPF Foundation) 1588*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_configure_umem(ifobject, ifobject->umem, bufs, umem_sz); 1589*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1590*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1591*d1aec26fSBastien Curutchet (eBPF Foundation) 1592*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_configure(test, ifobject, ifobject->umem, false); 1593*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1594*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1595*d1aec26fSBastien Curutchet (eBPF Foundation) 1596*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->xsk = &ifobject->xsk_arr[0]; 1597*d1aec26fSBastien Curutchet (eBPF Foundation) 1598*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobject->rx_on) 1599*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1600*d1aec26fSBastien Curutchet (eBPF Foundation) 1601*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_populate_fill_ring(ifobject->umem, ifobject->xsk->pkt_stream, 1602*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->use_fill_ring); 1603*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1604*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1605*d1aec26fSBastien Curutchet (eBPF Foundation) 1606*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) { 1607*d1aec26fSBastien Curutchet (eBPF Foundation) ifobject->xsk = &ifobject->xsk_arr[i]; 1608*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, i); 1609*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1610*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 1611*d1aec26fSBastien Curutchet (eBPF Foundation) } 1612*d1aec26fSBastien Curutchet (eBPF Foundation) 1613*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1614*d1aec26fSBastien Curutchet (eBPF Foundation) } 1615*d1aec26fSBastien Curutchet (eBPF Foundation) 1616*d1aec26fSBastien Curutchet (eBPF Foundation) void *worker_testapp_validate_tx(void *arg) 1617*d1aec26fSBastien Curutchet (eBPF Foundation) { 1618*d1aec26fSBastien Curutchet (eBPF Foundation) struct test_spec *test = (struct test_spec *)arg; 1619*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobject = test->ifobj_tx; 1620*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1621*d1aec26fSBastien Curutchet (eBPF Foundation) 1622*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->current_step == 1) { 1623*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobject->shared_umem) { 1624*d1aec26fSBastien Curutchet (eBPF Foundation) if (thread_common_ops(test, ifobject)) { 1625*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1626*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1627*d1aec26fSBastien Curutchet (eBPF Foundation) } 1628*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1629*d1aec26fSBastien Curutchet (eBPF Foundation) if (thread_common_ops_tx(test, ifobject)) { 1630*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1631*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1632*d1aec26fSBastien Curutchet (eBPF Foundation) } 1633*d1aec26fSBastien Curutchet (eBPF Foundation) } 1634*d1aec26fSBastien Curutchet (eBPF Foundation) } 1635*d1aec26fSBastien Curutchet (eBPF Foundation) 1636*d1aec26fSBastien Curutchet (eBPF Foundation) err = send_pkts(test, ifobject); 1637*d1aec26fSBastien Curutchet (eBPF Foundation) 1638*d1aec26fSBastien Curutchet (eBPF Foundation) if (!err && ifobject->validation_func) 1639*d1aec26fSBastien Curutchet (eBPF Foundation) err = ifobject->validation_func(ifobject); 1640*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1641*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1642*d1aec26fSBastien Curutchet (eBPF Foundation) 1643*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1644*d1aec26fSBastien Curutchet (eBPF Foundation) } 1645*d1aec26fSBastien Curutchet (eBPF Foundation) 1646*d1aec26fSBastien Curutchet (eBPF Foundation) void *worker_testapp_validate_rx(void *arg) 1647*d1aec26fSBastien Curutchet (eBPF Foundation) { 1648*d1aec26fSBastien Curutchet (eBPF Foundation) struct test_spec *test = (struct test_spec *)arg; 1649*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobject = test->ifobj_rx; 1650*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1651*d1aec26fSBastien Curutchet (eBPF Foundation) 1652*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->current_step == 1) { 1653*d1aec26fSBastien Curutchet (eBPF Foundation) err = thread_common_ops(test, ifobject); 1654*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1655*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_clear_xskmap(ifobject->xskmap); 1656*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, 0); 1657*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1658*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error: Failed to update xskmap, error %s\n", 1659*d1aec26fSBastien Curutchet (eBPF Foundation) strerror(-err)); 1660*d1aec26fSBastien Curutchet (eBPF Foundation) } 1661*d1aec26fSBastien Curutchet (eBPF Foundation) 1662*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_barrier_wait(&barr); 1663*d1aec26fSBastien Curutchet (eBPF Foundation) 1664*d1aec26fSBastien Curutchet (eBPF Foundation) /* We leave only now in case of error to avoid getting stuck in the barrier */ 1665*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1666*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1667*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1668*d1aec26fSBastien Curutchet (eBPF Foundation) } 1669*d1aec26fSBastien Curutchet (eBPF Foundation) 1670*d1aec26fSBastien Curutchet (eBPF Foundation) err = receive_pkts(test); 1671*d1aec26fSBastien Curutchet (eBPF Foundation) 1672*d1aec26fSBastien Curutchet (eBPF Foundation) if (!err && ifobject->validation_func) 1673*d1aec26fSBastien Curutchet (eBPF Foundation) err = ifobject->validation_func(ifobject); 1674*d1aec26fSBastien Curutchet (eBPF Foundation) 1675*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1676*d1aec26fSBastien Curutchet (eBPF Foundation) if (!test->adjust_tail) { 1677*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1678*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1679*d1aec26fSBastien Curutchet (eBPF Foundation) bool supported; 1680*d1aec26fSBastien Curutchet (eBPF Foundation) 1681*d1aec26fSBastien Curutchet (eBPF Foundation) if (is_adjust_tail_supported(ifobject->xdp_progs, &supported)) 1682*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1683*d1aec26fSBastien Curutchet (eBPF Foundation) else if (!supported) 1684*d1aec26fSBastien Curutchet (eBPF Foundation) test->adjust_tail_support = false; 1685*d1aec26fSBastien Curutchet (eBPF Foundation) else 1686*d1aec26fSBastien Curutchet (eBPF Foundation) test->fail = true; 1687*d1aec26fSBastien Curutchet (eBPF Foundation) } 1688*d1aec26fSBastien Curutchet (eBPF Foundation) } 1689*d1aec26fSBastien Curutchet (eBPF Foundation) 1690*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1691*d1aec26fSBastien Curutchet (eBPF Foundation) } 1692*d1aec26fSBastien Curutchet (eBPF Foundation) 1693*d1aec26fSBastien Curutchet (eBPF Foundation) static void testapp_clean_xsk_umem(struct ifobject *ifobj) 1694*d1aec26fSBastien Curutchet (eBPF Foundation) { 1695*d1aec26fSBastien Curutchet (eBPF Foundation) u64 umem_sz = ifobj->umem->num_frames * ifobj->umem->frame_size; 1696*d1aec26fSBastien Curutchet (eBPF Foundation) 1697*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->shared_umem) 1698*d1aec26fSBastien Curutchet (eBPF Foundation) umem_sz *= 2; 1699*d1aec26fSBastien Curutchet (eBPF Foundation) 1700*d1aec26fSBastien Curutchet (eBPF Foundation) umem_sz = ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE; 1701*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_umem__delete(ifobj->umem->umem); 1702*d1aec26fSBastien Curutchet (eBPF Foundation) munmap(ifobj->umem->buffer, umem_sz); 1703*d1aec26fSBastien Curutchet (eBPF Foundation) } 1704*d1aec26fSBastien Curutchet (eBPF Foundation) 1705*d1aec26fSBastien Curutchet (eBPF Foundation) static void handler(int signum) 1706*d1aec26fSBastien Curutchet (eBPF Foundation) { 1707*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_exit(NULL); 1708*d1aec26fSBastien Curutchet (eBPF Foundation) } 1709*d1aec26fSBastien Curutchet (eBPF Foundation) 1710*d1aec26fSBastien Curutchet (eBPF Foundation) static bool xdp_prog_changed_rx(struct test_spec *test) 1711*d1aec26fSBastien Curutchet (eBPF Foundation) { 1712*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj = test->ifobj_rx; 1713*d1aec26fSBastien Curutchet (eBPF Foundation) 1714*d1aec26fSBastien Curutchet (eBPF Foundation) return ifobj->xdp_prog != test->xdp_prog_rx || ifobj->mode != test->mode; 1715*d1aec26fSBastien Curutchet (eBPF Foundation) } 1716*d1aec26fSBastien Curutchet (eBPF Foundation) 1717*d1aec26fSBastien Curutchet (eBPF Foundation) static bool xdp_prog_changed_tx(struct test_spec *test) 1718*d1aec26fSBastien Curutchet (eBPF Foundation) { 1719*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj = test->ifobj_tx; 1720*d1aec26fSBastien Curutchet (eBPF Foundation) 1721*d1aec26fSBastien Curutchet (eBPF Foundation) return ifobj->xdp_prog != test->xdp_prog_tx || ifobj->mode != test->mode; 1722*d1aec26fSBastien Curutchet (eBPF Foundation) } 1723*d1aec26fSBastien Curutchet (eBPF Foundation) 1724*d1aec26fSBastien Curutchet (eBPF Foundation) static int xsk_reattach_xdp(struct ifobject *ifobj, struct bpf_program *xdp_prog, 1725*d1aec26fSBastien Curutchet (eBPF Foundation) struct bpf_map *xskmap, enum test_mode mode) 1726*d1aec26fSBastien Curutchet (eBPF Foundation) { 1727*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1728*d1aec26fSBastien Curutchet (eBPF Foundation) 1729*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_detach_xdp_program(ifobj->ifindex, mode_to_xdp_flags(ifobj->mode)); 1730*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_attach_xdp_program(xdp_prog, ifobj->ifindex, mode_to_xdp_flags(mode)); 1731*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1732*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error attaching XDP program\n"); 1733*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 1734*d1aec26fSBastien Curutchet (eBPF Foundation) } 1735*d1aec26fSBastien Curutchet (eBPF Foundation) 1736*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj->mode != mode && (mode == TEST_MODE_DRV || mode == TEST_MODE_ZC)) 1737*d1aec26fSBastien Curutchet (eBPF Foundation) if (!xsk_is_in_mode(ifobj->ifindex, XDP_FLAGS_DRV_MODE)) { 1738*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("ERROR: XDP prog not in DRV mode\n"); 1739*d1aec26fSBastien Curutchet (eBPF Foundation) return -EINVAL; 1740*d1aec26fSBastien Curutchet (eBPF Foundation) } 1741*d1aec26fSBastien Curutchet (eBPF Foundation) 1742*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xdp_prog = xdp_prog; 1743*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xskmap = xskmap; 1744*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->mode = mode; 1745*d1aec26fSBastien Curutchet (eBPF Foundation) 1746*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1747*d1aec26fSBastien Curutchet (eBPF Foundation) } 1748*d1aec26fSBastien Curutchet (eBPF Foundation) 1749*d1aec26fSBastien Curutchet (eBPF Foundation) static int xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_rx, 1750*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj_tx) 1751*d1aec26fSBastien Curutchet (eBPF Foundation) { 1752*d1aec26fSBastien Curutchet (eBPF Foundation) int err = 0; 1753*d1aec26fSBastien Curutchet (eBPF Foundation) 1754*d1aec26fSBastien Curutchet (eBPF Foundation) if (xdp_prog_changed_rx(test)) { 1755*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_reattach_xdp(ifobj_rx, test->xdp_prog_rx, test->xskmap_rx, test->mode); 1756*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) 1757*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 1758*d1aec26fSBastien Curutchet (eBPF Foundation) } 1759*d1aec26fSBastien Curutchet (eBPF Foundation) 1760*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj_tx || ifobj_tx->shared_umem) 1761*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 1762*d1aec26fSBastien Curutchet (eBPF Foundation) 1763*d1aec26fSBastien Curutchet (eBPF Foundation) if (xdp_prog_changed_tx(test)) 1764*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode); 1765*d1aec26fSBastien Curutchet (eBPF Foundation) 1766*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 1767*d1aec26fSBastien Curutchet (eBPF Foundation) } 1768*d1aec26fSBastien Curutchet (eBPF Foundation) 1769*d1aec26fSBastien Curutchet (eBPF Foundation) static void clean_sockets(struct test_spec *test, struct ifobject *ifobj) 1770*d1aec26fSBastien Curutchet (eBPF Foundation) { 1771*d1aec26fSBastien Curutchet (eBPF Foundation) u32 i; 1772*d1aec26fSBastien Curutchet (eBPF Foundation) 1773*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj || !test) 1774*d1aec26fSBastien Curutchet (eBPF Foundation) return; 1775*d1aec26fSBastien Curutchet (eBPF Foundation) 1776*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < test->nb_sockets; i++) 1777*d1aec26fSBastien Curutchet (eBPF Foundation) xsk_socket__delete(ifobj->xsk_arr[i].xsk); 1778*d1aec26fSBastien Curutchet (eBPF Foundation) } 1779*d1aec26fSBastien Curutchet (eBPF Foundation) 1780*d1aec26fSBastien Curutchet (eBPF Foundation) static void clean_umem(struct test_spec *test, struct ifobject *ifobj1, struct ifobject *ifobj2) 1781*d1aec26fSBastien Curutchet (eBPF Foundation) { 1782*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj1) 1783*d1aec26fSBastien Curutchet (eBPF Foundation) return; 1784*d1aec26fSBastien Curutchet (eBPF Foundation) 1785*d1aec26fSBastien Curutchet (eBPF Foundation) testapp_clean_xsk_umem(ifobj1); 1786*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj2 && !ifobj2->shared_umem) 1787*d1aec26fSBastien Curutchet (eBPF Foundation) testapp_clean_xsk_umem(ifobj2); 1788*d1aec26fSBastien Curutchet (eBPF Foundation) } 1789*d1aec26fSBastien Curutchet (eBPF Foundation) 1790*d1aec26fSBastien Curutchet (eBPF Foundation) static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1, 1791*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj2) 1792*d1aec26fSBastien Curutchet (eBPF Foundation) { 1793*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_t t0, t1; 1794*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 1795*d1aec26fSBastien Curutchet (eBPF Foundation) 1796*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mtu > MAX_ETH_PKT_SIZE) { 1797*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mode == TEST_MODE_ZC && (!ifobj1->multi_buff_zc_supp || 1798*d1aec26fSBastien Curutchet (eBPF Foundation) (ifobj2 && !ifobj2->multi_buff_zc_supp))) { 1799*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Multi buffer for zero-copy not supported.\n"); 1800*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 1801*d1aec26fSBastien Curutchet (eBPF Foundation) } 1802*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mode != TEST_MODE_ZC && (!ifobj1->multi_buff_supp || 1803*d1aec26fSBastien Curutchet (eBPF Foundation) (ifobj2 && !ifobj2->multi_buff_supp))) { 1804*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Multi buffer not supported.\n"); 1805*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 1806*d1aec26fSBastien Curutchet (eBPF Foundation) } 1807*d1aec26fSBastien Curutchet (eBPF Foundation) } 1808*d1aec26fSBastien Curutchet (eBPF Foundation) err = test_spec_set_mtu(test, test->mtu); 1809*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 1810*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error, could not set mtu.\n"); 1811*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1812*d1aec26fSBastien Curutchet (eBPF Foundation) } 1813*d1aec26fSBastien Curutchet (eBPF Foundation) 1814*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj2) { 1815*d1aec26fSBastien Curutchet (eBPF Foundation) if (pthread_barrier_init(&barr, NULL, 2)) 1816*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1817*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_reset(ifobj2->xsk->pkt_stream); 1818*d1aec26fSBastien Curutchet (eBPF Foundation) } 1819*d1aec26fSBastien Curutchet (eBPF Foundation) 1820*d1aec26fSBastien Curutchet (eBPF Foundation) test->current_step++; 1821*d1aec26fSBastien Curutchet (eBPF Foundation) pkt_stream_reset(ifobj1->xsk->pkt_stream); 1822*d1aec26fSBastien Curutchet (eBPF Foundation) pkts_in_flight = 0; 1823*d1aec26fSBastien Curutchet (eBPF Foundation) 1824*d1aec26fSBastien Curutchet (eBPF Foundation) signal(SIGUSR1, handler); 1825*d1aec26fSBastien Curutchet (eBPF Foundation) /*Spawn RX thread */ 1826*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_create(&t0, NULL, ifobj1->func_ptr, test); 1827*d1aec26fSBastien Curutchet (eBPF Foundation) 1828*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj2) { 1829*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_barrier_wait(&barr); 1830*d1aec26fSBastien Curutchet (eBPF Foundation) if (pthread_barrier_destroy(&barr)) { 1831*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_kill(t0, SIGUSR1); 1832*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, ifobj1); 1833*d1aec26fSBastien Curutchet (eBPF Foundation) clean_umem(test, ifobj1, NULL); 1834*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1835*d1aec26fSBastien Curutchet (eBPF Foundation) } 1836*d1aec26fSBastien Curutchet (eBPF Foundation) 1837*d1aec26fSBastien Curutchet (eBPF Foundation) /*Spawn TX thread */ 1838*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_create(&t1, NULL, ifobj2->func_ptr, test); 1839*d1aec26fSBastien Curutchet (eBPF Foundation) 1840*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_join(t1, NULL); 1841*d1aec26fSBastien Curutchet (eBPF Foundation) } 1842*d1aec26fSBastien Curutchet (eBPF Foundation) 1843*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj2) 1844*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_kill(t0, SIGUSR1); 1845*d1aec26fSBastien Curutchet (eBPF Foundation) else 1846*d1aec26fSBastien Curutchet (eBPF Foundation) pthread_join(t0, NULL); 1847*d1aec26fSBastien Curutchet (eBPF Foundation) 1848*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->total_steps == test->current_step || test->fail) { 1849*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, ifobj1); 1850*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, ifobj2); 1851*d1aec26fSBastien Curutchet (eBPF Foundation) clean_umem(test, ifobj1, ifobj2); 1852*d1aec26fSBastien Curutchet (eBPF Foundation) } 1853*d1aec26fSBastien Curutchet (eBPF Foundation) 1854*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->fail) 1855*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1856*d1aec26fSBastien Curutchet (eBPF Foundation) 1857*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1858*d1aec26fSBastien Curutchet (eBPF Foundation) } 1859*d1aec26fSBastien Curutchet (eBPF Foundation) 1860*d1aec26fSBastien Curutchet (eBPF Foundation) static int testapp_validate_traffic(struct test_spec *test) 1861*d1aec26fSBastien Curutchet (eBPF Foundation) { 1862*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj_rx = test->ifobj_rx; 1863*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj_tx = test->ifobj_tx; 1864*d1aec26fSBastien Curutchet (eBPF Foundation) 1865*d1aec26fSBastien Curutchet (eBPF Foundation) if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp) || 1866*d1aec26fSBastien Curutchet (eBPF Foundation) (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) { 1867*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("No huge pages present.\n"); 1868*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 1869*d1aec26fSBastien Curutchet (eBPF Foundation) } 1870*d1aec26fSBastien Curutchet (eBPF Foundation) 1871*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->set_ring) { 1872*d1aec26fSBastien Curutchet (eBPF Foundation) if (ifobj_tx->hw_ring_size_supp) { 1873*d1aec26fSBastien Curutchet (eBPF Foundation) if (set_ring_size(ifobj_tx)) { 1874*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Failed to change HW ring size.\n"); 1875*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1876*d1aec26fSBastien Curutchet (eBPF Foundation) } 1877*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 1878*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Changing HW ring size not supported.\n"); 1879*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 1880*d1aec26fSBastien Curutchet (eBPF Foundation) } 1881*d1aec26fSBastien Curutchet (eBPF Foundation) } 1882*d1aec26fSBastien Curutchet (eBPF Foundation) 1883*d1aec26fSBastien Curutchet (eBPF Foundation) if (xsk_attach_xdp_progs(test, ifobj_rx, ifobj_tx)) 1884*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1885*d1aec26fSBastien Curutchet (eBPF Foundation) return __testapp_validate_traffic(test, ifobj_rx, ifobj_tx); 1886*d1aec26fSBastien Curutchet (eBPF Foundation) } 1887*d1aec26fSBastien Curutchet (eBPF Foundation) 1888*d1aec26fSBastien Curutchet (eBPF Foundation) static int testapp_validate_traffic_single_thread(struct test_spec *test, struct ifobject *ifobj) 1889*d1aec26fSBastien Curutchet (eBPF Foundation) { 1890*d1aec26fSBastien Curutchet (eBPF Foundation) return __testapp_validate_traffic(test, ifobj, NULL); 1891*d1aec26fSBastien Curutchet (eBPF Foundation) } 1892*d1aec26fSBastien Curutchet (eBPF Foundation) 1893*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_teardown(struct test_spec *test) 1894*d1aec26fSBastien Curutchet (eBPF Foundation) { 1895*d1aec26fSBastien Curutchet (eBPF Foundation) int i; 1896*d1aec26fSBastien Curutchet (eBPF Foundation) 1897*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 0; i < MAX_TEARDOWN_ITER; i++) { 1898*d1aec26fSBastien Curutchet (eBPF Foundation) if (testapp_validate_traffic(test)) 1899*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1900*d1aec26fSBastien Curutchet (eBPF Foundation) test_spec_reset(test); 1901*d1aec26fSBastien Curutchet (eBPF Foundation) } 1902*d1aec26fSBastien Curutchet (eBPF Foundation) 1903*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1904*d1aec26fSBastien Curutchet (eBPF Foundation) } 1905*d1aec26fSBastien Curutchet (eBPF Foundation) 1906*d1aec26fSBastien Curutchet (eBPF Foundation) static void swap_directions(struct ifobject **ifobj1, struct ifobject **ifobj2) 1907*d1aec26fSBastien Curutchet (eBPF Foundation) { 1908*d1aec26fSBastien Curutchet (eBPF Foundation) thread_func_t tmp_func_ptr = (*ifobj1)->func_ptr; 1909*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *tmp_ifobj = (*ifobj1); 1910*d1aec26fSBastien Curutchet (eBPF Foundation) 1911*d1aec26fSBastien Curutchet (eBPF Foundation) (*ifobj1)->func_ptr = (*ifobj2)->func_ptr; 1912*d1aec26fSBastien Curutchet (eBPF Foundation) (*ifobj2)->func_ptr = tmp_func_ptr; 1913*d1aec26fSBastien Curutchet (eBPF Foundation) 1914*d1aec26fSBastien Curutchet (eBPF Foundation) *ifobj1 = *ifobj2; 1915*d1aec26fSBastien Curutchet (eBPF Foundation) *ifobj2 = tmp_ifobj; 1916*d1aec26fSBastien Curutchet (eBPF Foundation) } 1917*d1aec26fSBastien Curutchet (eBPF Foundation) 1918*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_bidirectional(struct test_spec *test) 1919*d1aec26fSBastien Curutchet (eBPF Foundation) { 1920*d1aec26fSBastien Curutchet (eBPF Foundation) int res; 1921*d1aec26fSBastien Curutchet (eBPF Foundation) 1922*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->rx_on = true; 1923*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->tx_on = true; 1924*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 2; 1925*d1aec26fSBastien Curutchet (eBPF Foundation) if (testapp_validate_traffic(test)) 1926*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1927*d1aec26fSBastien Curutchet (eBPF Foundation) 1928*d1aec26fSBastien Curutchet (eBPF Foundation) print_verbose("Switching Tx/Rx direction\n"); 1929*d1aec26fSBastien Curutchet (eBPF Foundation) swap_directions(&test->ifobj_rx, &test->ifobj_tx); 1930*d1aec26fSBastien Curutchet (eBPF Foundation) res = __testapp_validate_traffic(test, test->ifobj_rx, test->ifobj_tx); 1931*d1aec26fSBastien Curutchet (eBPF Foundation) 1932*d1aec26fSBastien Curutchet (eBPF Foundation) swap_directions(&test->ifobj_rx, &test->ifobj_tx); 1933*d1aec26fSBastien Curutchet (eBPF Foundation) return res; 1934*d1aec26fSBastien Curutchet (eBPF Foundation) } 1935*d1aec26fSBastien Curutchet (eBPF Foundation) 1936*d1aec26fSBastien Curutchet (eBPF Foundation) static int swap_xsk_resources(struct test_spec *test) 1937*d1aec26fSBastien Curutchet (eBPF Foundation) { 1938*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 1939*d1aec26fSBastien Curutchet (eBPF Foundation) 1940*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk_arr[0].pkt_stream = NULL; 1941*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk_arr[0].pkt_stream = NULL; 1942*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk_arr[1].pkt_stream = test->tx_pkt_stream_default; 1943*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk_arr[1].pkt_stream = test->rx_pkt_stream_default; 1944*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk = &test->ifobj_tx->xsk_arr[1]; 1945*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk = &test->ifobj_rx->xsk_arr[1]; 1946*d1aec26fSBastien Curutchet (eBPF Foundation) 1947*d1aec26fSBastien Curutchet (eBPF Foundation) ret = xsk_update_xskmap(test->ifobj_rx->xskmap, test->ifobj_rx->xsk->xsk, 0); 1948*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 1949*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1950*d1aec26fSBastien Curutchet (eBPF Foundation) 1951*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_PASS; 1952*d1aec26fSBastien Curutchet (eBPF Foundation) } 1953*d1aec26fSBastien Curutchet (eBPF Foundation) 1954*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_prog_cleanup(struct test_spec *test) 1955*d1aec26fSBastien Curutchet (eBPF Foundation) { 1956*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 2; 1957*d1aec26fSBastien Curutchet (eBPF Foundation) test->nb_sockets = 2; 1958*d1aec26fSBastien Curutchet (eBPF Foundation) if (testapp_validate_traffic(test)) 1959*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1960*d1aec26fSBastien Curutchet (eBPF Foundation) 1961*d1aec26fSBastien Curutchet (eBPF Foundation) if (swap_xsk_resources(test)) { 1962*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, test->ifobj_rx); 1963*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, test->ifobj_tx); 1964*d1aec26fSBastien Curutchet (eBPF Foundation) clean_umem(test, test->ifobj_rx, test->ifobj_tx); 1965*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1966*d1aec26fSBastien Curutchet (eBPF Foundation) } 1967*d1aec26fSBastien Curutchet (eBPF Foundation) 1968*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 1969*d1aec26fSBastien Curutchet (eBPF Foundation) } 1970*d1aec26fSBastien Curutchet (eBPF Foundation) 1971*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_headroom(struct test_spec *test) 1972*d1aec26fSBastien Curutchet (eBPF Foundation) { 1973*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->frame_headroom = UMEM_HEADROOM_TEST_SIZE; 1974*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 1975*d1aec26fSBastien Curutchet (eBPF Foundation) } 1976*d1aec26fSBastien Curutchet (eBPF Foundation) 1977*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_stats_rx_dropped(struct test_spec *test) 1978*d1aec26fSBastien Curutchet (eBPF Foundation) { 1979*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mode == TEST_MODE_ZC) { 1980*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Can not run RX_DROPPED test for ZC mode\n"); 1981*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 1982*d1aec26fSBastien Curutchet (eBPF Foundation) } 1983*d1aec26fSBastien Curutchet (eBPF Foundation) 1984*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace_half(test, MIN_PKT_SIZE * 4, 0)) 1985*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1986*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->frame_headroom = test->ifobj_rx->umem->frame_size - 1987*d1aec26fSBastien Curutchet (eBPF Foundation) XDP_PACKET_HEADROOM - MIN_PKT_SIZE * 3; 1988*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_receive_half(test)) 1989*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1990*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->validation_func = validate_rx_dropped; 1991*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 1992*d1aec26fSBastien Curutchet (eBPF Foundation) } 1993*d1aec26fSBastien Curutchet (eBPF Foundation) 1994*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_stats_tx_invalid_descs(struct test_spec *test) 1995*d1aec26fSBastien Curutchet (eBPF Foundation) { 1996*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace_half(test, XSK_UMEM__INVALID_FRAME_SIZE, 0)) 1997*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 1998*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->validation_func = validate_tx_invalid_descs; 1999*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2000*d1aec26fSBastien Curutchet (eBPF Foundation) } 2001*d1aec26fSBastien Curutchet (eBPF Foundation) 2002*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_stats_rx_full(struct test_spec *test) 2003*d1aec26fSBastien Curutchet (eBPF Foundation) { 2004*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE)) 2005*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2006*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2007*d1aec26fSBastien Curutchet (eBPF Foundation) 2008*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->rxqsize = DEFAULT_UMEM_BUFFERS; 2009*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->release_rx = false; 2010*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->validation_func = validate_rx_full; 2011*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2012*d1aec26fSBastien Curutchet (eBPF Foundation) } 2013*d1aec26fSBastien Curutchet (eBPF Foundation) 2014*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_stats_fill_empty(struct test_spec *test) 2015*d1aec26fSBastien Curutchet (eBPF Foundation) { 2016*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE)) 2017*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2018*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2019*d1aec26fSBastien Curutchet (eBPF Foundation) 2020*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->use_fill_ring = false; 2021*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->validation_func = validate_fill_empty; 2022*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2023*d1aec26fSBastien Curutchet (eBPF Foundation) } 2024*d1aec26fSBastien Curutchet (eBPF Foundation) 2025*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_send_receive_unaligned(struct test_spec *test) 2026*d1aec26fSBastien Curutchet (eBPF Foundation) { 2027*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->unaligned_mode = true; 2028*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->unaligned_mode = true; 2029*d1aec26fSBastien Curutchet (eBPF Foundation) /* Let half of the packets straddle a 4K buffer boundary */ 2030*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace_half(test, MIN_PKT_SIZE, -MIN_PKT_SIZE / 2)) 2031*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2032*d1aec26fSBastien Curutchet (eBPF Foundation) 2033*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2034*d1aec26fSBastien Curutchet (eBPF Foundation) } 2035*d1aec26fSBastien Curutchet (eBPF Foundation) 2036*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_send_receive_unaligned_mb(struct test_spec *test) 2037*d1aec26fSBastien Curutchet (eBPF Foundation) { 2038*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2039*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->unaligned_mode = true; 2040*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->unaligned_mode = true; 2041*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE)) 2042*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2043*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2044*d1aec26fSBastien Curutchet (eBPF Foundation) } 2045*d1aec26fSBastien Curutchet (eBPF Foundation) 2046*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_single_pkt(struct test_spec *test) 2047*d1aec26fSBastien Curutchet (eBPF Foundation) { 2048*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt pkts[] = {{0, MIN_PKT_SIZE, 0, true}}; 2049*d1aec26fSBastien Curutchet (eBPF Foundation) 2050*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2051*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2052*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2053*d1aec26fSBastien Curutchet (eBPF Foundation) } 2054*d1aec26fSBastien Curutchet (eBPF Foundation) 2055*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_send_receive_mb(struct test_spec *test) 2056*d1aec26fSBastien Curutchet (eBPF Foundation) { 2057*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2058*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE)) 2059*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2060*d1aec26fSBastien Curutchet (eBPF Foundation) 2061*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2062*d1aec26fSBastien Curutchet (eBPF Foundation) } 2063*d1aec26fSBastien Curutchet (eBPF Foundation) 2064*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_invalid_desc_mb(struct test_spec *test) 2065*d1aec26fSBastien Curutchet (eBPF Foundation) { 2066*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_info *umem = test->ifobj_tx->umem; 2067*d1aec26fSBastien Curutchet (eBPF Foundation) u64 umem_size = umem->num_frames * umem->frame_size; 2068*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt pkts[] = { 2069*d1aec26fSBastien Curutchet (eBPF Foundation) /* Valid packet for synch to start with */ 2070*d1aec26fSBastien Curutchet (eBPF Foundation) {0, MIN_PKT_SIZE, 0, true, 0}, 2071*d1aec26fSBastien Curutchet (eBPF Foundation) /* Zero frame len is not legal */ 2072*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2073*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2074*d1aec26fSBastien Curutchet (eBPF Foundation) {0, 0, 0, false, 0}, 2075*d1aec26fSBastien Curutchet (eBPF Foundation) /* Invalid address in the second frame */ 2076*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2077*d1aec26fSBastien Curutchet (eBPF Foundation) {umem_size, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2078*d1aec26fSBastien Curutchet (eBPF Foundation) /* Invalid len in the middle */ 2079*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2080*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2081*d1aec26fSBastien Curutchet (eBPF Foundation) /* Invalid options in the middle */ 2082*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2083*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XSK_DESC__INVALID_OPTION}, 2084*d1aec26fSBastien Curutchet (eBPF Foundation) /* Transmit 2 frags, receive 3 */ 2085*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, XDP_PKT_CONTD}, 2086*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, 0}, 2087*d1aec26fSBastien Curutchet (eBPF Foundation) /* Middle frame crosses chunk boundary with small length */ 2088*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2089*d1aec26fSBastien Curutchet (eBPF Foundation) {-MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false, 0}, 2090*d1aec26fSBastien Curutchet (eBPF Foundation) /* Valid packet for synch so that something is received */ 2091*d1aec26fSBastien Curutchet (eBPF Foundation) {0, MIN_PKT_SIZE, 0, true, 0}}; 2092*d1aec26fSBastien Curutchet (eBPF Foundation) 2093*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->unaligned_mode) { 2094*d1aec26fSBastien Curutchet (eBPF Foundation) /* Crossing a chunk boundary allowed */ 2095*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[12].valid = true; 2096*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[13].valid = true; 2097*d1aec26fSBastien Curutchet (eBPF Foundation) } 2098*d1aec26fSBastien Curutchet (eBPF Foundation) 2099*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2100*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2101*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2102*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2103*d1aec26fSBastien Curutchet (eBPF Foundation) } 2104*d1aec26fSBastien Curutchet (eBPF Foundation) 2105*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_invalid_desc(struct test_spec *test) 2106*d1aec26fSBastien Curutchet (eBPF Foundation) { 2107*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_umem_info *umem = test->ifobj_tx->umem; 2108*d1aec26fSBastien Curutchet (eBPF Foundation) u64 umem_size = umem->num_frames * umem->frame_size; 2109*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt pkts[] = { 2110*d1aec26fSBastien Curutchet (eBPF Foundation) /* Zero packet address allowed */ 2111*d1aec26fSBastien Curutchet (eBPF Foundation) {0, MIN_PKT_SIZE, 0, true}, 2112*d1aec26fSBastien Curutchet (eBPF Foundation) /* Allowed packet */ 2113*d1aec26fSBastien Curutchet (eBPF Foundation) {0, MIN_PKT_SIZE, 0, true}, 2114*d1aec26fSBastien Curutchet (eBPF Foundation) /* Straddling the start of umem */ 2115*d1aec26fSBastien Curutchet (eBPF Foundation) {-2, MIN_PKT_SIZE, 0, false}, 2116*d1aec26fSBastien Curutchet (eBPF Foundation) /* Packet too large */ 2117*d1aec26fSBastien Curutchet (eBPF Foundation) {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false}, 2118*d1aec26fSBastien Curutchet (eBPF Foundation) /* Up to end of umem allowed */ 2119*d1aec26fSBastien Curutchet (eBPF Foundation) {umem_size - MIN_PKT_SIZE - 2 * umem->frame_size, MIN_PKT_SIZE, 0, true}, 2120*d1aec26fSBastien Curutchet (eBPF Foundation) /* After umem ends */ 2121*d1aec26fSBastien Curutchet (eBPF Foundation) {umem_size, MIN_PKT_SIZE, 0, false}, 2122*d1aec26fSBastien Curutchet (eBPF Foundation) /* Straddle the end of umem */ 2123*d1aec26fSBastien Curutchet (eBPF Foundation) {umem_size - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false}, 2124*d1aec26fSBastien Curutchet (eBPF Foundation) /* Straddle a 4K boundary */ 2125*d1aec26fSBastien Curutchet (eBPF Foundation) {0x1000 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false}, 2126*d1aec26fSBastien Curutchet (eBPF Foundation) /* Straddle a 2K boundary */ 2127*d1aec26fSBastien Curutchet (eBPF Foundation) {0x800 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, true}, 2128*d1aec26fSBastien Curutchet (eBPF Foundation) /* Valid packet for synch so that something is received */ 2129*d1aec26fSBastien Curutchet (eBPF Foundation) {0, MIN_PKT_SIZE, 0, true}}; 2130*d1aec26fSBastien Curutchet (eBPF Foundation) 2131*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->unaligned_mode) { 2132*d1aec26fSBastien Curutchet (eBPF Foundation) /* Crossing a page boundary allowed */ 2133*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[7].valid = true; 2134*d1aec26fSBastien Curutchet (eBPF Foundation) } 2135*d1aec26fSBastien Curutchet (eBPF Foundation) if (umem->frame_size == XSK_UMEM__DEFAULT_FRAME_SIZE / 2) { 2136*d1aec26fSBastien Curutchet (eBPF Foundation) /* Crossing a 2K frame size boundary not allowed */ 2137*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[8].valid = false; 2138*d1aec26fSBastien Curutchet (eBPF Foundation) } 2139*d1aec26fSBastien Curutchet (eBPF Foundation) 2140*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->ifobj_tx->shared_umem) { 2141*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[4].offset += umem_size; 2142*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[5].offset += umem_size; 2143*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[6].offset += umem_size; 2144*d1aec26fSBastien Curutchet (eBPF Foundation) } 2145*d1aec26fSBastien Curutchet (eBPF Foundation) 2146*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2147*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2148*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2149*d1aec26fSBastien Curutchet (eBPF Foundation) } 2150*d1aec26fSBastien Curutchet (eBPF Foundation) 2151*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_drop(struct test_spec *test) 2152*d1aec26fSBastien Curutchet (eBPF Foundation) { 2153*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2154*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2155*d1aec26fSBastien Curutchet (eBPF Foundation) 2156*d1aec26fSBastien Curutchet (eBPF Foundation) test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_drop, skel_tx->progs.xsk_xdp_drop, 2157*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->maps.xsk, skel_tx->maps.xsk); 2158*d1aec26fSBastien Curutchet (eBPF Foundation) 2159*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_receive_half(test)) 2160*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2161*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2162*d1aec26fSBastien Curutchet (eBPF Foundation) } 2163*d1aec26fSBastien Curutchet (eBPF Foundation) 2164*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_metadata_copy(struct test_spec *test) 2165*d1aec26fSBastien Curutchet (eBPF Foundation) { 2166*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2167*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2168*d1aec26fSBastien Curutchet (eBPF Foundation) 2169*d1aec26fSBastien Curutchet (eBPF Foundation) test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_populate_metadata, 2170*d1aec26fSBastien Curutchet (eBPF Foundation) skel_tx->progs.xsk_xdp_populate_metadata, 2171*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->maps.xsk, skel_tx->maps.xsk); 2172*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->use_metadata = true; 2173*d1aec26fSBastien Curutchet (eBPF Foundation) 2174*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->bss->count = 0; 2175*d1aec26fSBastien Curutchet (eBPF Foundation) 2176*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2177*d1aec26fSBastien Curutchet (eBPF Foundation) } 2178*d1aec26fSBastien Curutchet (eBPF Foundation) 2179*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_shared_umem(struct test_spec *test) 2180*d1aec26fSBastien Curutchet (eBPF Foundation) { 2181*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2182*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2183*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 2184*d1aec26fSBastien Curutchet (eBPF Foundation) 2185*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 1; 2186*d1aec26fSBastien Curutchet (eBPF Foundation) test->nb_sockets = 2; 2187*d1aec26fSBastien Curutchet (eBPF Foundation) 2188*d1aec26fSBastien Curutchet (eBPF Foundation) test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_shared_umem, 2189*d1aec26fSBastien Curutchet (eBPF Foundation) skel_tx->progs.xsk_xdp_shared_umem, 2190*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->maps.xsk, skel_tx->maps.xsk); 2191*d1aec26fSBastien Curutchet (eBPF Foundation) 2192*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_even_odd_sequence(test)) 2193*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2194*d1aec26fSBastien Curutchet (eBPF Foundation) 2195*d1aec26fSBastien Curutchet (eBPF Foundation) ret = testapp_validate_traffic(test); 2196*d1aec26fSBastien Curutchet (eBPF Foundation) 2197*d1aec26fSBastien Curutchet (eBPF Foundation) release_even_odd_sequence(test); 2198*d1aec26fSBastien Curutchet (eBPF Foundation) 2199*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 2200*d1aec26fSBastien Curutchet (eBPF Foundation) } 2201*d1aec26fSBastien Curutchet (eBPF Foundation) 2202*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_poll_txq_tmout(struct test_spec *test) 2203*d1aec26fSBastien Curutchet (eBPF Foundation) { 2204*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->use_poll = true; 2205*d1aec26fSBastien Curutchet (eBPF Foundation) /* create invalid frame by set umem frame_size and pkt length equal to 2048 */ 2206*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->frame_size = 2048; 2207*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, 2 * DEFAULT_PKT_CNT, 2048)) 2208*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2209*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic_single_thread(test, test->ifobj_tx); 2210*d1aec26fSBastien Curutchet (eBPF Foundation) } 2211*d1aec26fSBastien Curutchet (eBPF Foundation) 2212*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_poll_rxq_tmout(struct test_spec *test) 2213*d1aec26fSBastien Curutchet (eBPF Foundation) { 2214*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->use_poll = true; 2215*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic_single_thread(test, test->ifobj_rx); 2216*d1aec26fSBastien Curutchet (eBPF Foundation) } 2217*d1aec26fSBastien Curutchet (eBPF Foundation) 2218*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_too_many_frags(struct test_spec *test) 2219*d1aec26fSBastien Curutchet (eBPF Foundation) { 2220*d1aec26fSBastien Curutchet (eBPF Foundation) struct pkt *pkts; 2221*d1aec26fSBastien Curutchet (eBPF Foundation) u32 max_frags, i; 2222*d1aec26fSBastien Curutchet (eBPF Foundation) int ret = TEST_FAILURE; 2223*d1aec26fSBastien Curutchet (eBPF Foundation) 2224*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mode == TEST_MODE_ZC) { 2225*d1aec26fSBastien Curutchet (eBPF Foundation) max_frags = test->ifobj_tx->xdp_zc_max_segs; 2226*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 2227*d1aec26fSBastien Curutchet (eBPF Foundation) max_frags = get_max_skb_frags(); 2228*d1aec26fSBastien Curutchet (eBPF Foundation) if (!max_frags) { 2229*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Can't get MAX_SKB_FRAGS from system, using default (17)\n"); 2230*d1aec26fSBastien Curutchet (eBPF Foundation) max_frags = 17; 2231*d1aec26fSBastien Curutchet (eBPF Foundation) } 2232*d1aec26fSBastien Curutchet (eBPF Foundation) max_frags += 1; 2233*d1aec26fSBastien Curutchet (eBPF Foundation) } 2234*d1aec26fSBastien Curutchet (eBPF Foundation) 2235*d1aec26fSBastien Curutchet (eBPF Foundation) pkts = calloc(2 * max_frags + 2, sizeof(struct pkt)); 2236*d1aec26fSBastien Curutchet (eBPF Foundation) if (!pkts) 2237*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2238*d1aec26fSBastien Curutchet (eBPF Foundation) 2239*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2240*d1aec26fSBastien Curutchet (eBPF Foundation) 2241*d1aec26fSBastien Curutchet (eBPF Foundation) /* Valid packet for synch */ 2242*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[0].len = MIN_PKT_SIZE; 2243*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[0].valid = true; 2244*d1aec26fSBastien Curutchet (eBPF Foundation) 2245*d1aec26fSBastien Curutchet (eBPF Foundation) /* One valid packet with the max amount of frags */ 2246*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = 1; i < max_frags + 1; i++) { 2247*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].len = MIN_PKT_SIZE; 2248*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].options = XDP_PKT_CONTD; 2249*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].valid = true; 2250*d1aec26fSBastien Curutchet (eBPF Foundation) } 2251*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[max_frags].options = 0; 2252*d1aec26fSBastien Curutchet (eBPF Foundation) 2253*d1aec26fSBastien Curutchet (eBPF Foundation) /* An invalid packet with the max amount of frags but signals packet 2254*d1aec26fSBastien Curutchet (eBPF Foundation) * continues on the last frag 2255*d1aec26fSBastien Curutchet (eBPF Foundation) */ 2256*d1aec26fSBastien Curutchet (eBPF Foundation) for (i = max_frags + 1; i < 2 * max_frags + 1; i++) { 2257*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].len = MIN_PKT_SIZE; 2258*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].options = XDP_PKT_CONTD; 2259*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[i].valid = false; 2260*d1aec26fSBastien Curutchet (eBPF Foundation) } 2261*d1aec26fSBastien Curutchet (eBPF Foundation) 2262*d1aec26fSBastien Curutchet (eBPF Foundation) /* Valid packet for synch */ 2263*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[2 * max_frags + 1].len = MIN_PKT_SIZE; 2264*d1aec26fSBastien Curutchet (eBPF Foundation) pkts[2 * max_frags + 1].valid = true; 2265*d1aec26fSBastien Curutchet (eBPF Foundation) 2266*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_generate_custom(test, pkts, 2 * max_frags + 2)) { 2267*d1aec26fSBastien Curutchet (eBPF Foundation) free(pkts); 2268*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2269*d1aec26fSBastien Curutchet (eBPF Foundation) } 2270*d1aec26fSBastien Curutchet (eBPF Foundation) 2271*d1aec26fSBastien Curutchet (eBPF Foundation) ret = testapp_validate_traffic(test); 2272*d1aec26fSBastien Curutchet (eBPF Foundation) free(pkts); 2273*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 2274*d1aec26fSBastien Curutchet (eBPF Foundation) } 2275*d1aec26fSBastien Curutchet (eBPF Foundation) 2276*d1aec26fSBastien Curutchet (eBPF Foundation) static int xsk_load_xdp_programs(struct ifobject *ifobj) 2277*d1aec26fSBastien Curutchet (eBPF Foundation) { 2278*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xdp_progs = xsk_xdp_progs__open_and_load(); 2279*d1aec26fSBastien Curutchet (eBPF Foundation) if (libbpf_get_error(ifobj->xdp_progs)) 2280*d1aec26fSBastien Curutchet (eBPF Foundation) return libbpf_get_error(ifobj->xdp_progs); 2281*d1aec26fSBastien Curutchet (eBPF Foundation) 2282*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 2283*d1aec26fSBastien Curutchet (eBPF Foundation) } 2284*d1aec26fSBastien Curutchet (eBPF Foundation) 2285*d1aec26fSBastien Curutchet (eBPF Foundation) /* Simple test */ 2286*d1aec26fSBastien Curutchet (eBPF Foundation) static bool hugepages_present(void) 2287*d1aec26fSBastien Curutchet (eBPF Foundation) { 2288*d1aec26fSBastien Curutchet (eBPF Foundation) size_t mmap_sz = 2 * DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE; 2289*d1aec26fSBastien Curutchet (eBPF Foundation) void *bufs; 2290*d1aec26fSBastien Curutchet (eBPF Foundation) 2291*d1aec26fSBastien Curutchet (eBPF Foundation) bufs = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, 2292*d1aec26fSBastien Curutchet (eBPF Foundation) MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, MAP_HUGE_2MB); 2293*d1aec26fSBastien Curutchet (eBPF Foundation) if (bufs == MAP_FAILED) 2294*d1aec26fSBastien Curutchet (eBPF Foundation) return false; 2295*d1aec26fSBastien Curutchet (eBPF Foundation) 2296*d1aec26fSBastien Curutchet (eBPF Foundation) mmap_sz = ceil_u64(mmap_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE; 2297*d1aec26fSBastien Curutchet (eBPF Foundation) munmap(bufs, mmap_sz); 2298*d1aec26fSBastien Curutchet (eBPF Foundation) return true; 2299*d1aec26fSBastien Curutchet (eBPF Foundation) } 2300*d1aec26fSBastien Curutchet (eBPF Foundation) 2301*d1aec26fSBastien Curutchet (eBPF Foundation) int init_iface(struct ifobject *ifobj, thread_func_t func_ptr) 2302*d1aec26fSBastien Curutchet (eBPF Foundation) { 2303*d1aec26fSBastien Curutchet (eBPF Foundation) LIBBPF_OPTS(bpf_xdp_query_opts, query_opts); 2304*d1aec26fSBastien Curutchet (eBPF Foundation) int err; 2305*d1aec26fSBastien Curutchet (eBPF Foundation) 2306*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->func_ptr = func_ptr; 2307*d1aec26fSBastien Curutchet (eBPF Foundation) 2308*d1aec26fSBastien Curutchet (eBPF Foundation) err = xsk_load_xdp_programs(ifobj); 2309*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 2310*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error loading XDP program\n"); 2311*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 2312*d1aec26fSBastien Curutchet (eBPF Foundation) } 2313*d1aec26fSBastien Curutchet (eBPF Foundation) 2314*d1aec26fSBastien Curutchet (eBPF Foundation) if (hugepages_present()) 2315*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->unaligned_supp = true; 2316*d1aec26fSBastien Curutchet (eBPF Foundation) 2317*d1aec26fSBastien Curutchet (eBPF Foundation) err = bpf_xdp_query(ifobj->ifindex, XDP_FLAGS_DRV_MODE, &query_opts); 2318*d1aec26fSBastien Curutchet (eBPF Foundation) if (err) { 2319*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Error querying XDP capabilities\n"); 2320*d1aec26fSBastien Curutchet (eBPF Foundation) return err; 2321*d1aec26fSBastien Curutchet (eBPF Foundation) } 2322*d1aec26fSBastien Curutchet (eBPF Foundation) if (query_opts.feature_flags & NETDEV_XDP_ACT_RX_SG) 2323*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->multi_buff_supp = true; 2324*d1aec26fSBastien Curutchet (eBPF Foundation) if (query_opts.feature_flags & NETDEV_XDP_ACT_XSK_ZEROCOPY) { 2325*d1aec26fSBastien Curutchet (eBPF Foundation) if (query_opts.xdp_zc_max_segs > 1) { 2326*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->multi_buff_zc_supp = true; 2327*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xdp_zc_max_segs = query_opts.xdp_zc_max_segs; 2328*d1aec26fSBastien Curutchet (eBPF Foundation) } else { 2329*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xdp_zc_max_segs = 0; 2330*d1aec26fSBastien Curutchet (eBPF Foundation) } 2331*d1aec26fSBastien Curutchet (eBPF Foundation) } 2332*d1aec26fSBastien Curutchet (eBPF Foundation) 2333*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 2334*d1aec26fSBastien Curutchet (eBPF Foundation) } 2335*d1aec26fSBastien Curutchet (eBPF Foundation) 2336*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_send_receive(struct test_spec *test) 2337*d1aec26fSBastien Curutchet (eBPF Foundation) { 2338*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2339*d1aec26fSBastien Curutchet (eBPF Foundation) } 2340*d1aec26fSBastien Curutchet (eBPF Foundation) 2341*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_send_receive_2k_frame(struct test_spec *test) 2342*d1aec26fSBastien Curutchet (eBPF Foundation) { 2343*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->frame_size = 2048; 2344*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->frame_size = 2048; 2345*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MIN_PKT_SIZE)) 2346*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2347*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2348*d1aec26fSBastien Curutchet (eBPF Foundation) } 2349*d1aec26fSBastien Curutchet (eBPF Foundation) 2350*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_poll_rx(struct test_spec *test) 2351*d1aec26fSBastien Curutchet (eBPF Foundation) { 2352*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->use_poll = true; 2353*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2354*d1aec26fSBastien Curutchet (eBPF Foundation) } 2355*d1aec26fSBastien Curutchet (eBPF Foundation) 2356*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_poll_tx(struct test_spec *test) 2357*d1aec26fSBastien Curutchet (eBPF Foundation) { 2358*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->use_poll = true; 2359*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2360*d1aec26fSBastien Curutchet (eBPF Foundation) } 2361*d1aec26fSBastien Curutchet (eBPF Foundation) 2362*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_aligned_inv_desc(struct test_spec *test) 2363*d1aec26fSBastien Curutchet (eBPF Foundation) { 2364*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc(test); 2365*d1aec26fSBastien Curutchet (eBPF Foundation) } 2366*d1aec26fSBastien Curutchet (eBPF Foundation) 2367*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_aligned_inv_desc_2k_frame(struct test_spec *test) 2368*d1aec26fSBastien Curutchet (eBPF Foundation) { 2369*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->frame_size = 2048; 2370*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->frame_size = 2048; 2371*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc(test); 2372*d1aec26fSBastien Curutchet (eBPF Foundation) } 2373*d1aec26fSBastien Curutchet (eBPF Foundation) 2374*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_unaligned_inv_desc(struct test_spec *test) 2375*d1aec26fSBastien Curutchet (eBPF Foundation) { 2376*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->unaligned_mode = true; 2377*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->unaligned_mode = true; 2378*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc(test); 2379*d1aec26fSBastien Curutchet (eBPF Foundation) } 2380*d1aec26fSBastien Curutchet (eBPF Foundation) 2381*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test) 2382*d1aec26fSBastien Curutchet (eBPF Foundation) { 2383*d1aec26fSBastien Curutchet (eBPF Foundation) u64 page_size, umem_size; 2384*d1aec26fSBastien Curutchet (eBPF Foundation) 2385*d1aec26fSBastien Curutchet (eBPF Foundation) /* Odd frame size so the UMEM doesn't end near a page boundary. */ 2386*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->frame_size = 4001; 2387*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->frame_size = 4001; 2388*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->unaligned_mode = true; 2389*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->unaligned_mode = true; 2390*d1aec26fSBastien Curutchet (eBPF Foundation) /* This test exists to test descriptors that staddle the end of 2391*d1aec26fSBastien Curutchet (eBPF Foundation) * the UMEM but not a page. 2392*d1aec26fSBastien Curutchet (eBPF Foundation) */ 2393*d1aec26fSBastien Curutchet (eBPF Foundation) page_size = sysconf(_SC_PAGESIZE); 2394*d1aec26fSBastien Curutchet (eBPF Foundation) umem_size = test->ifobj_tx->umem->num_frames * test->ifobj_tx->umem->frame_size; 2395*d1aec26fSBastien Curutchet (eBPF Foundation) assert(umem_size % page_size > MIN_PKT_SIZE); 2396*d1aec26fSBastien Curutchet (eBPF Foundation) assert(umem_size % page_size < page_size - MIN_PKT_SIZE); 2397*d1aec26fSBastien Curutchet (eBPF Foundation) 2398*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc(test); 2399*d1aec26fSBastien Curutchet (eBPF Foundation) } 2400*d1aec26fSBastien Curutchet (eBPF Foundation) 2401*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_aligned_inv_desc_mb(struct test_spec *test) 2402*d1aec26fSBastien Curutchet (eBPF Foundation) { 2403*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc_mb(test); 2404*d1aec26fSBastien Curutchet (eBPF Foundation) } 2405*d1aec26fSBastien Curutchet (eBPF Foundation) 2406*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_unaligned_inv_desc_mb(struct test_spec *test) 2407*d1aec26fSBastien Curutchet (eBPF Foundation) { 2408*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->umem->unaligned_mode = true; 2409*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->unaligned_mode = true; 2410*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_invalid_desc_mb(test); 2411*d1aec26fSBastien Curutchet (eBPF Foundation) } 2412*d1aec26fSBastien Curutchet (eBPF Foundation) 2413*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_metadata(struct test_spec *test) 2414*d1aec26fSBastien Curutchet (eBPF Foundation) { 2415*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_xdp_metadata_copy(test); 2416*d1aec26fSBastien Curutchet (eBPF Foundation) } 2417*d1aec26fSBastien Curutchet (eBPF Foundation) 2418*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_xdp_metadata_mb(struct test_spec *test) 2419*d1aec26fSBastien Curutchet (eBPF Foundation) { 2420*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2421*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_xdp_metadata_copy(test); 2422*d1aec26fSBastien Curutchet (eBPF Foundation) } 2423*d1aec26fSBastien Curutchet (eBPF Foundation) 2424*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_hw_sw_min_ring_size(struct test_spec *test) 2425*d1aec26fSBastien Curutchet (eBPF Foundation) { 2426*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 2427*d1aec26fSBastien Curutchet (eBPF Foundation) 2428*d1aec26fSBastien Curutchet (eBPF Foundation) test->set_ring = true; 2429*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 2; 2430*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->ring.tx_pending = DEFAULT_BATCH_SIZE; 2431*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->ring.rx_pending = DEFAULT_BATCH_SIZE * 2; 2432*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->batch_size = 1; 2433*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->batch_size = 1; 2434*d1aec26fSBastien Curutchet (eBPF Foundation) ret = testapp_validate_traffic(test); 2435*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 2436*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 2437*d1aec26fSBastien Curutchet (eBPF Foundation) 2438*d1aec26fSBastien Curutchet (eBPF Foundation) /* Set batch size to hw_ring_size - 1 */ 2439*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->batch_size = DEFAULT_BATCH_SIZE - 1; 2440*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->batch_size = DEFAULT_BATCH_SIZE - 1; 2441*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2442*d1aec26fSBastien Curutchet (eBPF Foundation) } 2443*d1aec26fSBastien Curutchet (eBPF Foundation) 2444*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_hw_sw_max_ring_size(struct test_spec *test) 2445*d1aec26fSBastien Curutchet (eBPF Foundation) { 2446*d1aec26fSBastien Curutchet (eBPF Foundation) u32 max_descs = XSK_RING_PROD__DEFAULT_NUM_DESCS * 4; 2447*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 2448*d1aec26fSBastien Curutchet (eBPF Foundation) 2449*d1aec26fSBastien Curutchet (eBPF Foundation) test->set_ring = true; 2450*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 2; 2451*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->ring.tx_pending = test->ifobj_tx->ring.tx_max_pending; 2452*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->ring.rx_pending = test->ifobj_tx->ring.rx_max_pending; 2453*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->num_frames = max_descs; 2454*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->fill_size = max_descs; 2455*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->umem->comp_size = max_descs; 2456*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 2457*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 2458*d1aec26fSBastien Curutchet (eBPF Foundation) 2459*d1aec26fSBastien Curutchet (eBPF Foundation) ret = testapp_validate_traffic(test); 2460*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 2461*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 2462*d1aec26fSBastien Curutchet (eBPF Foundation) 2463*d1aec26fSBastien Curutchet (eBPF Foundation) /* Set batch_size to 8152 for testing, as the ice HW ignores the 3 lowest bits when 2464*d1aec26fSBastien Curutchet (eBPF Foundation) * updating the Rx HW tail register. 2465*d1aec26fSBastien Curutchet (eBPF Foundation) */ 2466*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8; 2467*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_rx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8; 2468*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, max_descs, MIN_PKT_SIZE)) { 2469*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, test->ifobj_tx); 2470*d1aec26fSBastien Curutchet (eBPF Foundation) clean_sockets(test, test->ifobj_rx); 2471*d1aec26fSBastien Curutchet (eBPF Foundation) clean_umem(test, test->ifobj_rx, test->ifobj_tx); 2472*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2473*d1aec26fSBastien Curutchet (eBPF Foundation) } 2474*d1aec26fSBastien Curutchet (eBPF Foundation) 2475*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2476*d1aec26fSBastien Curutchet (eBPF Foundation) } 2477*d1aec26fSBastien Curutchet (eBPF Foundation) 2478*d1aec26fSBastien Curutchet (eBPF Foundation) static int testapp_xdp_adjust_tail(struct test_spec *test, int adjust_value) 2479*d1aec26fSBastien Curutchet (eBPF Foundation) { 2480*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2481*d1aec26fSBastien Curutchet (eBPF Foundation) struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2482*d1aec26fSBastien Curutchet (eBPF Foundation) 2483*d1aec26fSBastien Curutchet (eBPF Foundation) test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_adjust_tail, 2484*d1aec26fSBastien Curutchet (eBPF Foundation) skel_tx->progs.xsk_xdp_adjust_tail, 2485*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->maps.xsk, skel_tx->maps.xsk); 2486*d1aec26fSBastien Curutchet (eBPF Foundation) 2487*d1aec26fSBastien Curutchet (eBPF Foundation) skel_rx->bss->adjust_value = adjust_value; 2488*d1aec26fSBastien Curutchet (eBPF Foundation) 2489*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2490*d1aec26fSBastien Curutchet (eBPF Foundation) } 2491*d1aec26fSBastien Curutchet (eBPF Foundation) 2492*d1aec26fSBastien Curutchet (eBPF Foundation) static int testapp_adjust_tail(struct test_spec *test, u32 value, u32 pkt_len) 2493*d1aec26fSBastien Curutchet (eBPF Foundation) { 2494*d1aec26fSBastien Curutchet (eBPF Foundation) int ret; 2495*d1aec26fSBastien Curutchet (eBPF Foundation) 2496*d1aec26fSBastien Curutchet (eBPF Foundation) test->adjust_tail_support = true; 2497*d1aec26fSBastien Curutchet (eBPF Foundation) test->adjust_tail = true; 2498*d1aec26fSBastien Curutchet (eBPF Foundation) test->total_steps = 1; 2499*d1aec26fSBastien Curutchet (eBPF Foundation) 2500*d1aec26fSBastien Curutchet (eBPF Foundation) ret = pkt_stream_replace_ifobject(test->ifobj_tx, DEFAULT_BATCH_SIZE, pkt_len); 2501*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 2502*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2503*d1aec26fSBastien Curutchet (eBPF Foundation) 2504*d1aec26fSBastien Curutchet (eBPF Foundation) ret = pkt_stream_replace_ifobject(test->ifobj_rx, DEFAULT_BATCH_SIZE, pkt_len + value); 2505*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 2506*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2507*d1aec26fSBastien Curutchet (eBPF Foundation) 2508*d1aec26fSBastien Curutchet (eBPF Foundation) ret = testapp_xdp_adjust_tail(test, value); 2509*d1aec26fSBastien Curutchet (eBPF Foundation) if (ret) 2510*d1aec26fSBastien Curutchet (eBPF Foundation) return ret; 2511*d1aec26fSBastien Curutchet (eBPF Foundation) 2512*d1aec26fSBastien Curutchet (eBPF Foundation) if (!test->adjust_tail_support) { 2513*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("%s %sResize pkt with bpf_xdp_adjust_tail() not supported\n", 2514*d1aec26fSBastien Curutchet (eBPF Foundation) mode_string(test), busy_poll_string(test)); 2515*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 2516*d1aec26fSBastien Curutchet (eBPF Foundation) } 2517*d1aec26fSBastien Curutchet (eBPF Foundation) 2518*d1aec26fSBastien Curutchet (eBPF Foundation) return 0; 2519*d1aec26fSBastien Curutchet (eBPF Foundation) } 2520*d1aec26fSBastien Curutchet (eBPF Foundation) 2521*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_adjust_tail_shrink(struct test_spec *test) 2522*d1aec26fSBastien Curutchet (eBPF Foundation) { 2523*d1aec26fSBastien Curutchet (eBPF Foundation) /* Shrink by 4 bytes for testing purpose */ 2524*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_adjust_tail(test, -4, MIN_PKT_SIZE * 2); 2525*d1aec26fSBastien Curutchet (eBPF Foundation) } 2526*d1aec26fSBastien Curutchet (eBPF Foundation) 2527*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_adjust_tail_shrink_mb(struct test_spec *test) 2528*d1aec26fSBastien Curutchet (eBPF Foundation) { 2529*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2530*d1aec26fSBastien Curutchet (eBPF Foundation) /* Shrink by the frag size */ 2531*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_adjust_tail(test, -XSK_UMEM__MAX_FRAME_SIZE, XSK_UMEM__LARGE_FRAME_SIZE * 2); 2532*d1aec26fSBastien Curutchet (eBPF Foundation) } 2533*d1aec26fSBastien Curutchet (eBPF Foundation) 2534*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_adjust_tail_grow(struct test_spec *test) 2535*d1aec26fSBastien Curutchet (eBPF Foundation) { 2536*d1aec26fSBastien Curutchet (eBPF Foundation) /* Grow by 4 bytes for testing purpose */ 2537*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_adjust_tail(test, 4, MIN_PKT_SIZE * 2); 2538*d1aec26fSBastien Curutchet (eBPF Foundation) } 2539*d1aec26fSBastien Curutchet (eBPF Foundation) 2540*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_adjust_tail_grow_mb(struct test_spec *test) 2541*d1aec26fSBastien Curutchet (eBPF Foundation) { 2542*d1aec26fSBastien Curutchet (eBPF Foundation) test->mtu = MAX_ETH_JUMBO_SIZE; 2543*d1aec26fSBastien Curutchet (eBPF Foundation) /* Grow by (frag_size - last_frag_Size) - 1 to stay inside the last fragment */ 2544*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_adjust_tail(test, (XSK_UMEM__MAX_FRAME_SIZE / 2) - 1, 2545*d1aec26fSBastien Curutchet (eBPF Foundation) XSK_UMEM__LARGE_FRAME_SIZE * 2); 2546*d1aec26fSBastien Curutchet (eBPF Foundation) } 2547*d1aec26fSBastien Curutchet (eBPF Foundation) 2548*d1aec26fSBastien Curutchet (eBPF Foundation) int testapp_tx_queue_consumer(struct test_spec *test) 2549*d1aec26fSBastien Curutchet (eBPF Foundation) { 2550*d1aec26fSBastien Curutchet (eBPF Foundation) int nr_packets; 2551*d1aec26fSBastien Curutchet (eBPF Foundation) 2552*d1aec26fSBastien Curutchet (eBPF Foundation) if (test->mode == TEST_MODE_ZC) { 2553*d1aec26fSBastien Curutchet (eBPF Foundation) ksft_print_msg("Can not run TX_QUEUE_CONSUMER test for ZC mode\n"); 2554*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_SKIP; 2555*d1aec26fSBastien Curutchet (eBPF Foundation) } 2556*d1aec26fSBastien Curutchet (eBPF Foundation) 2557*d1aec26fSBastien Curutchet (eBPF Foundation) nr_packets = MAX_TX_BUDGET_DEFAULT + 1; 2558*d1aec26fSBastien Curutchet (eBPF Foundation) if (pkt_stream_replace(test, nr_packets, MIN_PKT_SIZE)) 2559*d1aec26fSBastien Curutchet (eBPF Foundation) return TEST_FAILURE; 2560*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->batch_size = nr_packets; 2561*d1aec26fSBastien Curutchet (eBPF Foundation) test->ifobj_tx->xsk->check_consumer = true; 2562*d1aec26fSBastien Curutchet (eBPF Foundation) 2563*d1aec26fSBastien Curutchet (eBPF Foundation) return testapp_validate_traffic(test); 2564*d1aec26fSBastien Curutchet (eBPF Foundation) } 2565*d1aec26fSBastien Curutchet (eBPF Foundation) 2566*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobject_create(void) 2567*d1aec26fSBastien Curutchet (eBPF Foundation) { 2568*d1aec26fSBastien Curutchet (eBPF Foundation) struct ifobject *ifobj; 2569*d1aec26fSBastien Curutchet (eBPF Foundation) 2570*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj = calloc(1, sizeof(struct ifobject)); 2571*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj) 2572*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 2573*d1aec26fSBastien Curutchet (eBPF Foundation) 2574*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->xsk_arr = calloc(MAX_SOCKETS, sizeof(*ifobj->xsk_arr)); 2575*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj->xsk_arr) 2576*d1aec26fSBastien Curutchet (eBPF Foundation) goto out_xsk_arr; 2577*d1aec26fSBastien Curutchet (eBPF Foundation) 2578*d1aec26fSBastien Curutchet (eBPF Foundation) ifobj->umem = calloc(1, sizeof(*ifobj->umem)); 2579*d1aec26fSBastien Curutchet (eBPF Foundation) if (!ifobj->umem) 2580*d1aec26fSBastien Curutchet (eBPF Foundation) goto out_umem; 2581*d1aec26fSBastien Curutchet (eBPF Foundation) 2582*d1aec26fSBastien Curutchet (eBPF Foundation) return ifobj; 2583*d1aec26fSBastien Curutchet (eBPF Foundation) 2584*d1aec26fSBastien Curutchet (eBPF Foundation) out_umem: 2585*d1aec26fSBastien Curutchet (eBPF Foundation) free(ifobj->xsk_arr); 2586*d1aec26fSBastien Curutchet (eBPF Foundation) out_xsk_arr: 2587*d1aec26fSBastien Curutchet (eBPF Foundation) free(ifobj); 2588*d1aec26fSBastien Curutchet (eBPF Foundation) return NULL; 2589*d1aec26fSBastien Curutchet (eBPF Foundation) } 2590*d1aec26fSBastien Curutchet (eBPF Foundation) 2591*d1aec26fSBastien Curutchet (eBPF Foundation) void ifobject_delete(struct ifobject *ifobj) 2592*d1aec26fSBastien Curutchet (eBPF Foundation) { 2593*d1aec26fSBastien Curutchet (eBPF Foundation) free(ifobj->umem); 2594*d1aec26fSBastien Curutchet (eBPF Foundation) free(ifobj->xsk_arr); 2595*d1aec26fSBastien Curutchet (eBPF Foundation) free(ifobj); 2596*d1aec26fSBastien Curutchet (eBPF Foundation) } 2597