summaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-07-09 12:24:15 -0700
committerJakub Kicinski <kuba@kernel.org>2022-07-09 12:24:16 -0700
commit0076cad30135f95bf9a144269906f9b7a4eb542c (patch)
tree1a48680205d7b23123a3864c25c814d6d0dfbd8e /samples
parent877d4e3cedd18cd5a4cef7685b64af72f8322ac1 (diff)
parent24bdfdd2ec343c94adf38fb5bc699f12e543713b (diff)
downloadlinux-0076cad30135f95bf9a144269906f9b7a4eb542c.tar.gz
linux-0076cad30135f95bf9a144269906f9b7a4eb542c.tar.bz2
linux-0076cad30135f95bf9a144269906f9b7a4eb542c.zip
Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2022-07-09 We've added 94 non-merge commits during the last 19 day(s) which contain a total of 125 files changed, 5141 insertions(+), 6701 deletions(-). The main changes are: 1) Add new way for performing BTF type queries to BPF, from Daniel Müller. 2) Add inlining of calls to bpf_loop() helper when its function callback is statically known, from Eduard Zingerman. 3) Implement BPF TCP CC framework usability improvements, from Jörn-Thorben Hinz. 4) Add LSM flavor for attaching per-cgroup BPF programs to existing LSM hooks, from Stanislav Fomichev. 5) Remove all deprecated libbpf APIs in prep for 1.0 release, from Andrii Nakryiko. 6) Add benchmarks around local_storage to BPF selftests, from Dave Marchevsky. 7) AF_XDP sample removal (given move to libxdp) and various improvements around AF_XDP selftests, from Magnus Karlsson & Maciej Fijalkowski. 8) Add bpftool improvements for memcg probing and bash completion, from Quentin Monnet. 9) Add arm64 JIT support for BPF-2-BPF coupled with tail calls, from Jakub Sitnicki. 10) Sockmap optimizations around throughput of UDP transmissions which have been improved by 61%, from Cong Wang. 11) Rework perf's BPF prologue code to remove deprecated functions, from Jiri Olsa. 12) Fix sockmap teardown path to avoid sleepable sk_psock_stop, from John Fastabend. 13) Fix libbpf's cleanup around legacy kprobe/uprobe on error case, from Chuang Wang. 14) Fix libbpf's bpf_helpers.h to work with gcc for the case of its sec/pragma macro, from James Hilliard. 15) Fix libbpf's pt_regs macros for riscv to use a0 for RC register, from Yixun Lan. 16) Fix bpftool to show the name of type BPF_OBJ_LINK, from Yafang Shao. * https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (94 commits) selftests/bpf: Fix xdp_synproxy build failure if CONFIG_NF_CONNTRACK=m/n bpf: Correctly propagate errors up from bpf_core_composites_match libbpf: Disable SEC pragma macro on GCC bpf: Check attach_func_proto more carefully in check_return_code selftests/bpf: Add test involving restrict type qualifier bpftool: Add support for KIND_RESTRICT to gen min_core_btf command MAINTAINERS: Add entry for AF_XDP selftests files selftests, xsk: Rename AF_XDP testing app bpf, docs: Remove deprecated xsk libbpf APIs description selftests/bpf: Add benchmark for local_storage RCU Tasks Trace usage libbpf, riscv: Use a0 for RC register libbpf: Remove unnecessary usdt_rel_ip assignments selftests/bpf: Fix few more compiler warnings selftests/bpf: Fix bogus uninitialized variable warning bpftool: Remove zlib feature test from Makefile libbpf: Cleanup the legacy uprobe_event on failed add/attach_event() libbpf: Fix wrong variable used in perf_event_uprobe_open_legacy() libbpf: Cleanup the legacy kprobe_event on failed add/attach_event() selftests/bpf: Add type match test against kernel's task_struct selftests/bpf: Add nested type to type based tests ... ==================== Link: https://lore.kernel.org/r/20220708233145.32365-1-daniel@iogearbox.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/Makefile9
-rw-r--r--samples/bpf/xdp1_kern.c11
-rw-r--r--samples/bpf/xdp2_kern.c11
-rw-r--r--samples/bpf/xdp_tx_iptunnel_kern.c2
-rw-r--r--samples/bpf/xdpsock.h19
-rw-r--r--samples/bpf/xdpsock_ctrl_proc.c190
-rw-r--r--samples/bpf/xdpsock_kern.c24
-rw-r--r--samples/bpf/xdpsock_user.c2019
-rw-r--r--samples/bpf/xsk_fwd.c1085
9 files changed, 17 insertions, 3353 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 03e3d3529ac9..5002a5b9a7da 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -45,9 +45,6 @@ tprogs-y += xdp_rxq_info
tprogs-y += syscall_tp
tprogs-y += cpustat
tprogs-y += xdp_adjust_tail
-tprogs-y += xdpsock
-tprogs-y += xdpsock_ctrl_proc
-tprogs-y += xsk_fwd
tprogs-y += xdp_fwd
tprogs-y += task_fd_query
tprogs-y += xdp_sample_pkts
@@ -109,9 +106,6 @@ xdp_rxq_info-objs := xdp_rxq_info_user.o
syscall_tp-objs := syscall_tp_user.o
cpustat-objs := cpustat_user.o
xdp_adjust_tail-objs := xdp_adjust_tail_user.o
-xdpsock-objs := xdpsock_user.o
-xdpsock_ctrl_proc-objs := xdpsock_ctrl_proc.o
-xsk_fwd-objs := xsk_fwd.o
xdp_fwd-objs := xdp_fwd_user.o
task_fd_query-objs := task_fd_query_user.o $(TRACE_HELPERS)
xdp_sample_pkts-objs := xdp_sample_pkts_user.o
@@ -179,7 +173,6 @@ always-y += xdp_sample_pkts_kern.o
always-y += ibumad_kern.o
always-y += hbm_out_kern.o
always-y += hbm_edt_kern.o
-always-y += xdpsock_kern.o
ifeq ($(ARCH), arm)
# Strip all except -D__LINUX_ARM_ARCH__ option needed to handle linux
@@ -224,8 +217,6 @@ TPROGLDLIBS_tracex4 += -lrt
TPROGLDLIBS_trace_output += -lrt
TPROGLDLIBS_map_perf_test += -lrt
TPROGLDLIBS_test_overhead += -lrt
-TPROGLDLIBS_xdpsock += -pthread -lcap
-TPROGLDLIBS_xsk_fwd += -pthread
# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
# make M=samples/bpf LLC=~/git/llvm-project/llvm/build/bin/llc CLANG=~/git/llvm-project/llvm/build/bin/clang
diff --git a/samples/bpf/xdp1_kern.c b/samples/bpf/xdp1_kern.c
index f0c5d95084de..0a5c704badd0 100644
--- a/samples/bpf/xdp1_kern.c
+++ b/samples/bpf/xdp1_kern.c
@@ -39,11 +39,13 @@ static int parse_ipv6(void *data, u64 nh_off, void *data_end)
return ip6h->nexthdr;
}
-SEC("xdp1")
+#define XDPBUFSIZE 64
+SEC("xdp.frags")
int xdp_prog1(struct xdp_md *ctx)
{
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
+ __u8 pkt[XDPBUFSIZE] = {};
+ void *data_end = &pkt[XDPBUFSIZE-1];
+ void *data = pkt;
struct ethhdr *eth = data;
int rc = XDP_DROP;
long *value;
@@ -51,6 +53,9 @@ int xdp_prog1(struct xdp_md *ctx)
u64 nh_off;
u32 ipproto;
+ if (bpf_xdp_load_bytes(ctx, 0, pkt, sizeof(pkt)))
+ return rc;
+
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
return rc;
diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c
index d8a64ab077b0..3332ba6bb95f 100644
--- a/samples/bpf/xdp2_kern.c
+++ b/samples/bpf/xdp2_kern.c
@@ -55,11 +55,13 @@ static int parse_ipv6(void *data, u64 nh_off, void *data_end)
return ip6h->nexthdr;
}
-SEC("xdp1")
+#define XDPBUFSIZE 64
+SEC("xdp.frags")
int xdp_prog1(struct xdp_md *ctx)
{
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
+ __u8 pkt[XDPBUFSIZE] = {};
+ void *data_end = &pkt[XDPBUFSIZE-1];
+ void *data = pkt;
struct ethhdr *eth = data;
int rc = XDP_DROP;
long *value;
@@ -67,6 +69,9 @@ int xdp_prog1(struct xdp_md *ctx)
u64 nh_off;
u32 ipproto;
+ if (bpf_xdp_load_bytes(ctx, 0, pkt, sizeof(pkt)))
+ return rc;
+
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
return rc;
diff --git a/samples/bpf/xdp_tx_iptunnel_kern.c b/samples/bpf/xdp_tx_iptunnel_kern.c
index 575d57e4b8d6..0e2bca3a3fff 100644
--- a/samples/bpf/xdp_tx_iptunnel_kern.c
+++ b/samples/bpf/xdp_tx_iptunnel_kern.c
@@ -212,7 +212,7 @@ static __always_inline int handle_ipv6(struct xdp_md *xdp)
return XDP_TX;
}
-SEC("xdp_tx_iptunnel")
+SEC("xdp.frags")
int _xdp_tx_iptunnel(struct xdp_md *xdp)
{
void *data_end = (void *)(long)xdp->data_end;
diff --git a/samples/bpf/xdpsock.h b/samples/bpf/xdpsock.h
deleted file mode 100644
index fd70cce60712..000000000000
--- a/samples/bpf/xdpsock.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright(c) 2019 Intel Corporation.
- */
-
-#ifndef XDPSOCK_H_
-#define XDPSOCK_H_
-
-#define MAX_SOCKS 4
-
-#define SOCKET_NAME "sock_cal_bpf_fd"
-#define MAX_NUM_OF_CLIENTS 10
-
-#define CLOSE_CONN 1
-
-typedef __u64 u64;
-typedef __u32 u32;
-
-#endif /* XDPSOCK_H */
diff --git a/samples/bpf/xdpsock_ctrl_proc.c b/samples/bpf/xdpsock_ctrl_proc.c
deleted file mode 100644
index 28b5f2a9fa08..000000000000
--- a/samples/bpf/xdpsock_ctrl_proc.c
+++ /dev/null
@@ -1,190 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2017 - 2018 Intel Corporation. */
-
-#include <errno.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <net/if.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <bpf/bpf.h>
-#include <bpf/xsk.h>
-#include "xdpsock.h"
-
-/* libbpf APIs for AF_XDP are deprecated starting from v0.7 */
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-static const char *opt_if = "";
-
-static struct option long_options[] = {
- {"interface", required_argument, 0, 'i'},
- {0, 0, 0, 0}
-};
-
-static void usage(const char *prog)
-{
- const char *str =
- " Usage: %s [OPTIONS]\n"
- " Options:\n"
- " -i, --interface=n Run on interface n\n"
- "\n";
- fprintf(stderr, "%s\n", str);
-
- exit(0);
-}
-
-static void parse_command_line(int argc, char **argv)
-{
- int option_index, c;
-
- opterr = 0;
-
- for (;;) {
- c = getopt_long(argc, argv, "i:",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c) {
- case 'i':
- opt_if = optarg;
- break;
- default:
- usage(basename(argv[0]));
- }
- }
-}
-
-static int send_xsks_map_fd(int sock, int fd)
-{
- char cmsgbuf[CMSG_SPACE(sizeof(int))];
- struct msghdr msg;
- struct iovec iov;
- int value = 0;
-
- if (fd == -1) {
- fprintf(stderr, "Incorrect fd = %d\n", fd);
- return -1;
- }
- iov.iov_base = &value;
- iov.iov_len = sizeof(int);
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = CMSG_LEN(sizeof(int));
-
- struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
-
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-
- *(int *)CMSG_DATA(cmsg) = fd;
- int ret = sendmsg(sock, &msg, 0);
-
- if (ret == -1) {
- fprintf(stderr, "Sendmsg failed with %s", strerror(errno));
- return -errno;
- }
-
- return ret;
-}
-
-int
-main(int argc, char **argv)
-{
- struct sockaddr_un server;
- int listening = 1;
- int rval, msgsock;
- int ifindex = 0;
- int flag = 1;
- int cmd = 0;
- int sock;
- int err;
- int xsks_map_fd;
-
- parse_command_line(argc, argv);
-
- ifindex = if_nametoindex(opt_if);
- if (ifindex == 0) {
- fprintf(stderr, "Unable to get ifindex for Interface %s. Reason:%s",
- opt_if, strerror(errno));
- return -errno;
- }
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- fprintf(stderr, "Opening socket stream failed: %s", strerror(errno));
- return -errno;
- }
-
- server.sun_family = AF_UNIX;
- strcpy(server.sun_path, SOCKET_NAME);
-
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
-
- if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un))) {
- fprintf(stderr, "Binding to socket stream failed: %s", strerror(errno));
- return -errno;
- }
-
- listen(sock, MAX_NUM_OF_CLIENTS);
-
- err = xsk_setup_xdp_prog(ifindex, &xsks_map_fd);
- if (err) {
- fprintf(stderr, "Setup of xdp program failed\n");
- goto close_sock;
- }
-
- while (listening) {
- msgsock = accept(sock, 0, 0);
- if (msgsock == -1) {
- fprintf(stderr, "Error accepting connection: %s", strerror(errno));
- err = -errno;
- goto close_sock;
- }
- err = send_xsks_map_fd(msgsock, xsks_map_fd);
- if (err <= 0) {
- fprintf(stderr, "Error %d sending xsks_map_fd\n", err);
- goto cleanup;
- }
- do {
- rval = read(msgsock, &cmd, sizeof(int));
- if (rval < 0) {
- fprintf(stderr, "Error reading stream message");
- } else {
- if (cmd != CLOSE_CONN)
- fprintf(stderr, "Recv unknown cmd = %d\n", cmd);
- listening = 0;
- break;
- }
- } while (rval > 0);
- }
- close(msgsock);
- close(sock);
- unlink(SOCKET_NAME);
-
- /* Unset fd for given ifindex */
- err = bpf_xdp_detach(ifindex, 0, NULL);
- if (err) {
- fprintf(stderr, "Error when unsetting bpf prog_fd for ifindex(%d)\n", ifindex);
- return err;
- }
-
- return 0;
-
-cleanup:
- close(msgsock);
-close_sock:
- close(sock);
- unlink(SOCKET_NAME);
- return err;
-}
diff --git a/samples/bpf/xdpsock_kern.c b/samples/bpf/xdpsock_kern.c
deleted file mode 100644
index 05430484375c..000000000000
--- a/samples/bpf/xdpsock_kern.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/bpf.h>
-#include <bpf/bpf_helpers.h>
-#include "xdpsock.h"
-
-/* This XDP program is only needed for the XDP_SHARED_UMEM mode.
- * If you do not use this mode, libbpf can supply an XDP program for you.
- */
-
-struct {
- __uint(type, BPF_MAP_TYPE_XSKMAP);
- __uint(max_entries, MAX_SOCKS);
- __uint(key_size, sizeof(int));
- __uint(value_size, sizeof(int));
-} xsks_map SEC(".maps");
-
-static unsigned int rr;
-
-SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
-{
- rr = (rr + 1) & (MAX_SOCKS - 1);
-
- return bpf_redirect_map(&xsks_map, rr, XDP_DROP);
-}
diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
deleted file mode 100644
index be7d2572e3e6..000000000000
--- a/samples/bpf/xdpsock_user.c
+++ /dev/null
@@ -1,2019 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2017 - 2018 Intel Corporation. */
-
-#include <errno.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <linux/bpf.h>
-#include <linux/if_link.h>
-#include <linux/if_xdp.h>
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <linux/limits.h>
-#include <linux/udp.h>
-#include <arpa/inet.h>
-#include <locale.h>
-#include <net/ethernet.h>
-#include <netinet/ether.h>
-#include <net/if.h>
-#include <poll.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <time.h>
-#include <unistd.h>
-#include <sched.h>
-
-#include <bpf/libbpf.h>
-#include <bpf/xsk.h>
-#include <bpf/bpf.h>
-#include "xdpsock.h"
-
-/* libbpf APIs for AF_XDP are deprecated starting from v0.7 */
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-#ifndef SOL_XDP
-#define SOL_XDP 283
-#endif
-
-#ifndef AF_XDP
-#define AF_XDP 44
-#endif
-
-#ifndef PF_XDP
-#define PF_XDP AF_XDP
-#endif
-
-#define NUM_FRAMES (4 * 1024)
-#define MIN_PKT_SIZE 64
-
-#define DEBUG_HEXDUMP 0
-
-#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
-#define VLAN_PRIO_SHIFT 13
-#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
-#define VLAN_VID__DEFAULT 1
-#define VLAN_PRI__DEFAULT 0
-
-#define NSEC_PER_SEC 1000000000UL
-#define NSEC_PER_USEC 1000
-
-#define SCHED_PRI__DEFAULT 0
-
-typedef __u64 u64;
-typedef __u32 u32;
-typedef __u16 u16;
-typedef __u8 u8;
-
-static unsigned long prev_time;
-static long tx_cycle_diff_min;
-static long tx_cycle_diff_max;
-static double tx_cycle_diff_ave;
-static long tx_cycle_cnt;
-
-enum benchmark_type {
- BENCH_RXDROP = 0,
- BENCH_TXONLY = 1,
- BENCH_L2FWD = 2,
-};
-
-static enum benchmark_type opt_bench = BENCH_RXDROP;
-static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
-static const char *opt_if = "";
-static int opt_ifindex;
-static int opt_queue;
-static unsigned long opt_duration;
-static unsigned long start_time;
-static bool benchmark_done;
-static u32 opt_batch_size = 64;
-static int opt_pkt_count;
-static u16 opt_pkt_size = MIN_PKT_SIZE;
-static u32 opt_pkt_fill_pattern = 0x12345678;
-static bool opt_vlan_tag;
-static u16 opt_pkt_vlan_id = VLAN_VID__DEFAULT;
-static u16 opt_pkt_vlan_pri = VLAN_PRI__DEFAULT;
-static struct ether_addr opt_txdmac = {{ 0x3c, 0xfd, 0xfe,
- 0x9e, 0x7f, 0x71 }};
-static struct ether_addr opt_txsmac = {{ 0xec, 0xb1, 0xd7,
- 0x98, 0x3a, 0xc0 }};
-static bool opt_extra_stats;
-static bool opt_quiet;
-static bool opt_app_stats;
-static const char *opt_irq_str = "";
-static u32 irq_no;
-static int irqs_at_init = -1;
-static u32 sequence;
-static int opt_poll;
-static int opt_interval = 1;
-static int opt_retries = 3;
-static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
-static u32 opt_umem_flags;
-static int opt_unaligned_chunks;
-static int opt_mmap_flags;
-static int opt_xsk_frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
-static int opt_timeout = 1000;
-static bool opt_need_wakeup = true;
-static u32 opt_num_xsks = 1;
-static u32 prog_id;
-static bool opt_busy_poll;
-static bool opt_reduced_cap;
-static clockid_t opt_clock = CLOCK_MONOTONIC;
-static unsigned long opt_tx_cycle_ns;
-static int opt_schpolicy = SCHED_OTHER;
-static int opt_schprio = SCHED_PRI__DEFAULT;
-static bool opt_tstamp;
-
-struct vlan_ethhdr {
- unsigned char h_dest[6];
- unsigned char h_source[6];
- __be16 h_vlan_proto;
- __be16 h_vlan_TCI;
- __be16 h_vlan_encapsulated_proto;
-};
-
-#define PKTGEN_MAGIC 0xbe9be955
-struct pktgen_hdr {
- __be32 pgh_magic;
- __be32 seq_num;
- __be32 tv_sec;
- __be32 tv_usec;
-};
-
-struct xsk_ring_stats {
- unsigned long rx_npkts;
- unsigned long tx_npkts;
- unsigned long rx_dropped_npkts;
- unsigned long rx_invalid_npkts;
- unsigned long tx_invalid_npkts;
- unsigned long rx_full_npkts;
- unsigned long rx_fill_empty_npkts;
- unsigned long tx_empty_npkts;
- unsigned long prev_rx_npkts;
- unsigned long prev_tx_npkts;
- unsigned long prev_rx_dropped_npkts;
- unsigned long prev_rx_invalid_npkts;
- unsigned long prev_tx_invalid_npkts;
- unsigned long prev_rx_full_npkts;
- unsigned long prev_rx_fill_empty_npkts;
- unsigned long prev_tx_empty_npkts;
-};
-
-struct xsk_driver_stats {
- unsigned long intrs;
- unsigned long prev_intrs;
-};
-
-struct xsk_app_stats {
- unsigned long rx_empty_polls;
- unsigned long fill_fail_polls;
- unsigned long copy_tx_sendtos;
- unsigned long tx_wakeup_sendtos;
- unsigned long opt_polls;
- unsigned long prev_rx_empty_polls;
- unsigned long prev_fill_fail_polls;
- unsigned long prev_copy_tx_sendtos;
- unsigned long prev_tx_wakeup_sendtos;
- unsigned long prev_opt_polls;
-};
-
-struct xsk_umem_info {
- struct xsk_ring_prod fq;
- struct xsk_ring_cons cq;
- struct xsk_umem *umem;
- void *buffer;
-};
-
-struct xsk_socket_info {
- struct xsk_ring_cons rx;
- struct xsk_ring_prod tx;
- struct xsk_umem_info *umem;
- struct xsk_socket *xsk;
- struct xsk_ring_stats ring_stats;
- struct xsk_app_stats app_stats;
- struct xsk_driver_stats drv_stats;
- u32 outstanding_tx;
-};
-
-static const struct clockid_map {
- const char *name;
- clockid_t clockid;
-} clockids_map[] = {
- { "REALTIME", CLOCK_REALTIME },
- { "TAI", CLOCK_TAI },
- { "BOOTTIME", CLOCK_BOOTTIME },
- { "MONOTONIC", CLOCK_MONOTONIC },
- { NULL }
-};
-
-static const struct sched_map {
- const char *name;
- int policy;
-} schmap[] = {
- { "OTHER", SCHED_OTHER },
- { "FIFO", SCHED_FIFO },
- { NULL }
-};
-
-static int num_socks;
-struct xsk_socket_info *xsks[MAX_SOCKS];
-int sock;
-
-static int get_clockid(clockid_t *id, const char *name)
-{
- const struct clockid_map *clk;
-
- for (clk = clockids_map; clk->name; clk++) {
- if (strcasecmp(clk->name, name) == 0) {
- *id = clk->clockid;
- return 0;
- }
- }
-
- return -1;
-}
-
-static int get_schpolicy(int *policy, const char *name)
-{
- const struct sched_map *sch;
-
- for (sch = schmap; sch->name; sch++) {
- if (strcasecmp(sch->name, name) == 0) {
- *policy = sch->policy;
- return 0;
- }
- }
-
- return -1;
-}
-
-static unsigned long get_nsecs(void)
-{
- struct timespec ts;
-
- clock_gettime(opt_clock, &ts);
- return ts.tv_sec * 1000000000UL + ts.tv_nsec;
-}
-
-static void print_benchmark(bool running)
-{
- const char *bench_str = "INVALID";
-
- if (opt_bench == BENCH_RXDROP)
- bench_str = "rxdrop";
- else if (opt_bench == BENCH_TXONLY)
- bench_str = "txonly";
- else if (opt_bench == BENCH_L2FWD)
- bench_str = "l2fwd";
-
- printf("%s:%d %s ", opt_if, opt_queue, bench_str);
- if (opt_xdp_flags & XDP_FLAGS_SKB_MODE)
- printf("xdp-skb ");
- else if (opt_xdp_flags & XDP_FLAGS_DRV_MODE)
- printf("xdp-drv ");
- else
- printf(" ");
-
- if (opt_poll)
- printf("poll() ");
-
- if (running) {
- printf("running...");
- fflush(stdout);
- }
-}
-
-static int xsk_get_xdp_stats(int fd, struct xsk_socket_info *xsk)
-{
- struct xdp_statistics stats;
- socklen_t optlen;
- int err;
-
- optlen = sizeof(stats);
- err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen);
- if (err)
- return err;
-
- if (optlen == sizeof(struct xdp_statistics)) {
- xsk->ring_stats.rx_dropped_npkts = stats.rx_dropped;
- xsk->ring_stats.rx_invalid_npkts = stats.rx_invalid_descs;
- xsk->ring_stats.tx_invalid_npkts = stats.tx_invalid_descs;
- xsk->ring_stats.rx_full_npkts = stats.rx_ring_full;
- xsk->ring_stats.rx_fill_empty_npkts = stats.rx_fill_ring_empty_descs;
- xsk->ring_stats.tx_empty_npkts = stats.tx_ring_empty_descs;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static void dump_app_stats(long dt)
-{
- int i;
-
- for (i = 0; i < num_socks && xsks[i]; i++) {
- char *fmt = "%-18s %'-14.0f %'-14lu\n";
- double rx_empty_polls_ps, fill_fail_polls_ps, copy_tx_sendtos_ps,
- tx_wakeup_sendtos_ps, opt_polls_ps;
-
- rx_empty_polls_ps = (xsks[i]->app_stats.rx_empty_polls -
- xsks[i]->app_stats.prev_rx_empty_polls) * 1000000000. / dt;
- fill_fail_polls_ps = (xsks[i]->app_stats.fill_fail_polls -
- xsks[i]->app_stats.prev_fill_fail_polls) * 1000000000. / dt;
- copy_tx_sendtos_ps = (xsks[i]->app_stats.copy_tx_sendtos -
- xsks[i]->app_stats.prev_copy_tx_sendtos) * 1000000000. / dt;
- tx_wakeup_sendtos_ps = (xsks[i]->app_stats.tx_wakeup_sendtos -
- xsks[i]->app_stats.prev_tx_wakeup_sendtos)
- * 1000000000. / dt;
- opt_polls_ps = (xsks[i]->app_stats.opt_polls -
- xsks[i]->app_stats.prev_opt_polls) * 1000000000. / dt;
-
- printf("\n%-18s %-14s %-14s\n", "", "calls/s", "count");
- printf(fmt, "rx empty polls", rx_empty_polls_ps, xsks[i]->app_stats.rx_empty_polls);
- printf(fmt, "fill fail polls", fill_fail_polls_ps,
- xsks[i]->app_stats.fill_fail_polls);
- printf(fmt, "copy tx sendtos", copy_tx_sendtos_ps,
- xsks[i]->app_stats.copy_tx_sendtos);
- printf(fmt, "tx wakeup sendtos", tx_wakeup_sendtos_ps,
- xsks[i]->app_stats.tx_wakeup_sendtos);
- printf(fmt, "opt polls", opt_polls_ps, xsks[i]->app_stats.opt_polls);
-
- xsks[i]->app_stats.prev_rx_empty_polls = xsks[i]->app_stats.rx_empty_polls;
- xsks[i]->app_stats.prev_fill_fail_polls = xsks[i]->app_stats.fill_fail_polls;
- xsks[i]->app_stats.prev_copy_tx_sendtos = xsks[i]->app_stats.copy_tx_sendtos;
- xsks[i]->app_stats.prev_tx_wakeup_sendtos = xsks[i]->app_stats.tx_wakeup_sendtos;
- xsks[i]->app_stats.prev_opt_polls = xsks[i]->app_stats.opt_polls;
- }
-
- if (opt_tx_cycle_ns) {
- printf("\n%-18s %-10s %-10s %-10s %-10s %-10s\n",
- "", "period", "min", "ave", "max", "cycle");
- printf("%-18s %-10lu %-10lu %-10lu %-10lu %-10lu\n",
- "Cyclic TX", opt_tx_cycle_ns, tx_cycle_diff_min,
- (long)(tx_cycle_diff_ave / tx_cycle_cnt),
- tx_cycle_diff_max, tx_cycle_cnt);
- }
-}
-
-static bool get_interrupt_number(void)
-{
- FILE *f_int_proc;
- char line[4096];
- bool found = false;
-
- f_int_proc = fopen("/proc/interrupts", "r");
- if (f_int_proc == NULL) {
- printf("Failed to open /proc/interrupts.\n");
- return found;
- }
-
- while (!feof(f_int_proc) && !found) {
- /* Make sure to read a full line at a time */
- if (fgets(line, sizeof(line), f_int_proc) == NULL ||
- line[strlen(line) - 1] != '\n') {
- printf("Error reading from interrupts file\n");
- break;
- }
-
- /* Extract interrupt number from line */
- if (strstr(line, opt_irq_str) != NULL) {
- irq_no = atoi(line);
- found = true;
- break;
- }
- }
-
- fclose(f_int_proc);
-
- return found;
-}
-
-static int get_irqs(void)
-{
- char count_path[PATH_MAX];
- int total_intrs = -1;
- FILE *f_count_proc;
- char line[4096];
-
- snprintf(count_path, sizeof(count_path),
- "/sys/kernel/irq/%i/per_cpu_count", irq_no);
- f_count_proc = fopen(count_path, "r");
- if (f_count_proc == NULL) {
- printf("Failed to open %s\n", count_path);
- return total_intrs;
- }
-
- if (fgets(line, sizeof(line), f_count_proc) == NULL ||
- line[strlen(line) - 1] != '\n') {
- printf("Error reading from %s\n", count_path);
- } else {
- static const char com[2] = ",";
- char *token;
-
- total_intrs = 0;
- token = strtok(line, com);
- while (token != NULL) {
- /* sum up interrupts across all cores */
- total_intrs += atoi(token);
- token = strtok(NULL, com);
- }
- }
-
- fclose(f_count_proc);
-
- return total_intrs;
-}
-
-static void dump_driver_stats(long dt)
-{
- int i;
-
- for (i = 0; i < num_socks && xsks[i]; i++) {
- char *fmt = "%-18s %'-14.0f %'-14lu\n";
- double intrs_ps;
- int n_ints = get_irqs();
-
- if (n_ints < 0) {
- printf("error getting intr info for intr %i\n", irq_no);
- return;
- }
- xsks[i]->drv_stats.intrs = n_ints - irqs_at_init;
-
- intrs_ps = (xsks[i]->drv_stats.intrs - xsks[i]->drv_stats.prev_intrs) *
- 1000000000. / dt;
-
- printf("\n%-18s %-14s %-14s\n", "", "intrs/s", "count");
- printf(fmt, "irqs", intrs_ps, xsks[i]->drv_stats.intrs);
-
- xsks[i]->drv_stats.prev_intrs = xsks[i]->drv_stats.intrs;
- }
-}
-
-static void dump_stats(void)
-{
- unsigned long now = get_nsecs();
- long dt = now - prev_time;
- int i;
-
- prev_time = now;
-
- for (i = 0; i < num_socks && xsks[i]; i++) {
- char *fmt = "%-18s %'-14.0f %'-14lu\n";
- double rx_pps, tx_pps, dropped_pps, rx_invalid_pps, full_pps, fill_empty_pps,
- tx_invalid_pps, tx_empty_pps;
-
- rx_pps = (xsks[i]->ring_stats.rx_npkts - xsks[i]->ring_stats.prev_rx_npkts) *
- 1000000000. / dt;
- tx_pps = (xsks[i]->ring_stats.tx_npkts - xsks[i]->ring_stats.prev_tx_npkts) *
- 1000000000. / dt;
-
- printf("\n sock%d@", i);
- print_benchmark(false);
- printf("\n");
-
- printf("%-18s %-14s %-14s %-14.2f\n", "", "pps", "pkts",
- dt / 1000000000.);
- printf(fmt, "rx", rx_pps, xsks[i]->ring_stats.rx_npkts);
- printf(fmt, "tx", tx_pps, xsks[i]->ring_stats.tx_npkts);
-
- xsks[i]->ring_stats.prev_rx_npkts = xsks[i]->ring_stats.rx_npkts;
- xsks[i]->ring_stats.prev_tx_npkts = xsks[i]->ring_stats.tx_npkts;
-
- if (opt_extra_stats) {
- if (!xsk_get_xdp_stats(xsk_socket__fd(xsks[i]->xsk), xsks[i])) {
- dropped_pps = (xsks[i]->ring_stats.rx_dropped_npkts -
- xsks[i]->ring_stats.prev_rx_dropped_npkts) *
- 1000000000. / dt;
- rx_invalid_pps = (xsks[i]->ring_stats.rx_invalid_npkts -
- xsks[i]->ring_stats.prev_rx_invalid_npkts) *
- 1000000000. / dt;
- tx_invalid_pps = (xsks[i]->ring_stats.tx_invalid_npkts -
- xsks[i]->ring_stats.prev_tx_invalid_npkts) *
- 1000000000. / dt;
- full_pps = (xsks[i]->ring_stats.rx_full_npkts -
- xsks[i]->ring_stats.prev_rx_full_npkts) *
- 1000000000. / dt;
- fill_empty_pps = (xsks[i]->ring_stats.rx_fill_empty_npkts -
- xsks[i]->ring_stats.prev_rx_fill_empty_npkts) *
- 1000000000. / dt;
- tx_empty_pps = (xsks[i]->ring_stats.tx_empty_npkts -
- xsks[i]->ring_stats.prev_tx_empty_npkts) *
- 1000000000. / dt;
-
- printf(fmt, "rx dropped", dropped_pps,
- xsks[i]->ring_stats.rx_dropped_npkts);
- printf(fmt, "rx invalid", rx_invalid_pps,
- xsks[i]->ring_stats.rx_invalid_npkts);
- printf(fmt, "tx invalid", tx_invalid_pps,
- xsks[i]->ring_stats.tx_invalid_npkts);
- printf(fmt, "rx queue full", full_pps,
- xsks[i]->ring_stats.rx_full_npkts);
- printf(fmt, "fill ring empty", fill_empty_pps,
- xsks[i]->ring_stats.rx_fill_empty_npkts);
- printf(fmt, "tx ring empty", tx_empty_pps,
- xsks[i]->ring_stats.tx_empty_npkts);
-
- xsks[i]->ring_stats.prev_rx_dropped_npkts =
- xsks[i]->ring_stats.rx_dropped_npkts;
- xsks[i]->ring_stats.prev_rx_invalid_npkts =
- xsks[i]->ring_stats.rx_invalid_npkts;
- xsks[i]->ring_stats.prev_tx_invalid_npkts =
- xsks[i]->ring_stats.tx_invalid_npkts;
- xsks[i]->ring_stats.prev_rx_full_npkts =
- xsks[i]->ring_stats.rx_full_npkts;
- xsks[i]->ring_stats.prev_rx_fill_empty_npkts =
- xsks[i]->ring_stats.rx_fill_empty_npkts;
- xsks[i]->ring_stats.prev_tx_empty_npkts =
- xsks[i]->ring_stats.tx_empty_npkts;
- } else {
- printf("%-15s\n", "Error retrieving extra stats");
- }
- }
- }
-
- if (opt_app_stats)
- dump_app_stats(dt);
- if (irq_no)
- dump_driver_stats(dt);
-}
-
-static bool is_benchmark_done(void)
-{
- if (opt_duration > 0) {
- unsigned long dt = (get_nsecs() - start_time);
-
- if (dt >= opt_duration)
- benchmark_done = true;
- }
- return benchmark_done;
-}
-
-static void *poller(void *arg)
-{
- (void)arg;
- while (!is_benchmark_done()) {
- sleep(opt_interval);
- dump_stats();
- }
-
- return NULL;
-}
-
-static void remove_xdp_program(void)
-{
- u32 curr_prog_id = 0;
-
- if (bpf_xdp_query_id(opt_ifindex, opt_xdp_flags, &curr_prog_id)) {
- printf("bpf_xdp_query_id failed\n");
- exit(EXIT_FAILURE);
- }
-
- if (prog_id == curr_prog_id)
- bpf_xdp_detach(opt_ifindex, opt_xdp_flags, NULL);
- else if (!curr_prog_id)
- printf("couldn't find a prog id on a given interface\n");
- else
- printf("program on interface changed, not removing\n");
-}
-
-static void int_exit(int sig)
-{
- benchmark_done = true;
-}
-
-static void __exit_with_error(int error, const char *file, const char *func,
- int line)
-{
- fprintf(stderr, "%s:%s:%i: errno: %d/\"%s\"\n", file, func,
- line, error, strerror(error));
-
- if (opt_num_xsks > 1)
- remove_xdp_program();
- exit(EXIT_FAILURE);
-}
-
-#define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__)
-
-static void xdpsock_cleanup(void)
-{
- struct xsk_umem *umem = xsks[0]->umem->umem;
- int i, cmd = CLOSE_CONN;
-
- dump_stats();
- for (i = 0; i < num_socks; i++)
- xsk_socket__delete(xsks[i]->xsk);
- (void)xsk_umem__delete(umem);
-
- if (opt_reduced_cap) {
- if (write(sock, &cmd, sizeof(int)) < 0)
- exit_with_error(errno);
- }
-
- if (opt_num_xsks > 1)
- remove_xdp_program();
-}
-
-static void swap_mac_addresses(void *data)
-{
- struct ether_header *eth = (struct ether_header *)data;
- struct ether_addr *src_addr = (struct ether_addr *)&eth->ether_shost;
- struct ether_addr *dst_addr = (struct ether_addr *)&eth->ether_dhost;
- struct ether_addr tmp;
-
- tmp = *src_addr;
- *src_addr = *dst_addr;
- *dst_addr = tmp;
-}
-
-static void hex_dump(void *pkt, size_t length, u64 addr)
-{
- const unsigned char *address = (unsigned char *)pkt;
- const unsigned char *line = address;
- size_t line_size = 32;
- unsigned char c;
- char buf[32];
- int i = 0;
-
- if (!DEBUG_HEXDUMP)
- return;
-
- sprintf(buf, "addr=%llu", addr);
- printf("length = %zu\n", length);
- printf("%s | ", buf);