summaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-15 18:04:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-15 18:04:25 -0400
commit9a76aba02a37718242d7cdc294f0a3901928aa57 (patch)
tree2040d038f85d2120f21af83b0793efd5af1864e3 /samples
parent0a957467c5fd46142bc9c52758ffc552d4c5e2f7 (diff)
parent26a1ccc6c117be8e33e0410fce8c5298b0015b99 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Highlights: - Gustavo A. R. Silva keeps working on the implicit switch fallthru changes. - Support 802.11ax High-Efficiency wireless in cfg80211 et al, From Luca Coelho. - Re-enable ASPM in r8169, from Kai-Heng Feng. - Add virtual XFRM interfaces, which avoids all of the limitations of existing IPSEC tunnels. From Steffen Klassert. - Convert GRO over to use a hash table, so that when we have many flows active we don't traverse a long list during accumluation. - Many new self tests for routing, TC, tunnels, etc. Too many contributors to mention them all, but I'm really happy to keep seeing this stuff. - Hardware timestamping support for dpaa_eth/fsl-fman from Yangbo Lu. - Lots of cleanups and fixes in L2TP code from Guillaume Nault. - Add IPSEC offload support to netdevsim, from Shannon Nelson. - Add support for slotting with non-uniform distribution to netem packet scheduler, from Yousuk Seung. - Add UDP GSO support to mlx5e, from Boris Pismenny. - Support offloading of Team LAG in NFP, from John Hurley. - Allow to configure TX queue selection based upon RX queue, from Amritha Nambiar. - Support ethtool ring size configuration in aquantia, from Anton Mikaev. - Support DSCP and flowlabel per-transport in SCTP, from Xin Long. - Support list based batching and stack traversal of SKBs, this is very exciting work. From Edward Cree. - Busyloop optimizations in vhost_net, from Toshiaki Makita. - Introduce the ETF qdisc, which allows time based transmissions. IGB can offload this in hardware. From Vinicius Costa Gomes. - Add parameter support to devlink, from Moshe Shemesh. - Several multiplication and division optimizations for BPF JIT in nfp driver, from Jiong Wang. - Lots of prepatory work to make more of the packet scheduler layer lockless, when possible, from Vlad Buslov. - Add ACK filter and NAT awareness to sch_cake packet scheduler, from Toke Høiland-Jørgensen. - Support regions and region snapshots in devlink, from Alex Vesker. - Allow to attach XDP programs to both HW and SW at the same time on a given device, with initial support in nfp. From Jakub Kicinski. - Add TLS RX offload and support in mlx5, from Ilya Lesokhin. - Use PHYLIB in r8169 driver, from Heiner Kallweit. - All sorts of changes to support Spectrum 2 in mlxsw driver, from Ido Schimmel. - PTP support in mv88e6xxx DSA driver, from Andrew Lunn. - Make TCP_USER_TIMEOUT socket option more accurate, from Jon Maxwell. - Support for templates in packet scheduler classifier, from Jiri Pirko. - IPV6 support in RDS, from Ka-Cheong Poon. - Native tproxy support in nf_tables, from Máté Eckl. - Maintain IP fragment queue in an rbtree, but optimize properly for in-order frags. From Peter Oskolkov. - Improvde handling of ACKs on hole repairs, from Yuchung Cheng" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1996 commits) bpf: test: fix spelling mistake "REUSEEPORT" -> "REUSEPORT" hv/netvsc: Fix NULL dereference at single queue mode fallback net: filter: mark expected switch fall-through xen-netfront: fix warn message as irq device name has '/' cxgb4: Add new T5 PCI device ids 0x50af and 0x50b0 net: dsa: mv88e6xxx: missing unlock on error path rds: fix building with IPV6=m inet/connection_sock: prefer _THIS_IP_ to current_text_addr net: dsa: mv88e6xxx: bitwise vs logical bug net: sock_diag: Fix spectre v1 gadget in __sock_diag_cmd() ieee802154: hwsim: using right kind of iteration net: hns3: Add vlan filter setting by ethtool command -K net: hns3: Set tx ring' tc info when netdev is up net: hns3: Remove tx ring BD len register in hns3_enet net: hns3: Fix desc num set to default when setting channel net: hns3: Fix for phy link issue when using marvell phy driver net: hns3: Fix for information of phydev lost problem when down/up net: hns3: Fix for command format parsing error in hclge_is_all_function_id_zero net: hns3: Add support for serdes loopback selftest bnxt_en: take coredump_record structure off stack ...
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/Makefile25
-rw-r--r--samples/bpf/bpf_load.c3
-rw-r--r--samples/bpf/hash_func01.h55
-rw-r--r--samples/bpf/test_cgrp2_attach2.c21
-rw-r--r--samples/bpf/test_cgrp2_sock2.c2
-rw-r--r--samples/bpf/xdp_fwd_user.c34
-rw-r--r--samples/bpf/xdp_redirect_cpu_kern.c114
-rw-r--r--samples/bpf/xdp_redirect_cpu_user.c4
-rw-r--r--samples/bpf/xdp_rxq_info_kern.c43
-rw-r--r--samples/bpf/xdp_rxq_info_user.c45
-rw-r--r--samples/bpf/xdp_sample_pkts_kern.c66
-rw-r--r--samples/bpf/xdp_sample_pkts_user.c169
-rw-r--r--samples/bpf/xdpsock_user.c43
13 files changed, 590 insertions, 34 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index bd9f6c2a808e..36f9f41d094b 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -52,6 +52,7 @@ hostprogs-y += xdp_adjust_tail
52hostprogs-y += xdpsock 52hostprogs-y += xdpsock
53hostprogs-y += xdp_fwd 53hostprogs-y += xdp_fwd
54hostprogs-y += task_fd_query 54hostprogs-y += task_fd_query
55hostprogs-y += xdp_sample_pkts
55 56
56# Libbpf dependencies 57# Libbpf dependencies
57LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a 58LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
@@ -104,9 +105,10 @@ xdp_rxq_info-objs := xdp_rxq_info_user.o
104syscall_tp-objs := bpf_load.o syscall_tp_user.o 105syscall_tp-objs := bpf_load.o syscall_tp_user.o
105cpustat-objs := bpf_load.o cpustat_user.o 106cpustat-objs := bpf_load.o cpustat_user.o
106xdp_adjust_tail-objs := xdp_adjust_tail_user.o 107xdp_adjust_tail-objs := xdp_adjust_tail_user.o
107xdpsock-objs := bpf_load.o xdpsock_user.o 108xdpsock-objs := xdpsock_user.o
108xdp_fwd-objs := bpf_load.o xdp_fwd_user.o 109xdp_fwd-objs := xdp_fwd_user.o
109task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) 110task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
111xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
110 112
111# Tell kbuild to always build the programs 113# Tell kbuild to always build the programs
112always := $(hostprogs-y) 114always := $(hostprogs-y)
@@ -163,6 +165,7 @@ always += xdp_adjust_tail_kern.o
163always += xdpsock_kern.o 165always += xdpsock_kern.o
164always += xdp_fwd_kern.o 166always += xdp_fwd_kern.o
165always += task_fd_query_kern.o 167always += task_fd_query_kern.o
168always += xdp_sample_pkts_kern.o
166 169
167KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include 170KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include
168KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/ 171KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/
@@ -179,6 +182,7 @@ HOSTCFLAGS_spintest_user.o += -I$(srctree)/tools/lib/bpf/
179HOSTCFLAGS_trace_event_user.o += -I$(srctree)/tools/lib/bpf/ 182HOSTCFLAGS_trace_event_user.o += -I$(srctree)/tools/lib/bpf/
180HOSTCFLAGS_sampleip_user.o += -I$(srctree)/tools/lib/bpf/ 183HOSTCFLAGS_sampleip_user.o += -I$(srctree)/tools/lib/bpf/
181HOSTCFLAGS_task_fd_query_user.o += -I$(srctree)/tools/lib/bpf/ 184HOSTCFLAGS_task_fd_query_user.o += -I$(srctree)/tools/lib/bpf/
185HOSTCFLAGS_xdp_sample_pkts_user.o += -I$(srctree)/tools/lib/bpf/
182 186
183KBUILD_HOSTLDLIBS += $(LIBBPF) -lelf 187KBUILD_HOSTLDLIBS += $(LIBBPF) -lelf
184HOSTLDLIBS_tracex4 += -lrt 188HOSTLDLIBS_tracex4 += -lrt
@@ -191,6 +195,8 @@ HOSTLDLIBS_xdpsock += -pthread
191# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang 195# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
192LLC ?= llc 196LLC ?= llc
193CLANG ?= clang 197CLANG ?= clang
198LLVM_OBJCOPY ?= llvm-objcopy
199BTF_PAHOLE ?= pahole
194 200
195# Detect that we're cross compiling and use the cross compiler 201# Detect that we're cross compiling and use the cross compiler
196ifdef CROSS_COMPILE 202ifdef CROSS_COMPILE
@@ -198,6 +204,16 @@ HOSTCC = $(CROSS_COMPILE)gcc
198CLANG_ARCH_ARGS = -target $(ARCH) 204CLANG_ARCH_ARGS = -target $(ARCH)
199endif 205endif
200 206
207BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
208BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
209BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm')
210
211ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),)
212 EXTRA_CFLAGS += -g
213 LLC_FLAGS += -mattr=dwarfris
214 DWARF2BTF = y
215endif
216
201# Trick to allow make to be run from this directory 217# Trick to allow make to be run from this directory
202all: 218all:
203 $(MAKE) -C ../../ $(CURDIR)/ BPF_SAMPLES_PATH=$(CURDIR) 219 $(MAKE) -C ../../ $(CURDIR)/ BPF_SAMPLES_PATH=$(CURDIR)
@@ -256,4 +272,7 @@ $(obj)/%.o: $(src)/%.c
256 -Wno-gnu-variable-sized-type-not-at-end \ 272 -Wno-gnu-variable-sized-type-not-at-end \
257 -Wno-address-of-packed-member -Wno-tautological-compare \ 273 -Wno-address-of-packed-member -Wno-tautological-compare \
258 -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \ 274 -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \
259 -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@ 275 -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@
276ifeq ($(DWARF2BTF),y)
277 $(BTF_PAHOLE) -J $@
278endif
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 89161c9ed466..904e775d1a44 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -107,6 +107,9 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
107 return -1; 107 return -1;
108 } 108 }
109 109
110 if (prog_cnt == MAX_PROGS)
111 return -1;
112
110 fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version, 113 fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,
111 bpf_log_buf, BPF_LOG_BUF_SIZE); 114 bpf_log_buf, BPF_LOG_BUF_SIZE);
112 if (fd < 0) { 115 if (fd < 0) {
diff --git a/samples/bpf/hash_func01.h b/samples/bpf/hash_func01.h
new file mode 100644
index 000000000000..38255812e376
--- /dev/null
+++ b/samples/bpf/hash_func01.h
@@ -0,0 +1,55 @@
1/* SPDX-License-Identifier: LGPL-2.1
2 *
3 * Based on Paul Hsieh's (LGPG 2.1) hash function
4 * From: http://www.azillionmonkeys.com/qed/hash.html
5 */
6
7#define get16bits(d) (*((const __u16 *) (d)))
8
9static __always_inline
10__u32 SuperFastHash (const char *data, int len, __u32 initval) {
11 __u32 hash = initval;
12 __u32 tmp;
13 int rem;
14
15 if (len <= 0 || data == NULL) return 0;
16
17 rem = len & 3;
18 len >>= 2;
19
20 /* Main loop */
21#pragma clang loop unroll(full)
22 for (;len > 0; len--) {
23 hash += get16bits (data);
24 tmp = (get16bits (data+2) << 11) ^ hash;
25 hash = (hash << 16) ^ tmp;
26 data += 2*sizeof (__u16);
27 hash += hash >> 11;
28 }
29
30 /* Handle end cases */
31 switch (rem) {
32 case 3: hash += get16bits (data);
33 hash ^= hash << 16;
34 hash ^= ((signed char)data[sizeof (__u16)]) << 18;
35 hash += hash >> 11;
36 break;
37 case 2: hash += get16bits (data);
38 hash ^= hash << 11;
39 hash += hash >> 17;
40 break;
41 case 1: hash += (signed char)*data;
42 hash ^= hash << 10;
43 hash += hash >> 1;
44 }
45
46 /* Force "avalanching" of final 127 bits */
47 hash ^= hash << 3;
48 hash += hash >> 5;
49 hash ^= hash << 4;
50 hash += hash >> 17;
51 hash ^= hash << 25;
52 hash += hash >> 6;
53
54 return hash;
55}
diff --git a/samples/bpf/test_cgrp2_attach2.c b/samples/bpf/test_cgrp2_attach2.c
index b453e6a161be..180f9d813bca 100644
--- a/samples/bpf/test_cgrp2_attach2.c
+++ b/samples/bpf/test_cgrp2_attach2.c
@@ -8,7 +8,8 @@
8 * information. The number of invocations of the program, which maps 8 * information. The number of invocations of the program, which maps
9 * to the number of packets received, is stored to key 0. Key 1 is 9 * to the number of packets received, is stored to key 0. Key 1 is
10 * incremented on each iteration by the number of bytes stored in 10 * incremented on each iteration by the number of bytes stored in
11 * the skb. 11 * the skb. The program also stores the number of received bytes
12 * in the cgroup storage.
12 * 13 *
13 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH 14 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
14 * 15 *
@@ -21,12 +22,15 @@
21#include <stdio.h> 22#include <stdio.h>
22#include <stdlib.h> 23#include <stdlib.h>
23#include <assert.h> 24#include <assert.h>
25#include <sys/resource.h>
26#include <sys/time.h>
24#include <unistd.h> 27#include <unistd.h>
25 28
26#include <linux/bpf.h> 29#include <linux/bpf.h>
27#include <bpf/bpf.h> 30#include <bpf/bpf.h>
28 31
29#include "bpf_insn.h" 32#include "bpf_insn.h"
33#include "bpf_rlimit.h"
30#include "cgroup_helpers.h" 34#include "cgroup_helpers.h"
31 35
32#define FOO "/foo" 36#define FOO "/foo"
@@ -205,6 +209,8 @@ static int map_fd = -1;
205 209
206static int prog_load_cnt(int verdict, int val) 210static int prog_load_cnt(int verdict, int val)
207{ 211{
212 int cgroup_storage_fd;
213
208 if (map_fd < 0) 214 if (map_fd < 0)
209 map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 8, 1, 0); 215 map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 8, 1, 0);
210 if (map_fd < 0) { 216 if (map_fd < 0) {
@@ -212,6 +218,13 @@ static int prog_load_cnt(int verdict, int val)
212 return -1; 218 return -1;
213 } 219 }
214 220
221 cgroup_storage_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE,
222 sizeof(struct bpf_cgroup_storage_key), 8, 0, 0);
223 if (cgroup_storage_fd < 0) {
224 printf("failed to create map '%s'\n", strerror(errno));
225 return -1;
226 }
227
215 struct bpf_insn prog[] = { 228 struct bpf_insn prog[] = {
216 BPF_MOV32_IMM(BPF_REG_0, 0), 229 BPF_MOV32_IMM(BPF_REG_0, 0),
217 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ 230 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
@@ -222,6 +235,11 @@ static int prog_load_cnt(int verdict, int val)
222 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 235 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
223 BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */ 236 BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */
224 BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ 237 BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */
238 BPF_LD_MAP_FD(BPF_REG_1, cgroup_storage_fd),
239 BPF_MOV64_IMM(BPF_REG_2, 0),
240 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage),
241 BPF_MOV64_IMM(BPF_REG_1, val),
242 BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_0, BPF_REG_1, 0, 0),
225 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ 243 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
226 BPF_EXIT_INSN(), 244 BPF_EXIT_INSN(),
227 }; 245 };
@@ -237,6 +255,7 @@ static int prog_load_cnt(int verdict, int val)
237 printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); 255 printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
238 return 0; 256 return 0;
239 } 257 }
258 close(cgroup_storage_fd);
240 return ret; 259 return ret;
241} 260}
242 261
diff --git a/samples/bpf/test_cgrp2_sock2.c b/samples/bpf/test_cgrp2_sock2.c
index 3b5be2364975..a9277b118c33 100644
--- a/samples/bpf/test_cgrp2_sock2.c
+++ b/samples/bpf/test_cgrp2_sock2.c
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
51 if (argc > 3) 51 if (argc > 3)
52 filter_id = atoi(argv[3]); 52 filter_id = atoi(argv[3]);
53 53
54 if (filter_id > prog_cnt) { 54 if (filter_id >= prog_cnt) {
55 printf("Invalid program id; program not found in file\n"); 55 printf("Invalid program id; program not found in file\n");
56 return EXIT_FAILURE; 56 return EXIT_FAILURE;
57 } 57 }
diff --git a/samples/bpf/xdp_fwd_user.c b/samples/bpf/xdp_fwd_user.c
index a87a2048ed32..f88e1d7093d6 100644
--- a/samples/bpf/xdp_fwd_user.c
+++ b/samples/bpf/xdp_fwd_user.c
@@ -24,8 +24,7 @@
24#include <fcntl.h> 24#include <fcntl.h>
25#include <libgen.h> 25#include <libgen.h>
26 26
27#include "bpf_load.h" 27#include "bpf/libbpf.h"
28#include "bpf_util.h"
29#include <bpf/bpf.h> 28#include <bpf/bpf.h>
30 29
31 30
@@ -63,9 +62,15 @@ static void usage(const char *prog)
63 62
64int main(int argc, char **argv) 63int main(int argc, char **argv)
65{ 64{
65 struct bpf_prog_load_attr prog_load_attr = {
66 .prog_type = BPF_PROG_TYPE_XDP,
67 };
68 const char *prog_name = "xdp_fwd";
69 struct bpf_program *prog;
66 char filename[PATH_MAX]; 70 char filename[PATH_MAX];
71 struct bpf_object *obj;
67 int opt, i, idx, err; 72 int opt, i, idx, err;
68 int prog_id = 0; 73 int prog_fd, map_fd;
69 int attach = 1; 74 int attach = 1;
70 int ret = 0; 75 int ret = 0;
71 76
@@ -75,7 +80,7 @@ int main(int argc, char **argv)
75 attach = 0; 80 attach = 0;
76 break; 81 break;
77 case 'D': 82 case 'D':
78 prog_id = 1; 83 prog_name = "xdp_fwd_direct";
79 break; 84 break;
80 default: 85 default:
81 usage(basename(argv[0])); 86 usage(basename(argv[0]));
@@ -90,6 +95,7 @@ int main(int argc, char **argv)
90 95
91 if (attach) { 96 if (attach) {
92 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 97 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
98 prog_load_attr.file = filename;
93 99
94 if (access(filename, O_RDONLY) < 0) { 100 if (access(filename, O_RDONLY) < 0) {
95 printf("error accessing file %s: %s\n", 101 printf("error accessing file %s: %s\n",
@@ -97,19 +103,25 @@ int main(int argc, char **argv)
97 return 1; 103 return 1;
98 } 104 }
99 105
100 if (load_bpf_file(filename)) { 106 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
101 printf("%s", bpf_log_buf);
102 return 1; 107 return 1;
103 }
104 108
105 if (!prog_fd[prog_id]) { 109 prog = bpf_object__find_program_by_title(obj, prog_name);
106 printf("load_bpf_file: %s\n", strerror(errno)); 110 prog_fd = bpf_program__fd(prog);
111 if (prog_fd < 0) {
112 printf("program not found: %s\n", strerror(prog_fd));
113 return 1;
114 }
115 map_fd = bpf_map__fd(bpf_object__find_map_by_name(obj,
116 "tx_port"));
117 if (map_fd < 0) {
118 printf("map not found: %s\n", strerror(map_fd));
107 return 1; 119 return 1;
108 } 120 }
109 } 121 }
110 if (attach) { 122 if (attach) {
111 for (i = 1; i < 64; ++i) 123 for (i = 1; i < 64; ++i)
112 bpf_map_update_elem(map_fd[0], &i, &i, 0); 124 bpf_map_update_elem(map_fd, &i, &i, 0);
113 } 125 }
114 126
115 for (i = optind; i < argc; ++i) { 127 for (i = optind; i < argc; ++i) {
@@ -126,7 +138,7 @@ int main(int argc, char **argv)
126 if (err) 138 if (err)
127 ret = err; 139 ret = err;
128 } else { 140 } else {
129 err = do_attach(idx, prog_fd[prog_id], argv[i]); 141 err = do_attach(idx, prog_fd, argv[i]);
130 if (err) 142 if (err)
131 ret = err; 143 ret = err;
132 } 144 }
diff --git a/samples/bpf/xdp_redirect_cpu_kern.c b/samples/bpf/xdp_redirect_cpu_kern.c
index 4938dcbaecbf..a306d1c75622 100644
--- a/samples/bpf/xdp_redirect_cpu_kern.c
+++ b/samples/bpf/xdp_redirect_cpu_kern.c
@@ -13,6 +13,7 @@
13 13
14#include <uapi/linux/bpf.h> 14#include <uapi/linux/bpf.h>
15#include "bpf_helpers.h" 15#include "bpf_helpers.h"
16#include "hash_func01.h"
16 17
17#define MAX_CPUS 64 /* WARNING - sync with _user.c */ 18#define MAX_CPUS 64 /* WARNING - sync with _user.c */
18 19
@@ -134,7 +135,16 @@ bool parse_eth(struct ethhdr *eth, void *data_end,
134 return false; 135 return false;
135 eth_type = vlan_hdr->h_vlan_encapsulated_proto; 136 eth_type = vlan_hdr->h_vlan_encapsulated_proto;
136 } 137 }
137 /* TODO: Handle double VLAN tagged packet */ 138 /* Handle double VLAN tagged packet */
139 if (eth_type == htons(ETH_P_8021Q) || eth_type == htons(ETH_P_8021AD)) {
140 struct vlan_hdr *vlan_hdr;
141
142 vlan_hdr = (void *)eth + offset;
143 offset += sizeof(*vlan_hdr);
144 if ((void *)eth + offset > data_end)
145 return false;
146 eth_type = vlan_hdr->h_vlan_encapsulated_proto;
147 }
138 148
139 *eth_proto = ntohs(eth_type); 149 *eth_proto = ntohs(eth_type);
140 *l3_offset = offset; 150 *l3_offset = offset;
@@ -452,6 +462,108 @@ int xdp_prognum4_ddos_filter_pktgen(struct xdp_md *ctx)
452 return bpf_redirect_map(&cpu_map, cpu_dest, 0); 462 return bpf_redirect_map(&cpu_map, cpu_dest, 0);
453} 463}
454 464
465/* Hashing initval */
466#define INITVAL 15485863
467
468static __always_inline
469u32 get_ipv4_hash_ip_pair(struct xdp_md *ctx, u64 nh_off)
470{
471 void *data_end = (void *)(long)ctx->data_end;
472 void *data = (void *)(long)ctx->data;
473 struct iphdr *iph = data + nh_off;
474 u32 cpu_hash;
475
476 if (iph + 1 > data_end)
477 return 0;
478
479 cpu_hash = iph->saddr + iph->daddr;
480 cpu_hash = SuperFastHash((char *)&cpu_hash, 4, INITVAL + iph->protocol);
481
482 return cpu_hash;
483}
484
485static __always_inline
486u32 get_ipv6_hash_ip_pair(struct xdp_md *ctx, u64 nh_off)
487{
488 void *data_end = (void *)(long)ctx->data_end;
489 void *data = (void *)(long)ctx->data;
490 struct ipv6hdr *ip6h = data + nh_off;
491 u32 cpu_hash;
492
493 if (ip6h + 1 > data_end)
494 return 0;
495
496 cpu_hash = ip6h->saddr.s6_addr32[0] + ip6h->daddr.s6_addr32[0];
497 cpu_hash += ip6h->saddr.s6_addr32[1] + ip6h->daddr.s6_addr32[1];
498 cpu_hash += ip6h->saddr.s6_addr32[2] + ip6h->daddr.s6_addr32[2];
499 cpu_hash += ip6h->saddr.s6_addr32[3] + ip6h->daddr.s6_addr32[3];
500 cpu_hash = SuperFastHash((char *)&cpu_hash, 4, INITVAL + ip6h->nexthdr);
501
502 return cpu_hash;
503}
504
505/* Load-Balance traffic based on hashing IP-addrs + L4-proto. The
506 * hashing scheme is symmetric, meaning swapping IP src/dest still hit
507 * same CPU.
508 */
509SEC("xdp_cpu_map5_lb_hash_ip_pairs")
510int xdp_prognum5_lb_hash_ip_pairs(struct xdp_md *ctx)
511{
512 void *data_end = (void *)(long)ctx->data_end;
513 void *data = (void *)(long)ctx->data;
514 struct ethhdr *eth = data;
515 u8 ip_proto = IPPROTO_UDP;
516 struct datarec *rec;
517 u16 eth_proto = 0;
518 u64 l3_offset = 0;
519 u32 cpu_dest = 0;
520 u32 cpu_idx = 0;
521 u32 *cpu_lookup;
522 u32 *cpu_max;
523 u32 cpu_hash;
524 u32 key = 0;
525
526 /* Count RX packet in map */
527 rec = bpf_map_lookup_elem(&rx_cnt, &key);
528 if (!rec)
529 return XDP_ABORTED;
530 rec->processed++;
531
532 cpu_max = bpf_map_lookup_elem(&cpus_count, &key);
533 if (!cpu_max)
534 return XDP_ABORTED;
535
536 if (!(parse_eth(eth, data_end, &eth_proto, &l3_offset)))
537 return XDP_PASS; /* Just skip */
538
539 /* Hash for IPv4 and IPv6 */
540 switch (eth_proto) {
541 case ETH_P_IP:
542 cpu_hash = get_ipv4_hash_ip_pair(ctx, l3_offset);
543 break;
544 case ETH_P_IPV6:
545 cpu_hash = get_ipv6_hash_ip_pair(ctx, l3_offset);
546 break;
547 case ETH_P_ARP: /* ARP packet handled on CPU idx 0 */
548 default:
549 cpu_hash = 0;
550 }
551
552 /* Choose CPU based on hash */
553 cpu_idx = cpu_hash % *cpu_max;
554
555 cpu_lookup = bpf_map_lookup_elem(&cpus_available, &cpu_idx);
556 if (!cpu_lookup)
557 return XDP_ABORTED;
558 cpu_dest = *cpu_lookup;
559
560 if (cpu_dest >= MAX_CPUS) {
561 rec->issue++;
562 return XDP_ABORTED;
563 }
564
565 return bpf_redirect_map(&cpu_map, cpu_dest, 0);
566}
455 567
456char _license[] SEC("license") = "GPL"; 568char _license[] SEC("license") = "GPL";
457 569
diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c
index 4b4d78fffe30..9a6c7e0a6dd1 100644
--- a/samples/bpf/xdp_redirect_cpu_user.c
+++ b/samples/bpf/xdp_redirect_cpu_user.c
@@ -22,7 +22,7 @@ static const char *__doc__ =
22#define MAX_CPUS 64 /* WARNING - sync with _kern.c */ 22#define MAX_CPUS 64 /* WARNING - sync with _kern.c */
23 23
24/* How many xdp_progs are defined in _kern.c */ 24/* How many xdp_progs are defined in _kern.c */
25#define MAX_PROG 5 25#define MAX_PROG 6
26 26
27/* Wanted to get rid of bpf_load.h and fake-"libbpf.h" (and instead 27/* Wanted to get rid of bpf_load.h and fake-"libbpf.h" (and instead
28 * use bpf/libbpf.h), but cannot as (currently) needed for XDP 28 * use bpf/libbpf.h), but cannot as (currently) needed for XDP
@@ -567,7 +567,7 @@ int main(int argc, char **argv)
567 int added_cpus = 0; 567 int added_cpus = 0;
568 int longindex = 0; 568 int longindex = 0;
569 int interval = 2; 569 int interval = 2;
570 int prog_num = 0; 570 int prog_num = 5;
571 int add_cpu = -1; 571 int add_cpu = -1;
572 __u32 qsize; 572 __u32 qsize;
573 int opt; 573 int opt;
diff --git a/samples/bpf/xdp_rxq_info_kern.c b/samples/bpf/xdp_rxq_info_kern.c
index 3fd209291653..222a83eed1cb 100644
--- a/samples/bpf/xdp_rxq_info_kern.c
+++ b/samples/bpf/xdp_rxq_info_kern.c
@@ -4,6 +4,8 @@
4 * Example howto extract XDP RX-queue info 4 * Example howto extract XDP RX-queue info
5 */ 5 */
6#include <uapi/linux/bpf.h> 6#include <uapi/linux/bpf.h>
7#include <uapi/linux/if_ether.h>
8#include <uapi/linux/in.h>
7#include "bpf_helpers.h" 9#include "bpf_helpers.h"
8 10
9/* Config setup from with userspace 11/* Config setup from with userspace
@@ -14,6 +16,12 @@
14struct config { 16struct config {
15 __u32 action; 17 __u32 action;
16 int ifindex; 18 int ifindex;
19 __u32 options;
20};
21enum cfg_options_flags {
22 NO_TOUCH = 0x0U,
23 READ_MEM = 0x1U,
24 SWAP_MAC = 0x2U,
17}; 25};
18struct bpf_map_def SEC("maps") config_map = { 26struct bpf_map_def SEC("maps") config_map = {
19 .type = BPF_MAP_TYPE_ARRAY, 27 .type = BPF_MAP_TYPE_ARRAY,
@@ -45,6 +53,23 @@ struct bpf_map_def SEC("maps") rx_queue_index_map = {
45 .max_entries = MAX_RXQs + 1, 53 .max_entries = MAX_RXQs + 1,
46}; 54};
47 55
56static __always_inline
57void swap_src_dst_mac(void *data)
58{
59 unsigned short *p = data;
60 unsigned short dst[3];
61
62 dst[0] = p[0];
63 dst[1] = p[1];
64 dst[2] = p[2];
65 p[0] = p[3];
66 p[1] = p[4];
67 p[2] = p[5];
68 p[3] = dst[0];
69 p[4] = dst[1];
70 p[5] = dst[2];
71}
72
48SEC("xdp_prog0") 73SEC("xdp_prog0")
49int xdp_prognum0(struct xdp_md *ctx) 74int xdp_prognum0(struct xdp_md *ctx)
50{ 75{
@@ -90,6 +115,24 @@ int xdp_prognum0(struct xdp_md *ctx)
90 if (key == MAX_RXQs) 115 if (key == MAX_RXQs)
91 rxq_rec->issue++; 116 rxq_rec->issue++;
92 117
118 /* Default: Don't touch packet data, only count packets */
119 if (unlikely(config->options & (READ_MEM|SWAP_MAC))) {
120 struct ethhdr *eth = data;
121
122 if (eth + 1 > data_end)
123 return XDP_ABORTED;
124
125 /* Avoid compiler removing this: Drop non 802.3 Ethertypes */
126 if (ntohs(eth->h_proto) < ETH_P_802_3_MIN)
127 return XDP_ABORTED;
128
129 /* XDP_TX requires changing MAC-addrs, else HW may drop.
130 * Can also be enabled with --swapmac (for test purposes)
131 */
132 if (unlikely(config->options & SWAP_MAC))
133 swap_src_dst_mac(data);
134 }
135
93 return config->action; 136 return config->action;
94} 137}
95 138
diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c
index e4e9ba52bff0..248a7eab9531 100644
--- a/samples/bpf/xdp_rxq_info_user.c
+++ b/samples/bpf/xdp_rxq_info_user.c
@@ -50,6 +50,8 @@ static const struct option long_options[] = {
50 {"sec", required_argument, NULL, 's' }, 50 {"sec", required_argument, NULL, 's' },
51 {"no-separators", no_argument, NULL, 'z' }, 51 {"no-separators", no_argument, NULL, 'z' },
52 {"action", required_argument, NULL, 'a' }, 52 {"action", required_argument, NULL, 'a' },
53 {"readmem", no_argument, NULL, 'r' },
54 {"swapmac", no_argument, NULL, 'm' },
53 {0, 0, NULL, 0 } 55 {0, 0, NULL, 0 }
54}; 56};
55 57
@@ -66,6 +68,12 @@ static void int_exit(int sig)
66struct config { 68struct config {
67 __u32 action; 69 __u32 action;
68 int ifindex; 70 int ifindex;
71 __u32 options;
72};
73enum cfg_options_flags {
74 NO_TOUCH = 0x0U,
75 READ_MEM = 0x1U,
76 SWAP_MAC = 0x2U,
69}; 77};
70#define XDP_ACTION_MAX (XDP_TX + 1) 78#define XDP_ACTION_MAX (XDP_TX + 1)
71#define XDP_ACTION_MAX_STRLEN 11 79#define XDP_ACTION_MAX_STRLEN 11
@@ -109,6 +117,18 @@ static void list_xdp_actions(void)
109 printf("\n"); 117 printf("\n");
110} 118}
111 119
120static char* options2str(enum cfg_options_flags flag)
121{
122 if (flag == NO_TOUCH)
123 return "no_touch";
124 if (flag & SWAP_MAC)
125 return "swapmac";
126 if (flag & READ_MEM)
127 return "read";
128 fprintf(stderr, "ERR: Unknown config option flags");
129 exit(EXIT_FAIL);
130}
131
112static void usage(char *argv[]) 132static void usage(char *argv[])
113{ 133{
114 int i; 134 int i;
@@ -305,7 +325,7 @@ static __u64 calc_errs_pps(struct datarec *r,
305 325
306static void stats_print(struct stats_record *stats_rec, 326static void stats_print(struct stats_record *stats_rec,
307 struct stats_record *stats_prev, 327 struct stats_record *stats_prev,
308 int action) 328 int action, __u32 cfg_opt)
309{ 329{
310 unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries; 330 unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
311 unsigned int nr_cpus = bpf_num_possible_cpus(); 331 unsigned int nr_cpus = bpf_num_possible_cpus();
@@ -316,8 +336,8 @@ static void stats_print(struct stats_record *stats_rec,
316 int i; 336 int i;
317 337
318 /* Header */ 338 /* Header */
319 printf("\nRunning XDP on dev:%s (ifindex:%d) action:%s\n", 339 printf("\nRunning XDP on dev:%s (ifindex:%d) action:%s options:%s\n",
320 ifname, ifindex, action2str(action)); 340 ifname, ifindex, action2str(action), options2str(cfg_opt));
321 341
322 /* stats_global_map */ 342 /* stats_global_map */
323 { 343 {
@@ -399,7 +419,7 @@ static inline void swap(struct stats_record **a, struct stats_record **b)
399 *b = tmp; 419 *b = tmp;
400} 420}
401 421
402static void stats_poll(int interval, int action) 422static void stats_poll(int interval, int action, __u32 cfg_opt)
403{ 423{
404 struct stats_record *record, *prev; 424 struct stats_record *record, *prev;
405 425
@@ -410,7 +430,7 @@ static void stats_poll(int interval, int action)
410 while (1) { 430 while (1) {
411 swap(&prev, &record); 431 swap(&prev, &record);
412 stats_collect(record); 432 stats_collect(record);
413 stats_print(record, prev, action); 433 stats_print(record, prev, action, cfg_opt);
414 sleep(interval); 434 sleep(interval);
415 } 435 }
416 436
@@ -421,6 +441,7 @@ static void stats_poll(int interval, int action)
421 441
422int main(int argc, char **argv) 442int main(int argc, char **argv)
423{ 443{
444 __u32 cfg_options= NO_TOUCH ; /* Default: Don't touch packet memory */
424 struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY}; 445 struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
425 struct bpf_prog_load_attr prog_load_attr = { 446 struct bpf_prog_load_attr prog_load_attr = {
426 .prog_type = BPF_PROG_TYPE_XDP, 447 .prog_type = BPF_PROG_TYPE_XDP,
@@ -435,6 +456,7 @@ int main(int argc, char **argv)
435 int interval = 2; 456 int interval = 2;
436 __u32 key = 0; 457 __u32 key = 0;
437 458
459
438 char action_str_buf[XDP_ACTION_MAX_STRLEN + 1 /* for \0 */] = { 0 }; 460 char action_str_buf[XDP_ACTION_MAX_STRLEN + 1 /* for \0 */] = { 0 };
439 int action = XDP_PASS; /* Default action */ 461 int action = XDP_PASS; /* Default action */
440 char *action_str = NULL; 462 char *action_str = NULL;
@@ -496,6 +518,12 @@ int main(int argc, char **argv)
496 action_str = (char *)&action_str_buf; 518 action_str = (char *)&action_str_buf;
497 strncpy(action_str, optarg, XDP_ACTION_MAX_STRLEN); 519 strncpy(action_str, optarg, XDP_ACTION_MAX_STRLEN);
498 break; 520 break;
521 case 'r':
522 cfg_options |= READ_MEM;
523 break;
524 case 'm':
525 cfg_options |= SWAP_MAC;
526 break;
499 case 'h': 527 case 'h':
500 error: 528 error:
501 default: 529 default:
@@ -523,6 +551,11 @@ int main(int argc, char **argv)
523 } 551 }
524 cfg.action = action; 552 cfg.action = action;
525 553
554 /* XDP_TX requires changing MAC-addrs, else HW may drop */
555 if (action == XDP_TX)
556 cfg_options |= SWAP_MAC;
557 cfg.options = cfg_options;
558
526 /* Trick to pretty printf with thousands separators use %' */ 559 /* Trick to pretty printf with thousands separators use %' */
527 if (use_separators) 560 if (use_separators)
528 setlocale(LC_NUMERIC, "en_US"); 561 setlocale(LC_NUMERIC, "en_US");
@@ -542,6 +575,6 @@ int main(int argc, char **argv)
542 return EXIT_FAIL_XDP; 575 return EXIT_FAIL_XDP;
543 } 576 }
544 577
545 stats_poll(interval, action); 578 stats_poll(interval, action, cfg_options);
546 return EXIT_OK; 579 return EXIT_OK;
547} 580}
diff --git a/samples/bpf/xdp_sample_pkts_kern.c b/samples/bpf/xdp_sample_pkts_kern.c
new file mode 100644
index 000000000000..f7ca8b850978
--- /dev/null
+++ b/samples/bpf/xdp_sample_pkts_kern.c
@@ -0,0 +1,66 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/ptrace.h>
3#include <linux/version.h>
4#include <uapi/linux/bpf.h>
5#include "bpf_helpers.h"
6
7#define SAMPLE_SIZE 64ul
8#define MAX_CPUS 128
9
10#define bpf_printk(fmt, ...) \
11({ \
12 char ____fmt[] = fmt; \
13 bpf_trace_printk(____fmt, sizeof(____fmt), \
14 ##__VA_ARGS__); \
15})
16
17struct bpf_map_def SEC("maps") my_map = {
18 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
19 .key_size = sizeof(int),
20 .value_size = sizeof(u32),
21 .max_entries = MAX_CPUS,
22};
23
24SEC("xdp_sample")
25int xdp_sample_prog(struct xdp_md *ctx)
26{
27 void *data_end = (void *)(long)ctx->data_end;
28 void *data = (void *)(long)ctx->data;
29
30 /* Metadata will be in the perf event before the packet data. */
31 struct S {
32 u16 cookie;
33 u16 pkt_len;
34 } __packed metadata;
35
36 if (data < data_end) {
37 /* The XDP perf_event_output handler will use the upper 32 bits
38 * of the flags argument as a number of bytes to include of the
39 * packet payload in the event data. If the size is too big, the
40 * call to bpf_perf_event_output will fail and return -EFAULT.
41 *
42 * See bpf_xdp_event_output in net/core/filter.c.
43 *
44 * The BPF_F_CURRENT_CPU flag means that the event output fd
45 * will be indexed by the CPU number in the event map.
46 */
47 u64 flags = BPF_F_CURRENT_CPU;
48 u16 sample_size;
49 int ret;
50
51 metadata.cookie = 0xdead;
52 metadata.pkt_len = (u16)(data_end - data);
53 sample_size = min(metadata.pkt_len, SAMPLE_SIZE);
54 flags |= (u64)sample_size << 32;
55
56 ret = bpf_perf_event_output(ctx, &my_map, flags,
57 &metadata, sizeof(metadata));
58 if (ret)
59 bpf_printk("perf_event_output failed: %d\n", ret);
60 }
61
62 return XDP_PASS;
63}
64
65char _license[] SEC("license") = "GPL";
66u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c
new file mode 100644
index 000000000000..8dd87c1eb560
--- /dev/null
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -0,0 +1,169 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <linux/perf_event.h>
6#include <linux/bpf.h>
7#include <net/if.h>
8#include <errno.h>
9#include <assert.h>
10#include <sys/sysinfo.h>
11#include <sys/ioctl.h>
12#include <signal.h>
13#include <libbpf.h>
14#include <bpf/bpf.h>
15
16#include "perf-sys.h"
17#include "trace_helpers.h"
18
19#define MAX_CPUS 128
20static int pmu_fds[MAX_CPUS], if_idx;
21static struct perf_event_mmap_page *headers[MAX_CPUS];
22static char *if_name;
23
24static int do_attach(int idx, int fd, const char *name)
25{
26 int err;
27
28 err = bpf_set_link_xdp_fd(idx, fd, 0);
29 if (err < 0)
30 printf("ERROR: failed to attach program to %s\n", name);
31
32 return err;
33}
34
35static int do_detach(int idx, const char *name)
36{
37 int err;
38
39 err = bpf_set_link_xdp_fd(idx, -1, 0);
40 if (err < 0)
41 printf("ERROR: failed to detach program from %s\n", name);
42
43 return err;
44}
45
46#define SAMPLE_SIZE 64
47
48static int print_bpf_output(void *data, int size)
49{
50 struct {
51 __u16 cookie;
52 __u16 pkt_len;
53 __u8 pkt_data[SAMPLE_SIZE];
54 } __packed *e = data;
55 int i;
56
57 if (e->cookie != 0xdead) {
58 printf("BUG cookie %x sized %d\n",
59 e->cookie, size);
60 return LIBBPF_PERF_EVENT_ERROR;
61 }
62
63 printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len);
64 for (i = 0; i < 14 && i < e->pkt_len; i++)
65 printf("%02x ", e->pkt_data[i]);
66 printf("\n");
67
68 return LIBBPF_PERF_EVENT_CONT;
69}
70
71static void test_bpf_perf_event(int map_fd, int num)
72{
73 struct perf_event_attr attr = {
74 .sample_type = PERF_SAMPLE_RAW,
75 .type = PERF_TYPE_SOFTWARE,
76 .config = PERF_COUNT_SW_BPF_OUTPUT,
77 .wakeup_events = 1, /* get an fd notification for every event */
78 };
79 int i;
80
81 for (i = 0; i < num; i++) {
82 int key = i;
83
84 pmu_fds[i] = sys_perf_event_open(&attr, -1/*pid*/, i/*cpu*/,
85 -1/*group_fd*/, 0);
86
87 assert(pmu_fds[i] >= 0);
88 assert(bpf_map_update_elem(map_fd, &key,
89 &pmu_fds[i], BPF_ANY) == 0);
90 ioctl(pmu_fds[i], PERF_EVENT_IOC_ENABLE, 0);
91 }
92}
93
94static void sig_handler(int signo)
95{
96 do_detach(if_idx, if_name);
97 exit(0);
98}
99
100int main(int argc, char **argv)
101{
102 struct bpf_prog_load_attr prog_load_attr = {
103 .prog_type = BPF_PROG_TYPE_XDP,
104 };
105 struct bpf_object *obj;
106 struct bpf_map *map;
107 int prog_fd, map_fd;
108 char filename[256];
109 int ret, err, i;
110 int numcpus;
111
112 if (argc < 2) {
113 printf("Usage: %s <ifname>\n", argv[0]);
114 return 1;
115 }
116
117 numcpus = get_nprocs();
118 if (numcpus > MAX_CPUS)
119 numcpus = MAX_CPUS;
120
121 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
122 prog_load_attr.file = filename;
123
124 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
125 return 1;
126
127 if (!prog_fd) {
128 printf("load_bpf_file: %s\n", strerror(errno));
129 return 1;
130 }
131
132 map = bpf_map__next(NULL, obj);
133 if (!map) {
134 printf("finding a map in obj file failed\n");
135 return 1;
136 }
137 map_fd = bpf_map__fd(map);
138
139 if_idx = if_nametoindex(argv[1]);
140 if (!if_idx)
141 if_idx = strtoul(argv[1], NULL, 0);
142
143 if (!if_idx) {
144 fprintf(stderr, "Invalid ifname\n");
145 return 1;
146 }
147 if_name = argv[1];
148 err = do_attach(if_idx, prog_fd, argv[1]);
149 if (err)
150 return err;
151
152 if (signal(SIGINT, sig_handler) ||
153 signal(SIGHUP, sig_handler) ||
154 signal(SIGTERM, sig_handler)) {
155 perror("signal");
156 return 1;
157 }
158
159 test_bpf_perf_event(map_fd, numcpus);
160
161 for (i = 0; i < numcpus; i++)
162 if (perf_event_mmap_header(pmu_fds[i], &headers[i]) < 0)
163 return 1;
164
165 ret = perf_event_poller_multi(pmu_fds, headers, numcpus,
166 print_bpf_output);
167 kill(0, SIGINT);
168 return ret;
169}
diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
index 5904b1543831..4914788b6727 100644
--- a/samples/bpf/xdpsock_user.c
+++ b/samples/bpf/xdpsock_user.c
@@ -26,7 +26,7 @@
26#include <sys/types.h> 26#include <sys/types.h>
27#include <poll.h> 27#include <poll.h>
28 28
29#include "bpf_load.h" 29#include "bpf/libbpf.h"
30#include "bpf_util.h" 30#include "bpf_util.h"
31#include <bpf/bpf.h> 31#include <bpf/bpf.h>
32 32
@@ -145,8 +145,13 @@ static void dump_stats(void);
145 } while (0) 145 } while (0)
146 146
147#define barrier() __asm__ __volatile__("": : :"memory") 147#define barrier() __asm__ __volatile__("": : :"memory")
148#ifdef __aarch64__
149#define u_smp_rmb() __asm__ __volatile__("dmb ishld": : :"memory")
150#define u_smp_wmb() __asm__ __volatile__("dmb ishst": : :"memory")
151#else
148#define u_smp_rmb() barrier() 152#define u_smp_rmb() barrier()
149#define u_smp_wmb() barrier() 153#define u_smp_wmb() barrier()
154#endif
150#define likely(x) __builtin_expect(!!(x), 1) 155#define likely(x) __builtin_expect(!!(x), 1)
151#define unlikely(x) __builtin_expect(!!(x), 0) 156#define unlikely(x) __builtin_expect(!!(x), 0)
152 157
@@ -886,7 +891,13 @@ static void l2fwd(struct xdpsock *xsk)
886int main(int argc, char **argv) 891int main(int argc, char **argv)
887{ 892{
888 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 893 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
894 struct bpf_prog_load_attr prog_load_attr = {
895 .prog_type = BPF_PROG_TYPE_XDP,
896 };
897 int prog_fd, qidconf_map, xsks_map;
898 struct bpf_object *obj;
889 char xdp_filename[256]; 899 char xdp_filename[256];
900 struct bpf_map *map;
890 int i, ret, key = 0; 901 int i, ret, key = 0;
891 pthread_t pt; 902 pthread_t pt;
892 903
@@ -899,24 +910,38 @@ int main(int argc, char **argv)
899 } 910 }
900 911
901 snprintf(xdp_filename, sizeof(xdp_filename), "%s_kern.o", argv[0]); 912 snprintf(xdp_filename, sizeof(xdp_filename), "%s_kern.o", argv[0]);
913 prog_load_attr.file = xdp_filename;
902 914
903 if (load_bpf_file(xdp_filename)) { 915 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
904 fprintf(stderr, "ERROR: load_bpf_file %s\n", bpf_log_buf); 916 exit(EXIT_FAILURE);
917 if (prog_fd < 0) {
918 fprintf(stderr, "ERROR: no program found: %s\n",
919 strerror(prog_fd));
905 exit(EXIT_FAILURE); 920 exit(EXIT_FAILURE);
906 } 921 }
907 922
908 if (!prog_fd[0]) { 923 map = bpf_object__find_map_by_name(obj, "qidconf_map");
909 fprintf(stderr, "ERROR: load_bpf_file: \"%s\"\n", 924 qidconf_map = bpf_map__fd(map);
910 strerror(errno)); 925 if (qidconf_map < 0) {
926 fprintf(stderr, "ERROR: no qidconf map found: %s\n",
927 strerror(qidconf_map));
928 exit(EXIT_FAILURE);
929 }
930
931 map = bpf_object__find_map_by_name(obj, "xsks_map");
932 xsks_map = bpf_map__fd(map);
933 if (xsks_map < 0) {
934 fprintf(stderr, "ERROR: no xsks map found: %s\n",
935 strerror(xsks_map));
911 exit(EXIT_FAILURE); 936 exit(EXIT_FAILURE);
912 } 937 }
913 938
914 if (bpf_set_link_xdp_fd(opt_ifindex, prog_fd[0], opt_xdp_flags) < 0) { 939 if (bpf_set_link_xdp_fd(opt_ifindex, prog_fd, opt_xdp_flags) < 0) {
915 fprintf(stderr, "ERROR: link set xdp fd failed\n"); 940 fprintf(stderr, "ERROR: link set xdp fd failed\n");
916 exit(EXIT_FAILURE); 941 exit(EXIT_FAILURE);
917 } 942 }
918 943
919 ret = bpf_map_update_elem(map_fd[0], &key, &opt_queue, 0); 944 ret = bpf_map_update_elem(qidconf_map, &key, &opt_queue, 0);
920 if (ret) { 945 if (ret) {
921 fprintf(stderr, "ERROR: bpf_map_update_elem qidconf\n"); 946 fprintf(stderr, "ERROR: bpf_map_update_elem qidconf\n");
922 exit(EXIT_FAILURE); 947 exit(EXIT_FAILURE);
@@ -933,7 +958,7 @@ int main(int argc, char **argv)
933 /* ...and insert them into the map. */ 958 /* ...and insert them into the map. */
934 for (i = 0; i < num_socks; i++) { 959 for (i = 0; i < num_socks; i++) {
935 key = i; 960 key = i;
936 ret = bpf_map_update_elem(map_fd[1], &key, &xsks[i]->sfd, 0); 961 ret = bpf_map_update_elem(xsks_map, &key, &xsks[i]->sfd, 0);
937 if (ret) { 962 if (ret) {
938 fprintf(stderr, "ERROR: bpf_map_update_elem %d\n", i); 963 fprintf(stderr, "ERROR: bpf_map_update_elem %d\n", i);
939 exit(EXIT_FAILURE); 964 exit(EXIT_FAILURE);