The typical XDP memory scheme is one packet per page. Change the AF_XDP frame size in libbpf to 4096, which is the page size on x86, to allow libbpf to be used with the drivers with the packet-per-page scheme.
Add a command line option -f to xdpsock to allow to specify a custom frame size. Signed-off-by: Maxim Mikityanskiy <maxi...@mellanox.com> --- samples/bpf/xdpsock_user.c | 39 +++++++++++++++++++++++++------------- tools/lib/bpf/xsk.h | 2 +- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c index a6b13025ee79..3746f699cf2f 100644 --- a/samples/bpf/xdpsock_user.c +++ b/samples/bpf/xdpsock_user.c @@ -69,6 +69,7 @@ static int opt_queue; static int opt_poll; static int opt_interval = 1; static u32 opt_xdp_bind_flags; +static int opt_xsk_frame_shift = XSK_UMEM__DEFAULT_FRAME_SHIFT; static __u32 prog_id; struct xsk_umem_info { @@ -93,6 +94,11 @@ struct xsk_socket_info { static int num_socks; struct xsk_socket_info *xsks[MAX_SOCKS]; +static inline int get_buf_size(int frames) +{ + return frames << opt_xsk_frame_shift; +} + static unsigned long get_nsecs(void) { struct timespec ts; @@ -277,6 +283,12 @@ static size_t gen_eth_frame(struct xsk_umem_info *umem, u64 addr) static struct xsk_umem_info *xsk_configure_umem(void *buffer, u64 size) { struct xsk_umem_info *umem; + struct xsk_umem_config cfg = { + .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS, + .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS, + .frame_size = get_buf_size(1), + .frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM, + }; int ret; umem = calloc(1, sizeof(*umem)); @@ -284,7 +296,7 @@ static struct xsk_umem_info *xsk_configure_umem(void *buffer, u64 size) exit_with_error(errno); ret = xsk_umem__create(&umem->umem, buffer, size, &umem->fq, &umem->cq, - NULL); + &cfg); if (ret) exit_with_error(-ret); @@ -325,9 +337,8 @@ static struct xsk_socket_info *xsk_configure_socket(struct xsk_umem_info *umem) if (ret != XSK_RING_PROD__DEFAULT_NUM_DESCS) exit_with_error(-ret); for (i = 0; - i < XSK_RING_PROD__DEFAULT_NUM_DESCS * - XSK_UMEM__DEFAULT_FRAME_SIZE; - i += XSK_UMEM__DEFAULT_FRAME_SIZE) + i < get_buf_size(XSK_RING_PROD__DEFAULT_NUM_DESCS); + i += get_buf_size(1)) *xsk_ring_prod__fill_addr(&xsk->umem->fq, idx++) = i; xsk_ring_prod__submit(&xsk->umem->fq, XSK_RING_PROD__DEFAULT_NUM_DESCS); @@ -348,6 +359,7 @@ static struct option long_options[] = { {"zero-copy", no_argument, 0, 'z'}, {"copy", no_argument, 0, 'c'}, {"combined", no_argument, 0, 'C'}, + {"frame-shift", required_argument, 0, 'f'}, {0, 0, 0, 0} }; @@ -368,8 +380,9 @@ static void usage(const char *prog) " -z, --zero-copy Force zero-copy mode.\n" " -c, --copy Force copy mode.\n" " -C, --combined Driver supports combined XSK and non-XSK traffic in a channel.\n" + " -f, --frame-shift=n Set the frame shift (default is %d, frame size is 1 << frame-shift).\n" "\n"; - fprintf(stderr, str, prog); + fprintf(stderr, str, prog, XSK_UMEM__DEFAULT_FRAME_SHIFT); exit(EXIT_FAILURE); } @@ -380,7 +393,7 @@ static void parse_command_line(int argc, char **argv) opterr = 0; for (;;) { - c = getopt_long(argc, argv, "Frtli:q:psSNn:czC", long_options, + c = getopt_long(argc, argv, "Frtli:q:psSNn:czCf:", long_options, &option_index); if (c == -1) break; @@ -426,6 +439,9 @@ static void parse_command_line(int argc, char **argv) case 'C': opt_libbpf_flags |= XSK_LIBBPF_FLAGS__COMBINED_CHANNELS; break; + case 'f': + opt_xsk_frame_shift = atoi(optarg); + break; default: usage(basename(argv[0])); } @@ -589,8 +605,7 @@ static void tx_only(struct xsk_socket_info *xsk) for (i = 0; i < BATCH_SIZE; i++) { xsk_ring_prod__tx_desc(&xsk->tx, idx + i)->addr - = (frame_nb + i) << - XSK_UMEM__DEFAULT_FRAME_SHIFT; + = get_buf_size(frame_nb + i); xsk_ring_prod__tx_desc(&xsk->tx, idx + i)->len = sizeof(pkt_data) - 1; } @@ -667,20 +682,18 @@ int main(int argc, char **argv) } ret = posix_memalign(&bufs, getpagesize(), /* PAGE_SIZE aligned */ - NUM_FRAMES * XSK_UMEM__DEFAULT_FRAME_SIZE); + get_buf_size(NUM_FRAMES)); if (ret) exit_with_error(ret); /* Create sockets... */ - umem = xsk_configure_umem(bufs, - NUM_FRAMES * XSK_UMEM__DEFAULT_FRAME_SIZE); + umem = xsk_configure_umem(bufs, get_buf_size(NUM_FRAMES)); xsks[num_socks++] = xsk_configure_socket(umem); if (opt_bench == BENCH_TXONLY) { int i; - for (i = 0; i < NUM_FRAMES * XSK_UMEM__DEFAULT_FRAME_SIZE; - i += XSK_UMEM__DEFAULT_FRAME_SIZE) + for (i = 0; i < get_buf_size(NUM_FRAMES); i += get_buf_size(1)) (void)gen_eth_frame(umem, i); } diff --git a/tools/lib/bpf/xsk.h b/tools/lib/bpf/xsk.h index 72a49b102ab3..946245a7272e 100644 --- a/tools/lib/bpf/xsk.h +++ b/tools/lib/bpf/xsk.h @@ -157,7 +157,7 @@ LIBBPF_API int xsk_socket__fd(const struct xsk_socket *xsk); #define XSK_RING_CONS__DEFAULT_NUM_DESCS 2048 #define XSK_RING_PROD__DEFAULT_NUM_DESCS 2048 -#define XSK_UMEM__DEFAULT_FRAME_SHIFT 11 /* 2048 bytes */ +#define XSK_UMEM__DEFAULT_FRAME_SHIFT 12 /* 4096 bytes */ #define XSK_UMEM__DEFAULT_FRAME_SIZE (1 << XSK_UMEM__DEFAULT_FRAME_SHIFT) #define XSK_UMEM__DEFAULT_FRAME_HEADROOM 0 -- 2.19.1