Linux 4.19.133
[linux/fpc-iii.git] / tools / testing / selftests / bpf / test_sockmap_kern.h
blob8e8e41780bb9f8a9eb8f5611e1610ab1d10b705a
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
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"
18 /* Sockmap sample program connects a client and a backend together
19 * using cgroups.
21 * client:X <---> frontend:80 client:X <---> backend:80
23 * For simplicity we hard code values here and bind 1:1. The hard
24 * coded values are part of the setup in sockmap.sh script that
25 * is associated with this BPF program.
27 * The bpf_printk is verbose and prints information as connections
28 * are established and verdicts are decided.
31 #define bpf_printk(fmt, ...) \
32 ({ \
33 char ____fmt[] = fmt; \
34 bpf_trace_printk(____fmt, sizeof(____fmt), \
35 ##__VA_ARGS__); \
38 struct bpf_map_def SEC("maps") sock_map = {
39 .type = TEST_MAP_TYPE,
40 .key_size = sizeof(int),
41 .value_size = sizeof(int),
42 .max_entries = 20,
45 struct bpf_map_def SEC("maps") sock_map_txmsg = {
46 .type = TEST_MAP_TYPE,
47 .key_size = sizeof(int),
48 .value_size = sizeof(int),
49 .max_entries = 20,
52 struct bpf_map_def SEC("maps") sock_map_redir = {
53 .type = TEST_MAP_TYPE,
54 .key_size = sizeof(int),
55 .value_size = sizeof(int),
56 .max_entries = 20,
59 struct bpf_map_def SEC("maps") sock_apply_bytes = {
60 .type = BPF_MAP_TYPE_ARRAY,
61 .key_size = sizeof(int),
62 .value_size = sizeof(int),
63 .max_entries = 1
66 struct bpf_map_def SEC("maps") sock_cork_bytes = {
67 .type = BPF_MAP_TYPE_ARRAY,
68 .key_size = sizeof(int),
69 .value_size = sizeof(int),
70 .max_entries = 1
73 struct bpf_map_def SEC("maps") sock_pull_bytes = {
74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int),
76 .value_size = sizeof(int),
77 .max_entries = 2
80 struct bpf_map_def SEC("maps") sock_redir_flags = {
81 .type = BPF_MAP_TYPE_ARRAY,
82 .key_size = sizeof(int),
83 .value_size = sizeof(int),
84 .max_entries = 1
87 struct bpf_map_def SEC("maps") sock_skb_opts = {
88 .type = BPF_MAP_TYPE_ARRAY,
89 .key_size = sizeof(int),
90 .value_size = sizeof(int),
91 .max_entries = 1
94 SEC("sk_skb1")
95 int bpf_prog1(struct __sk_buff *skb)
97 return skb->len;
100 SEC("sk_skb2")
101 int bpf_prog2(struct __sk_buff *skb)
103 __u32 lport = skb->local_port;
104 __u32 rport = skb->remote_port;
105 int len, *f, ret, zero = 0;
106 __u64 flags = 0;
108 if (lport == 10000)
109 ret = 10;
110 else
111 ret = 1;
113 len = (__u32)skb->data_end - (__u32)skb->data;
114 f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
115 if (f && *f) {
116 ret = 3;
117 flags = *f;
120 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
121 len, flags);
122 #ifdef SOCKMAP
123 return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
124 #else
125 return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
126 #endif
130 SEC("sockops")
131 int bpf_sockmap(struct bpf_sock_ops *skops)
133 __u32 lport, rport;
134 int op, err = 0, index, key, ret;
137 op = (int) skops->op;
139 switch (op) {
140 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
141 lport = skops->local_port;
142 rport = skops->remote_port;
144 if (lport == 10000) {
145 ret = 1;
146 #ifdef SOCKMAP
147 err = bpf_sock_map_update(skops, &sock_map, &ret,
148 BPF_NOEXIST);
149 #else
150 err = bpf_sock_hash_update(skops, &sock_map, &ret,
151 BPF_NOEXIST);
152 #endif
153 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
154 lport, bpf_ntohl(rport), err);
156 break;
157 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
158 lport = skops->local_port;
159 rport = skops->remote_port;
161 if (bpf_ntohl(rport) == 10001) {
162 ret = 10;
163 #ifdef SOCKMAP
164 err = bpf_sock_map_update(skops, &sock_map, &ret,
165 BPF_NOEXIST);
166 #else
167 err = bpf_sock_hash_update(skops, &sock_map, &ret,
168 BPF_NOEXIST);
169 #endif
170 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
171 lport, bpf_ntohl(rport), err);
173 break;
174 default:
175 break;
178 return 0;
181 SEC("sk_msg1")
182 int bpf_prog4(struct sk_msg_md *msg)
184 int *bytes, zero = 0, one = 1;
185 int *start, *end;
187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
188 if (bytes)
189 bpf_msg_apply_bytes(msg, *bytes);
190 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
191 if (bytes)
192 bpf_msg_cork_bytes(msg, *bytes);
193 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
194 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
195 if (start && end)
196 bpf_msg_pull_data(msg, *start, *end, 0);
197 return SK_PASS;
200 SEC("sk_msg2")
201 int bpf_prog5(struct sk_msg_md *msg)
203 int err1 = -1, err2 = -1, zero = 0, one = 1;
204 int *bytes, *start, *end, len1, len2;
206 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
207 if (bytes)
208 err1 = bpf_msg_apply_bytes(msg, *bytes);
209 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
210 if (bytes)
211 err2 = bpf_msg_cork_bytes(msg, *bytes);
212 len1 = (__u64)msg->data_end - (__u64)msg->data;
213 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
214 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
215 if (start && end) {
216 int err;
218 bpf_printk("sk_msg2: pull(%i:%i)\n",
219 start ? *start : 0, end ? *end : 0);
220 err = bpf_msg_pull_data(msg, *start, *end, 0);
221 if (err)
222 bpf_printk("sk_msg2: pull_data err %i\n",
223 err);
224 len2 = (__u64)msg->data_end - (__u64)msg->data;
225 bpf_printk("sk_msg2: length update %i->%i\n",
226 len1, len2);
228 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
229 len1, err1, err2);
230 return SK_PASS;
233 SEC("sk_msg3")
234 int bpf_prog6(struct sk_msg_md *msg)
236 int *bytes, zero = 0, one = 1, key = 0;
237 int *start, *end, *f;
238 __u64 flags = 0;
240 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
241 if (bytes)
242 bpf_msg_apply_bytes(msg, *bytes);
243 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
244 if (bytes)
245 bpf_msg_cork_bytes(msg, *bytes);
246 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
247 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
248 if (start && end)
249 bpf_msg_pull_data(msg, *start, *end, 0);
250 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
251 if (f && *f) {
252 key = 2;
253 flags = *f;
255 #ifdef SOCKMAP
256 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
257 #else
258 return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
259 #endif
262 SEC("sk_msg4")
263 int bpf_prog7(struct sk_msg_md *msg)
265 int err1 = 0, err2 = 0, zero = 0, one = 1, key = 0;
266 int *f, *bytes, *start, *end, len1, len2;
267 __u64 flags = 0;
269 int err;
270 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
271 if (bytes)
272 err1 = bpf_msg_apply_bytes(msg, *bytes);
273 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
274 if (bytes)
275 err2 = bpf_msg_cork_bytes(msg, *bytes);
276 len1 = (__u64)msg->data_end - (__u64)msg->data;
277 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
278 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
279 if (start && end) {
281 bpf_printk("sk_msg2: pull(%i:%i)\n",
282 start ? *start : 0, end ? *end : 0);
283 err = bpf_msg_pull_data(msg, *start, *end, 0);
284 if (err)
285 bpf_printk("sk_msg2: pull_data err %i\n",
286 err);
287 len2 = (__u64)msg->data_end - (__u64)msg->data;
288 bpf_printk("sk_msg2: length update %i->%i\n",
289 len1, len2);
291 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
292 if (f && *f) {
293 key = 2;
294 flags = *f;
296 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
297 len1, flags, err1 ? err1 : err2);
298 #ifdef SOCKMAP
299 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
300 #else
301 err = bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
302 #endif
303 bpf_printk("sk_msg3: err %i\n", err);
304 return err;
307 SEC("sk_msg5")
308 int bpf_prog8(struct sk_msg_md *msg)
310 void *data_end = (void *)(long) msg->data_end;
311 void *data = (void *)(long) msg->data;
312 int ret = 0, *bytes, zero = 0;
314 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
315 if (bytes) {
316 ret = bpf_msg_apply_bytes(msg, *bytes);
317 if (ret)
318 return SK_DROP;
319 } else {
320 return SK_DROP;
322 return SK_PASS;
324 SEC("sk_msg6")
325 int bpf_prog9(struct sk_msg_md *msg)
327 void *data_end = (void *)(long) msg->data_end;
328 void *data = (void *)(long) msg->data;
329 int ret = 0, *bytes, zero = 0;
331 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
332 if (bytes) {
333 if (((__u64)data_end - (__u64)data) >= *bytes)
334 return SK_PASS;
335 ret = bpf_msg_cork_bytes(msg, *bytes);
336 if (ret)
337 return SK_DROP;
339 return SK_PASS;
342 SEC("sk_msg7")
343 int bpf_prog10(struct sk_msg_md *msg)
345 int *bytes, zero = 0, one = 1;
346 int *start, *end;
348 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
349 if (bytes)
350 bpf_msg_apply_bytes(msg, *bytes);
351 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
352 if (bytes)
353 bpf_msg_cork_bytes(msg, *bytes);
354 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
355 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
356 if (start && end)
357 bpf_msg_pull_data(msg, *start, *end, 0);
359 return SK_DROP;
362 int _version SEC("version") = 1;
363 char _license[] SEC("license") = "GPL";