aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/Makefile3
-rw-r--r--tools/testing/selftests/bpf/bpf_endian.h1
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h4
-rw-r--r--tools/testing/selftests/bpf/bpf_util.h37
-rw-r--r--tools/testing/selftests/bpf/cgroup_helpers.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c67
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_flow.c18
-rw-r--r--tools/testing/selftests/bpf/progs/loop1.c28
-rw-r--r--tools/testing/selftests/bpf/progs/loop2.c28
-rw-r--r--tools/testing/selftests/bpf/progs/loop3.c22
-rw-r--r--tools/testing/selftests/bpf/progs/netcnt_prog.c22
-rw-r--r--tools/testing/selftests/bpf/progs/pyperf.h6
-rw-r--r--tools/testing/selftests/bpf/progs/pyperf600.c9
-rw-r--r--tools/testing/selftests/bpf/progs/pyperf600_nounroll.c8
-rw-r--r--tools/testing/selftests/bpf/progs/socket_cookie_prog.c49
-rw-r--r--tools/testing/selftests/bpf/progs/sockmap_parse_prog.c1
-rw-r--r--tools/testing/selftests/bpf/progs/sockmap_tcp_msg_prog.c2
-rw-r--r--tools/testing/selftests/bpf/progs/sockmap_verdict_prog.c1
-rw-r--r--tools/testing/selftests/bpf/progs/strobemeta.c10
-rw-r--r--tools/testing/selftests/bpf/progs/strobemeta.h528
-rw-r--r--tools/testing/selftests/bpf/progs/strobemeta_nounroll1.c9
-rw-r--r--tools/testing/selftests/bpf/progs/strobemeta_nounroll2.c9
-rw-r--r--tools/testing/selftests/bpf/progs/test_btf_newkv.c73
-rw-r--r--tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c27
-rw-r--r--tools/testing/selftests/bpf/progs/test_global_data.c27
-rw-r--r--tools/testing/selftests/bpf/progs/test_l4lb.c45
-rw-r--r--tools/testing/selftests/bpf/progs/test_l4lb_noinline.c45
-rw-r--r--tools/testing/selftests/bpf/progs/test_map_lock.c22
-rw-r--r--tools/testing/selftests/bpf/progs/test_seg6_loop.c261
-rw-r--r--tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c45
-rw-r--r--tools/testing/selftests/bpf/progs/test_send_signal_kern.c22
-rw-r--r--tools/testing/selftests/bpf/progs/test_sock_fields_kern.c60
-rw-r--r--tools/testing/selftests/bpf/progs/test_spin_lock.c33
-rw-r--r--tools/testing/selftests/bpf/progs/test_stacktrace_build_id.c44
-rw-r--r--tools/testing/selftests/bpf/progs/test_stacktrace_map.c40
-rw-r--r--tools/testing/selftests/bpf/progs/test_sysctl_loop1.c71
-rw-r--r--tools/testing/selftests/bpf/progs/test_sysctl_loop2.c72
-rw-r--r--tools/testing/selftests/bpf/progs/test_sysctl_prog.c5
-rw-r--r--tools/testing/selftests/bpf/progs/test_tcp_estats.c9
-rw-r--r--tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c18
-rw-r--r--tools/testing/selftests/bpf/progs/test_tcpnotify_kern.c18
-rw-r--r--tools/testing/selftests/bpf/progs/test_xdp.c18
-rw-r--r--tools/testing/selftests/bpf/progs/test_xdp_loop.c231
-rw-r--r--tools/testing/selftests/bpf/progs/test_xdp_noinline.c60
-rw-r--r--tools/testing/selftests/bpf/test_btf.c10
-rw-r--r--tools/testing/selftests/bpf/test_select_reuseport.c54
-rw-r--r--tools/testing/selftests/bpf/test_socket_cookie.c24
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c11
-rw-r--r--tools/testing/selftests/bpf/verifier/calls.c22
-rw-r--r--tools/testing/selftests/bpf/verifier/cfg.c11
-rw-r--r--tools/testing/selftests/bpf/verifier/direct_packet_access.c3
-rw-r--r--tools/testing/selftests/bpf/verifier/helper_access_var_len.c28
-rw-r--r--tools/testing/selftests/bpf/verifier/loops1.c161
-rw-r--r--tools/testing/selftests/bpf/verifier/prevent_map_lookup.c15
-rw-r--r--tools/testing/selftests/bpf/verifier/sock.c18
55 files changed, 2119 insertions, 348 deletions
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index d8df5c9b5b2f..fb5ce43e28b3 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -280,4 +280,5 @@ $(OUTPUT)/verifier/tests.h: $(VERIFIER_TESTS_DIR) $(VERIFIER_TEST_FILES)
280 ) > $(VERIFIER_TESTS_H)) 280 ) > $(VERIFIER_TESTS_H))
281 281
282EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \ 282EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \
283 $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) 283 $(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \
284 feature
diff --git a/tools/testing/selftests/bpf/bpf_endian.h b/tools/testing/selftests/bpf/bpf_endian.h
index b25595ea4a78..05f036df8a4c 100644
--- a/tools/testing/selftests/bpf/bpf_endian.h
+++ b/tools/testing/selftests/bpf/bpf_endian.h
@@ -2,6 +2,7 @@
2#ifndef __BPF_ENDIAN__ 2#ifndef __BPF_ENDIAN__
3#define __BPF_ENDIAN__ 3#define __BPF_ENDIAN__
4 4
5#include <linux/stddef.h>
5#include <linux/swab.h> 6#include <linux/swab.h>
6 7
7/* LLVM's BPF target selects the endianness of the CPU 8/* LLVM's BPF target selects the endianness of the CPU
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index e6d243b7cd74..1a5b1accf091 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -31,7 +31,7 @@ static int (*bpf_map_pop_elem)(void *map, void *value) =
31 (void *) BPF_FUNC_map_pop_elem; 31 (void *) BPF_FUNC_map_pop_elem;
32static int (*bpf_map_peek_elem)(void *map, void *value) = 32static int (*bpf_map_peek_elem)(void *map, void *value) =
33 (void *) BPF_FUNC_map_peek_elem; 33 (void *) BPF_FUNC_map_peek_elem;
34static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) = 34static int (*bpf_probe_read)(void *dst, int size, const void *unsafe_ptr) =
35 (void *) BPF_FUNC_probe_read; 35 (void *) BPF_FUNC_probe_read;
36static unsigned long long (*bpf_ktime_get_ns)(void) = 36static unsigned long long (*bpf_ktime_get_ns)(void) =
37 (void *) BPF_FUNC_ktime_get_ns; 37 (void *) BPF_FUNC_ktime_get_ns;
@@ -62,7 +62,7 @@ static int (*bpf_perf_event_output)(void *ctx, void *map,
62 (void *) BPF_FUNC_perf_event_output; 62 (void *) BPF_FUNC_perf_event_output;
63static int (*bpf_get_stackid)(void *ctx, void *map, int flags) = 63static int (*bpf_get_stackid)(void *ctx, void *map, int flags) =
64 (void *) BPF_FUNC_get_stackid; 64 (void *) BPF_FUNC_get_stackid;
65static int (*bpf_probe_write_user)(void *dst, void *src, int size) = 65static int (*bpf_probe_write_user)(void *dst, const void *src, int size) =
66 (void *) BPF_FUNC_probe_write_user; 66 (void *) BPF_FUNC_probe_write_user;
67static int (*bpf_current_task_under_cgroup)(void *map, int index) = 67static int (*bpf_current_task_under_cgroup)(void *map, int index) =
68 (void *) BPF_FUNC_current_task_under_cgroup; 68 (void *) BPF_FUNC_current_task_under_cgroup;
diff --git a/tools/testing/selftests/bpf/bpf_util.h b/tools/testing/selftests/bpf/bpf_util.h
index a29206ebbd13..ec219f84e041 100644
--- a/tools/testing/selftests/bpf/bpf_util.h
+++ b/tools/testing/selftests/bpf/bpf_util.h
@@ -6,44 +6,17 @@
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h> 7#include <string.h>
8#include <errno.h> 8#include <errno.h>
9#include <libbpf.h> /* libbpf_num_possible_cpus */
9 10
10static inline unsigned int bpf_num_possible_cpus(void) 11static inline unsigned int bpf_num_possible_cpus(void)
11{ 12{
12 static const char *fcpu = "/sys/devices/system/cpu/possible"; 13 int possible_cpus = libbpf_num_possible_cpus();
13 unsigned int start, end, possible_cpus = 0;
14 char buff[128];
15 FILE *fp;
16 int len, n, i, j = 0;
17 14
18 fp = fopen(fcpu, "r"); 15 if (possible_cpus < 0) {
19 if (!fp) { 16 printf("Failed to get # of possible cpus: '%s'!\n",
20 printf("Failed to open %s: '%s'!\n", fcpu, strerror(errno)); 17 strerror(-possible_cpus));
21 exit(1); 18 exit(1);
22 } 19 }
23
24 if (!fgets(buff, sizeof(buff), fp)) {
25 printf("Failed to read %s!\n", fcpu);
26 exit(1);
27 }
28
29 len = strlen(buff);
30 for (i = 0; i <= len; i++) {
31 if (buff[i] == ',' || buff[i] == '\0') {
32 buff[i] = '\0';
33 n = sscanf(&buff[j], "%u-%u", &start, &end);
34 if (n <= 0) {
35 printf("Failed to retrieve # possible CPUs!\n");
36 exit(1);
37 } else if (n == 1) {
38 end = start;
39 }
40 possible_cpus += end - start + 1;
41 j = i + 1;
42 }
43 }
44
45 fclose(fp);
46
47 return possible_cpus; 20 return possible_cpus;
48} 21}
49 22
diff --git a/tools/testing/selftests/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c
index 0d89f0396be4..e95c33e333a4 100644
--- a/tools/testing/selftests/bpf/cgroup_helpers.c
+++ b/tools/testing/selftests/bpf/cgroup_helpers.c
@@ -47,7 +47,7 @@ int enable_all_controllers(char *cgroup_path)
47 char buf[PATH_MAX]; 47 char buf[PATH_MAX];
48 char *c, *c2; 48 char *c, *c2;
49 int fd, cfd; 49 int fd, cfd;
50 size_t len; 50 ssize_t len;
51 51
52 snprintf(path, sizeof(path), "%s/cgroup.controllers", cgroup_path); 52 snprintf(path, sizeof(path), "%s/cgroup.controllers", cgroup_path);
53 fd = open(path, O_RDONLY); 53 fd = open(path, O_RDONLY);
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
index c0091137074b..e1b55261526f 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
@@ -5,7 +5,7 @@ static int libbpf_debug_print(enum libbpf_print_level level,
5 const char *format, va_list args) 5 const char *format, va_list args)
6{ 6{
7 if (level != LIBBPF_DEBUG) 7 if (level != LIBBPF_DEBUG)
8 return 0; 8 return vfprintf(stderr, format, args);
9 9
10 if (!strstr(format, "verifier log")) 10 if (!strstr(format, "verifier log"))
11 return 0; 11 return 0;
@@ -32,24 +32,69 @@ static int check_load(const char *file, enum bpf_prog_type type)
32 32
33void test_bpf_verif_scale(void) 33void test_bpf_verif_scale(void)
34{ 34{
35 const char *scale[] = { 35 const char *sched_cls[] = {
36 "./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o" 36 "./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o",
37 }; 37 };
38 const char *pyperf[] = { 38 const char *raw_tp[] = {
39 "./pyperf50.o", "./pyperf100.o", "./pyperf180.o" 39 /* full unroll by llvm */
40 "./pyperf50.o", "./pyperf100.o", "./pyperf180.o",
41
42 /* partial unroll. llvm will unroll loop ~150 times.
43 * C loop count -> 600.
44 * Asm loop count -> 4.
45 * 16k insns in loop body.
46 * Total of 5 such loops. Total program size ~82k insns.
47 */
48 "./pyperf600.o",
49
50 /* no unroll at all.
51 * C loop count -> 600.
52 * ASM loop count -> 600.
53 * ~110 insns in loop body.
54 * Total of 5 such loops. Total program size ~1500 insns.
55 */
56 "./pyperf600_nounroll.o",
57
58 "./loop1.o", "./loop2.o",
59
60 /* partial unroll. 19k insn in a loop.
61 * Total program size 20.8k insn.
62 * ~350k processed_insns
63 */
64 "./strobemeta.o",
65
66 /* no unroll, tiny loops */
67 "./strobemeta_nounroll1.o",
68 "./strobemeta_nounroll2.o",
69 };
70 const char *cg_sysctl[] = {
71 "./test_sysctl_loop1.o", "./test_sysctl_loop2.o",
40 }; 72 };
41 int err, i; 73 int err, i;
42 74
43 if (verifier_stats) 75 if (verifier_stats)
44 libbpf_set_print(libbpf_debug_print); 76 libbpf_set_print(libbpf_debug_print);
45 77
46 for (i = 0; i < ARRAY_SIZE(scale); i++) { 78 err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT);
47 err = check_load(scale[i], BPF_PROG_TYPE_SCHED_CLS); 79 printf("test_scale:loop3:%s\n", err ? (error_cnt--, "OK") : "FAIL");
48 printf("test_scale:%s:%s\n", scale[i], err ? "FAIL" : "OK"); 80
81 for (i = 0; i < ARRAY_SIZE(sched_cls); i++) {
82 err = check_load(sched_cls[i], BPF_PROG_TYPE_SCHED_CLS);
83 printf("test_scale:%s:%s\n", sched_cls[i], err ? "FAIL" : "OK");
49 } 84 }
50 85
51 for (i = 0; i < ARRAY_SIZE(pyperf); i++) { 86 for (i = 0; i < ARRAY_SIZE(raw_tp); i++) {
52 err = check_load(pyperf[i], BPF_PROG_TYPE_RAW_TRACEPOINT); 87 err = check_load(raw_tp[i], BPF_PROG_TYPE_RAW_TRACEPOINT);
53 printf("test_scale:%s:%s\n", pyperf[i], err ? "FAIL" : "OK"); 88 printf("test_scale:%s:%s\n", raw_tp[i], err ? "FAIL" : "OK");
54 } 89 }
90
91 for (i = 0; i < ARRAY_SIZE(cg_sysctl); i++) {
92 err = check_load(cg_sysctl[i], BPF_PROG_TYPE_CGROUP_SYSCTL);
93 printf("test_scale:%s:%s\n", cg_sysctl[i], err ? "FAIL" : "OK");
94 }
95 err = check_load("./test_xdp_loop.o", BPF_PROG_TYPE_XDP);
96 printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK");
97
98 err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL);
99 printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK");
55} 100}
diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c
index 81ad9a0b29d0..849f42e548b5 100644
--- a/tools/testing/selftests/bpf/progs/bpf_flow.c
+++ b/tools/testing/selftests/bpf/progs/bpf_flow.c
@@ -57,17 +57,25 @@ struct frag_hdr {
57 __be32 identification; 57 __be32 identification;
58}; 58};
59 59
60struct bpf_map_def SEC("maps") jmp_table = { 60struct {
61 __u32 type;
62 __u32 max_entries;
63 __u32 key_size;
64 __u32 value_size;
65} jmp_table SEC(".maps") = {
61 .type = BPF_MAP_TYPE_PROG_ARRAY, 66 .type = BPF_MAP_TYPE_PROG_ARRAY,
67 .max_entries = 8,
62 .key_size = sizeof(__u32), 68 .key_size = sizeof(__u32),
63 .value_size = sizeof(__u32), 69 .value_size = sizeof(__u32),
64 .max_entries = 8
65}; 70};
66 71
67struct bpf_map_def SEC("maps") last_dissection = { 72struct {
73 __u32 type;
74 __u32 max_entries;
75 __u32 *key;
76 struct bpf_flow_keys *value;
77} last_dissection SEC(".maps") = {
68 .type = BPF_MAP_TYPE_ARRAY, 78 .type = BPF_MAP_TYPE_ARRAY,
69 .key_size = sizeof(__u32),
70 .value_size = sizeof(struct bpf_flow_keys),
71 .max_entries = 1, 79 .max_entries = 1,
72}; 80};
73 81
diff --git a/tools/testing/selftests/bpf/progs/loop1.c b/tools/testing/selftests/bpf/progs/loop1.c
new file mode 100644
index 000000000000..dea395af9ea9
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/loop1.c
@@ -0,0 +1,28 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#include <linux/sched.h>
4#include <linux/ptrace.h>
5#include <stdint.h>
6#include <stddef.h>
7#include <stdbool.h>
8#include <linux/bpf.h>
9#include "bpf_helpers.h"
10
11char _license[] SEC("license") = "GPL";
12
13SEC("raw_tracepoint/kfree_skb")
14int nested_loops(volatile struct pt_regs* ctx)
15{
16 int i, j, sum = 0, m;
17
18 for (j = 0; j < 300; j++)
19 for (i = 0; i < j; i++) {
20 if (j & 1)
21 m = ctx->rax;
22 else
23 m = j;
24 sum += i * m;
25 }
26
27 return sum;
28}
diff --git a/tools/testing/selftests/bpf/progs/loop2.c b/tools/testing/selftests/bpf/progs/loop2.c
new file mode 100644
index 000000000000..0637bd8e8bcf
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/loop2.c
@@ -0,0 +1,28 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#include <linux/sched.h>
4#include <linux/ptrace.h>
5#include <stdint.h>
6#include <stddef.h>
7#include <stdbool.h>
8#include <linux/bpf.h>
9#include "bpf_helpers.h"
10
11char _license[] SEC("license") = "GPL";
12
13SEC("raw_tracepoint/consume_skb")
14int while_true(volatile struct pt_regs* ctx)
15{
16 int i = 0;
17
18 while (true) {
19 if (ctx->rax & 1)
20 i += 3;
21 else
22 i += 7;
23 if (i > 40)
24 break;
25 }
26
27 return i;
28}
diff --git a/tools/testing/selftests/bpf/progs/loop3.c b/tools/testing/selftests/bpf/progs/loop3.c
new file mode 100644
index 000000000000..30a0f6cba080
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/loop3.c
@@ -0,0 +1,22 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#include <linux/sched.h>
4#include <linux/ptrace.h>
5#include <stdint.h>
6#include <stddef.h>
7#include <stdbool.h>
8#include <linux/bpf.h>
9#include "bpf_helpers.h"
10
11char _license[] SEC("license") = "GPL";
12
13SEC("raw_tracepoint/consume_skb")
14int while_true(volatile struct pt_regs* ctx)
15{
16 __u64 i = 0, sum = 0;
17 do {
18 i++;
19 sum += ctx->rax;
20 } while (i < 0x100000000ULL);
21 return sum;
22}
diff --git a/tools/testing/selftests/bpf/progs/netcnt_prog.c b/tools/testing/selftests/bpf/progs/netcnt_prog.c
index 9f741e69cebe..a25c82a5b7c8 100644
--- a/tools/testing/selftests/bpf/progs/netcnt_prog.c
+++ b/tools/testing/selftests/bpf/progs/netcnt_prog.c
@@ -10,24 +10,22 @@
10#define REFRESH_TIME_NS 100000000 10#define REFRESH_TIME_NS 100000000
11#define NS_PER_SEC 1000000000 11#define NS_PER_SEC 1000000000
12 12
13struct bpf_map_def SEC("maps") percpu_netcnt = { 13struct {
14 __u32 type;
15 struct bpf_cgroup_storage_key *key;
16 struct percpu_net_cnt *value;
17} percpu_netcnt SEC(".maps") = {
14 .type = BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, 18 .type = BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
15 .key_size = sizeof(struct bpf_cgroup_storage_key),
16 .value_size = sizeof(struct percpu_net_cnt),
17}; 19};
18 20
19BPF_ANNOTATE_KV_PAIR(percpu_netcnt, struct bpf_cgroup_storage_key, 21struct {
20 struct percpu_net_cnt); 22 __u32 type;
21 23 struct bpf_cgroup_storage_key *key;
22struct bpf_map_def SEC("maps") netcnt = { 24 struct net_cnt *value;
25} netcnt SEC(".maps") = {
23 .type = BPF_MAP_TYPE_CGROUP_STORAGE, 26 .type = BPF_MAP_TYPE_CGROUP_STORAGE,
24 .key_size = sizeof(struct bpf_cgroup_storage_key),
25 .value_size = sizeof(struct net_cnt),
26}; 27};
27 28
28BPF_ANNOTATE_KV_PAIR(netcnt, struct bpf_cgroup_storage_key,
29 struct net_cnt);
30
31SEC("cgroup/skb") 29SEC("cgroup/skb")
32int bpf_nextcnt(struct __sk_buff *skb) 30int bpf_nextcnt(struct __sk_buff *skb)
33{ 31{
diff --git a/tools/testing/selftests/bpf/progs/pyperf.h b/tools/testing/selftests/bpf/progs/pyperf.h
index 0cc5e4ee90bd..6b0781391be5 100644
--- a/tools/testing/selftests/bpf/progs/pyperf.h
+++ b/tools/testing/selftests/bpf/progs/pyperf.h
@@ -220,7 +220,11 @@ static inline __attribute__((__always_inline__)) int __on_event(struct pt_regs *
220 int32_t* symbol_counter = bpf_map_lookup_elem(&symbolmap, &sym); 220 int32_t* symbol_counter = bpf_map_lookup_elem(&symbolmap, &sym);
221 if (symbol_counter == NULL) 221 if (symbol_counter == NULL)
222 return 0; 222 return 0;
223#pragma unroll 223#ifdef NO_UNROLL
224#pragma clang loop unroll(disable)
225#else
226#pragma clang loop unroll(full)
227#endif
224 /* Unwind python stack */ 228 /* Unwind python stack */
225 for (int i = 0; i < STACK_MAX_LEN; ++i) { 229 for (int i = 0; i < STACK_MAX_LEN; ++i) {
226 if (frame_ptr && get_frame_data(frame_ptr, pidData, &frame, &sym)) { 230 if (frame_ptr && get_frame_data(frame_ptr, pidData, &frame, &sym)) {
diff --git a/tools/testing/selftests/bpf/progs/pyperf600.c b/tools/testing/selftests/bpf/progs/pyperf600.c
new file mode 100644
index 000000000000..cb49b89e37cd
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/pyperf600.c
@@ -0,0 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#define STACK_MAX_LEN 600
4/* clang will not unroll the loop 600 times.
5 * Instead it will unroll it to the amount it deemed
6 * appropriate, but the loop will still execute 600 times.
7 * Total program size is around 90k insns
8 */
9#include "pyperf.h"
diff --git a/tools/testing/selftests/bpf/progs/pyperf600_nounroll.c b/tools/testing/selftests/bpf/progs/pyperf600_nounroll.c
new file mode 100644
index 000000000000..6beff7502f4d
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/pyperf600_nounroll.c
@@ -0,0 +1,8 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#define STACK_MAX_LEN 600
4#define NO_UNROLL
5/* clang will not unroll at all.
6 * Total program size is around 2k insns
7 */
8#include "pyperf.h"
diff --git a/tools/testing/selftests/bpf/progs/socket_cookie_prog.c b/tools/testing/selftests/bpf/progs/socket_cookie_prog.c
index 9ff8ac4b0bf6..6aabb681fb9a 100644
--- a/tools/testing/selftests/bpf/progs/socket_cookie_prog.c
+++ b/tools/testing/selftests/bpf/progs/socket_cookie_prog.c
@@ -7,25 +7,36 @@
7#include "bpf_helpers.h" 7#include "bpf_helpers.h"
8#include "bpf_endian.h" 8#include "bpf_endian.h"
9 9
10struct bpf_map_def SEC("maps") socket_cookies = { 10struct socket_cookie {
11 .type = BPF_MAP_TYPE_HASH, 11 __u64 cookie_key;
12 .key_size = sizeof(__u64), 12 __u32 cookie_value;
13 .value_size = sizeof(__u32), 13};
14 .max_entries = 1 << 8, 14
15struct {
16 __u32 type;
17 __u32 map_flags;
18 int *key;
19 struct socket_cookie *value;
20} socket_cookies SEC(".maps") = {
21 .type = BPF_MAP_TYPE_SK_STORAGE,
22 .map_flags = BPF_F_NO_PREALLOC,
15}; 23};
16 24
17SEC("cgroup/connect6") 25SEC("cgroup/connect6")
18int set_cookie(struct bpf_sock_addr *ctx) 26int set_cookie(struct bpf_sock_addr *ctx)
19{ 27{
20 __u32 cookie_value = 0xFF; 28 struct socket_cookie *p;
21 __u64 cookie_key;
22 29
23 if (ctx->family != AF_INET6 || ctx->user_family != AF_INET6) 30 if (ctx->family != AF_INET6 || ctx->user_family != AF_INET6)
24 return 1; 31 return 1;
25 32
26 cookie_key = bpf_get_socket_cookie(ctx); 33 p = bpf_sk_storage_get(&socket_cookies, ctx->sk, 0,
27 if (bpf_map_update_elem(&socket_cookies, &cookie_key, &cookie_value, 0)) 34 BPF_SK_STORAGE_GET_F_CREATE);
28 return 0; 35 if (!p)
36 return 1;
37
38 p->cookie_value = 0xFF;
39 p->cookie_key = bpf_get_socket_cookie(ctx);
29 40
30 return 1; 41 return 1;
31} 42}
@@ -33,9 +44,8 @@ int set_cookie(struct bpf_sock_addr *ctx)
33SEC("sockops") 44SEC("sockops")
34int update_cookie(struct bpf_sock_ops *ctx) 45int update_cookie(struct bpf_sock_ops *ctx)
35{ 46{
36 __u32 new_cookie_value; 47 struct bpf_sock *sk;
37 __u32 *cookie_value; 48 struct socket_cookie *p;
38 __u64 cookie_key;
39 49
40 if (ctx->family != AF_INET6) 50 if (ctx->family != AF_INET6)
41 return 1; 51 return 1;
@@ -43,14 +53,17 @@ int update_cookie(struct bpf_sock_ops *ctx)
43 if (ctx->op != BPF_SOCK_OPS_TCP_CONNECT_CB) 53 if (ctx->op != BPF_SOCK_OPS_TCP_CONNECT_CB)
44 return 1; 54 return 1;
45 55
46 cookie_key = bpf_get_socket_cookie(ctx); 56 if (!ctx->sk)
57 return 1;
58
59 p = bpf_sk_storage_get(&socket_cookies, ctx->sk, 0, 0);
60 if (!p)
61 return 1;
47 62
48 cookie_value = bpf_map_lookup_elem(&socket_cookies, &cookie_key); 63 if (p->cookie_key != bpf_get_socket_cookie(ctx))
49 if (!cookie_value)
50 return 1; 64 return 1;
51 65
52 new_cookie_value = (ctx->local_port << 8) | *cookie_value; 66 p->cookie_value = (ctx->local_port << 8) | p->cookie_value;
53 bpf_map_update_elem(&socket_cookies, &cookie_key, &new_cookie_value, 0);
54 67
55 return 1; 68 return 1;
56} 69}
diff --git a/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c b/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
index ed3e4a551c57..9390e0244259 100644
--- a/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
+++ b/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
@@ -1,6 +1,5 @@
1#include <linux/bpf.h> 1#include <linux/bpf.h>
2#include "bpf_helpers.h" 2#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h" 3#include "bpf_endian.h"
5 4
6int _version SEC("version") = 1; 5int _version SEC("version") = 1;
diff --git a/tools/testing/selftests/bpf/progs/sockmap_tcp_msg_prog.c b/tools/testing/selftests/bpf/progs/sockmap_tcp_msg_prog.c
index 65fbfdb6cd3a..e80484d98a1a 100644
--- a/tools/testing/selftests/bpf/progs/sockmap_tcp_msg_prog.c
+++ b/tools/testing/selftests/bpf/progs/sockmap_tcp_msg_prog.c
@@ -1,6 +1,6 @@
1#include <linux/bpf.h> 1#include <linux/bpf.h>
2
2#include "bpf_helpers.h" 3#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h" 4#include "bpf_endian.h"
5 5
6int _version SEC("version") = 1; 6int _version SEC("version") = 1;
diff --git a/tools/testing/selftests/bpf/progs/sockmap_verdict_prog.c b/tools/testing/selftests/bpf/progs/sockmap_verdict_prog.c
index bdc22be46f2e..d85c874ef25e 100644
--- a/tools/testing/selftests/bpf/progs/sockmap_verdict_prog.c
+++ b/tools/testing/selftests/bpf/progs/sockmap_verdict_prog.c
@@ -1,6 +1,5 @@
1#include <linux/bpf.h> 1#include <linux/bpf.h>
2#include "bpf_helpers.h" 2#include "bpf_helpers.h"
3#include "bpf_util.h"
4#include "bpf_endian.h" 3#include "bpf_endian.h"
5 4
6int _version SEC("version") = 1; 5int _version SEC("version") = 1;
diff --git a/tools/testing/selftests/bpf/progs/strobemeta.c b/tools/testing/selftests/bpf/progs/strobemeta.c
new file mode 100644
index 000000000000..d3df3d86f092
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/strobemeta.c
@@ -0,0 +1,10 @@
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2// Copyright (c) 2019 Facebook
3
4#define STROBE_MAX_INTS 2
5#define STROBE_MAX_STRS 25
6#define STROBE_MAX_MAPS 100
7#define STROBE_MAX_MAP_ENTRIES 20
8/* full unroll by llvm #undef NO_UNROLL */
9#include "strobemeta.h"
10
diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h
new file mode 100644
index 000000000000..1ff73f60a3e4
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/strobemeta.h
@@ -0,0 +1,528 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3
4#include <stdint.h>
5#include <stddef.h>
6#include <stdbool.h>
7#include <linux/bpf.h>
8#include <linux/ptrace.h>
9#include <linux/sched.h>
10#include <linux/types.h>
11#include "bpf_helpers.h"
12
13typedef uint32_t pid_t;
14struct task_struct {};
15
16#define TASK_COMM_LEN 16
17#define PERF_MAX_STACK_DEPTH 127
18
19#define STROBE_TYPE_INVALID 0
20#define STROBE_TYPE_INT 1
21#define STROBE_TYPE_STR 2
22#define STROBE_TYPE_MAP 3
23
24#define STACK_TABLE_EPOCH_SHIFT 20
25#define STROBE_MAX_STR_LEN 1
26#define STROBE_MAX_CFGS 32
27#define STROBE_MAX_PAYLOAD \
28 (STROBE_MAX_STRS * STROBE_MAX_STR_LEN + \
29 STROBE_MAX_MAPS * (1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
30
31struct strobe_value_header {
32 /*
33 * meaning depends on type:
34 * 1. int: 0, if value not set, 1 otherwise
35 * 2. str: 1 always, whether value is set or not is determined by ptr
36 * 3. map: 1 always, pointer points to additional struct with number
37 * of entries (up to STROBE_MAX_MAP_ENTRIES)
38 */
39 uint16_t len;
40 /*
41 * _reserved might be used for some future fields/flags, but we always
42 * want to keep strobe_value_header to be 8 bytes, so BPF can read 16
43 * bytes in one go and get both header and value
44 */
45 uint8_t _reserved[6];
46};
47
48/*
49 * strobe_value_generic is used from BPF probe only, but needs to be a union
50 * of strobe_value_int/strobe_value_str/strobe_value_map
51 */
52struct strobe_value_generic {
53 struct strobe_value_header header;
54 union {
55 int64_t val;
56 void *ptr;
57 };
58};
59
60struct strobe_value_int {
61 struct strobe_value_header header;
62 int64_t value;
63};
64
65struct strobe_value_str {
66 struct strobe_value_header header;
67 const char* value;
68};
69
70struct strobe_value_map {
71 struct strobe_value_header header;
72 const struct strobe_map_raw* value;
73};
74
75struct strobe_map_entry {
76 const char* key;
77 const char* val;
78};
79
80/*
81 * Map of C-string key/value pairs with fixed maximum capacity. Each map has
82 * corresponding int64 ID, which application can use (or ignore) in whatever
83 * way appropriate. Map is "write-only", there is no way to get data out of
84 * map. Map is intended to be used to provide metadata for profilers and is
85 * not to be used for internal in-app communication. All methods are
86 * thread-safe.
87 */
88struct strobe_map_raw {
89 /*
90 * general purpose unique ID that's up to application to decide
91 * whether and how to use; for request metadata use case id is unique
92 * request ID that's used to match metadata with stack traces on
93 * Strobelight backend side
94 */
95 int64_t id;
96 /* number of used entries in map */
97 int64_t cnt;
98 /*
99 * having volatile doesn't change anything on BPF side, but clang
100 * emits warnings for passing `volatile const char *` into
101 * bpf_probe_read_str that expects just `const char *`
102 */
103 const char* tag;
104 /*
105 * key/value entries, each consisting of 2 pointers to key and value
106 * C strings
107 */
108 struct strobe_map_entry entries[STROBE_MAX_MAP_ENTRIES];
109};
110
111/* Following values define supported values of TLS mode */
112#define TLS_NOT_SET -1
113#define TLS_LOCAL_EXEC 0
114#define TLS_IMM_EXEC 1
115#define TLS_GENERAL_DYN 2
116
117/*
118 * structure that universally represents TLS location (both for static
119 * executables and shared libraries)
120 */
121struct strobe_value_loc {
122 /*
123 * tls_mode defines what TLS mode was used for particular metavariable:
124 * - -1 (TLS_NOT_SET) - no metavariable;
125 * - 0 (TLS_LOCAL_EXEC) - Local Executable mode;
126 * - 1 (TLS_IMM_EXEC) - Immediate Executable mode;
127 * - 2 (TLS_GENERAL_DYN) - General Dynamic mode;
128 * Local Dynamic mode is not yet supported, because never seen in
129 * practice. Mode defines how offset field is interpreted. See
130 * calc_location() in below for details.
131 */
132 int64_t tls_mode;
133 /*
134 * TLS_LOCAL_EXEC: offset from thread pointer (fs:0 for x86-64,
135 * tpidr_el0 for aarch64).
136 * TLS_IMM_EXEC: absolute address of GOT entry containing offset
137 * from thread pointer;
138 * TLS_GENERAL_DYN: absolute addres of double GOT entry
139 * containing tls_index_t struct;
140 */
141 int64_t offset;
142};
143
144struct strobemeta_cfg {
145 int64_t req_meta_idx;
146 struct strobe_value_loc int_locs[STROBE_MAX_INTS];
147 struct strobe_value_loc str_locs[STROBE_MAX_STRS];
148 struct strobe_value_loc map_locs[STROBE_MAX_MAPS];
149};
150
151struct strobe_map_descr {
152 uint64_t id;
153 int16_t tag_len;
154 /*
155 * cnt <0 - map value isn't set;
156 * 0 - map has id set, but no key/value entries
157 */
158 int16_t cnt;
159 /*
160 * both key_lens[i] and val_lens[i] should be >0 for present key/value
161 * entry
162 */
163 uint16_t key_lens[STROBE_MAX_MAP_ENTRIES];
164 uint16_t val_lens[STROBE_MAX_MAP_ENTRIES];
165};
166
167struct strobemeta_payload {
168 /* req_id has valid request ID, if req_meta_valid == 1 */
169 int64_t req_id;
170 uint8_t req_meta_valid;
171 /*
172 * mask has Nth bit set to 1, if Nth metavar was present and
173 * successfully read
174 */
175 uint64_t int_vals_set_mask;
176 int64_t int_vals[STROBE_MAX_INTS];
177 /* len is >0 for present values */
178 uint16_t str_lens[STROBE_MAX_STRS];
179 /* if map_descrs[i].cnt == -1, metavar is not present/set */
180 struct strobe_map_descr map_descrs[STROBE_MAX_MAPS];
181 /*
182 * payload has compactly packed values of str and map variables in the
183 * form: strval1\0strval2\0map1key1\0map1val1\0map2key1\0map2val1\0
184 * (and so on); str_lens[i], key_lens[i] and val_lens[i] determines
185 * value length
186 */
187 char payload[STROBE_MAX_PAYLOAD];
188};
189
190struct strobelight_bpf_sample {
191 uint64_t ktime;
192 char comm[TASK_COMM_LEN];
193 pid_t pid;
194 int user_stack_id;
195 int kernel_stack_id;
196 int has_meta;
197 struct strobemeta_payload metadata;
198 /*
199 * makes it possible to pass (<real payload size> + 1) as data size to
200 * perf_submit() to avoid perf_submit's paranoia about passing zero as
201 * size, as it deduces that <real payload size> might be
202 * **theoretically** zero
203 */
204 char dummy_safeguard;
205};
206
207struct bpf_map_def SEC("maps") samples = {
208 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
209 .key_size = sizeof(int),
210 .value_size = sizeof(int),
211 .max_entries = 32,
212};
213
214struct bpf_map_def SEC("maps") stacks_0 = {
215 .type = BPF_MAP_TYPE_STACK_TRACE,
216 .key_size = sizeof(uint32_t),
217 .value_size = sizeof(uint64_t) * PERF_MAX_STACK_DEPTH,
218 .max_entries = 16,
219};
220
221struct bpf_map_def SEC("maps") stacks_1 = {
222 .type = BPF_MAP_TYPE_STACK_TRACE,
223 .key_size = sizeof(uint32_t),
224 .value_size = sizeof(uint64_t) * PERF_MAX_STACK_DEPTH,
225 .max_entries = 16,
226};
227
228struct bpf_map_def SEC("maps") sample_heap = {
229 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
230 .key_size = sizeof(uint32_t),
231 .value_size = sizeof(struct strobelight_bpf_sample),
232 .max_entries = 1,
233};
234
235struct bpf_map_def SEC("maps") strobemeta_cfgs = {
236 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
237 .key_size = sizeof(pid_t),
238 .value_size = sizeof(struct strobemeta_cfg),
239 .max_entries = STROBE_MAX_CFGS,
240};
241
242/* Type for the dtv. */
243/* https://github.com/lattera/glibc/blob/master/nptl/sysdeps/x86_64/tls.h#L34 */
244typedef union dtv {
245 size_t counter;
246 struct {
247 void* val;
248 bool is_static;
249 } pointer;
250} dtv_t;
251
252/* Partial definition for tcbhead_t */
253/* https://github.com/bminor/glibc/blob/master/sysdeps/x86_64/nptl/tls.h#L42 */
254struct tcbhead {
255 void* tcb;
256 dtv_t* dtv;
257};
258
259/*
260 * TLS module/offset information for shared library case.
261 * For x86-64, this is mapped onto two entries in GOT.
262 * For aarch64, this is pointed to by second GOT entry.
263 */
264struct tls_index {
265 uint64_t module;
266 uint64_t offset;
267};
268
269static inline __attribute__((always_inline))
270void *calc_location(struct strobe_value_loc *loc, void *tls_base)
271{
272 /*
273 * tls_mode value is:
274 * - -1 (TLS_NOT_SET), if no metavar is present;
275 * - 0 (TLS_LOCAL_EXEC), if metavar uses Local Executable mode of TLS
276 * (offset from fs:0 for x86-64 or tpidr_el0 for aarch64);
277 * - 1 (TLS_IMM_EXEC), if metavar uses Immediate Executable mode of TLS;
278 * - 2 (TLS_GENERAL_DYN), if metavar uses General Dynamic mode of TLS;
279 * This schema allows to use something like:
280 * (tls_mode + 1) * (tls_base + offset)
281 * to get NULL for "no metavar" location, or correct pointer for local
282 * executable mode without doing extra ifs.
283 */
284 if (loc->tls_mode <= TLS_LOCAL_EXEC) {
285 /* static executable is simple, we just have offset from
286 * tls_base */
287 void *addr = tls_base + loc->offset;
288 /* multiply by (tls_mode + 1) to get NULL, if we have no
289 * metavar in this slot */
290 return (void *)((loc->tls_mode + 1) * (int64_t)addr);
291 }
292 /*
293 * Other modes are more complicated, we need to jump through few hoops.
294 *
295 * For immediate executable mode (currently supported only for aarch64):
296 * - loc->offset is pointing to a GOT entry containing fixed offset
297 * relative to tls_base;
298 *
299 * For general dynamic mode:
300 * - loc->offset is pointing to a beginning of double GOT entries;
301 * - (for aarch64 only) second entry points to tls_index_t struct;
302 * - (for x86-64 only) two GOT entries are already tls_index_t;
303 * - tls_index_t->module is used to find start of TLS section in
304 * which variable resides;
305 * - tls_index_t->offset provides offset within that TLS section,
306 * pointing to value of variable.
307 */
308 struct tls_index tls_index;
309 dtv_t *dtv;
310 void *tls_ptr;
311
312 bpf_probe_read(&tls_index, sizeof(struct tls_index),
313 (void *)loc->offset);
314 /* valid module index is always positive */
315 if (tls_index.module > 0) {
316 /* dtv = ((struct tcbhead *)tls_base)->dtv[tls_index.module] */
317 bpf_probe_read(&dtv, sizeof(dtv),
318 &((struct tcbhead *)tls_base)->dtv);
319 dtv += tls_index.module;
320 } else {
321 dtv = NULL;
322 }
323 bpf_probe_read(&tls_ptr, sizeof(void *), dtv);
324 /* if pointer has (void *)-1 value, then TLS wasn't initialized yet */
325 return tls_ptr && tls_ptr != (void *)-1
326 ? tls_ptr + tls_index.offset
327 : NULL;
328}
329
330static inline __attribute__((always_inline))
331void read_int_var(struct strobemeta_cfg *cfg, size_t idx, void *tls_base,
332 struct strobe_value_generic *value,
333 struct strobemeta_payload *data)
334{
335 void *location = calc_location(&cfg->int_locs[idx], tls_base);
336 if (!location)
337 return;
338
339 bpf_probe_read(value, sizeof(struct strobe_value_generic), location);
340 data->int_vals[idx] = value->val;
341 if (value->header.len)
342 data->int_vals_set_mask |= (1 << idx);
343}
344
345static inline __attribute__((always_inline))
346uint64_t read_str_var(struct strobemeta_cfg* cfg, size_t idx, void *tls_base,
347 struct strobe_value_generic *value,
348 struct strobemeta_payload *data, void *payload)
349{
350 void *location;
351 uint32_t len;
352
353 data->str_lens[idx] = 0;
354 location = calc_location(&cfg->str_locs[idx], tls_base);
355 if (!location)
356 return 0;
357
358 bpf_probe_read(value, sizeof(struct strobe_value_generic), location);
359 len = bpf_probe_read_str(payload, STROBE_MAX_STR_LEN, value->ptr);
360 /*
361 * if bpf_probe_read_str returns error (<0), due to casting to
362 * unsinged int, it will become big number, so next check is
363 * sufficient to check for errors AND prove to BPF verifier, that
364 * bpf_probe_read_str won't return anything bigger than
365 * STROBE_MAX_STR_LEN
366 */
367 if (len > STROBE_MAX_STR_LEN)
368 return 0;
369
370 data->str_lens[idx] = len;
371 return len;
372}
373
374static inline __attribute__((always_inline))
375void *read_map_var(struct strobemeta_cfg *cfg, size_t idx, void *tls_base,
376 struct strobe_value_generic *value,
377 struct strobemeta_payload* data, void *payload)
378{
379 struct strobe_map_descr* descr = &data->map_descrs[idx];
380 struct strobe_map_raw map;
381 void *location;
382 uint32_t len;
383 int i;
384
385 descr->tag_len = 0; /* presume no tag is set */
386 descr->cnt = -1; /* presume no value is set */
387
388 location = calc_location(&cfg->map_locs[idx], tls_base);
389 if (!location)
390 return payload;
391
392 bpf_probe_read(value, sizeof(struct strobe_value_generic), location);
393 if (bpf_probe_read(&map, sizeof(struct strobe_map_raw), value->ptr))
394 return payload;
395
396 descr->id = map.id;
397 descr->cnt = map.cnt;
398 if (cfg->req_meta_idx == idx) {
399 data->req_id = map.id;
400 data->req_meta_valid = 1;
401 }
402
403 len = bpf_probe_read_str(payload, STROBE_MAX_STR_LEN, map.tag);
404 if (len <= STROBE_MAX_STR_LEN) {
405 descr->tag_len = len;
406 payload += len;
407 }
408
409#ifdef NO_UNROLL
410#pragma clang loop unroll(disable)
411#else
412#pragma unroll
413#endif
414 for (int i = 0; i < STROBE_MAX_MAP_ENTRIES && i < map.cnt; ++i) {
415 descr->key_lens[i] = 0;
416 len = bpf_probe_read_str(payload, STROBE_MAX_STR_LEN,
417 map.entries[i].key);
418 if (len <= STROBE_MAX_STR_LEN) {
419 descr->key_lens[i] = len;
420 payload += len;
421 }
422 descr->val_lens[i] = 0;
423 len = bpf_probe_read_str(payload, STROBE_MAX_STR_LEN,
424 map.entries[i].val);
425 if (len <= STROBE_MAX_STR_LEN) {
426 descr->val_lens[i] = len;
427 payload += len;
428 }
429 }
430
431 return payload;
432}
433
434/*
435 * read_strobe_meta returns NULL, if no metadata was read; otherwise returns
436 * pointer to *right after* payload ends
437 */
438static inline __attribute__((always_inline))
439void *read_strobe_meta(struct task_struct* task,
440 struct strobemeta_payload* data) {
441 pid_t pid = bpf_get_current_pid_tgid() >> 32;
442 struct strobe_value_generic value = {0};
443 struct strobemeta_cfg *cfg;
444 void *tls_base, *payload;
445
446 cfg = bpf_map_lookup_elem(&strobemeta_cfgs, &pid);
447 if (!cfg)
448 return NULL;
449
450 data->int_vals_set_mask = 0;
451 data->req_meta_valid = 0;
452 payload = data->payload;
453 /*
454 * we don't have struct task_struct definition, it should be:
455 * tls_base = (void *)task->thread.fsbase;
456 */
457 tls_base = (void *)task;
458
459#ifdef NO_UNROLL
460#pragma clang loop unroll(disable)
461#else
462#pragma unroll
463#endif
464 for (int i = 0; i < STROBE_MAX_INTS; ++i) {
465 read_int_var(cfg, i, tls_base, &value, data);
466 }
467#ifdef NO_UNROLL
468#pragma clang loop unroll(disable)
469#else
470#pragma unroll
471#endif
472 for (int i = 0; i < STROBE_MAX_STRS; ++i) {
473 payload += read_str_var(cfg, i, tls_base, &value, data, payload);
474 }
475#ifdef NO_UNROLL
476#pragma clang loop unroll(disable)
477#else
478#pragma unroll
479#endif
480 for (int i = 0; i < STROBE_MAX_MAPS; ++i) {
481 payload = read_map_var(cfg, i, tls_base, &value, data, payload);
482 }
483 /*
484 * return pointer right after end of payload, so it's possible to
485 * calculate exact amount of useful data that needs to be sent
486 */
487 return payload;
488}
489
490SEC("raw_tracepoint/kfree_skb")
491int on_event(struct pt_regs *ctx) {
492 pid_t pid = bpf_get_current_pid_tgid() >> 32;
493 struct strobelight_bpf_sample* sample;
494 struct task_struct *task;
495 uint32_t zero = 0;
496 uint64_t ktime_ns;
497 void *sample_end;
498
499 sample = bpf_map_lookup_elem(&sample_heap, &zero);
500 if (!sample)
501 return 0; /* this will never happen */
502
503 sample->pid = pid;
504 bpf_get_current_comm(&sample->comm, TASK_COMM_LEN);
505 ktime_ns = bpf_ktime_get_ns();
506 sample->ktime = ktime_ns;
507
508 task = (struct task_struct *)bpf_get_current_task();
509 sample_end = read_strobe_meta(task, &sample->metadata);
510 sample->has_meta = sample_end != NULL;
511 sample_end = sample_end ? : &sample->metadata;
512
513 if ((ktime_ns >> STACK_TABLE_EPOCH_SHIFT) & 1) {
514 sample->kernel_stack_id = bpf_get_stackid(ctx, &stacks_1, 0);
515 sample->user_stack_id = bpf_get_stackid(ctx, &stacks_1, BPF_F_USER_STACK);
516 } else {
517 sample->kernel_stack_id = bpf_get_stackid(ctx, &stacks_0, 0);
518 sample->user_stack_id = bpf_get_stackid(ctx, &stacks_0, BPF_F_USER_STACK);
519 }
520
521 uint64_t sample_size = sample_end - (void *)sample;
522 /* should always be true */
523 if (sample_size < sizeof(struct strobelight_bpf_sample))
524 bpf_perf_event_output(ctx, &samples, 0, sample, 1 + sample_size);
525 return 0;
526}
527
528char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/strobemeta_nounroll1.c b/tools/testing/selftests/bpf/progs/strobemeta_nounroll1.c
new file mode 100644
index 000000000000..f0a1669e11d6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/strobemeta_nounroll1.c
@@ -0,0 +1,9 @@
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2// Copyright (c) 2019 Facebook
3
4#define STROBE_MAX_INTS 2
5#define STROBE_MAX_STRS 25
6#define STROBE_MAX_MAPS 13
7#define STROBE_MAX_MAP_ENTRIES 20
8#define NO_UNROLL
9#include "strobemeta.h"
diff --git a/tools/testing/selftests/bpf/progs/strobemeta_nounroll2.c b/tools/testing/selftests/bpf/progs/strobemeta_nounroll2.c
new file mode 100644
index 000000000000..4291a7d642e7
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/strobemeta_nounroll2.c
@@ -0,0 +1,9 @@
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2// Copyright (c) 2019 Facebook
3
4#define STROBE_MAX_INTS 2
5#define STROBE_MAX_STRS 25
6#define STROBE_MAX_MAPS 30
7#define STROBE_MAX_MAP_ENTRIES 20
8#define NO_UNROLL
9#include "strobemeta.h"
diff --git a/tools/testing/selftests/bpf/progs/test_btf_newkv.c b/tools/testing/selftests/bpf/progs/test_btf_newkv.c
new file mode 100644
index 000000000000..28c16bb583b6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_btf_newkv.c
@@ -0,0 +1,73 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/* Copyright (c) 2018 Facebook */
3#include <linux/bpf.h>
4#include "bpf_helpers.h"
5
6int _version SEC("version") = 1;
7
8struct ipv_counts {
9 unsigned int v4;
10 unsigned int v6;
11};
12
13/* just to validate we can handle maps in multiple sections */
14struct bpf_map_def SEC("maps") btf_map_legacy = {
15 .type = BPF_MAP_TYPE_ARRAY,
16 .key_size = sizeof(int),
17 .value_size = sizeof(long long),
18 .max_entries = 4,
19};
20
21BPF_ANNOTATE_KV_PAIR(btf_map_legacy, int, struct ipv_counts);
22
23struct {
24 int *key;
25 struct ipv_counts *value;
26 unsigned int type;
27 unsigned int max_entries;
28} btf_map SEC(".maps") = {
29 .type = BPF_MAP_TYPE_ARRAY,
30 .max_entries = 4,
31};
32
33struct dummy_tracepoint_args {
34 unsigned long long pad;
35 struct sock *sock;
36};
37
38__attribute__((noinline))
39static int test_long_fname_2(struct dummy_tracepoint_args *arg)
40{
41 struct ipv_counts *counts;
42 int key = 0;
43
44 if (!arg->sock)
45 return 0;
46
47 counts = bpf_map_lookup_elem(&btf_map, &key);
48 if (!counts)
49 return 0;
50
51 counts->v6++;
52
53 /* just verify we can reference both maps */
54 counts = bpf_map_lookup_elem(&btf_map_legacy, &key);
55 if (!counts)
56 return 0;
57
58 return 0;
59}
60
61__attribute__((noinline))
62static int test_long_fname_1(struct dummy_tracepoint_args *arg)
63{
64 return test_long_fname_2(arg);
65}
66
67SEC("dummy_tracepoint")
68int _dummy_tracepoint(struct dummy_tracepoint_args *arg)
69{
70 return test_long_fname_1(arg);
71}
72
73char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
index f6d9f238e00a..aaa6ec250e15 100644
--- a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
+++ b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
@@ -15,17 +15,25 @@ struct stack_trace_t {
15 struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP]; 15 struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
16}; 16};
17 17
18struct bpf_map_def SEC("maps") perfmap = { 18struct {
19 __u32 type;
20 __u32 max_entries;
21 __u32 key_size;
22 __u32 value_size;
23} perfmap SEC(".maps") = {
19 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, 24 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
25 .max_entries = 2,
20 .key_size = sizeof(int), 26 .key_size = sizeof(int),
21 .value_size = sizeof(__u32), 27 .value_size = sizeof(__u32),
22 .max_entries = 2,
23}; 28};
24 29
25struct bpf_map_def SEC("maps") stackdata_map = { 30struct {
31 __u32 type;
32 __u32 max_entries;
33 __u32 *key;
34 struct stack_trace_t *value;
35} stackdata_map SEC(".maps") = {
26 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 36 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(struct stack_trace_t),
29 .max_entries = 1, 37 .max_entries = 1,
30}; 38};
31 39
@@ -47,10 +55,13 @@ struct bpf_map_def SEC("maps") stackdata_map = {
47 * issue and avoid complicated C programming massaging. 55 * issue and avoid complicated C programming massaging.
48 * This is an acceptable workaround since there is one entry here. 56 * This is an acceptable workaround since there is one entry here.
49 */ 57 */
50struct bpf_map_def SEC("maps") rawdata_map = { 58struct {
59 __u32 type;
60 __u32 max_entries;
61 __u32 *key;
62 __u64 (*value)[2 * MAX_STACK_RAWTP];
63} rawdata_map SEC(".maps") = {
51 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 64 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
52 .key_size = sizeof(__u32),
53 .value_size = MAX_STACK_RAWTP * sizeof(__u64) * 2,
54 .max_entries = 1, 65 .max_entries = 1,
55}; 66};
56 67
diff --git a/tools/testing/selftests/bpf/progs/test_global_data.c b/tools/testing/selftests/bpf/progs/test_global_data.c
index 5ab14e941980..866cc7ddbe43 100644
--- a/tools/testing/selftests/bpf/progs/test_global_data.c
+++ b/tools/testing/selftests/bpf/progs/test_global_data.c
@@ -7,17 +7,23 @@
7 7
8#include "bpf_helpers.h" 8#include "bpf_helpers.h"
9 9
10struct bpf_map_def SEC("maps") result_number = { 10struct {
11 __u32 type;
12 __u32 max_entries;
13 __u32 *key;
14 __u64 *value;
15} result_number SEC(".maps") = {
11 .type = BPF_MAP_TYPE_ARRAY, 16 .type = BPF_MAP_TYPE_ARRAY,
12 .key_size = sizeof(__u32),
13 .value_size = sizeof(__u64),
14 .max_entries = 11, 17 .max_entries = 11,
15}; 18};
16 19
17struct bpf_map_def SEC("maps") result_string = { 20struct {
21 __u32 type;
22 __u32 max_entries;
23 __u32 *key;
24 const char (*value)[32];
25} result_string SEC(".maps") = {
18 .type = BPF_MAP_TYPE_ARRAY, 26 .type = BPF_MAP_TYPE_ARRAY,
19 .key_size = sizeof(__u32),
20 .value_size = 32,
21 .max_entries = 5, 27 .max_entries = 5,
22}; 28};
23 29
@@ -27,10 +33,13 @@ struct foo {
27 __u64 c; 33 __u64 c;
28}; 34};
29 35
30struct bpf_map_def SEC("maps") result_struct = { 36struct {
37 __u32 type;
38 __u32 max_entries;
39 __u32 *key;
40 struct foo *value;
41} result_struct SEC(".maps") = {
31 .type = BPF_MAP_TYPE_ARRAY, 42 .type = BPF_MAP_TYPE_ARRAY,
32 .key_size = sizeof(__u32),
33 .value_size = sizeof(struct foo),
34 .max_entries = 5, 43 .max_entries = 5,
35}; 44};
36 45
diff --git a/tools/testing/selftests/bpf/progs/test_l4lb.c b/tools/testing/selftests/bpf/progs/test_l4lb.c
index 1e10c9590991..848cbb90f581 100644
--- a/tools/testing/selftests/bpf/progs/test_l4lb.c
+++ b/tools/testing/selftests/bpf/progs/test_l4lb.c
@@ -169,38 +169,53 @@ struct eth_hdr {
169 unsigned short eth_proto; 169 unsigned short eth_proto;
170}; 170};
171 171
172struct bpf_map_def SEC("maps") vip_map = { 172struct {
173 __u32 type;
174 __u32 max_entries;
175 struct vip *key;
176 struct vip_meta *value;
177} vip_map SEC(".maps") = {
173 .type = BPF_MAP_TYPE_HASH, 178 .type = BPF_MAP_TYPE_HASH,
174 .key_size = sizeof(struct vip),
175 .value_size = sizeof(struct vip_meta),
176 .max_entries = MAX_VIPS, 179 .max_entries = MAX_VIPS,
177}; 180};
178 181
179struct bpf_map_def SEC("maps") ch_rings = { 182struct {
183 __u32 type;
184 __u32 max_entries;
185 __u32 *key;
186 __u32 *value;
187} ch_rings SEC(".maps") = {
180 .type = BPF_MAP_TYPE_ARRAY, 188 .type = BPF_MAP_TYPE_ARRAY,
181 .key_size = sizeof(__u32),
182 .value_size = sizeof(__u32),
183 .max_entries = CH_RINGS_SIZE, 189 .max_entries = CH_RINGS_SIZE,
184}; 190};
185 191
186struct bpf_map_def SEC("maps") reals = { 192struct {
193 __u32 type;
194 __u32 max_entries;
195 __u32 *key;
196 struct real_definition *value;
197} reals SEC(".maps") = {
187 .type = BPF_MAP_TYPE_ARRAY, 198 .type = BPF_MAP_TYPE_ARRAY,
188 .key_size = sizeof(__u32),
189 .value_size = sizeof(struct real_definition),
190 .max_entries = MAX_REALS, 199 .max_entries = MAX_REALS,
191}; 200};
192 201
193struct bpf_map_def SEC("maps") stats = { 202struct {
203 __u32 type;
204 __u32 max_entries;
205 __u32 *key;
206 struct vip_stats *value;
207} stats SEC(".maps") = {
194 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 208 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
195 .key_size = sizeof(__u32),
196 .value_size = sizeof(struct vip_stats),
197 .max_entries = MAX_VIPS, 209 .max_entries = MAX_VIPS,
198}; 210};
199 211
200struct bpf_map_def SEC("maps") ctl_array = { 212struct {
213 __u32 type;
214 __u32 max_entries;
215 __u32 *key;
216 struct ctl_value *value;
217} ctl_array SEC(".maps") = {
201 .type = BPF_MAP_TYPE_ARRAY, 218 .type = BPF_MAP_TYPE_ARRAY,
202 .key_size = sizeof(__u32),
203 .value_size = sizeof(struct ctl_value),
204 .max_entries = CTL_MAP_SIZE, 219 .max_entries = CTL_MAP_SIZE,
205}; 220};
206 221
diff --git a/tools/testing/selftests/bpf/progs/test_l4lb_noinline.c b/tools/testing/selftests/bpf/progs/test_l4lb_noinline.c
index ba44a14e6dc4..c63ecf3ca573 100644
--- a/tools/testing/selftests/bpf/progs/test_l4lb_noinline.c
+++ b/tools/testing/selftests/bpf/progs/test_l4lb_noinline.c
@@ -165,38 +165,53 @@ struct eth_hdr {
165 unsigned short eth_proto; 165 unsigned short eth_proto;
166}; 166};
167 167
168struct bpf_map_def SEC("maps") vip_map = { 168struct {
169 __u32 type;
170 __u32 max_entries;
171 struct vip *key;
172 struct vip_meta *value;
173} vip_map SEC(".maps") = {
169 .type = BPF_MAP_TYPE_HASH, 174 .type = BPF_MAP_TYPE_HASH,
170 .key_size = sizeof(struct vip),
171 .value_size = sizeof(struct vip_meta),
172 .max_entries = MAX_VIPS, 175 .max_entries = MAX_VIPS,
173}; 176};
174 177
175struct bpf_map_def SEC("maps") ch_rings = { 178struct {
179 __u32 type;
180 __u32 max_entries;
181 __u32 *key;
182 __u32 *value;
183} ch_rings SEC(".maps") = {
176 .type = BPF_MAP_TYPE_ARRAY, 184 .type = BPF_MAP_TYPE_ARRAY,
177 .key_size = sizeof(__u32),
178 .value_size = sizeof(__u32),
179 .max_entries = CH_RINGS_SIZE, 185 .max_entries = CH_RINGS_SIZE,
180}; 186};
181 187
182struct bpf_map_def SEC("maps") reals = { 188struct {
189 __u32 type;
190 __u32 max_entries;
191 __u32 *key;
192 struct real_definition *value;
193} reals SEC(".maps") = {
183 .type = BPF_MAP_TYPE_ARRAY, 194 .type = BPF_MAP_TYPE_ARRAY,
184 .key_size = sizeof(__u32),
185 .value_size = sizeof(struct real_definition),
186 .max_entries = MAX_REALS, 195 .max_entries = MAX_REALS,
187}; 196};
188 197
189struct bpf_map_def SEC("maps") stats = { 198struct {
199 __u32 type;
200 __u32 max_entries;
201 __u32 *key;
202 struct vip_stats *value;
203} stats SEC(".maps") = {
190 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 204 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
191 .key_size = sizeof(__u32),
192 .value_size = sizeof(struct vip_stats),
193 .max_entries = MAX_VIPS, 205 .max_entries = MAX_VIPS,
194}; 206};
195 207
196struct bpf_map_def SEC("maps") ctl_array = { 208struct {
209 __u32 type;
210 __u32 max_entries;
211 __u32 *key;
212 struct ctl_value *value;
213} ctl_array SEC(".maps") = {
197 .type = BPF_MAP_TYPE_ARRAY, 214 .type = BPF_MAP_TYPE_ARRAY,
198 .key_size = sizeof(__u32),
199 .value_size = sizeof(struct ctl_value),
200 .max_entries = CTL_MAP_SIZE, 215 .max_entries = CTL_MAP_SIZE,
201}; 216};
202 217
diff --git a/tools/testing/selftests/bpf/progs/test_map_lock.c b/tools/testing/selftests/bpf/progs/test_map_lock.c
index af8cc68ed2f9..40d9c2853393 100644
--- a/tools/testing/selftests/bpf/progs/test_map_lock.c
+++ b/tools/testing/selftests/bpf/progs/test_map_lock.c
@@ -11,29 +11,31 @@ struct hmap_elem {
11 int var[VAR_NUM]; 11 int var[VAR_NUM];
12}; 12};
13 13
14struct bpf_map_def SEC("maps") hash_map = { 14struct {
15 __u32 type;
16 __u32 max_entries;
17 __u32 *key;
18 struct hmap_elem *value;
19} hash_map SEC(".maps") = {
15 .type = BPF_MAP_TYPE_HASH, 20 .type = BPF_MAP_TYPE_HASH,
16 .key_size = sizeof(int),
17 .value_size = sizeof(struct hmap_elem),
18 .max_entries = 1, 21 .max_entries = 1,
19}; 22};
20 23
21BPF_ANNOTATE_KV_PAIR(hash_map, int, struct hmap_elem);
22
23struct array_elem { 24struct array_elem {
24 struct bpf_spin_lock lock; 25 struct bpf_spin_lock lock;
25 int var[VAR_NUM]; 26 int var[VAR_NUM];
26}; 27};
27 28
28struct bpf_map_def SEC("maps") array_map = { 29struct {
30 __u32 type;
31 __u32 max_entries;
32 int *key;
33 struct array_elem *value;
34} array_map SEC(".maps") = {
29 .type = BPF_MAP_TYPE_ARRAY, 35 .type = BPF_MAP_TYPE_ARRAY,
30 .key_size = sizeof(int),
31 .value_size = sizeof(struct array_elem),
32 .max_entries = 1, 36 .max_entries = 1,
33}; 37};
34 38
35BPF_ANNOTATE_KV_PAIR(array_map, int, struct array_elem);
36
37SEC("map_lock_demo") 39SEC("map_lock_demo")
38int bpf_map_lock_test(struct __sk_buff *skb) 40int bpf_map_lock_test(struct __sk_buff *skb)
39{ 41{
diff --git a/tools/testing/selftests/bpf/progs/test_seg6_loop.c b/tools/testing/selftests/bpf/progs/test_seg6_loop.c
new file mode 100644
index 000000000000..463964d79f73
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_seg6_loop.c
@@ -0,0 +1,261 @@
1#include <stddef.h>
2#include <inttypes.h>
3#include <errno.h>
4#include <linux/seg6_local.h>
5#include <linux/bpf.h>
6#include "bpf_helpers.h"
7#include "bpf_endian.h"
8
9/* Packet parsing state machine helpers. */
10#define cursor_advance(_cursor, _len) \
11 ({ void *_tmp = _cursor; _cursor += _len; _tmp; })
12
13#define SR6_FLAG_ALERT (1 << 4)
14
15#define htonll(x) ((bpf_htonl(1)) == 1 ? (x) : ((uint64_t)bpf_htonl((x) & \
16 0xFFFFFFFF) << 32) | bpf_htonl((x) >> 32))
17#define ntohll(x) ((bpf_ntohl(1)) == 1 ? (x) : ((uint64_t)bpf_ntohl((x) & \
18 0xFFFFFFFF) << 32) | bpf_ntohl((x) >> 32))
19#define BPF_PACKET_HEADER __attribute__((packed))
20
21struct ip6_t {
22 unsigned int ver:4;
23 unsigned int priority:8;
24 unsigned int flow_label:20;
25 unsigned short payload_len;
26 unsigned char next_header;
27 unsigned char hop_limit;
28 unsigned long long src_hi;
29 unsigned long long src_lo;
30 unsigned long long dst_hi;
31 unsigned long long dst_lo;
32} BPF_PACKET_HEADER;
33
34struct ip6_addr_t {
35 unsigned long long hi;
36 unsigned long long lo;
37} BPF_PACKET_HEADER;
38
39struct ip6_srh_t {
40 unsigned char nexthdr;
41 unsigned char hdrlen;
42 unsigned char type;
43 unsigned char segments_left;
44 unsigned char first_segment;
45 unsigned char flags;
46 unsigned short tag;
47
48 struct ip6_addr_t segments[0];
49} BPF_PACKET_HEADER;
50
51struct sr6_tlv_t {
52 unsigned char type;
53 unsigned char len;
54 unsigned char value[0];
55} BPF_PACKET_HEADER;
56
57static __attribute__((always_inline)) struct ip6_srh_t *get_srh(struct __sk_buff *skb)
58{
59 void *cursor, *data_end;
60 struct ip6_srh_t *srh;
61 struct ip6_t *ip;
62 uint8_t *ipver;
63
64 data_end = (void *)(long)skb->data_end;
65 cursor = (void *)(long)skb->data;
66 ipver = (uint8_t *)cursor;
67
68 if ((void *)ipver + sizeof(*ipver) > data_end)
69 return NULL;
70
71 if ((*ipver >> 4) != 6)
72 return NULL;
73
74 ip = cursor_advance(cursor, sizeof(*ip));
75 if ((void *)ip + sizeof(*ip) > data_end)
76 return NULL;
77
78 if (ip->next_header != 43)
79 return NULL;
80
81 srh = cursor_advance(cursor, sizeof(*srh));
82 if ((void *)srh + sizeof(*srh) > data_end)
83 return NULL;
84
85 if (srh->type != 4)
86 return NULL;
87
88 return srh;
89}
90
91static __attribute__((always_inline))
92int update_tlv_pad(struct __sk_buff *skb, uint32_t new_pad,
93 uint32_t old_pad, uint32_t pad_off)
94{
95 int err;
96
97 if (new_pad != old_pad) {
98 err = bpf_lwt_seg6_adjust_srh(skb, pad_off,
99 (int) new_pad - (int) old_pad);
100 if (err)
101 return err;
102 }
103
104 if (new_pad > 0) {
105 char pad_tlv_buf[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0};
107 struct sr6_tlv_t *pad_tlv = (struct sr6_tlv_t *) pad_tlv_buf;
108
109 pad_tlv->type = SR6_TLV_PADDING;
110 pad_tlv->len = new_pad - 2;
111
112 err = bpf_lwt_seg6_store_bytes(skb, pad_off,
113 (void *)pad_tlv_buf, new_pad);
114 if (err)
115 return err;
116 }
117
118 return 0;
119}
120
121static __attribute__((always_inline))
122int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh,
123 uint32_t *tlv_off, uint32_t *pad_size,
124 uint32_t *pad_off)
125{
126 uint32_t srh_off, cur_off;
127 int offset_valid = 0;
128 int err;
129
130 srh_off = (char *)srh - (char *)(long)skb->data;
131 // cur_off = end of segments, start of possible TLVs
132 cur_off = srh_off + sizeof(*srh) +
133 sizeof(struct ip6_addr_t) * (srh->first_segment + 1);
134
135 *pad_off = 0;
136
137 // we can only go as far as ~10 TLVs due to the BPF max stack size
138 #pragma clang loop unroll(disable)
139 for (int i = 0; i < 100; i++) {
140 struct sr6_tlv_t tlv;
141
142 if (cur_off == *tlv_off)
143 offset_valid = 1;
144
145 if (cur_off >= srh_off + ((srh->hdrlen + 1) << 3))
146 break;
147
148 err = bpf_skb_load_bytes(skb, cur_off, &tlv, sizeof(tlv));
149 if (err)
150 return err;
151
152 if (tlv.type == SR6_TLV_PADDING) {
153 *pad_size = tlv.len + sizeof(tlv);
154 *pad_off = cur_off;
155
156 if (*tlv_off == srh_off) {
157 *tlv_off = cur_off;
158 offset_valid = 1;
159 }
160 break;
161
162 } else if (tlv.type == SR6_TLV_HMAC) {
163 break;
164 }
165
166 cur_off += sizeof(tlv) + tlv.len;
167 } // we reached the padding or HMAC TLVs, or the end of the SRH
168
169 if (*pad_off == 0)
170 *pad_off = cur_off;
171
172 if (*tlv_off == -1)
173 *tlv_off = cur_off;
174 else if (!offset_valid)
175 return -EINVAL;
176
177 return 0;
178}
179
180static __attribute__((always_inline))
181int add_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off,
182 struct sr6_tlv_t *itlv, uint8_t tlv_size)
183{
184 uint32_t srh_off = (char *)srh - (char *)(long)skb->data;
185 uint8_t len_remaining, new_pad;
186 uint32_t pad_off = 0;
187 uint32_t pad_size = 0;
188 uint32_t partial_srh_len;
189 int err;
190
191 if (tlv_off != -1)
192 tlv_off += srh_off;
193
194 if (itlv->type == SR6_TLV_PADDING || itlv->type == SR6_TLV_HMAC)
195 return -EINVAL;
196
197 err = is_valid_tlv_boundary(skb, srh, &tlv_off, &pad_size, &pad_off);
198 if (err)
199 return err;
200
201 err = bpf_lwt_seg6_adjust_srh(skb, tlv_off, sizeof(*itlv) + itlv->len);
202 if (err)
203 return err;
204
205 err = bpf_lwt_seg6_store_bytes(skb, tlv_off, (void *)itlv, tlv_size);
206 if (err)
207 return err;
208
209 // the following can't be moved inside update_tlv_pad because the
210 // bpf verifier has some issues with it
211 pad_off += sizeof(*itlv) + itlv->len;
212 partial_srh_len = pad_off - srh_off;
213 len_remaining = partial_srh_len % 8;
214 new_pad = 8 - len_remaining;
215
216 if (new_pad == 1) // cannot pad for 1 byte only
217 new_pad = 9;
218 else if (new_pad == 8)
219 new_pad = 0;
220
221 return update_tlv_pad(skb, new_pad, pad_size, pad_off);
222}
223
224// Add an Egress TLV fc00::4, add the flag A,
225// and apply End.X action to fc42::1
226SEC("lwt_seg6local")
227int __add_egr_x(struct __sk_buff *skb)
228{
229 unsigned long long hi = 0xfc42000000000000;
230 unsigned long long lo = 0x1;
231 struct ip6_srh_t *srh = get_srh(skb);
232 uint8_t new_flags = SR6_FLAG_ALERT;
233 struct ip6_addr_t addr;
234 int err, offset;
235
236 if (srh == NULL)
237 return BPF_DROP;
238
239 uint8_t tlv[20] = {2, 18, 0, 0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
240 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4};
241
242 err = add_tlv(skb, srh, (srh->hdrlen+1) << 3,
243 (struct sr6_tlv_t *)&tlv, 20);
244 if (err)
245 return BPF_DROP;
246
247 offset = sizeof(struct ip6_t) + offsetof(struct ip6_srh_t, flags);
248 err = bpf_lwt_seg6_store_bytes(skb, offset,
249 (void *)&new_flags, sizeof(new_flags));
250 if (err)
251 return BPF_DROP;
252
253 addr.lo = htonll(lo);
254 addr.hi = htonll(hi);
255 err = bpf_lwt_seg6_action(skb, SEG6_LOCAL_ACTION_END_X,
256 (void *)&addr, sizeof(addr));
257 if (err)
258 return BPF_DROP;
259 return BPF_REDIRECT;
260}
261char __license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c b/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c
index 5b54ec637ada..435a9527733e 100644
--- a/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c
@@ -21,38 +21,55 @@ int _version SEC("version") = 1;
21#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 21#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
22#endif 22#endif
23 23
24struct bpf_map_def SEC("maps") outer_map = { 24struct {
25 __u32 type;
26 __u32 max_entries;
27 __u32 key_size;
28 __u32 value_size;
29} outer_map SEC(".maps") = {
25 .type = BPF_MAP_TYPE_ARRAY_OF_MAPS, 30 .type = BPF_MAP_TYPE_ARRAY_OF_MAPS,
31 .max_entries = 1,
26 .key_size = sizeof(__u32), 32 .key_size = sizeof(__u32),
27 .value_size = sizeof(__u32), 33 .value_size = sizeof(__u32),
28 .max_entries = 1,
29}; 34};
30 35
31struct bpf_map_def SEC("maps") result_map = { 36struct {
37 __u32 type;
38 __u32 max_entries;
39 __u32 *key;
40 __u32 *value;
41} result_map SEC(".maps") = {
32 .type = BPF_MAP_TYPE_ARRAY, 42 .type = BPF_MAP_TYPE_ARRAY,
33 .key_size = sizeof(__u32),
34 .value_size = sizeof(__u32),
35 .max_entries = NR_RESULTS, 43 .max_entries = NR_RESULTS,
36}; 44};
37 45
38struct bpf_map_def SEC("maps") tmp_index_ovr_map = { 46struct {
47 __u32 type;
48 __u32 max_entries;
49 __u32 *key;
50 int *value;
51} tmp_index_ovr_map SEC(".maps") = {
39 .type = BPF_MAP_TYPE_ARRAY, 52 .type = BPF_MAP_TYPE_ARRAY,
40 .key_size = sizeof(__u32),
41 .value_size = sizeof(int),
42 .max_entries = 1, 53 .max_entries = 1,
43}; 54};
44 55
45struct bpf_map_def SEC("maps") linum_map = { 56struct {
57 __u32 type;
58 __u32 max_entries;
59 __u32 *key;
60 __u32 *value;
61} linum_map SEC(".maps") = {
46 .type = BPF_MAP_TYPE_ARRAY, 62 .type = BPF_MAP_TYPE_ARRAY,
47 .key_size = sizeof(__u32),
48 .value_size = sizeof(__u32),
49 .max_entries = 1, 63 .max_entries = 1,
50}; 64};
51 65
52struct bpf_map_def SEC("maps") data_check_map = { 66struct {
67 __u32 type;
68 __u32 max_entries;
69 __u32 *key;
70 struct data_check *value;
71} data_check_map SEC(".maps") = {
53 .type = BPF_MAP_TYPE_ARRAY, 72 .type = BPF_MAP_TYPE_ARRAY,
54 .key_size = sizeof(__u32),
55 .value_size = sizeof(struct data_check),
56 .max_entries = 1, 73 .max_entries = 1,
57}; 74};
58 75
diff --git a/tools/testing/selftests/bpf/progs/test_send_signal_kern.c b/tools/testing/selftests/bpf/progs/test_send_signal_kern.c
index 45a1a1a2c345..6ac68be5d68b 100644
--- a/tools/testing/selftests/bpf/progs/test_send_signal_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_send_signal_kern.c
@@ -4,24 +4,26 @@
4#include <linux/version.h> 4#include <linux/version.h>
5#include "bpf_helpers.h" 5#include "bpf_helpers.h"
6 6
7struct bpf_map_def SEC("maps") info_map = { 7struct {
8 __u32 type;
9 __u32 max_entries;
10 __u32 *key;
11 __u64 *value;
12} info_map SEC(".maps") = {
8 .type = BPF_MAP_TYPE_ARRAY, 13 .type = BPF_MAP_TYPE_ARRAY,
9 .key_size = sizeof(__u32),
10 .value_size = sizeof(__u64),
11 .max_entries = 1, 14 .max_entries = 1,
12}; 15};
13 16
14BPF_ANNOTATE_KV_PAIR(info_map, __u32, __u64); 17struct {
15 18 __u32 type;
16struct bpf_map_def SEC("maps") status_map = { 19 __u32 max_entries;
20 __u32 *key;
21 __u64 *value;
22} status_map SEC(".maps") = {
17 .type = BPF_MAP_TYPE_ARRAY, 23 .type = BPF_MAP_TYPE_ARRAY,
18 .key_size = sizeof(__u32),
19 .value_size = sizeof(__u64),
20 .max_entries = 1, 24 .max_entries = 1,
21}; 25};
22 26
23BPF_ANNOTATE_KV_PAIR(status_map, __u32, __u64);
24
25SEC("send_signal_demo") 27SEC("send_signal_demo")
26int bpf_send_signal_test(void *ctx) 28int bpf_send_signal_test(void *ctx)
27{ 29{
diff --git a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
index 1c39e4ccb7f1..c3d383d650cb 100644
--- a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
@@ -27,31 +27,43 @@ enum bpf_linum_array_idx {
27 __NR_BPF_LINUM_ARRAY_IDX, 27 __NR_BPF_LINUM_ARRAY_IDX,
28}; 28};
29 29
30struct bpf_map_def SEC("maps") addr_map = { 30struct {
31 __u32 type;
32 __u32 max_entries;
33 __u32 *key;
34 struct sockaddr_in6 *value;
35} addr_map SEC(".maps") = {
31 .type = BPF_MAP_TYPE_ARRAY, 36 .type = BPF_MAP_TYPE_ARRAY,
32 .key_size = sizeof(__u32),
33 .value_size = sizeof(struct sockaddr_in6),
34 .max_entries = __NR_BPF_ADDR_ARRAY_IDX, 37 .max_entries = __NR_BPF_ADDR_ARRAY_IDX,
35}; 38};
36 39
37struct bpf_map_def SEC("maps") sock_result_map = { 40struct {
41 __u32 type;
42 __u32 max_entries;
43 __u32 *key;
44 struct bpf_sock *value;
45} sock_result_map SEC(".maps") = {
38 .type = BPF_MAP_TYPE_ARRAY, 46 .type = BPF_MAP_TYPE_ARRAY,
39 .key_size = sizeof(__u32),
40 .value_size = sizeof(struct bpf_sock),
41 .max_entries = __NR_BPF_RESULT_ARRAY_IDX, 47 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
42}; 48};
43 49
44struct bpf_map_def SEC("maps") tcp_sock_result_map = { 50struct {
51 __u32 type;
52 __u32 max_entries;
53 __u32 *key;
54 struct bpf_tcp_sock *value;
55} tcp_sock_result_map SEC(".maps") = {
45 .type = BPF_MAP_TYPE_ARRAY, 56 .type = BPF_MAP_TYPE_ARRAY,
46 .key_size = sizeof(__u32),
47 .value_size = sizeof(struct bpf_tcp_sock),
48 .max_entries = __NR_BPF_RESULT_ARRAY_IDX, 57 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
49}; 58};
50 59
51struct bpf_map_def SEC("maps") linum_map = { 60struct {
61 __u32 type;
62 __u32 max_entries;
63 __u32 *key;
64 __u32 *value;
65} linum_map SEC(".maps") = {
52 .type = BPF_MAP_TYPE_ARRAY, 66 .type = BPF_MAP_TYPE_ARRAY,
53 .key_size = sizeof(__u32),
54 .value_size = sizeof(__u32),
55 .max_entries = __NR_BPF_LINUM_ARRAY_IDX, 67 .max_entries = __NR_BPF_LINUM_ARRAY_IDX,
56}; 68};
57 69
@@ -60,26 +72,26 @@ struct bpf_spinlock_cnt {
60 __u32 cnt; 72 __u32 cnt;
61}; 73};
62 74
63struct bpf_map_def SEC("maps") sk_pkt_out_cnt = { 75struct {
76 __u32 type;
77 __u32 map_flags;
78 int *key;
79 struct bpf_spinlock_cnt *value;
80} sk_pkt_out_cnt SEC(".maps") = {
64 .type = BPF_MAP_TYPE_SK_STORAGE, 81 .type = BPF_MAP_TYPE_SK_STORAGE,
65 .key_size = sizeof(int),
66 .value_size = sizeof(struct bpf_spinlock_cnt),
67 .max_entries = 0,
68 .map_flags = BPF_F_NO_PREALLOC, 82 .map_flags = BPF_F_NO_PREALLOC,
69}; 83};
70 84
71BPF_ANNOTATE_KV_PAIR(sk_pkt_out_cnt, int, struct bpf_spinlock_cnt); 85struct {
72 86 __u32 type;
73struct bpf_map_def SEC("maps") sk_pkt_out_cnt10 = { 87 __u32 map_flags;
88 int *key;
89 struct bpf_spinlock_cnt *value;
90} sk_pkt_out_cnt10 SEC(".maps") = {
74 .type = BPF_MAP_TYPE_SK_STORAGE, 91 .type = BPF_MAP_TYPE_SK_STORAGE,
75 .key_size = sizeof(int),
76 .value_size = sizeof(struct bpf_spinlock_cnt),
77 .max_entries = 0,
78 .map_flags = BPF_F_NO_PREALLOC, 92 .map_flags = BPF_F_NO_PREALLOC,
79}; 93};
80 94
81BPF_ANNOTATE_KV_PAIR(sk_pkt_out_cnt10, int, struct bpf_spinlock_cnt);
82
83static bool is_loopback6(__u32 *a6) 95static bool is_loopback6(__u32 *a6)
84{ 96{
85 return !a6[0] && !a6[1] && !a6[2] && a6[3] == bpf_htonl(1); 97 return !a6[0] && !a6[1] && !a6[2] && a6[3] == bpf_htonl(1);
diff --git a/tools/testing/selftests/bpf/progs/test_spin_lock.c b/tools/testing/selftests/bpf/progs/test_spin_lock.c
index 40f904312090..0a77ae36d981 100644
--- a/tools/testing/selftests/bpf/progs/test_spin_lock.c
+++ b/tools/testing/selftests/bpf/progs/test_spin_lock.c
@@ -10,30 +10,29 @@ struct hmap_elem {
10 int test_padding; 10 int test_padding;
11}; 11};
12 12
13struct bpf_map_def SEC("maps") hmap = { 13struct {
14 __u32 type;
15 __u32 max_entries;
16 int *key;
17 struct hmap_elem *value;
18} hmap SEC(".maps") = {
14 .type = BPF_MAP_TYPE_HASH, 19 .type = BPF_MAP_TYPE_HASH,
15 .key_size = sizeof(int),
16 .value_size = sizeof(struct hmap_elem),
17 .max_entries = 1, 20 .max_entries = 1,
18}; 21};
19 22
20BPF_ANNOTATE_KV_PAIR(hmap, int, struct hmap_elem);
21
22
23struct cls_elem { 23struct cls_elem {
24 struct bpf_spin_lock lock; 24 struct bpf_spin_lock lock;
25 volatile int cnt; 25 volatile int cnt;
26}; 26};
27 27
28struct bpf_map_def SEC("maps") cls_map = { 28struct {
29 __u32 type;
30 struct bpf_cgroup_storage_key *key;
31 struct cls_elem *value;
32} cls_map SEC(".maps") = {
29 .type = BPF_MAP_TYPE_CGROUP_STORAGE, 33 .type = BPF_MAP_TYPE_CGROUP_STORAGE,
30 .key_size = sizeof(struct bpf_cgroup_storage_key),
31 .value_size = sizeof(struct cls_elem),
32}; 34};
33 35
34BPF_ANNOTATE_KV_PAIR(cls_map, struct bpf_cgroup_storage_key,
35 struct cls_elem);
36
37struct bpf_vqueue { 36struct bpf_vqueue {
38 struct bpf_spin_lock lock; 37 struct bpf_spin_lock lock;
39 /* 4 byte hole */ 38 /* 4 byte hole */
@@ -42,14 +41,16 @@ struct bpf_vqueue {
42 unsigned int rate; 41 unsigned int rate;
43}; 42};
44 43
45struct bpf_map_def SEC("maps") vqueue = { 44struct {
45 __u32 type;
46 __u32 max_entries;
47 int *key;
48 struct bpf_vqueue *value;
49} vqueue SEC(".maps") = {
46 .type = BPF_MAP_TYPE_ARRAY, 50 .type = BPF_MAP_TYPE_ARRAY,
47 .key_size = sizeof(int),
48 .value_size = sizeof(struct bpf_vqueue),
49 .max_entries = 1, 51 .max_entries = 1,
50}; 52};
51 53
52BPF_ANNOTATE_KV_PAIR(vqueue, int, struct bpf_vqueue);
53#define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20) 54#define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)
54 55
55SEC("spin_lock_demo") 56SEC("spin_lock_demo")
diff --git a/tools/testing/selftests/bpf/progs/test_stacktrace_build_id.c b/tools/testing/selftests/bpf/progs/test_stacktrace_build_id.c
index d86c281e957f..fcf2280bb60c 100644
--- a/tools/testing/selftests/bpf/progs/test_stacktrace_build_id.c
+++ b/tools/testing/selftests/bpf/progs/test_stacktrace_build_id.c
@@ -8,34 +8,50 @@
8#define PERF_MAX_STACK_DEPTH 127 8#define PERF_MAX_STACK_DEPTH 127
9#endif 9#endif
10 10
11struct bpf_map_def SEC("maps") control_map = { 11struct {
12 __u32 type;
13 __u32 max_entries;
14 __u32 *key;
15 __u32 *value;
16} control_map SEC(".maps") = {
12 .type = BPF_MAP_TYPE_ARRAY, 17 .type = BPF_MAP_TYPE_ARRAY,
13 .key_size = sizeof(__u32),
14 .value_size = sizeof(__u32),
15 .max_entries = 1, 18 .max_entries = 1,
16}; 19};
17 20
18struct bpf_map_def SEC("maps") stackid_hmap = { 21struct {
22 __u32 type;
23 __u32 max_entries;
24 __u32 *key;
25 __u32 *value;
26} stackid_hmap SEC(".maps") = {
19 .type = BPF_MAP_TYPE_HASH, 27 .type = BPF_MAP_TYPE_HASH,
20 .key_size = sizeof(__u32),
21 .value_size = sizeof(__u32),
22 .max_entries = 16384, 28 .max_entries = 16384,
23}; 29};
24 30
25struct bpf_map_def SEC("maps") stackmap = { 31typedef struct bpf_stack_build_id stack_trace_t[PERF_MAX_STACK_DEPTH];
32
33struct {
34 __u32 type;
35 __u32 max_entries;
36 __u32 map_flags;
37 __u32 key_size;
38 __u32 value_size;
39} stackmap SEC(".maps") = {
26 .type = BPF_MAP_TYPE_STACK_TRACE, 40 .type = BPF_MAP_TYPE_STACK_TRACE,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(struct bpf_stack_build_id)
29 * PERF_MAX_STACK_DEPTH,
30 .max_entries = 128, 41 .max_entries = 128,
31 .map_flags = BPF_F_STACK_BUILD_ID, 42 .map_flags = BPF_F_STACK_BUILD_ID,
43 .key_size = sizeof(__u32),
44 .value_size = sizeof(stack_trace_t),
32}; 45};
33 46
34struct bpf_map_def SEC("maps") stack_amap = { 47struct {
48 __u32 type;
49 __u32 max_entries;
50 __u32 *key;
51 /* there seems to be a bug in kernel not handling typedef properly */
52 struct bpf_stack_build_id (*value)[PERF_MAX_STACK_DEPTH];
53} stack_amap SEC(".maps") = {
35 .type = BPF_MAP_TYPE_ARRAY, 54 .type = BPF_MAP_TYPE_ARRAY,
36 .key_size = sizeof(__u32),
37 .value_size = sizeof(struct bpf_stack_build_id)
38 * PERF_MAX_STACK_DEPTH,
39 .max_entries = 128, 55 .max_entries = 128,
40}; 56};
41 57
diff --git a/tools/testing/selftests/bpf/progs/test_stacktrace_map.c b/tools/testing/selftests/bpf/progs/test_stacktrace_map.c
index af111af7ca1a..7ad09adbf648 100644
--- a/tools/testing/selftests/bpf/progs/test_stacktrace_map.c
+++ b/tools/testing/selftests/bpf/progs/test_stacktrace_map.c
@@ -8,31 +8,47 @@
8#define PERF_MAX_STACK_DEPTH 127 8#define PERF_MAX_STACK_DEPTH 127
9#endif 9#endif
10 10
11struct bpf_map_def SEC("maps") control_map = { 11struct {
12 __u32 type;
13 __u32 max_entries;
14 __u32 *key;
15 __u32 *value;
16} control_map SEC(".maps") = {
12 .type = BPF_MAP_TYPE_ARRAY, 17 .type = BPF_MAP_TYPE_ARRAY,
13 .key_size = sizeof(__u32),
14 .value_size = sizeof(__u32),
15 .max_entries = 1, 18 .max_entries = 1,
16}; 19};
17 20
18struct bpf_map_def SEC("maps") stackid_hmap = { 21struct {
22 __u32 type;
23 __u32 max_entries;
24 __u32 *key;
25 __u32 *value;
26} stackid_hmap SEC(".maps") = {
19 .type = BPF_MAP_TYPE_HASH, 27 .type = BPF_MAP_TYPE_HASH,
20 .key_size = sizeof(__u32),
21 .value_size = sizeof(__u32),
22 .max_entries = 16384, 28 .max_entries = 16384,
23}; 29};
24 30
25struct bpf_map_def SEC("maps") stackmap = { 31typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH];
32
33struct {
34 __u32 type;
35 __u32 max_entries;
36 __u32 key_size;
37 __u32 value_size;
38} stackmap SEC(".maps") = {
26 .type = BPF_MAP_TYPE_STACK_TRACE, 39 .type = BPF_MAP_TYPE_STACK_TRACE,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(__u64) * PERF_MAX_STACK_DEPTH,
29 .max_entries = 16384, 40 .max_entries = 16384,
41 .key_size = sizeof(__u32),
42 .value_size = sizeof(stack_trace_t),
30}; 43};
31 44
32struct bpf_map_def SEC("maps") stack_amap = { 45struct {
46 __u32 type;
47 __u32 max_entries;
48 __u32 *key;
49 __u64 (*value)[PERF_MAX_STACK_DEPTH];
50} stack_amap SEC(".maps") = {
33 .type = BPF_MAP_TYPE_ARRAY, 51 .type = BPF_MAP_TYPE_ARRAY,
34 .key_size = sizeof(__u32),
35 .value_size = sizeof(__u64) * PERF_MAX_STACK_DEPTH,
36 .max_entries = 16384, 52 .max_entries = 16384,
37}; 53};
38 54
diff --git a/tools/testing/selftests/bpf/progs/test_sysctl_loop1.c b/tools/testing/selftests/bpf/progs/test_sysctl_loop1.c
new file mode 100644
index 000000000000..608a06871572
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_sysctl_loop1.c
@@ -0,0 +1,71 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3
4#include <stdint.h>
5#include <string.h>
6
7#include <linux/stddef.h>
8#include <linux/bpf.h>
9
10#include "bpf_helpers.h"
11
12#ifndef ARRAY_SIZE
13#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
14#endif
15
16/* tcp_mem sysctl has only 3 ints, but this test is doing TCP_MEM_LOOPS */
17#define TCP_MEM_LOOPS 28 /* because 30 doesn't fit into 512 bytes of stack */
18#define MAX_ULONG_STR_LEN 7
19#define MAX_VALUE_STR_LEN (TCP_MEM_LOOPS * MAX_ULONG_STR_LEN)
20
21static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx)
22{
23 volatile char tcp_mem_name[] = "net/ipv4/tcp_mem/very_very_very_very_long_pointless_string";
24 unsigned char i;
25 char name[64];
26 int ret;
27
28 memset(name, 0, sizeof(name));
29 ret = bpf_sysctl_get_name(ctx, name, sizeof(name), 0);
30 if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
31 return 0;
32
33#pragma clang loop unroll(disable)
34 for (i = 0; i < sizeof(tcp_mem_name); ++i)
35 if (name[i] != tcp_mem_name[i])
36 return 0;
37
38 return 1;
39}
40
41SEC("cgroup/sysctl")
42int sysctl_tcp_mem(struct bpf_sysctl *ctx)
43{
44 unsigned long tcp_mem[TCP_MEM_LOOPS] = {};
45 char value[MAX_VALUE_STR_LEN];
46 unsigned char i, off = 0;
47 int ret;
48
49 if (ctx->write)
50 return 0;
51
52 if (!is_tcp_mem(ctx))
53 return 0;
54
55 ret = bpf_sysctl_get_current_value(ctx, value, MAX_VALUE_STR_LEN);
56 if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
57 return 0;
58
59#pragma clang loop unroll(disable)
60 for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
61 ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
62 tcp_mem + i);
63 if (ret <= 0 || ret > MAX_ULONG_STR_LEN)
64 return 0;
65 off += ret & MAX_ULONG_STR_LEN;
66 }
67
68 return tcp_mem[0] < tcp_mem[1] && tcp_mem[1] < tcp_mem[2];
69}
70
71char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c b/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
new file mode 100644
index 000000000000..cb201cbe11e7
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
@@ -0,0 +1,72 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3
4#include <stdint.h>
5#include <string.h>
6
7#include <linux/stddef.h>
8#include <linux/bpf.h>
9
10#include "bpf_helpers.h"
11
12#ifndef ARRAY_SIZE
13#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
14#endif
15
16/* tcp_mem sysctl has only 3 ints, but this test is doing TCP_MEM_LOOPS */
17#define TCP_MEM_LOOPS 20 /* because 30 doesn't fit into 512 bytes of stack */
18#define MAX_ULONG_STR_LEN 7
19#define MAX_VALUE_STR_LEN (TCP_MEM_LOOPS * MAX_ULONG_STR_LEN)
20
21static __attribute__((noinline)) int is_tcp_mem(struct bpf_sysctl *ctx)
22{
23 volatile char tcp_mem_name[] = "net/ipv4/tcp_mem/very_very_very_very_long_pointless_string_to_stress_byte_loop";
24 unsigned char i;
25 char name[64];
26 int ret;
27
28 memset(name, 0, sizeof(name));
29 ret = bpf_sysctl_get_name(ctx, name, sizeof(name), 0);
30 if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
31 return 0;
32
33#pragma clang loop unroll(disable)
34 for (i = 0; i < sizeof(tcp_mem_name); ++i)
35 if (name[i] != tcp_mem_name[i])
36 return 0;
37
38 return 1;
39}
40
41
42SEC("cgroup/sysctl")
43int sysctl_tcp_mem(struct bpf_sysctl *ctx)
44{
45 unsigned long tcp_mem[TCP_MEM_LOOPS] = {};
46 char value[MAX_VALUE_STR_LEN];
47 unsigned char i, off = 0;
48 int ret;
49
50 if (ctx->write)
51 return 0;
52
53 if (!is_tcp_mem(ctx))
54 return 0;
55
56 ret = bpf_sysctl_get_current_value(ctx, value, MAX_VALUE_STR_LEN);
57 if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
58 return 0;
59
60#pragma clang loop unroll(disable)
61 for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
62 ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
63 tcp_mem + i);
64 if (ret <= 0 || ret > MAX_ULONG_STR_LEN)
65 return 0;
66 off += ret & MAX_ULONG_STR_LEN;
67 }
68
69 return tcp_mem[0] < tcp_mem[1] && tcp_mem[1] < tcp_mem[2];
70}
71
72char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_sysctl_prog.c b/tools/testing/selftests/bpf/progs/test_sysctl_prog.c
index a295cad805d7..5cbbff416998 100644
--- a/tools/testing/selftests/bpf/progs/test_sysctl_prog.c
+++ b/tools/testing/selftests/bpf/progs/test_sysctl_prog.c
@@ -8,7 +8,6 @@
8#include <linux/bpf.h> 8#include <linux/bpf.h>
9 9
10#include "bpf_helpers.h" 10#include "bpf_helpers.h"
11#include "bpf_util.h"
12 11
13/* Max supported length of a string with unsigned long in base 10 (pow2 - 1). */ 12/* Max supported length of a string with unsigned long in base 10 (pow2 - 1). */
14#define MAX_ULONG_STR_LEN 0xF 13#define MAX_ULONG_STR_LEN 0xF
@@ -16,6 +15,10 @@
16/* Max supported length of sysctl value string (pow2). */ 15/* Max supported length of sysctl value string (pow2). */
17#define MAX_VALUE_STR_LEN 0x40 16#define MAX_VALUE_STR_LEN 0x40
18 17
18#ifndef ARRAY_SIZE
19#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
20#endif
21
19static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx) 22static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx)
20{ 23{
21 char tcp_mem_name[] = "net/ipv4/tcp_mem"; 24 char tcp_mem_name[] = "net/ipv4/tcp_mem";
diff --git a/tools/testing/selftests/bpf/progs/test_tcp_estats.c b/tools/testing/selftests/bpf/progs/test_tcp_estats.c
index bee3bbecc0c4..df98f7e32832 100644
--- a/tools/testing/selftests/bpf/progs/test_tcp_estats.c
+++ b/tools/testing/selftests/bpf/progs/test_tcp_estats.c
@@ -148,10 +148,13 @@ struct tcp_estats_basic_event {
148 struct tcp_estats_conn_id conn_id; 148 struct tcp_estats_conn_id conn_id;
149}; 149};
150 150
151struct bpf_map_def SEC("maps") ev_record_map = { 151struct {
152 __u32 type;
153 __u32 max_entries;
154 __u32 *key;
155 struct tcp_estats_basic_event *value;
156} ev_record_map SEC(".maps") = {
152 .type = BPF_MAP_TYPE_HASH, 157 .type = BPF_MAP_TYPE_HASH,
153 .key_size = sizeof(__u32),
154 .value_size = sizeof(struct tcp_estats_basic_event),
155 .max_entries = 1024, 158 .max_entries = 1024,
156}; 159};
157 160
diff --git a/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c b/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c
index c7c3240e0dd4..38e10c9fd996 100644
--- a/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c
@@ -14,17 +14,23 @@
14#include "bpf_endian.h" 14#include "bpf_endian.h"
15#include "test_tcpbpf.h" 15#include "test_tcpbpf.h"
16 16
17struct bpf_map_def SEC("maps") global_map = { 17struct {
18 __u32 type;
19 __u32 max_entries;
20 __u32 *key;
21 struct tcpbpf_globals *value;
22} global_map SEC(".maps") = {
18 .type = BPF_MAP_TYPE_ARRAY, 23 .type = BPF_MAP_TYPE_ARRAY,
19 .key_size = sizeof(__u32),
20 .value_size = sizeof(struct tcpbpf_globals),
21 .max_entries = 4, 24 .max_entries = 4,
22}; 25};
23 26
24struct bpf_map_def SEC("maps") sockopt_results = { 27struct {
28 __u32 type;
29 __u32 max_entries;
30 __u32 *key;
31 int *value;
32} sockopt_results SEC(".maps") = {
25 .type = BPF_MAP_TYPE_ARRAY, 33 .type = BPF_MAP_TYPE_ARRAY,
26 .key_size = sizeof(__u32),
27 .value_size = sizeof(int),
28 .max_entries = 2, 34 .max_entries = 2,
29}; 35};
30 36
diff --git a/tools/testing/selftests/bpf/progs/test_tcpnotify_kern.c b/tools/testing/selftests/bpf/progs/test_tcpnotify_kern.c
index ec6db6e64c41..d073d37d4e27 100644
--- a/tools/testing/selftests/bpf/progs/test_tcpnotify_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_tcpnotify_kern.c
@@ -14,18 +14,26 @@
14#include "bpf_endian.h" 14#include "bpf_endian.h"
15#include "test_tcpnotify.h" 15#include "test_tcpnotify.h"
16 16
17struct bpf_map_def SEC("maps") global_map = { 17struct {
18 __u32 type;
19 __u32 max_entries;
20 __u32 *key;
21 struct tcpnotify_globals *value;
22} global_map SEC(".maps") = {
18 .type = BPF_MAP_TYPE_ARRAY, 23 .type = BPF_MAP_TYPE_ARRAY,
19 .key_size = sizeof(__u32),
20 .value_size = sizeof(struct tcpnotify_globals),
21 .max_entries = 4, 24 .max_entries = 4,
22}; 25};
23 26
24struct bpf_map_def SEC("maps") perf_event_map = { 27struct {
28 __u32 type;
29 __u32 max_entries;
30 __u32 key_size;
31 __u32 value_size;
32} perf_event_map SEC(".maps") = {
25 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, 33 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
34 .max_entries = 2,
26 .key_size = sizeof(int), 35 .key_size = sizeof(int),
27 .value_size = sizeof(__u32), 36 .value_size = sizeof(__u32),
28 .max_entries = 2,
29}; 37};
30 38
31int _version SEC("version") = 1; 39int _version SEC("version") = 1;
diff --git a/tools/testing/selftests/bpf/progs/test_xdp.c b/tools/testing/selftests/bpf/progs/test_xdp.c
index 5e7df8bb5b5d..ec3d2c1c8cf9 100644
--- a/tools/testing/selftests/bpf/progs/test_xdp.c
+++ b/tools/testing/selftests/bpf/progs/test_xdp.c
@@ -22,17 +22,23 @@
22 22
23int _version SEC("version") = 1; 23int _version SEC("version") = 1;
24 24
25struct bpf_map_def SEC("maps") rxcnt = { 25struct {
26 __u32 type;
27 __u32 max_entries;
28 __u32 *key;
29 __u64 *value;
30} rxcnt SEC(".maps") = {
26 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 31 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(__u64),
29 .max_entries = 256, 32 .max_entries = 256,
30}; 33};
31 34
32struct bpf_map_def SEC("maps") vip2tnl = { 35struct {
36 __u32 type;
37 __u32 max_entries;
38 struct vip *key;
39 struct iptnl_info *value;
40} vip2tnl SEC(".maps") = {
33 .type = BPF_MAP_TYPE_HASH, 41 .type = BPF_MAP_TYPE_HASH,
34 .key_size = sizeof(struct vip),
35 .value_size = sizeof(struct iptnl_info),
36 .max_entries = MAX_IPTNL_ENTRIES, 42 .max_entries = MAX_IPTNL_ENTRIES,
37}; 43};
38 44
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_loop.c b/tools/testing/selftests/bpf/progs/test_xdp_loop.c
new file mode 100644
index 000000000000..7fa4677df22e
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_loop.c
@@ -0,0 +1,231 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2019 Facebook
3#include <stddef.h>
4#include <string.h>
5#include <linux/bpf.h>
6#include <linux/if_ether.h>
7#include <linux/if_packet.h>
8#include <linux/ip.h>
9#include <linux/ipv6.h>
10#include <linux/in.h>
11#include <linux/udp.h>
12#include <linux/tcp.h>
13#include <linux/pkt_cls.h>
14#include <sys/socket.h>
15#include "bpf_helpers.h"
16#include "bpf_endian.h"
17#include "test_iptunnel_common.h"
18
19int _version SEC("version") = 1;
20
21struct bpf_map_def SEC("maps") rxcnt = {
22 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
23 .key_size = sizeof(__u32),
24 .value_size = sizeof(__u64),
25 .max_entries = 256,
26};
27
28struct bpf_map_def SEC("maps") vip2tnl = {
29 .type = BPF_MAP_TYPE_HASH,
30 .key_size = sizeof(struct vip),
31 .value_size = sizeof(struct iptnl_info),
32 .max_entries = MAX_IPTNL_ENTRIES,
33};
34
35static __always_inline void count_tx(__u32 protocol)
36{
37 __u64 *rxcnt_count;
38
39 rxcnt_count = bpf_map_lookup_elem(&rxcnt, &protocol);
40 if (rxcnt_count)
41 *rxcnt_count += 1;
42}
43
44static __always_inline int get_dport(void *trans_data, void *data_end,
45 __u8 protocol)
46{
47 struct tcphdr *th;
48 struct udphdr *uh;
49
50 switch (protocol) {
51 case IPPROTO_TCP:
52 th = (struct tcphdr *)trans_data;
53 if (th + 1 > data_end)
54 return -1;
55 return th->dest;
56 case IPPROTO_UDP:
57 uh = (struct udphdr *)trans_data;
58 if (uh + 1 > data_end)
59 return -1;
60 return uh->dest;
61 default:
62 return 0;
63 }
64}
65
66static __always_inline void set_ethhdr(struct ethhdr *new_eth,
67 const struct ethhdr *old_eth,
68 const struct iptnl_info *tnl,
69 __be16 h_proto)
70{
71 memcpy(new_eth->h_source, old_eth->h_dest, sizeof(new_eth->h_source));
72 memcpy(new_eth->h_dest, tnl->dmac, sizeof(new_eth->h_dest));
73 new_eth->h_proto = h_proto;
74}
75
76static __always_inline int handle_ipv4(struct xdp_md *xdp)
77{
78 void *data_end = (void *)(long)xdp->data_end;
79 void *data = (void *)(long)xdp->data;
80 struct iptnl_info *tnl;
81 struct ethhdr *new_eth;
82 struct ethhdr *old_eth;
83 struct iphdr *iph = data + sizeof(struct ethhdr);
84 __u16 *next_iph;
85 __u16 payload_len;
86 struct vip vip = {};
87 int dport;
88 __u32 csum = 0;
89 int i;
90
91 if (iph + 1 > data_end)
92 return XDP_DROP;
93
94 dport = get_dport(iph + 1, data_end, iph->protocol);
95 if (dport == -1)
96 return XDP_DROP;
97
98 vip.protocol = iph->protocol;
99 vip.family = AF_INET;
100 vip.daddr.v4 = iph->daddr;
101 vip.dport = dport;
102 payload_len = bpf_ntohs(iph->tot_len);
103
104 tnl = bpf_map_lookup_elem(&vip2tnl, &vip);
105 /* It only does v4-in-v4 */
106 if (!tnl || tnl->family != AF_INET)
107 return XDP_PASS;
108
109 if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(struct iphdr)))
110 return XDP_DROP;
111
112 data = (void *)(long)xdp->data;
113 data_end = (void *)(long)xdp->data_end;
114
115 new_eth = data;
116 iph = data + sizeof(*new_eth);
117 old_eth = data + sizeof(*iph);
118
119 if (new_eth + 1 > data_end ||
120 old_eth + 1 > data_end ||
121 iph + 1 > data_end)
122 return XDP_DROP;
123
124 set_ethhdr(new_eth, old_eth, tnl, bpf_htons(ETH_P_IP));
125
126 iph->version = 4;
127 iph->ihl = sizeof(*iph) >> 2;
128 iph->frag_off = 0;
129 iph->protocol = IPPROTO_IPIP;
130 iph->check = 0;
131 iph->tos = 0;
132 iph->tot_len = bpf_htons(payload_len + sizeof(*iph));
133 iph->daddr = tnl->daddr.v4;
134 iph->saddr = tnl->saddr.v4;
135 iph->ttl = 8;
136
137 next_iph = (__u16 *)iph;
138#pragma clang loop unroll(disable)
139 for (i = 0; i < sizeof(*iph) >> 1; i++)
140 csum += *next_iph++;
141
142 iph->check = ~((csum & 0xffff) + (csum >> 16));
143
144 count_tx(vip.protocol);
145
146 return XDP_TX;
147}
148
149static __always_inline int handle_ipv6(struct xdp_md *xdp)
150{
151 void *data_end = (void *)(long)xdp->data_end;
152 void *data = (void *)(long)xdp->data;
153 struct iptnl_info *tnl;
154 struct ethhdr *new_eth;
155 struct ethhdr *old_eth;
156 struct ipv6hdr *ip6h = data + sizeof(struct ethhdr);
157 __u16 payload_len;
158 struct vip vip = {};
159 int dport;
160
161 if (ip6h + 1 > data_end)
162 return XDP_DROP;
163
164 dport = get_dport(ip6h + 1, data_end, ip6h->nexthdr);
165 if (dport == -1)
166 return XDP_DROP;
167
168 vip.protocol = ip6h->nexthdr;
169 vip.family = AF_INET6;
170 memcpy(vip.daddr.v6, ip6h->daddr.s6_addr32, sizeof(vip.daddr));
171 vip.dport = dport;
172 payload_len = ip6h->payload_len;
173
174 tnl = bpf_map_lookup_elem(&vip2tnl, &vip);
175 /* It only does v6-in-v6 */
176 if (!tnl || tnl->family != AF_INET6)
177 return XDP_PASS;
178
179 if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(struct ipv6hdr)))
180 return XDP_DROP;
181
182 data = (void *)(long)xdp->data;
183 data_end = (void *)(long)xdp->data_end;
184
185 new_eth = data;
186 ip6h = data + sizeof(*new_eth);
187 old_eth = data + sizeof(*ip6h);
188
189 if (new_eth + 1 > data_end || old_eth + 1 > data_end ||
190 ip6h + 1 > data_end)
191 return XDP_DROP;
192
193 set_ethhdr(new_eth, old_eth, tnl, bpf_htons(ETH_P_IPV6));
194
195 ip6h->version = 6;
196 ip6h->priority = 0;
197 memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));
198 ip6h->payload_len = bpf_htons(bpf_ntohs(payload_len) + sizeof(*ip6h));
199 ip6h->nexthdr = IPPROTO_IPV6;
200 ip6h->hop_limit = 8;
201 memcpy(ip6h->saddr.s6_addr32, tnl->saddr.v6, sizeof(tnl->saddr.v6));
202 memcpy(ip6h->daddr.s6_addr32, tnl->daddr.v6, sizeof(tnl->daddr.v6));
203
204 count_tx(vip.protocol);
205
206 return XDP_TX;
207}
208
209SEC("xdp_tx_iptunnel")
210int _xdp_tx_iptunnel(struct xdp_md *xdp)
211{
212 void *data_end = (void *)(long)xdp->data_end;
213 void *data = (void *)(long)xdp->data;
214 struct ethhdr *eth = data;
215 __u16 h_proto;
216
217 if (eth + 1 > data_end)
218 return XDP_DROP;
219
220 h_proto = eth->h_proto;
221
222 if (h_proto == bpf_htons(ETH_P_IP))
223 return handle_ipv4(xdp);
224 else if (h_proto == bpf_htons(ETH_P_IPV6))
225
226 return handle_ipv6(xdp);
227 else
228 return XDP_DROP;
229}
230
231char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_noinline.c b/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
index 4fe6aaad22a4..d2eddb5553d1 100644
--- a/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
+++ b/tools/testing/selftests/bpf/progs/test_xdp_noinline.c
@@ -163,52 +163,66 @@ struct lb_stats {
163 __u64 v1; 163 __u64 v1;
164}; 164};
165 165
166struct bpf_map_def __attribute__ ((section("maps"), used)) vip_map = { 166struct {
167 __u32 type;
168 __u32 max_entries;
169 struct vip_definition *key;
170 struct vip_meta *value;
171} vip_map SEC(".maps") = {
167 .type = BPF_MAP_TYPE_HASH, 172 .type = BPF_MAP_TYPE_HASH,
168 .key_size = sizeof(struct vip_definition),
169 .value_size = sizeof(struct vip_meta),
170 .max_entries = 512, 173 .max_entries = 512,
171 .map_flags = 0,
172}; 174};
173 175
174struct bpf_map_def __attribute__ ((section("maps"), used)) lru_cache = { 176struct {
177 __u32 type;
178 __u32 max_entries;
179 __u32 map_flags;
180 struct flow_key *key;
181 struct real_pos_lru *value;
182} lru_cache SEC(".maps") = {
175 .type = BPF_MAP_TYPE_LRU_HASH, 183 .type = BPF_MAP_TYPE_LRU_HASH,
176 .key_size = sizeof(struct flow_key),
177 .value_size = sizeof(struct real_pos_lru),
178 .max_entries = 300, 184 .max_entries = 300,
179 .map_flags = 1U << 1, 185 .map_flags = 1U << 1,
180}; 186};
181 187
182struct bpf_map_def __attribute__ ((section("maps"), used)) ch_rings = { 188struct {
189 __u32 type;
190 __u32 max_entries;
191 __u32 *key;
192 __u32 *value;
193} ch_rings SEC(".maps") = {
183 .type = BPF_MAP_TYPE_ARRAY, 194 .type = BPF_MAP_TYPE_ARRAY,
184 .key_size = sizeof(__u32),
185 .value_size = sizeof(__u32),
186 .max_entries = 12 * 655, 195 .max_entries = 12 * 655,
187 .map_flags = 0,
188}; 196};
189 197
190struct bpf_map_def __attribute__ ((section("maps"), used)) reals = { 198struct {
199 __u32 type;
200 __u32 max_entries;
201 __u32 *key;
202 struct real_definition *value;
203} reals SEC(".maps") = {
191 .type = BPF_MAP_TYPE_ARRAY, 204 .type = BPF_MAP_TYPE_ARRAY,
192 .key_size = sizeof(__u32),
193 .value_size = sizeof(struct real_definition),
194 .max_entries = 40, 205 .max_entries = 40,
195 .map_flags = 0,
196}; 206};
197 207
198struct bpf_map_def __attribute__ ((section("maps"), used)) stats = { 208struct {
209 __u32 type;
210 __u32 max_entries;
211 __u32 *key;
212 struct lb_stats *value;
213} stats SEC(".maps") = {
199 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 214 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
200 .key_size = sizeof(__u32),
201 .value_size = sizeof(struct lb_stats),
202 .max_entries = 515, 215 .max_entries = 515,
203 .map_flags = 0,
204}; 216};
205 217
206struct bpf_map_def __attribute__ ((section("maps"), used)) ctl_array = { 218struct {
219 __u32 type;
220 __u32 max_entries;
221 __u32 *key;
222 struct ctl_value *value;
223} ctl_array SEC(".maps") = {
207 .type = BPF_MAP_TYPE_ARRAY, 224 .type = BPF_MAP_TYPE_ARRAY,
208 .key_size = sizeof(__u32),
209 .value_size = sizeof(struct ctl_value),
210 .max_entries = 16, 225 .max_entries = 16,
211 .map_flags = 0,
212}; 226};
213 227
214struct eth_hdr { 228struct eth_hdr {
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index 289daf54dec4..8351cb5f4a20 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -4016,13 +4016,9 @@ struct btf_file_test {
4016}; 4016};
4017 4017
4018static struct btf_file_test file_tests[] = { 4018static struct btf_file_test file_tests[] = {
4019{ 4019 { .file = "test_btf_haskv.o", },
4020 .file = "test_btf_haskv.o", 4020 { .file = "test_btf_newkv.o", },
4021}, 4021 { .file = "test_btf_nokv.o", .btf_kv_notfound = true, },
4022{
4023 .file = "test_btf_nokv.o",
4024 .btf_kv_notfound = true,
4025},
4026}; 4022};
4027 4023
4028static int do_test_file(unsigned int test_num) 4024static int do_test_file(unsigned int test_num)
diff --git a/tools/testing/selftests/bpf/test_select_reuseport.c b/tools/testing/selftests/bpf/test_select_reuseport.c
index 75646d9b34aa..7566c13eb51a 100644
--- a/tools/testing/selftests/bpf/test_select_reuseport.c
+++ b/tools/testing/selftests/bpf/test_select_reuseport.c
@@ -523,6 +523,58 @@ static void test_pass_on_err(int type, sa_family_t family)
523 printf("OK\n"); 523 printf("OK\n");
524} 524}
525 525
526static void test_detach_bpf(int type, sa_family_t family)
527{
528#ifdef SO_DETACH_REUSEPORT_BPF
529 __u32 nr_run_before = 0, nr_run_after = 0, tmp, i;
530 struct epoll_event ev;
531 int cli_fd, err, nev;
532 struct cmd cmd = {};
533 int optvalue = 0;
534
535 printf("%s: ", __func__);
536 err = setsockopt(sk_fds[0], SOL_SOCKET, SO_DETACH_REUSEPORT_BPF,
537 &optvalue, sizeof(optvalue));
538 CHECK(err == -1, "setsockopt(SO_DETACH_REUSEPORT_BPF)",
539 "err:%d errno:%d\n", err, errno);
540
541 err = setsockopt(sk_fds[1], SOL_SOCKET, SO_DETACH_REUSEPORT_BPF,
542 &optvalue, sizeof(optvalue));
543 CHECK(err == 0 || errno != ENOENT, "setsockopt(SO_DETACH_REUSEPORT_BPF)",
544 "err:%d errno:%d\n", err, errno);
545
546 for (i = 0; i < NR_RESULTS; i++) {
547 err = bpf_map_lookup_elem(result_map, &i, &tmp);
548 CHECK(err == -1, "lookup_elem(result_map)",
549 "i:%u err:%d errno:%d\n", i, err, errno);
550 nr_run_before += tmp;
551 }
552
553 cli_fd = send_data(type, family, &cmd, sizeof(cmd), PASS);
554 nev = epoll_wait(epfd, &ev, 1, 5);
555 CHECK(nev <= 0, "nev <= 0",
556 "nev:%d expected:1 type:%d family:%d data:(0, 0)\n",
557 nev, type, family);
558
559 for (i = 0; i < NR_RESULTS; i++) {
560 err = bpf_map_lookup_elem(result_map, &i, &tmp);
561 CHECK(err == -1, "lookup_elem(result_map)",
562 "i:%u err:%d errno:%d\n", i, err, errno);
563 nr_run_after += tmp;
564 }
565
566 CHECK(nr_run_before != nr_run_after,
567 "nr_run_before != nr_run_after",
568 "nr_run_before:%u nr_run_after:%u\n",
569 nr_run_before, nr_run_after);
570
571 printf("OK\n");
572 close(cli_fd);
573#else
574 printf("%s: SKIP\n", __func__);
575#endif
576}
577
526static void prepare_sk_fds(int type, sa_family_t family, bool inany) 578static void prepare_sk_fds(int type, sa_family_t family, bool inany)
527{ 579{
528 const int first = REUSEPORT_ARRAY_SIZE - 1; 580 const int first = REUSEPORT_ARRAY_SIZE - 1;
@@ -664,6 +716,8 @@ static void test_all(void)
664 test_pass(type, family); 716 test_pass(type, family);
665 test_syncookie(type, family); 717 test_syncookie(type, family);
666 test_pass_on_err(type, family); 718 test_pass_on_err(type, family);
719 /* Must be the last test */
720 test_detach_bpf(type, family);
667 721
668 cleanup_per_test(); 722 cleanup_per_test();
669 printf("\n"); 723 printf("\n");
diff --git a/tools/testing/selftests/bpf/test_socket_cookie.c b/tools/testing/selftests/bpf/test_socket_cookie.c
index cac8ee57a013..15653b0e26eb 100644
--- a/tools/testing/selftests/bpf/test_socket_cookie.c
+++ b/tools/testing/selftests/bpf/test_socket_cookie.c
@@ -18,6 +18,11 @@
18#define CG_PATH "/foo" 18#define CG_PATH "/foo"
19#define SOCKET_COOKIE_PROG "./socket_cookie_prog.o" 19#define SOCKET_COOKIE_PROG "./socket_cookie_prog.o"
20 20
21struct socket_cookie {
22 __u64 cookie_key;
23 __u32 cookie_value;
24};
25
21static int start_server(void) 26static int start_server(void)
22{ 27{
23 struct sockaddr_in6 addr; 28 struct sockaddr_in6 addr;
@@ -89,8 +94,7 @@ static int validate_map(struct bpf_map *map, int client_fd)
89 __u32 cookie_expected_value; 94 __u32 cookie_expected_value;
90 struct sockaddr_in6 addr; 95 struct sockaddr_in6 addr;
91 socklen_t len = sizeof(addr); 96 socklen_t len = sizeof(addr);
92 __u32 cookie_value; 97 struct socket_cookie val;
93 __u64 cookie_key;
94 int err = 0; 98 int err = 0;
95 int map_fd; 99 int map_fd;
96 100
@@ -101,17 +105,7 @@ static int validate_map(struct bpf_map *map, int client_fd)
101 105
102 map_fd = bpf_map__fd(map); 106 map_fd = bpf_map__fd(map);
103 107
104 err = bpf_map_get_next_key(map_fd, NULL, &cookie_key); 108 err = bpf_map_lookup_elem(map_fd, &client_fd, &val);
105 if (err) {
106 log_err("Can't get cookie key from map");
107 goto out;
108 }
109
110 err = bpf_map_lookup_elem(map_fd, &cookie_key, &cookie_value);
111 if (err) {
112 log_err("Can't get cookie value from map");
113 goto out;
114 }
115 109
116 err = getsockname(client_fd, (struct sockaddr *)&addr, &len); 110 err = getsockname(client_fd, (struct sockaddr *)&addr, &len);
117 if (err) { 111 if (err) {
@@ -120,8 +114,8 @@ static int validate_map(struct bpf_map *map, int client_fd)
120 } 114 }
121 115
122 cookie_expected_value = (ntohs(addr.sin6_port) << 8) | 0xFF; 116 cookie_expected_value = (ntohs(addr.sin6_port) << 8) | 0xFF;
123 if (cookie_value != cookie_expected_value) { 117 if (val.cookie_value != cookie_expected_value) {
124 log_err("Unexpected value in map: %x != %x", cookie_value, 118 log_err("Unexpected value in map: %x != %x", val.cookie_value,
125 cookie_expected_value); 119 cookie_expected_value);
126 goto err; 120 goto err;
127 } 121 }
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 6cb307201958..c5514daf8865 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -234,10 +234,10 @@ static void bpf_fill_scale1(struct bpf_test *self)
234 insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 234 insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
235 -8 * (k % 64 + 1)); 235 -8 * (k % 64 + 1));
236 } 236 }
237 /* every jump adds 1 step to insn_processed, so to stay exactly 237 /* is_state_visited() doesn't allocate state for pruning for every jump.
238 * within 1m limit add MAX_TEST_INSNS - MAX_JMP_SEQ - 1 MOVs and 1 EXIT 238 * Hence multiply jmps by 4 to accommodate that heuristic
239 */ 239 */
240 while (i < MAX_TEST_INSNS - MAX_JMP_SEQ - 1) 240 while (i < MAX_TEST_INSNS - MAX_JMP_SEQ * 4)
241 insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42); 241 insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42);
242 insn[i] = BPF_EXIT_INSN(); 242 insn[i] = BPF_EXIT_INSN();
243 self->prog_len = i + 1; 243 self->prog_len = i + 1;
@@ -266,10 +266,7 @@ static void bpf_fill_scale2(struct bpf_test *self)
266 insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 266 insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
267 -8 * (k % (64 - 4 * FUNC_NEST) + 1)); 267 -8 * (k % (64 - 4 * FUNC_NEST) + 1));
268 } 268 }
269 /* every jump adds 1 step to insn_processed, so to stay exactly 269 while (i < MAX_TEST_INSNS - MAX_JMP_SEQ * 4)
270 * within 1m limit add MAX_TEST_INSNS - MAX_JMP_SEQ - 1 MOVs and 1 EXIT
271 */
272 while (i < MAX_TEST_INSNS - MAX_JMP_SEQ - 1)
273 insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42); 270 insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42);
274 insn[i] = BPF_EXIT_INSN(); 271 insn[i] = BPF_EXIT_INSN();
275 self->prog_len = i + 1; 272 self->prog_len = i + 1;
diff --git a/tools/testing/selftests/bpf/verifier/calls.c b/tools/testing/selftests/bpf/verifier/calls.c
index 9093a8f64dc6..2d752c4f8d9d 100644
--- a/tools/testing/selftests/bpf/verifier/calls.c
+++ b/tools/testing/selftests/bpf/verifier/calls.c
@@ -215,9 +215,11 @@
215 BPF_MOV64_IMM(BPF_REG_0, 3), 215 BPF_MOV64_IMM(BPF_REG_0, 3),
216 BPF_JMP_IMM(BPF_JA, 0, 0, -6), 216 BPF_JMP_IMM(BPF_JA, 0, 0, -6),
217 }, 217 },
218 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 218 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
219 .errstr = "back-edge from insn", 219 .errstr_unpriv = "back-edge from insn",
220 .result = REJECT, 220 .result_unpriv = REJECT,
221 .result = ACCEPT,
222 .retval = 1,
221}, 223},
222{ 224{
223 "calls: conditional call 4", 225 "calls: conditional call 4",
@@ -250,22 +252,24 @@
250 BPF_MOV64_IMM(BPF_REG_0, 3), 252 BPF_MOV64_IMM(BPF_REG_0, 3),
251 BPF_EXIT_INSN(), 253 BPF_EXIT_INSN(),
252 }, 254 },
253 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 255 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
254 .errstr = "back-edge from insn", 256 .result = ACCEPT,
255 .result = REJECT, 257 .retval = 1,
256}, 258},
257{ 259{
258 "calls: conditional call 6", 260 "calls: conditional call 6",
259 .insns = { 261 .insns = {
262 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
263 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
260 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 264 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
261 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, -2), 265 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, -3),
262 BPF_EXIT_INSN(), 266 BPF_EXIT_INSN(),
263 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 267 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
264 offsetof(struct __sk_buff, mark)), 268 offsetof(struct __sk_buff, mark)),
265 BPF_EXIT_INSN(), 269 BPF_EXIT_INSN(),
266 }, 270 },
267 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 271 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
268 .errstr = "back-edge from insn", 272 .errstr = "infinite loop detected",
269 .result = REJECT, 273 .result = REJECT,
270}, 274},
271{ 275{
diff --git a/tools/testing/selftests/bpf/verifier/cfg.c b/tools/testing/selftests/bpf/verifier/cfg.c
index 349c0862fb4c..4eb76ed739ce 100644
--- a/tools/testing/selftests/bpf/verifier/cfg.c
+++ b/tools/testing/selftests/bpf/verifier/cfg.c
@@ -41,7 +41,8 @@
41 BPF_JMP_IMM(BPF_JA, 0, 0, -1), 41 BPF_JMP_IMM(BPF_JA, 0, 0, -1),
42 BPF_EXIT_INSN(), 42 BPF_EXIT_INSN(),
43 }, 43 },
44 .errstr = "back-edge", 44 .errstr = "unreachable insn 1",
45 .errstr_unpriv = "back-edge",
45 .result = REJECT, 46 .result = REJECT,
46}, 47},
47{ 48{
@@ -53,18 +54,20 @@
53 BPF_JMP_IMM(BPF_JA, 0, 0, -4), 54 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
54 BPF_EXIT_INSN(), 55 BPF_EXIT_INSN(),
55 }, 56 },
56 .errstr = "back-edge", 57 .errstr = "unreachable insn 4",
58 .errstr_unpriv = "back-edge",
57 .result = REJECT, 59 .result = REJECT,
58}, 60},
59{ 61{
60 "conditional loop", 62 "conditional loop",
61 .insns = { 63 .insns = {
62 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 64 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
63 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 65 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
64 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 66 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
65 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3), 67 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
66 BPF_EXIT_INSN(), 68 BPF_EXIT_INSN(),
67 }, 69 },
68 .errstr = "back-edge", 70 .errstr = "infinite loop detected",
71 .errstr_unpriv = "back-edge",
69 .result = REJECT, 72 .result = REJECT,
70}, 73},
diff --git a/tools/testing/selftests/bpf/verifier/direct_packet_access.c b/tools/testing/selftests/bpf/verifier/direct_packet_access.c
index d5c596fdc4b9..2c5fbe7bcd27 100644
--- a/tools/testing/selftests/bpf/verifier/direct_packet_access.c
+++ b/tools/testing/selftests/bpf/verifier/direct_packet_access.c
@@ -511,7 +511,8 @@
511 offsetof(struct __sk_buff, data)), 511 offsetof(struct __sk_buff, data)),
512 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 512 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
513 offsetof(struct __sk_buff, data_end)), 513 offsetof(struct __sk_buff, data_end)),
514 BPF_MOV64_IMM(BPF_REG_0, 0xffffffff), 514 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
515 offsetof(struct __sk_buff, mark)),
515 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 516 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
516 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 517 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
517 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff), 518 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffff),
diff --git a/tools/testing/selftests/bpf/verifier/helper_access_var_len.c b/tools/testing/selftests/bpf/verifier/helper_access_var_len.c
index 1f39d845c64f..67ab12410050 100644
--- a/tools/testing/selftests/bpf/verifier/helper_access_var_len.c
+++ b/tools/testing/selftests/bpf/verifier/helper_access_var_len.c
@@ -29,9 +29,9 @@
29{ 29{
30 "helper access to variable memory: stack, bitwise AND, zero included", 30 "helper access to variable memory: stack, bitwise AND, zero included",
31 .insns = { 31 .insns = {
32 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
32 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 33 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
33 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 34 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
34 BPF_MOV64_IMM(BPF_REG_2, 16),
35 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 35 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
36 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 36 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
37 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64), 37 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
@@ -46,9 +46,9 @@
46{ 46{
47 "helper access to variable memory: stack, bitwise AND + JMP, wrong max", 47 "helper access to variable memory: stack, bitwise AND + JMP, wrong max",
48 .insns = { 48 .insns = {
49 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
49 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 50 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
50 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 51 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
51 BPF_MOV64_IMM(BPF_REG_2, 16),
52 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 52 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
53 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 53 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
54 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 65), 54 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 65),
@@ -122,9 +122,9 @@
122{ 122{
123 "helper access to variable memory: stack, JMP, bounds + offset", 123 "helper access to variable memory: stack, JMP, bounds + offset",
124 .insns = { 124 .insns = {
125 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
125 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 126 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
126 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 127 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
127 BPF_MOV64_IMM(BPF_REG_2, 16),
128 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 128 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
129 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 129 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
130 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 5), 130 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 5),
@@ -143,9 +143,9 @@
143{ 143{
144 "helper access to variable memory: stack, JMP, wrong max", 144 "helper access to variable memory: stack, JMP, wrong max",
145 .insns = { 145 .insns = {
146 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
146 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 147 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
147 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 148 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
148 BPF_MOV64_IMM(BPF_REG_2, 16),
149 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 149 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
150 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 150 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
151 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 65, 4), 151 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 65, 4),
@@ -163,9 +163,9 @@
163{ 163{
164 "helper access to variable memory: stack, JMP, no max check", 164 "helper access to variable memory: stack, JMP, no max check",
165 .insns = { 165 .insns = {
166 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
166 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 167 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
167 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 168 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
168 BPF_MOV64_IMM(BPF_REG_2, 16),
169 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 169 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
170 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 170 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
171 BPF_MOV64_IMM(BPF_REG_4, 0), 171 BPF_MOV64_IMM(BPF_REG_4, 0),
@@ -183,9 +183,9 @@
183{ 183{
184 "helper access to variable memory: stack, JMP, no min check", 184 "helper access to variable memory: stack, JMP, no min check",
185 .insns = { 185 .insns = {
186 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
186 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 187 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
187 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 188 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
188 BPF_MOV64_IMM(BPF_REG_2, 16),
189 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 189 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
190 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 190 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
191 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3), 191 BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3),
@@ -201,9 +201,9 @@
201{ 201{
202 "helper access to variable memory: stack, JMP (signed), no min check", 202 "helper access to variable memory: stack, JMP (signed), no min check",
203 .insns = { 203 .insns = {
204 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
204 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 205 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
205 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 206 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
206 BPF_MOV64_IMM(BPF_REG_2, 16),
207 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 207 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
208 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 208 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
209 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 3), 209 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 3),
@@ -244,6 +244,7 @@
244{ 244{
245 "helper access to variable memory: map, JMP, wrong max", 245 "helper access to variable memory: map, JMP, wrong max",
246 .insns = { 246 .insns = {
247 BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
247 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 248 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
248 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 249 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
249 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 250 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
@@ -251,7 +252,7 @@
251 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 252 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
252 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10), 253 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
253 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 254 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
254 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)), 255 BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
255 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128), 256 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
256 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128), 257 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
257 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) + 1, 4), 258 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) + 1, 4),
@@ -262,7 +263,7 @@
262 BPF_MOV64_IMM(BPF_REG_0, 0), 263 BPF_MOV64_IMM(BPF_REG_0, 0),
263 BPF_EXIT_INSN(), 264 BPF_EXIT_INSN(),
264 }, 265 },
265 .fixup_map_hash_48b = { 3 }, 266 .fixup_map_hash_48b = { 4 },
266 .errstr = "invalid access to map value, value_size=48 off=0 size=49", 267 .errstr = "invalid access to map value, value_size=48 off=0 size=49",
267 .result = REJECT, 268 .result = REJECT,
268 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 269 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -296,6 +297,7 @@
296{ 297{
297 "helper access to variable memory: map adjusted, JMP, wrong max", 298 "helper access to variable memory: map adjusted, JMP, wrong max",
298 .insns = { 299 .insns = {
300 BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
299 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 301 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
300 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 302 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
301 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), 303 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
@@ -304,7 +306,7 @@
304 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11), 306 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
305 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 307 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
306 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20), 308 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20),
307 BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)), 309 BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
308 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128), 310 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
309 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128), 311 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
310 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) - 19, 4), 312 BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) - 19, 4),
@@ -315,7 +317,7 @@
315 BPF_MOV64_IMM(BPF_REG_0, 0), 317 BPF_MOV64_IMM(BPF_REG_0, 0),
316 BPF_EXIT_INSN(), 318 BPF_EXIT_INSN(),
317 }, 319 },
318 .fixup_map_hash_48b = { 3 }, 320 .fixup_map_hash_48b = { 4 },
319 .errstr = "R1 min value is outside of the array range", 321 .errstr = "R1 min value is outside of the array range",
320 .result = REJECT, 322 .result = REJECT,
321 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 323 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
@@ -337,8 +339,8 @@
337{ 339{
338 "helper access to variable memory: size > 0 not allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)", 340 "helper access to variable memory: size > 0 not allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)",
339 .insns = { 341 .insns = {
342 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
340 BPF_MOV64_IMM(BPF_REG_1, 0), 343 BPF_MOV64_IMM(BPF_REG_1, 0),
341 BPF_MOV64_IMM(BPF_REG_2, 1),
342 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128), 344 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
343 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128), 345 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
344 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64), 346 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
@@ -562,6 +564,7 @@
562{ 564{
563 "helper access to variable memory: 8 bytes leak", 565 "helper access to variable memory: 8 bytes leak",
564 .insns = { 566 .insns = {
567 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
565 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 568 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
566 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 569 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
567 BPF_MOV64_IMM(BPF_REG_0, 0), 570 BPF_MOV64_IMM(BPF_REG_0, 0),
@@ -572,7 +575,6 @@
572 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24), 575 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
573 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16), 576 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
574 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 577 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
575 BPF_MOV64_IMM(BPF_REG_2, 1),
576 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128), 578 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
577 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128), 579 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
578 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63), 580 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63),
diff --git a/tools/testing/selftests/bpf/verifier/loops1.c b/tools/testing/selftests/bpf/verifier/loops1.c
new file mode 100644
index 000000000000..5e980a5ab69d
--- /dev/null
+++ b/tools/testing/selftests/bpf/verifier/loops1.c
@@ -0,0 +1,161 @@
1{
2 "bounded loop, count to 4",
3 .insns = {
4 BPF_MOV64_IMM(BPF_REG_0, 0),
5 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
6 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -2),
7 BPF_EXIT_INSN(),
8 },
9 .result = ACCEPT,
10 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
11 .retval = 4,
12},
13{
14 "bounded loop, count to 20",
15 .insns = {
16 BPF_MOV64_IMM(BPF_REG_0, 0),
17 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 3),
18 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 20, -2),
19 BPF_EXIT_INSN(),
20 },
21 .result = ACCEPT,
22 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
23},
24{
25 "bounded loop, count from positive unknown to 4",
26 .insns = {
27 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
28 BPF_JMP_IMM(BPF_JSLT, BPF_REG_0, 0, 2),
29 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
30 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -2),
31 BPF_EXIT_INSN(),
32 },
33 .result = ACCEPT,
34 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
35 .retval = 4,
36},
37{
38 "bounded loop, count from totally unknown to 4",
39 .insns = {
40 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
41 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
42 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -2),
43 BPF_EXIT_INSN(),
44 },
45 .result = ACCEPT,
46 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
47},
48{
49 "bounded loop, count to 4 with equality",
50 .insns = {
51 BPF_MOV64_IMM(BPF_REG_0, 0),
52 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
53 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, -2),
54 BPF_EXIT_INSN(),
55 },
56 .result = ACCEPT,
57 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
58},
59{
60 "bounded loop, start in the middle",
61 .insns = {
62 BPF_MOV64_IMM(BPF_REG_0, 0),
63 BPF_JMP_A(1),
64 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
65 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -2),
66 BPF_EXIT_INSN(),
67 },
68 .result = REJECT,
69 .errstr = "back-edge",
70 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
71 .retval = 4,
72},
73{
74 "bounded loop containing a forward jump",
75 .insns = {
76 BPF_MOV64_IMM(BPF_REG_0, 0),
77 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
78 BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_0, 0),
79 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -3),
80 BPF_EXIT_INSN(),
81 },
82 .result = ACCEPT,
83 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
84 .retval = 4,
85},
86{
87 "bounded loop that jumps out rather than in",
88 .insns = {
89 BPF_MOV64_IMM(BPF_REG_6, 0),
90 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
91 BPF_JMP_IMM(BPF_JGT, BPF_REG_6, 10000, 2),
92 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
93 BPF_JMP_A(-4),
94 BPF_EXIT_INSN(),
95 },
96 .result = ACCEPT,
97 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
98},
99{
100 "infinite loop after a conditional jump",
101 .insns = {
102 BPF_MOV64_IMM(BPF_REG_0, 5),
103 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, 2),
104 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
105 BPF_JMP_A(-2),
106 BPF_EXIT_INSN(),
107 },
108 .result = REJECT,
109 .errstr = "program is too large",
110 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
111},
112{
113 "bounded recursion",
114 .insns = {
115 BPF_MOV64_IMM(BPF_REG_1, 0),
116 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1),
117 BPF_EXIT_INSN(),
118 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
119 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
120 BPF_JMP_IMM(BPF_JLT, BPF_REG_1, 4, 1),
121 BPF_EXIT_INSN(),
122 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -5),
123 BPF_EXIT_INSN(),
124 },
125 .result = REJECT,
126 .errstr = "back-edge",
127 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
128},
129{
130 "infinite loop in two jumps",
131 .insns = {
132 BPF_MOV64_IMM(BPF_REG_0, 0),
133 BPF_JMP_A(0),
134 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 4, -2),
135 BPF_EXIT_INSN(),
136 },
137 .result = REJECT,
138 .errstr = "loop detected",
139 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
140},
141{
142 "infinite loop: three-jump trick",
143 .insns = {
144 BPF_MOV64_IMM(BPF_REG_0, 0),
145 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
146 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
147 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 2, 1),
148 BPF_EXIT_INSN(),
149 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
150 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
151 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 2, 1),
152 BPF_EXIT_INSN(),
153 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
154 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1),
155 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 2, -11),
156 BPF_EXIT_INSN(),
157 },
158 .result = REJECT,
159 .errstr = "loop detected",
160 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
161},
diff --git a/tools/testing/selftests/bpf/verifier/prevent_map_lookup.c b/tools/testing/selftests/bpf/verifier/prevent_map_lookup.c
index bbdba990fefb..da7a4b37cb98 100644
--- a/tools/testing/selftests/bpf/verifier/prevent_map_lookup.c
+++ b/tools/testing/selftests/bpf/verifier/prevent_map_lookup.c
@@ -29,21 +29,6 @@
29 .prog_type = BPF_PROG_TYPE_SOCK_OPS, 29 .prog_type = BPF_PROG_TYPE_SOCK_OPS,
30}, 30},
31{ 31{
32 "prevent map lookup in xskmap",
33 .insns = {
34 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
35 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
36 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
37 BPF_LD_MAP_FD(BPF_REG_1, 0),
38 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
39 BPF_EXIT_INSN(),
40 },
41 .fixup_map_xskmap = { 3 },
42 .result = REJECT,
43 .errstr = "cannot pass map_type 17 into func bpf_map_lookup_elem",
44 .prog_type = BPF_PROG_TYPE_XDP,
45},
46{
47 "prevent map lookup in stack trace", 32 "prevent map lookup in stack trace",
48 .insns = { 33 .insns = {
49 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 34 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
diff --git a/tools/testing/selftests/bpf/verifier/sock.c b/tools/testing/selftests/bpf/verifier/sock.c
index b31cd2cf50d0..9ed192e14f5f 100644
--- a/tools/testing/selftests/bpf/verifier/sock.c
+++ b/tools/testing/selftests/bpf/verifier/sock.c
@@ -498,3 +498,21 @@
498 .result = REJECT, 498 .result = REJECT,
499 .errstr = "cannot pass map_type 24 into func bpf_map_lookup_elem", 499 .errstr = "cannot pass map_type 24 into func bpf_map_lookup_elem",
500}, 500},
501{
502 "bpf_map_lookup_elem(xskmap, &key); xs->queue_id",
503 .insns = {
504 BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0),
505 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
506 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
507 BPF_LD_MAP_FD(BPF_REG_1, 0),
508 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
509 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
510 BPF_EXIT_INSN(),
511 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct bpf_xdp_sock, queue_id)),
512 BPF_MOV64_IMM(BPF_REG_0, 0),
513 BPF_EXIT_INSN(),
514 },
515 .fixup_map_xskmap = { 3 },
516 .prog_type = BPF_PROG_TYPE_XDP,
517 .result = ACCEPT,
518},