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