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