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