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