summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf/progs/stack_arg_kfunc.c
blob: 345f2da2e361b2dfeab13f48d083fb1b8888199e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */

#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include "bpf_kfuncs.h"
#include "../test_kmods/bpf_testmod_kfunc.h"

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
	defined(__BPF_FEATURE_STACK_ARGUMENT)

const volatile bool has_stack_arg = true;

struct bpf_iter_testmod_seq {
	u64 :64;
	u64 :64;
};

extern int bpf_iter_testmod_seq_new(struct bpf_iter_testmod_seq *it, s64 value, int cnt) __ksym;
extern void bpf_iter_testmod_seq_destroy(struct bpf_iter_testmod_seq *it) __ksym;

struct timer_map_value {
	struct bpf_timer timer;
};

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(max_entries, 1);
	__type(key, int);
	__type(value, struct timer_map_value);
} kfunc_timer_map SEC(".maps");

SEC("tc")
int test_stack_arg_scalar(struct __sk_buff *skb)
{
	return bpf_kfunc_call_stack_arg(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}

SEC("tc")
int test_stack_arg_ptr(struct __sk_buff *skb)
{
	struct prog_test_pass1 p = { .x0 = 10, .x1 = 20 };

	return bpf_kfunc_call_stack_arg_ptr(1, 2, 3, 4, 5, 6, 7, 8, 9, &p);
}

SEC("tc")
int test_stack_arg_mix(struct __sk_buff *skb)
{
	struct prog_test_pass1 p = { .x0 = 10 };
	struct prog_test_pass1 q = { .x1 = 20 };

	return bpf_kfunc_call_stack_arg_mix(1, 2, 3, 4, 5, 6, 7, &p, 8, &q);
}

/* 1+2+3+4+5+6+7+8+9+sizeof(pkt_v4) = 45+54 = 99 */
SEC("tc")
int test_stack_arg_dynptr(struct __sk_buff *skb)
{
	struct bpf_dynptr ptr;

	bpf_dynptr_from_skb(skb, 0, &ptr);
	return bpf_kfunc_call_stack_arg_dynptr(1, 2, 3, 4, 5, 6, 7, 8, 9, &ptr);
}

/* 1 + 2 + 3 + 4 + 5 + (1 + 2 + ... + 16) = 15 + 136 = 151 */
SEC("tc")
int test_stack_arg_mem(struct __sk_buff *skb)
{
	char buf[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

	return bpf_kfunc_call_stack_arg_mem(1, 2, 3, 4, 5, buf, sizeof(buf));
}

/* 1+2+3+4+5+6+7+8+9+100 = 145 */
SEC("tc")
int test_stack_arg_iter(struct __sk_buff *skb)
{
	struct bpf_iter_testmod_seq it;
	u64 ret;

	bpf_iter_testmod_seq_new(&it, 100, 10);
	ret = bpf_kfunc_call_stack_arg_iter(1, 2, 3, 4, 5, 6, 7, 8, 9, &it);
	bpf_iter_testmod_seq_destroy(&it);
	return ret;
}

const char cstr[] = "hello";

/* 1+2+3+4+5+6+7+8+9 = 45 */
SEC("tc")
int test_stack_arg_const_str(struct __sk_buff *skb)
{
	return bpf_kfunc_call_stack_arg_const_str(1, 2, 3, 4, 5, 6, 7, 8, 9,
						  cstr);
}

/* 1+2+3+4+5+6+7+8+9 = 45 */
SEC("tc")
int test_stack_arg_timer(struct __sk_buff *skb)
{
	struct timer_map_value *val;
	int key = 0;

	val = bpf_map_lookup_elem(&kfunc_timer_map, &key);
	if (!val)
		return 0;
	return bpf_kfunc_call_stack_arg_timer(1, 2, 3, 4, 5, 6, 7, 8, 9,
					      &val->timer);
}

#else

const volatile bool has_stack_arg = false;

SEC("tc")
int test_stack_arg_scalar(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_ptr(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_mix(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_dynptr(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_mem(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_iter(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_const_str(struct __sk_buff *skb)
{
	return 0;
}

SEC("tc")
int test_stack_arg_timer(struct __sk_buff *skb)
{
	return 0;
}

#endif

char _license[] SEC("license") = "GPL";