Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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"
17
18/* Sockmap sample program connects a client and a backend together
19 * using cgroups.
20 *
21 * client:X <---> frontend:80 client:X <---> backend:80
22 *
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.
26 *
27 * The bpf_printk is verbose and prints information as connections
28 * are established and verdicts are decided.
29 */
30
31#define bpf_printk(fmt, ...) \
32({ \
33 char ____fmt[] = fmt; \
34 bpf_trace_printk(____fmt, sizeof(____fmt), \
35 ##__VA_ARGS__); \
36})
37
38struct 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,
43};
44
45struct 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,
50};
51
52struct 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,
57};
58
59struct 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
64};
65
66struct 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
71};
72
73struct bpf_map_def SEC("maps") sock_bytes = {
74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int),
76 .value_size = sizeof(int),
77 .max_entries = 6
78};
79
80struct 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
85};
86
87struct 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
92};
93
94SEC("sk_skb1")
95int bpf_prog1(struct __sk_buff *skb)
96{
97 return skb->len;
98}
99
100SEC("sk_skb2")
101int bpf_prog2(struct __sk_buff *skb)
102{
103 __u32 lport = skb->local_port;
104 __u32 rport = skb->remote_port;
105 int len, *f, ret, zero = 0;
106 __u64 flags = 0;
107
108 if (lport == 10000)
109 ret = 10;
110 else
111 ret = 1;
112
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;
118 }
119
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
127
128}
129
130SEC("sockops")
131int bpf_sockmap(struct bpf_sock_ops *skops)
132{
133 __u32 lport, rport;
134 int op, err = 0, index, key, ret;
135
136
137 op = (int) skops->op;
138
139 switch (op) {
140 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
141 lport = skops->local_port;
142 rport = skops->remote_port;
143
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);
155 }
156 break;
157 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
158 lport = skops->local_port;
159 rport = skops->remote_port;
160
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);
172 }
173 break;
174 default:
175 break;
176 }
177
178 return 0;
179}
180
181SEC("sk_msg1")
182int bpf_prog4(struct sk_msg_md *msg)
183{
184 int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
185 int *start, *end, *start_push, *end_push, *start_pop, *pop;
186
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_bytes, &zero);
194 end = bpf_map_lookup_elem(&sock_bytes, &one);
195 if (start && end)
196 bpf_msg_pull_data(msg, *start, *end, 0);
197 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
198 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
199 if (start_push && end_push)
200 bpf_msg_push_data(msg, *start_push, *end_push, 0);
201 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
202 pop = bpf_map_lookup_elem(&sock_bytes, &five);
203 if (start_pop && pop)
204 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
205 return SK_PASS;
206}
207
208SEC("sk_msg2")
209int bpf_prog5(struct sk_msg_md *msg)
210{
211 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
212 int *start, *end, *start_push, *end_push, *start_pop, *pop;
213 int *bytes, len1, len2 = 0, len3, len4;
214 int err1 = -1, err2 = -1;
215
216 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
217 if (bytes)
218 err1 = bpf_msg_apply_bytes(msg, *bytes);
219 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
220 if (bytes)
221 err2 = bpf_msg_cork_bytes(msg, *bytes);
222 len1 = (__u64)msg->data_end - (__u64)msg->data;
223 start = bpf_map_lookup_elem(&sock_bytes, &zero);
224 end = bpf_map_lookup_elem(&sock_bytes, &one);
225 if (start && end) {
226 int err;
227
228 bpf_printk("sk_msg2: pull(%i:%i)\n",
229 start ? *start : 0, end ? *end : 0);
230 err = bpf_msg_pull_data(msg, *start, *end, 0);
231 if (err)
232 bpf_printk("sk_msg2: pull_data err %i\n",
233 err);
234 len2 = (__u64)msg->data_end - (__u64)msg->data;
235 bpf_printk("sk_msg2: length update %i->%i\n",
236 len1, len2);
237 }
238
239 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
240 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
241 if (start_push && end_push) {
242 int err;
243
244 bpf_printk("sk_msg2: push(%i:%i)\n",
245 start_push ? *start_push : 0,
246 end_push ? *end_push : 0);
247 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
248 if (err)
249 bpf_printk("sk_msg2: push_data err %i\n", err);
250 len3 = (__u64)msg->data_end - (__u64)msg->data;
251 bpf_printk("sk_msg2: length push_update %i->%i\n",
252 len2 ? len2 : len1, len3);
253 }
254 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
255 pop = bpf_map_lookup_elem(&sock_bytes, &five);
256 if (start_pop && pop) {
257 int err;
258
259 bpf_printk("sk_msg2: pop(%i@%i)\n",
260 start_pop, pop);
261 err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
262 if (err)
263 bpf_printk("sk_msg2: pop_data err %i\n", err);
264 len4 = (__u64)msg->data_end - (__u64)msg->data;
265 bpf_printk("sk_msg2: length pop_data %i->%i\n",
266 len1 ? len1 : 0, len4);
267 }
268
269 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
270 len1, err1, err2);
271 return SK_PASS;
272}
273
274SEC("sk_msg3")
275int bpf_prog6(struct sk_msg_md *msg)
276{
277 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
278 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
279 __u64 flags = 0;
280
281 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
282 if (bytes)
283 bpf_msg_apply_bytes(msg, *bytes);
284 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
285 if (bytes)
286 bpf_msg_cork_bytes(msg, *bytes);
287
288 start = bpf_map_lookup_elem(&sock_bytes, &zero);
289 end = bpf_map_lookup_elem(&sock_bytes, &one);
290 if (start && end)
291 bpf_msg_pull_data(msg, *start, *end, 0);
292
293 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
294 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
295 if (start_push && end_push)
296 bpf_msg_push_data(msg, *start_push, *end_push, 0);
297
298 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
299 pop = bpf_map_lookup_elem(&sock_bytes, &five);
300 if (start_pop && pop)
301 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
302
303 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
304 if (f && *f) {
305 key = 2;
306 flags = *f;
307 }
308#ifdef SOCKMAP
309 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
310#else
311 return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
312#endif
313}
314
315SEC("sk_msg4")
316int bpf_prog7(struct sk_msg_md *msg)
317{
318 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
319 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
320 int len1, len2 = 0, len3, len4;
321 int err1 = 0, err2 = 0, key = 0;
322 __u64 flags = 0;
323
324 int err;
325 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
326 if (bytes)
327 err1 = bpf_msg_apply_bytes(msg, *bytes);
328 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
329 if (bytes)
330 err2 = bpf_msg_cork_bytes(msg, *bytes);
331 len1 = (__u64)msg->data_end - (__u64)msg->data;
332
333 start = bpf_map_lookup_elem(&sock_bytes, &zero);
334 end = bpf_map_lookup_elem(&sock_bytes, &one);
335 if (start && end) {
336 bpf_printk("sk_msg2: pull(%i:%i)\n",
337 start ? *start : 0, end ? *end : 0);
338 err = bpf_msg_pull_data(msg, *start, *end, 0);
339 if (err)
340 bpf_printk("sk_msg2: pull_data err %i\n",
341 err);
342 len2 = (__u64)msg->data_end - (__u64)msg->data;
343 bpf_printk("sk_msg2: length update %i->%i\n",
344 len1, len2);
345 }
346
347 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
348 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
349 if (start_push && end_push) {
350 bpf_printk("sk_msg4: push(%i:%i)\n",
351 start_push ? *start_push : 0,
352 end_push ? *end_push : 0);
353 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
354 if (err)
355 bpf_printk("sk_msg4: push_data err %i\n",
356 err);
357 len3 = (__u64)msg->data_end - (__u64)msg->data;
358 bpf_printk("sk_msg4: length push_update %i->%i\n",
359 len2 ? len2 : len1, len3);
360 }
361
362 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
363 pop = bpf_map_lookup_elem(&sock_bytes, &five);
364 if (start_pop && pop) {
365 int err;
366
367 bpf_printk("sk_msg4: pop(%i@%i)\n",
368 start_pop, pop);
369 err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
370 if (err)
371 bpf_printk("sk_msg4: pop_data err %i\n", err);
372 len4 = (__u64)msg->data_end - (__u64)msg->data;
373 bpf_printk("sk_msg4: length pop_data %i->%i\n",
374 len1 ? len1 : 0, len4);
375 }
376
377
378 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
379 if (f && *f) {
380 key = 2;
381 flags = *f;
382 }
383 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
384 len1, flags, err1 ? err1 : err2);
385#ifdef SOCKMAP
386 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
387#else
388 err = bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
389#endif
390 bpf_printk("sk_msg3: err %i\n", err);
391 return err;
392}
393
394SEC("sk_msg5")
395int bpf_prog8(struct sk_msg_md *msg)
396{
397 void *data_end = (void *)(long) msg->data_end;
398 void *data = (void *)(long) msg->data;
399 int ret = 0, *bytes, zero = 0;
400
401 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
402 if (bytes) {
403 ret = bpf_msg_apply_bytes(msg, *bytes);
404 if (ret)
405 return SK_DROP;
406 } else {
407 return SK_DROP;
408 }
409 return SK_PASS;
410}
411SEC("sk_msg6")
412int bpf_prog9(struct sk_msg_md *msg)
413{
414 void *data_end = (void *)(long) msg->data_end;
415 void *data = (void *)(long) msg->data;
416 int ret = 0, *bytes, zero = 0;
417
418 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
419 if (bytes) {
420 if (((__u64)data_end - (__u64)data) >= *bytes)
421 return SK_PASS;
422 ret = bpf_msg_cork_bytes(msg, *bytes);
423 if (ret)
424 return SK_DROP;
425 }
426 return SK_PASS;
427}
428
429SEC("sk_msg7")
430int bpf_prog10(struct sk_msg_md *msg)
431{
432 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
433 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
434
435 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
436 if (bytes)
437 bpf_msg_apply_bytes(msg, *bytes);
438 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
439 if (bytes)
440 bpf_msg_cork_bytes(msg, *bytes);
441 start = bpf_map_lookup_elem(&sock_bytes, &zero);
442 end = bpf_map_lookup_elem(&sock_bytes, &one);
443 if (start && end)
444 bpf_msg_pull_data(msg, *start, *end, 0);
445 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
446 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
447 if (start_push && end_push)
448 bpf_msg_push_data(msg, *start_push, *end_push, 0);
449 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
450 pop = bpf_map_lookup_elem(&sock_bytes, &five);
451 if (start_pop && pop)
452 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
453 bpf_printk("return sk drop\n");
454 return SK_DROP;
455}
456
457int _version SEC("version") = 1;
458char _license[] SEC("license") = "GPL";