1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2016 VMware |
3 | * Copyright (c) 2016 Facebook |
4 | * |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of version 2 of the GNU General Public |
7 | * License as published by the Free Software Foundation. |
8 | */ |
9 | #include <stddef.h> |
10 | #include <string.h> |
11 | #include <arpa/inet.h> |
12 | #include <linux/bpf.h> |
13 | #include <linux/if_ether.h> |
14 | #include <linux/if_packet.h> |
15 | #include <linux/if_tunnel.h> |
16 | #include <linux/ip.h> |
17 | #include <linux/ipv6.h> |
18 | #include <linux/icmp.h> |
19 | #include <linux/types.h> |
20 | #include <linux/socket.h> |
21 | #include <linux/pkt_cls.h> |
22 | #include <linux/erspan.h> |
23 | #include <linux/udp.h> |
24 | #include <bpf/bpf_helpers.h> |
25 | #include <bpf/bpf_endian.h> |
26 | |
27 | #define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret) |
28 | |
29 | #define VXLAN_UDP_PORT 4789 |
30 | |
31 | /* Only IPv4 address assigned to veth1. |
32 | * 172.16.1.200 |
33 | */ |
34 | #define ASSIGNED_ADDR_VETH1 0xac1001c8 |
35 | |
36 | struct geneve_opt { |
37 | __be16 opt_class; |
38 | __u8 type; |
39 | __u8 length:5; |
40 | __u8 r3:1; |
41 | __u8 r2:1; |
42 | __u8 r1:1; |
43 | __u8 opt_data[8]; /* hard-coded to 8 byte */ |
44 | }; |
45 | |
46 | struct vxlanhdr { |
47 | __be32 vx_flags; |
48 | __be32 vx_vni; |
49 | } __attribute__((packed)); |
50 | |
51 | struct vxlan_metadata { |
52 | __u32 gbp; |
53 | }; |
54 | |
55 | struct bpf_fou_encap { |
56 | __be16 sport; |
57 | __be16 dport; |
58 | }; |
59 | |
60 | enum bpf_fou_encap_type { |
61 | FOU_BPF_ENCAP_FOU, |
62 | FOU_BPF_ENCAP_GUE, |
63 | }; |
64 | |
65 | int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx, |
66 | struct bpf_fou_encap *encap, int type) __ksym; |
67 | int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx, |
68 | struct bpf_fou_encap *encap) __ksym; |
69 | |
70 | struct { |
71 | __uint(type, BPF_MAP_TYPE_ARRAY); |
72 | __uint(max_entries, 1); |
73 | __type(key, __u32); |
74 | __type(value, __u32); |
75 | } local_ip_map SEC(".maps" ); |
76 | |
77 | SEC("tc" ) |
78 | int gre_set_tunnel(struct __sk_buff *skb) |
79 | { |
80 | int ret; |
81 | struct bpf_tunnel_key key; |
82 | |
83 | __builtin_memset(&key, 0x0, sizeof(key)); |
84 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
85 | key.tunnel_id = 2; |
86 | key.tunnel_tos = 0; |
87 | key.tunnel_ttl = 64; |
88 | |
89 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
90 | BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER); |
91 | if (ret < 0) { |
92 | log_err(ret); |
93 | return TC_ACT_SHOT; |
94 | } |
95 | |
96 | return TC_ACT_OK; |
97 | } |
98 | |
99 | SEC("tc" ) |
100 | int gre_set_tunnel_no_key(struct __sk_buff *skb) |
101 | { |
102 | int ret; |
103 | struct bpf_tunnel_key key; |
104 | |
105 | __builtin_memset(&key, 0x0, sizeof(key)); |
106 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
107 | key.tunnel_ttl = 64; |
108 | |
109 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
110 | BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER | |
111 | BPF_F_NO_TUNNEL_KEY); |
112 | if (ret < 0) { |
113 | log_err(ret); |
114 | return TC_ACT_SHOT; |
115 | } |
116 | |
117 | return TC_ACT_OK; |
118 | } |
119 | |
120 | SEC("tc" ) |
121 | int gre_get_tunnel(struct __sk_buff *skb) |
122 | { |
123 | int ret; |
124 | struct bpf_tunnel_key key; |
125 | |
126 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); |
127 | if (ret < 0) { |
128 | log_err(ret); |
129 | return TC_ACT_SHOT; |
130 | } |
131 | |
132 | bpf_printk("key %d remote ip 0x%x\n" , key.tunnel_id, key.remote_ipv4); |
133 | return TC_ACT_OK; |
134 | } |
135 | |
136 | SEC("tc" ) |
137 | int ip6gretap_set_tunnel(struct __sk_buff *skb) |
138 | { |
139 | struct bpf_tunnel_key key; |
140 | int ret; |
141 | |
142 | __builtin_memset(&key, 0x0, sizeof(key)); |
143 | key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
144 | key.tunnel_id = 2; |
145 | key.tunnel_tos = 0; |
146 | key.tunnel_ttl = 64; |
147 | key.tunnel_label = 0xabcde; |
148 | |
149 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
150 | BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX | |
151 | BPF_F_SEQ_NUMBER); |
152 | if (ret < 0) { |
153 | log_err(ret); |
154 | return TC_ACT_SHOT; |
155 | } |
156 | |
157 | return TC_ACT_OK; |
158 | } |
159 | |
160 | SEC("tc" ) |
161 | int ip6gretap_get_tunnel(struct __sk_buff *skb) |
162 | { |
163 | struct bpf_tunnel_key key; |
164 | int ret; |
165 | |
166 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
167 | BPF_F_TUNINFO_IPV6); |
168 | if (ret < 0) { |
169 | log_err(ret); |
170 | return TC_ACT_SHOT; |
171 | } |
172 | |
173 | bpf_printk("key %d remote ip6 ::%x label %x\n" , |
174 | key.tunnel_id, key.remote_ipv6[3], key.tunnel_label); |
175 | |
176 | return TC_ACT_OK; |
177 | } |
178 | |
179 | SEC("tc" ) |
180 | int erspan_set_tunnel(struct __sk_buff *skb) |
181 | { |
182 | struct bpf_tunnel_key key; |
183 | struct erspan_metadata md; |
184 | int ret; |
185 | |
186 | __builtin_memset(&key, 0x0, sizeof(key)); |
187 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
188 | key.tunnel_id = 2; |
189 | key.tunnel_tos = 0; |
190 | key.tunnel_ttl = 64; |
191 | |
192 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
193 | BPF_F_ZERO_CSUM_TX); |
194 | if (ret < 0) { |
195 | log_err(ret); |
196 | return TC_ACT_SHOT; |
197 | } |
198 | |
199 | __builtin_memset(&md, 0, sizeof(md)); |
200 | #ifdef ERSPAN_V1 |
201 | md.version = 1; |
202 | md.u.index = bpf_htonl(123); |
203 | #else |
204 | __u8 direction = 1; |
205 | __u8 hwid = 7; |
206 | |
207 | md.version = 2; |
208 | md.u.md2.dir = direction; |
209 | md.u.md2.hwid = hwid & 0xf; |
210 | md.u.md2.hwid_upper = (hwid >> 4) & 0x3; |
211 | #endif |
212 | |
213 | ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); |
214 | if (ret < 0) { |
215 | log_err(ret); |
216 | return TC_ACT_SHOT; |
217 | } |
218 | |
219 | return TC_ACT_OK; |
220 | } |
221 | |
222 | SEC("tc" ) |
223 | int erspan_get_tunnel(struct __sk_buff *skb) |
224 | { |
225 | struct bpf_tunnel_key key; |
226 | struct erspan_metadata md; |
227 | int ret; |
228 | |
229 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); |
230 | if (ret < 0) { |
231 | log_err(ret); |
232 | return TC_ACT_SHOT; |
233 | } |
234 | |
235 | ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); |
236 | if (ret < 0) { |
237 | log_err(ret); |
238 | return TC_ACT_SHOT; |
239 | } |
240 | |
241 | bpf_printk("key %d remote ip 0x%x erspan version %d\n" , |
242 | key.tunnel_id, key.remote_ipv4, md.version); |
243 | |
244 | #ifdef ERSPAN_V1 |
245 | index = bpf_ntohl(md.u.index); |
246 | bpf_printk("\tindex %x\n" , index); |
247 | #else |
248 | bpf_printk("\tdirection %d hwid %x timestamp %u\n" , |
249 | md.u.md2.dir, |
250 | (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, |
251 | bpf_ntohl(md.u.md2.timestamp)); |
252 | #endif |
253 | |
254 | return TC_ACT_OK; |
255 | } |
256 | |
257 | SEC("tc" ) |
258 | int ip4ip6erspan_set_tunnel(struct __sk_buff *skb) |
259 | { |
260 | struct bpf_tunnel_key key; |
261 | struct erspan_metadata md; |
262 | int ret; |
263 | |
264 | __builtin_memset(&key, 0x0, sizeof(key)); |
265 | key.remote_ipv6[3] = bpf_htonl(0x11); |
266 | key.tunnel_id = 2; |
267 | key.tunnel_tos = 0; |
268 | key.tunnel_ttl = 64; |
269 | |
270 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
271 | BPF_F_TUNINFO_IPV6); |
272 | if (ret < 0) { |
273 | log_err(ret); |
274 | return TC_ACT_SHOT; |
275 | } |
276 | |
277 | __builtin_memset(&md, 0, sizeof(md)); |
278 | |
279 | #ifdef ERSPAN_V1 |
280 | md.u.index = bpf_htonl(123); |
281 | md.version = 1; |
282 | #else |
283 | __u8 direction = 0; |
284 | __u8 hwid = 17; |
285 | |
286 | md.version = 2; |
287 | md.u.md2.dir = direction; |
288 | md.u.md2.hwid = hwid & 0xf; |
289 | md.u.md2.hwid_upper = (hwid >> 4) & 0x3; |
290 | #endif |
291 | |
292 | ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); |
293 | if (ret < 0) { |
294 | log_err(ret); |
295 | return TC_ACT_SHOT; |
296 | } |
297 | |
298 | return TC_ACT_OK; |
299 | } |
300 | |
301 | SEC("tc" ) |
302 | int ip4ip6erspan_get_tunnel(struct __sk_buff *skb) |
303 | { |
304 | struct bpf_tunnel_key key; |
305 | struct erspan_metadata md; |
306 | int ret; |
307 | |
308 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
309 | BPF_F_TUNINFO_IPV6); |
310 | if (ret < 0) { |
311 | log_err(ret); |
312 | return TC_ACT_SHOT; |
313 | } |
314 | |
315 | ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); |
316 | if (ret < 0) { |
317 | log_err(ret); |
318 | return TC_ACT_SHOT; |
319 | } |
320 | |
321 | bpf_printk("ip6erspan get key %d remote ip6 ::%x erspan version %d\n" , |
322 | key.tunnel_id, key.remote_ipv4, md.version); |
323 | |
324 | #ifdef ERSPAN_V1 |
325 | index = bpf_ntohl(md.u.index); |
326 | bpf_printk("\tindex %x\n" , index); |
327 | #else |
328 | bpf_printk("\tdirection %d hwid %x timestamp %u\n" , |
329 | md.u.md2.dir, |
330 | (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, |
331 | bpf_ntohl(md.u.md2.timestamp)); |
332 | #endif |
333 | |
334 | return TC_ACT_OK; |
335 | } |
336 | |
337 | SEC("tc" ) |
338 | int vxlan_set_tunnel_dst(struct __sk_buff *skb) |
339 | { |
340 | struct bpf_tunnel_key key; |
341 | struct vxlan_metadata md; |
342 | __u32 index = 0; |
343 | __u32 *local_ip = NULL; |
344 | int ret = 0; |
345 | |
346 | local_ip = bpf_map_lookup_elem(&local_ip_map, &index); |
347 | if (!local_ip) { |
348 | log_err(ret); |
349 | return TC_ACT_SHOT; |
350 | } |
351 | |
352 | __builtin_memset(&key, 0x0, sizeof(key)); |
353 | key.local_ipv4 = 0xac100164; /* 172.16.1.100 */ |
354 | key.remote_ipv4 = *local_ip; |
355 | key.tunnel_id = 2; |
356 | key.tunnel_tos = 0; |
357 | key.tunnel_ttl = 64; |
358 | |
359 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
360 | BPF_F_ZERO_CSUM_TX); |
361 | if (ret < 0) { |
362 | log_err(ret); |
363 | return TC_ACT_SHOT; |
364 | } |
365 | |
366 | md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */ |
367 | ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); |
368 | if (ret < 0) { |
369 | log_err(ret); |
370 | return TC_ACT_SHOT; |
371 | } |
372 | |
373 | return TC_ACT_OK; |
374 | } |
375 | |
376 | SEC("tc" ) |
377 | int vxlan_set_tunnel_src(struct __sk_buff *skb) |
378 | { |
379 | struct bpf_tunnel_key key; |
380 | struct vxlan_metadata md; |
381 | __u32 index = 0; |
382 | __u32 *local_ip = NULL; |
383 | int ret = 0; |
384 | |
385 | local_ip = bpf_map_lookup_elem(&local_ip_map, &index); |
386 | if (!local_ip) { |
387 | log_err(ret); |
388 | return TC_ACT_SHOT; |
389 | } |
390 | |
391 | __builtin_memset(&key, 0x0, sizeof(key)); |
392 | key.local_ipv4 = *local_ip; |
393 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
394 | key.tunnel_id = 2; |
395 | key.tunnel_tos = 0; |
396 | key.tunnel_ttl = 64; |
397 | |
398 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
399 | BPF_F_ZERO_CSUM_TX); |
400 | if (ret < 0) { |
401 | log_err(ret); |
402 | return TC_ACT_SHOT; |
403 | } |
404 | |
405 | md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */ |
406 | ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); |
407 | if (ret < 0) { |
408 | log_err(ret); |
409 | return TC_ACT_SHOT; |
410 | } |
411 | |
412 | return TC_ACT_OK; |
413 | } |
414 | |
415 | SEC("tc" ) |
416 | int vxlan_get_tunnel_src(struct __sk_buff *skb) |
417 | { |
418 | int ret; |
419 | struct bpf_tunnel_key key; |
420 | struct vxlan_metadata md; |
421 | |
422 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
423 | BPF_F_TUNINFO_FLAGS); |
424 | if (ret < 0) { |
425 | log_err(ret); |
426 | return TC_ACT_SHOT; |
427 | } |
428 | |
429 | ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md)); |
430 | if (ret < 0) { |
431 | log_err(ret); |
432 | return TC_ACT_SHOT; |
433 | } |
434 | |
435 | if (key.local_ipv4 != ASSIGNED_ADDR_VETH1 || md.gbp != 0x800FF || |
436 | !(key.tunnel_flags & TUNNEL_KEY) || |
437 | (key.tunnel_flags & TUNNEL_CSUM)) { |
438 | bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x flags 0x%x\n" , |
439 | key.tunnel_id, key.local_ipv4, |
440 | key.remote_ipv4, md.gbp, |
441 | bpf_ntohs(key.tunnel_flags)); |
442 | log_err(ret); |
443 | return TC_ACT_SHOT; |
444 | } |
445 | |
446 | return TC_ACT_OK; |
447 | } |
448 | |
449 | SEC("tc" ) |
450 | int veth_set_outer_dst(struct __sk_buff *skb) |
451 | { |
452 | struct ethhdr *eth = (struct ethhdr *)(long)skb->data; |
453 | __u32 assigned_ip = bpf_htonl(ASSIGNED_ADDR_VETH1); |
454 | void *data_end = (void *)(long)skb->data_end; |
455 | struct udphdr *udph; |
456 | struct iphdr *iph; |
457 | int ret = 0; |
458 | __s64 csum; |
459 | |
460 | if ((void *)eth + sizeof(*eth) > data_end) { |
461 | log_err(ret); |
462 | return TC_ACT_SHOT; |
463 | } |
464 | |
465 | if (eth->h_proto != bpf_htons(ETH_P_IP)) |
466 | return TC_ACT_OK; |
467 | |
468 | iph = (struct iphdr *)(eth + 1); |
469 | if ((void *)iph + sizeof(*iph) > data_end) { |
470 | log_err(ret); |
471 | return TC_ACT_SHOT; |
472 | } |
473 | if (iph->protocol != IPPROTO_UDP) |
474 | return TC_ACT_OK; |
475 | |
476 | udph = (struct udphdr *)(iph + 1); |
477 | if ((void *)udph + sizeof(*udph) > data_end) { |
478 | log_err(ret); |
479 | return TC_ACT_SHOT; |
480 | } |
481 | if (udph->dest != bpf_htons(VXLAN_UDP_PORT)) |
482 | return TC_ACT_OK; |
483 | |
484 | if (iph->daddr != assigned_ip) { |
485 | csum = bpf_csum_diff(&iph->daddr, sizeof(__u32), &assigned_ip, |
486 | sizeof(__u32), 0); |
487 | if (bpf_skb_store_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr), |
488 | &assigned_ip, sizeof(__u32), 0) < 0) { |
489 | log_err(ret); |
490 | return TC_ACT_SHOT; |
491 | } |
492 | if (bpf_l3_csum_replace(skb, ETH_HLEN + offsetof(struct iphdr, check), |
493 | 0, csum, 0) < 0) { |
494 | log_err(ret); |
495 | return TC_ACT_SHOT; |
496 | } |
497 | bpf_skb_change_type(skb, PACKET_HOST); |
498 | } |
499 | return TC_ACT_OK; |
500 | } |
501 | |
502 | SEC("tc" ) |
503 | int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb) |
504 | { |
505 | struct bpf_tunnel_key key; |
506 | __u32 index = 0; |
507 | __u32 *local_ip; |
508 | int ret = 0; |
509 | |
510 | local_ip = bpf_map_lookup_elem(&local_ip_map, &index); |
511 | if (!local_ip) { |
512 | log_err(ret); |
513 | return TC_ACT_SHOT; |
514 | } |
515 | |
516 | __builtin_memset(&key, 0x0, sizeof(key)); |
517 | key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
518 | key.remote_ipv6[3] = bpf_htonl(*local_ip); |
519 | key.tunnel_id = 22; |
520 | key.tunnel_tos = 0; |
521 | key.tunnel_ttl = 64; |
522 | |
523 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
524 | BPF_F_TUNINFO_IPV6); |
525 | if (ret < 0) { |
526 | log_err(ret); |
527 | return TC_ACT_SHOT; |
528 | } |
529 | |
530 | return TC_ACT_OK; |
531 | } |
532 | |
533 | SEC("tc" ) |
534 | int ip6vxlan_set_tunnel_src(struct __sk_buff *skb) |
535 | { |
536 | struct bpf_tunnel_key key; |
537 | __u32 index = 0; |
538 | __u32 *local_ip; |
539 | int ret = 0; |
540 | |
541 | local_ip = bpf_map_lookup_elem(&local_ip_map, &index); |
542 | if (!local_ip) { |
543 | log_err(ret); |
544 | return TC_ACT_SHOT; |
545 | } |
546 | |
547 | __builtin_memset(&key, 0x0, sizeof(key)); |
548 | key.local_ipv6[3] = bpf_htonl(*local_ip); |
549 | key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
550 | key.tunnel_id = 22; |
551 | key.tunnel_tos = 0; |
552 | key.tunnel_ttl = 64; |
553 | |
554 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
555 | BPF_F_TUNINFO_IPV6); |
556 | if (ret < 0) { |
557 | log_err(ret); |
558 | return TC_ACT_SHOT; |
559 | } |
560 | |
561 | return TC_ACT_OK; |
562 | } |
563 | |
564 | SEC("tc" ) |
565 | int ip6vxlan_get_tunnel_src(struct __sk_buff *skb) |
566 | { |
567 | struct bpf_tunnel_key key; |
568 | __u32 index = 0; |
569 | __u32 *local_ip; |
570 | int ret = 0; |
571 | |
572 | local_ip = bpf_map_lookup_elem(&local_ip_map, &index); |
573 | if (!local_ip) { |
574 | log_err(ret); |
575 | return TC_ACT_SHOT; |
576 | } |
577 | |
578 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
579 | BPF_F_TUNINFO_IPV6 | BPF_F_TUNINFO_FLAGS); |
580 | if (ret < 0) { |
581 | log_err(ret); |
582 | return TC_ACT_SHOT; |
583 | } |
584 | |
585 | if (bpf_ntohl(key.local_ipv6[3]) != *local_ip || |
586 | !(key.tunnel_flags & TUNNEL_KEY) || |
587 | !(key.tunnel_flags & TUNNEL_CSUM)) { |
588 | bpf_printk("ip6vxlan key %d local ip6 ::%x remote ip6 ::%x label 0x%x flags 0x%x\n" , |
589 | key.tunnel_id, bpf_ntohl(key.local_ipv6[3]), |
590 | bpf_ntohl(key.remote_ipv6[3]), key.tunnel_label, |
591 | bpf_ntohs(key.tunnel_flags)); |
592 | bpf_printk("local_ip 0x%x\n" , *local_ip); |
593 | log_err(ret); |
594 | return TC_ACT_SHOT; |
595 | } |
596 | |
597 | return TC_ACT_OK; |
598 | } |
599 | |
600 | SEC("tc" ) |
601 | int geneve_set_tunnel(struct __sk_buff *skb) |
602 | { |
603 | int ret; |
604 | struct bpf_tunnel_key key; |
605 | struct geneve_opt gopt; |
606 | |
607 | __builtin_memset(&key, 0x0, sizeof(key)); |
608 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
609 | key.tunnel_id = 2; |
610 | key.tunnel_tos = 0; |
611 | key.tunnel_ttl = 64; |
612 | |
613 | __builtin_memset(&gopt, 0x0, sizeof(gopt)); |
614 | gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */ |
615 | gopt.type = 0x08; |
616 | gopt.r1 = 0; |
617 | gopt.r2 = 0; |
618 | gopt.r3 = 0; |
619 | gopt.length = 2; /* 4-byte multiple */ |
620 | *(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef); |
621 | |
622 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
623 | BPF_F_ZERO_CSUM_TX); |
624 | if (ret < 0) { |
625 | log_err(ret); |
626 | return TC_ACT_SHOT; |
627 | } |
628 | |
629 | ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt)); |
630 | if (ret < 0) { |
631 | log_err(ret); |
632 | return TC_ACT_SHOT; |
633 | } |
634 | |
635 | return TC_ACT_OK; |
636 | } |
637 | |
638 | SEC("tc" ) |
639 | int geneve_get_tunnel(struct __sk_buff *skb) |
640 | { |
641 | int ret; |
642 | struct bpf_tunnel_key key; |
643 | struct geneve_opt gopt; |
644 | |
645 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); |
646 | if (ret < 0) { |
647 | log_err(ret); |
648 | return TC_ACT_SHOT; |
649 | } |
650 | |
651 | ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt)); |
652 | if (ret < 0) |
653 | gopt.opt_class = 0; |
654 | |
655 | bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n" , |
656 | key.tunnel_id, key.remote_ipv4, gopt.opt_class); |
657 | return TC_ACT_OK; |
658 | } |
659 | |
660 | SEC("tc" ) |
661 | int ip6geneve_set_tunnel(struct __sk_buff *skb) |
662 | { |
663 | struct bpf_tunnel_key key; |
664 | struct geneve_opt gopt; |
665 | int ret; |
666 | |
667 | __builtin_memset(&key, 0x0, sizeof(key)); |
668 | key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
669 | key.tunnel_id = 22; |
670 | key.tunnel_tos = 0; |
671 | key.tunnel_ttl = 64; |
672 | |
673 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
674 | BPF_F_TUNINFO_IPV6); |
675 | if (ret < 0) { |
676 | log_err(ret); |
677 | return TC_ACT_SHOT; |
678 | } |
679 | |
680 | __builtin_memset(&gopt, 0x0, sizeof(gopt)); |
681 | gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */ |
682 | gopt.type = 0x08; |
683 | gopt.r1 = 0; |
684 | gopt.r2 = 0; |
685 | gopt.r3 = 0; |
686 | gopt.length = 2; /* 4-byte multiple */ |
687 | *(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef); |
688 | |
689 | ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt)); |
690 | if (ret < 0) { |
691 | log_err(ret); |
692 | return TC_ACT_SHOT; |
693 | } |
694 | |
695 | return TC_ACT_OK; |
696 | } |
697 | |
698 | SEC("tc" ) |
699 | int ip6geneve_get_tunnel(struct __sk_buff *skb) |
700 | { |
701 | struct bpf_tunnel_key key; |
702 | struct geneve_opt gopt; |
703 | int ret; |
704 | |
705 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
706 | BPF_F_TUNINFO_IPV6); |
707 | if (ret < 0) { |
708 | log_err(ret); |
709 | return TC_ACT_SHOT; |
710 | } |
711 | |
712 | ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt)); |
713 | if (ret < 0) |
714 | gopt.opt_class = 0; |
715 | |
716 | bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n" , |
717 | key.tunnel_id, key.remote_ipv4, gopt.opt_class); |
718 | |
719 | return TC_ACT_OK; |
720 | } |
721 | |
722 | SEC("tc" ) |
723 | int ipip_set_tunnel(struct __sk_buff *skb) |
724 | { |
725 | struct bpf_tunnel_key key = {}; |
726 | void *data = (void *)(long)skb->data; |
727 | struct iphdr *iph = data; |
728 | void *data_end = (void *)(long)skb->data_end; |
729 | int ret; |
730 | |
731 | /* single length check */ |
732 | if (data + sizeof(*iph) > data_end) { |
733 | log_err(1); |
734 | return TC_ACT_SHOT; |
735 | } |
736 | |
737 | key.tunnel_ttl = 64; |
738 | if (iph->protocol == IPPROTO_ICMP) { |
739 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
740 | } |
741 | |
742 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); |
743 | if (ret < 0) { |
744 | log_err(ret); |
745 | return TC_ACT_SHOT; |
746 | } |
747 | |
748 | return TC_ACT_OK; |
749 | } |
750 | |
751 | SEC("tc" ) |
752 | int ipip_get_tunnel(struct __sk_buff *skb) |
753 | { |
754 | int ret; |
755 | struct bpf_tunnel_key key; |
756 | |
757 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); |
758 | if (ret < 0) { |
759 | log_err(ret); |
760 | return TC_ACT_SHOT; |
761 | } |
762 | |
763 | bpf_printk("remote ip 0x%x\n" , key.remote_ipv4); |
764 | return TC_ACT_OK; |
765 | } |
766 | |
767 | SEC("tc" ) |
768 | int ipip_gue_set_tunnel(struct __sk_buff *skb) |
769 | { |
770 | struct bpf_tunnel_key key = {}; |
771 | struct bpf_fou_encap encap = {}; |
772 | void *data = (void *)(long)skb->data; |
773 | struct iphdr *iph = data; |
774 | void *data_end = (void *)(long)skb->data_end; |
775 | int ret; |
776 | |
777 | if (data + sizeof(*iph) > data_end) { |
778 | log_err(1); |
779 | return TC_ACT_SHOT; |
780 | } |
781 | |
782 | key.tunnel_ttl = 64; |
783 | if (iph->protocol == IPPROTO_ICMP) |
784 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
785 | |
786 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); |
787 | if (ret < 0) { |
788 | log_err(ret); |
789 | return TC_ACT_SHOT; |
790 | } |
791 | |
792 | encap.sport = 0; |
793 | encap.dport = bpf_htons(5555); |
794 | |
795 | ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_GUE); |
796 | if (ret < 0) { |
797 | log_err(ret); |
798 | return TC_ACT_SHOT; |
799 | } |
800 | |
801 | return TC_ACT_OK; |
802 | } |
803 | |
804 | SEC("tc" ) |
805 | int ipip_fou_set_tunnel(struct __sk_buff *skb) |
806 | { |
807 | struct bpf_tunnel_key key = {}; |
808 | struct bpf_fou_encap encap = {}; |
809 | void *data = (void *)(long)skb->data; |
810 | struct iphdr *iph = data; |
811 | void *data_end = (void *)(long)skb->data_end; |
812 | int ret; |
813 | |
814 | if (data + sizeof(*iph) > data_end) { |
815 | log_err(1); |
816 | return TC_ACT_SHOT; |
817 | } |
818 | |
819 | key.tunnel_ttl = 64; |
820 | if (iph->protocol == IPPROTO_ICMP) |
821 | key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ |
822 | |
823 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); |
824 | if (ret < 0) { |
825 | log_err(ret); |
826 | return TC_ACT_SHOT; |
827 | } |
828 | |
829 | encap.sport = 0; |
830 | encap.dport = bpf_htons(5555); |
831 | |
832 | ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_FOU); |
833 | if (ret < 0) { |
834 | log_err(ret); |
835 | return TC_ACT_SHOT; |
836 | } |
837 | |
838 | return TC_ACT_OK; |
839 | } |
840 | |
841 | SEC("tc" ) |
842 | int ipip_encap_get_tunnel(struct __sk_buff *skb) |
843 | { |
844 | int ret; |
845 | struct bpf_tunnel_key key = {}; |
846 | struct bpf_fou_encap encap = {}; |
847 | |
848 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); |
849 | if (ret < 0) { |
850 | log_err(ret); |
851 | return TC_ACT_SHOT; |
852 | } |
853 | |
854 | ret = bpf_skb_get_fou_encap(skb, &encap); |
855 | if (ret < 0) { |
856 | log_err(ret); |
857 | return TC_ACT_SHOT; |
858 | } |
859 | |
860 | if (bpf_ntohs(encap.dport) != 5555) |
861 | return TC_ACT_SHOT; |
862 | |
863 | bpf_printk("%d remote ip 0x%x, sport %d, dport %d\n" , ret, |
864 | key.remote_ipv4, bpf_ntohs(encap.sport), |
865 | bpf_ntohs(encap.dport)); |
866 | return TC_ACT_OK; |
867 | } |
868 | |
869 | SEC("tc" ) |
870 | int ipip6_set_tunnel(struct __sk_buff *skb) |
871 | { |
872 | struct bpf_tunnel_key key = {}; |
873 | void *data = (void *)(long)skb->data; |
874 | struct iphdr *iph = data; |
875 | void *data_end = (void *)(long)skb->data_end; |
876 | int ret; |
877 | |
878 | /* single length check */ |
879 | if (data + sizeof(*iph) > data_end) { |
880 | log_err(1); |
881 | return TC_ACT_SHOT; |
882 | } |
883 | |
884 | __builtin_memset(&key, 0x0, sizeof(key)); |
885 | key.tunnel_ttl = 64; |
886 | if (iph->protocol == IPPROTO_ICMP) { |
887 | key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
888 | } |
889 | |
890 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
891 | BPF_F_TUNINFO_IPV6); |
892 | if (ret < 0) { |
893 | log_err(ret); |
894 | return TC_ACT_SHOT; |
895 | } |
896 | |
897 | return TC_ACT_OK; |
898 | } |
899 | |
900 | SEC("tc" ) |
901 | int ipip6_get_tunnel(struct __sk_buff *skb) |
902 | { |
903 | int ret; |
904 | struct bpf_tunnel_key key; |
905 | |
906 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
907 | BPF_F_TUNINFO_IPV6); |
908 | if (ret < 0) { |
909 | log_err(ret); |
910 | return TC_ACT_SHOT; |
911 | } |
912 | |
913 | bpf_printk("remote ip6 %x::%x\n" , bpf_htonl(key.remote_ipv6[0]), |
914 | bpf_htonl(key.remote_ipv6[3])); |
915 | return TC_ACT_OK; |
916 | } |
917 | |
918 | SEC("tc" ) |
919 | int ip6ip6_set_tunnel(struct __sk_buff *skb) |
920 | { |
921 | struct bpf_tunnel_key key = {}; |
922 | void *data = (void *)(long)skb->data; |
923 | struct ipv6hdr *iph = data; |
924 | void *data_end = (void *)(long)skb->data_end; |
925 | int ret; |
926 | |
927 | /* single length check */ |
928 | if (data + sizeof(*iph) > data_end) { |
929 | log_err(1); |
930 | return TC_ACT_SHOT; |
931 | } |
932 | |
933 | key.tunnel_ttl = 64; |
934 | if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) { |
935 | key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ |
936 | } |
937 | |
938 | ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), |
939 | BPF_F_TUNINFO_IPV6); |
940 | if (ret < 0) { |
941 | log_err(ret); |
942 | return TC_ACT_SHOT; |
943 | } |
944 | |
945 | return TC_ACT_OK; |
946 | } |
947 | |
948 | SEC("tc" ) |
949 | int ip6ip6_get_tunnel(struct __sk_buff *skb) |
950 | { |
951 | int ret; |
952 | struct bpf_tunnel_key key; |
953 | |
954 | ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), |
955 | BPF_F_TUNINFO_IPV6); |
956 | if (ret < 0) { |
957 | log_err(ret); |
958 | return TC_ACT_SHOT; |
959 | } |
960 | |
961 | bpf_printk("remote ip6 %x::%x\n" , bpf_htonl(key.remote_ipv6[0]), |
962 | bpf_htonl(key.remote_ipv6[3])); |
963 | return TC_ACT_OK; |
964 | } |
965 | |
966 | SEC("tc" ) |
967 | int xfrm_get_state(struct __sk_buff *skb) |
968 | { |
969 | struct bpf_xfrm_state x; |
970 | int ret; |
971 | |
972 | ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0); |
973 | if (ret < 0) |
974 | return TC_ACT_OK; |
975 | |
976 | bpf_printk("reqid %d spi 0x%x remote ip 0x%x\n" , |
977 | x.reqid, bpf_ntohl(x.spi), |
978 | bpf_ntohl(x.remote_ipv4)); |
979 | return TC_ACT_OK; |
980 | } |
981 | |
982 | char _license[] SEC("license" ) = "GPL" ; |
983 | |