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