1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
9 #include <linux/ipv6.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
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.
32 __uint(type
, TEST_MAP_TYPE
);
33 __uint(max_entries
, 20);
34 __uint(key_size
, sizeof(int));
35 __uint(value_size
, sizeof(int));
36 } sock_map
SEC(".maps");
39 __uint(type
, TEST_MAP_TYPE
);
40 __uint(max_entries
, 20);
41 __uint(key_size
, sizeof(int));
42 __uint(value_size
, sizeof(int));
43 } sock_map_txmsg
SEC(".maps");
46 __uint(type
, TEST_MAP_TYPE
);
47 __uint(max_entries
, 20);
48 __uint(key_size
, sizeof(int));
49 __uint(value_size
, sizeof(int));
50 } sock_map_redir
SEC(".maps");
53 __uint(type
, BPF_MAP_TYPE_ARRAY
);
54 __uint(max_entries
, 1);
57 } sock_apply_bytes
SEC(".maps");
60 __uint(type
, BPF_MAP_TYPE_ARRAY
);
61 __uint(max_entries
, 1);
64 } sock_cork_bytes
SEC(".maps");
67 __uint(type
, BPF_MAP_TYPE_ARRAY
);
68 __uint(max_entries
, 6);
71 } sock_bytes
SEC(".maps");
74 __uint(type
, BPF_MAP_TYPE_ARRAY
);
75 __uint(max_entries
, 1);
78 } sock_redir_flags
SEC(".maps");
81 __uint(type
, BPF_MAP_TYPE_ARRAY
);
82 __uint(max_entries
, 1);
85 } sock_skb_opts
SEC(".maps");
88 int bpf_prog1(struct __sk_buff
*skb
)
94 int bpf_prog2(struct __sk_buff
*skb
)
96 __u32 lport
= skb
->local_port
;
97 __u32 rport
= skb
->remote_port
;
98 int len
, *f
, ret
, zero
= 0;
106 len
= (__u32
)skb
->data_end
- (__u32
)skb
->data
;
107 f
= bpf_map_lookup_elem(&sock_skb_opts
, &zero
);
113 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
116 return bpf_sk_redirect_map(skb
, &sock_map
, ret
, flags
);
118 return bpf_sk_redirect_hash(skb
, &sock_map
, &ret
, flags
);
124 int bpf_sockmap(struct bpf_sock_ops
*skops
)
127 int op
, err
= 0, index
, key
, ret
;
130 op
= (int) skops
->op
;
133 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB
:
134 lport
= skops
->local_port
;
135 rport
= skops
->remote_port
;
137 if (lport
== 10000) {
140 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
143 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
146 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
147 lport
, bpf_ntohl(rport
), err
);
150 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB
:
151 lport
= skops
->local_port
;
152 rport
= skops
->remote_port
;
154 if (bpf_ntohl(rport
) == 10001) {
157 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
160 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
163 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
164 lport
, bpf_ntohl(rport
), err
);
175 int bpf_prog4(struct sk_msg_md
*msg
)
177 int *bytes
, zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
178 int *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
;
180 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
182 bpf_msg_apply_bytes(msg
, *bytes
);
183 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
185 bpf_msg_cork_bytes(msg
, *bytes
);
186 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
187 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
189 bpf_msg_pull_data(msg
, *start
, *end
, 0);
190 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
191 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
192 if (start_push
&& end_push
)
193 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
194 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
195 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
196 if (start_pop
&& pop
)
197 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
202 int bpf_prog5(struct sk_msg_md
*msg
)
204 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
205 int *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
;
206 int *bytes
, len1
, len2
= 0, len3
, len4
;
207 int err1
= -1, err2
= -1;
209 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
211 err1
= bpf_msg_apply_bytes(msg
, *bytes
);
212 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
214 err2
= bpf_msg_cork_bytes(msg
, *bytes
);
215 len1
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
216 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
217 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
221 bpf_printk("sk_msg2: pull(%i:%i)\n",
222 start
? *start
: 0, end
? *end
: 0);
223 err
= bpf_msg_pull_data(msg
, *start
, *end
, 0);
225 bpf_printk("sk_msg2: pull_data err %i\n",
227 len2
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
228 bpf_printk("sk_msg2: length update %i->%i\n",
232 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
233 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
234 if (start_push
&& end_push
) {
237 bpf_printk("sk_msg2: push(%i:%i)\n",
238 start_push
? *start_push
: 0,
239 end_push
? *end_push
: 0);
240 err
= bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
242 bpf_printk("sk_msg2: push_data err %i\n", err
);
243 len3
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
244 bpf_printk("sk_msg2: length push_update %i->%i\n",
245 len2
? len2
: len1
, len3
);
247 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
248 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
249 if (start_pop
&& pop
) {
252 bpf_printk("sk_msg2: pop(%i@%i)\n",
254 err
= bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
256 bpf_printk("sk_msg2: pop_data err %i\n", err
);
257 len4
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
258 bpf_printk("sk_msg2: length pop_data %i->%i\n",
259 len1
? len1
: 0, len4
);
262 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
268 int bpf_prog6(struct sk_msg_md
*msg
)
270 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5, key
= 0;
271 int *bytes
, *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
, *f
;
274 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
276 bpf_msg_apply_bytes(msg
, *bytes
);
277 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
279 bpf_msg_cork_bytes(msg
, *bytes
);
281 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
282 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
284 bpf_msg_pull_data(msg
, *start
, *end
, 0);
286 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
287 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
288 if (start_push
&& end_push
)
289 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
291 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
292 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
293 if (start_pop
&& pop
)
294 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
296 f
= bpf_map_lookup_elem(&sock_redir_flags
, &zero
);
302 return bpf_msg_redirect_map(msg
, &sock_map_redir
, key
, flags
);
304 return bpf_msg_redirect_hash(msg
, &sock_map_redir
, &key
, flags
);
309 int bpf_prog7(struct sk_msg_md
*msg
)
311 int *bytes
, *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
, *f
;
312 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
313 int len1
, len2
= 0, len3
, len4
;
314 int err1
= 0, err2
= 0, key
= 0;
318 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
320 err1
= bpf_msg_apply_bytes(msg
, *bytes
);
321 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
323 err2
= bpf_msg_cork_bytes(msg
, *bytes
);
324 len1
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
326 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
327 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
329 bpf_printk("sk_msg2: pull(%i:%i)\n",
330 start
? *start
: 0, end
? *end
: 0);
331 err
= bpf_msg_pull_data(msg
, *start
, *end
, 0);
333 bpf_printk("sk_msg2: pull_data err %i\n",
335 len2
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
336 bpf_printk("sk_msg2: length update %i->%i\n",
340 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
341 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
342 if (start_push
&& end_push
) {
343 bpf_printk("sk_msg4: push(%i:%i)\n",
344 start_push
? *start_push
: 0,
345 end_push
? *end_push
: 0);
346 err
= bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
348 bpf_printk("sk_msg4: push_data err %i\n",
350 len3
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
351 bpf_printk("sk_msg4: length push_update %i->%i\n",
352 len2
? len2
: len1
, len3
);
355 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
356 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
357 if (start_pop
&& pop
) {
360 bpf_printk("sk_msg4: pop(%i@%i)\n",
362 err
= bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
364 bpf_printk("sk_msg4: pop_data err %i\n", err
);
365 len4
= (__u64
)msg
->data_end
- (__u64
)msg
->data
;
366 bpf_printk("sk_msg4: length pop_data %i->%i\n",
367 len1
? len1
: 0, len4
);
371 f
= bpf_map_lookup_elem(&sock_redir_flags
, &zero
);
376 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
377 len1
, flags
, err1
? err1
: err2
);
379 err
= bpf_msg_redirect_map(msg
, &sock_map_redir
, key
, flags
);
381 err
= bpf_msg_redirect_hash(msg
, &sock_map_redir
, &key
, flags
);
383 bpf_printk("sk_msg3: err %i\n", err
);
388 int bpf_prog8(struct sk_msg_md
*msg
)
390 void *data_end
= (void *)(long) msg
->data_end
;
391 void *data
= (void *)(long) msg
->data
;
392 int ret
= 0, *bytes
, zero
= 0;
394 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
396 ret
= bpf_msg_apply_bytes(msg
, *bytes
);
405 int bpf_prog9(struct sk_msg_md
*msg
)
407 void *data_end
= (void *)(long) msg
->data_end
;
408 void *data
= (void *)(long) msg
->data
;
409 int ret
= 0, *bytes
, zero
= 0;
411 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
413 if (((__u64
)data_end
- (__u64
)data
) >= *bytes
)
415 ret
= bpf_msg_cork_bytes(msg
, *bytes
);
423 int bpf_prog10(struct sk_msg_md
*msg
)
425 int *bytes
, *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
;
426 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
428 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
430 bpf_msg_apply_bytes(msg
, *bytes
);
431 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
433 bpf_msg_cork_bytes(msg
, *bytes
);
434 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
435 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
437 bpf_msg_pull_data(msg
, *start
, *end
, 0);
438 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
439 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
440 if (start_push
&& end_push
)
441 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
442 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
443 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
444 if (start_pop
&& pop
)
445 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
446 bpf_printk("return sk drop\n");
450 int _version
SEC("version") = 1;
451 char _license
[] SEC("license") = "GPL";