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