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 "vmlinux.h"
10#include <bpf/bpf_core_read.h>
11#include <bpf/bpf_helpers.h>
12#include <bpf/bpf_endian.h>
13#include "bpf_kfuncs.h"
14#include "bpf_tracing_net.h"
15
16#define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret)
17
18#define VXLAN_UDP_PORT		4789
19#define ETH_P_IP		0x0800
20#define PACKET_HOST		0
21#define TUNNEL_CSUM		bpf_htons(0x01)
22#define TUNNEL_KEY		bpf_htons(0x04)
23
24/* Only IPv4 address assigned to veth1.
25 * 172.16.1.200
26 */
27#define ASSIGNED_ADDR_VETH1 0xac1001c8
28
29int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx,
30			  struct bpf_fou_encap *encap, int type) __ksym;
31int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,
32			  struct bpf_fou_encap *encap) __ksym;
33struct xfrm_state *
34bpf_xdp_get_xfrm_state(struct xdp_md *ctx, struct bpf_xfrm_state_opts *opts,
35		       u32 opts__sz) __ksym;
36void bpf_xdp_xfrm_state_release(struct xfrm_state *x) __ksym;
37
38struct {
39	__uint(type, BPF_MAP_TYPE_ARRAY);
40	__uint(max_entries, 1);
41	__type(key, __u32);
42	__type(value, __u32);
43} local_ip_map SEC(".maps");
44
45SEC("tc")
46int gre_set_tunnel(struct __sk_buff *skb)
47{
48	int ret;
49	struct bpf_tunnel_key key;
50
51	__builtin_memset(&key, 0x0, sizeof(key));
52	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
53	key.tunnel_id = 2;
54	key.tunnel_tos = 0;
55	key.tunnel_ttl = 64;
56
57	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
58				     BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);
59	if (ret < 0) {
60		log_err(ret);
61		return TC_ACT_SHOT;
62	}
63
64	return TC_ACT_OK;
65}
66
67SEC("tc")
68int gre_set_tunnel_no_key(struct __sk_buff *skb)
69{
70	int ret;
71	struct bpf_tunnel_key key;
72
73	__builtin_memset(&key, 0x0, sizeof(key));
74	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
75	key.tunnel_ttl = 64;
76
77	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
78				     BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER |
79				     BPF_F_NO_TUNNEL_KEY);
80	if (ret < 0) {
81		log_err(ret);
82		return TC_ACT_SHOT;
83	}
84
85	return TC_ACT_OK;
86}
87
88SEC("tc")
89int gre_get_tunnel(struct __sk_buff *skb)
90{
91	int ret;
92	struct bpf_tunnel_key key;
93
94	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
95	if (ret < 0) {
96		log_err(ret);
97		return TC_ACT_SHOT;
98	}
99
100	bpf_printk("key %d remote ip 0x%x\n", key.tunnel_id, key.remote_ipv4);
101	return TC_ACT_OK;
102}
103
104SEC("tc")
105int ip6gretap_set_tunnel(struct __sk_buff *skb)
106{
107	struct bpf_tunnel_key key;
108	int ret;
109
110	__builtin_memset(&key, 0x0, sizeof(key));
111	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
112	key.tunnel_id = 2;
113	key.tunnel_tos = 0;
114	key.tunnel_ttl = 64;
115	key.tunnel_label = 0xabcde;
116
117	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
118				     BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
119				     BPF_F_SEQ_NUMBER);
120	if (ret < 0) {
121		log_err(ret);
122		return TC_ACT_SHOT;
123	}
124
125	return TC_ACT_OK;
126}
127
128SEC("tc")
129int ip6gretap_get_tunnel(struct __sk_buff *skb)
130{
131	struct bpf_tunnel_key key;
132	int ret;
133
134	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
135				     BPF_F_TUNINFO_IPV6);
136	if (ret < 0) {
137		log_err(ret);
138		return TC_ACT_SHOT;
139	}
140
141	bpf_printk("key %d remote ip6 ::%x label %x\n",
142		   key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
143
144	return TC_ACT_OK;
145}
146
147SEC("tc")
148int erspan_set_tunnel(struct __sk_buff *skb)
149{
150	struct bpf_tunnel_key key;
151	struct erspan_metadata md;
152	int ret;
153
154	__builtin_memset(&key, 0x0, sizeof(key));
155	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
156	key.tunnel_id = 2;
157	key.tunnel_tos = 0;
158	key.tunnel_ttl = 64;
159
160	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
161				     BPF_F_ZERO_CSUM_TX);
162	if (ret < 0) {
163		log_err(ret);
164		return TC_ACT_SHOT;
165	}
166
167	__builtin_memset(&md, 0, sizeof(md));
168#ifdef ERSPAN_V1
169	md.version = 1;
170	md.u.index = bpf_htonl(123);
171#else
172	__u8 direction = 1;
173	__u8 hwid = 7;
174
175	md.version = 2;
176	BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction);
177	BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf));
178	BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3);
179#endif
180
181	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
182	if (ret < 0) {
183		log_err(ret);
184		return TC_ACT_SHOT;
185	}
186
187	return TC_ACT_OK;
188}
189
190SEC("tc")
191int erspan_get_tunnel(struct __sk_buff *skb)
192{
193	struct bpf_tunnel_key key;
194	struct erspan_metadata md;
195	int ret;
196
197	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
198	if (ret < 0) {
199		log_err(ret);
200		return TC_ACT_SHOT;
201	}
202
203	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
204	if (ret < 0) {
205		log_err(ret);
206		return TC_ACT_SHOT;
207	}
208
209	bpf_printk("key %d remote ip 0x%x erspan version %d\n",
210		   key.tunnel_id, key.remote_ipv4, md.version);
211
212#ifdef ERSPAN_V1
213	index = bpf_ntohl(md.u.index);
214	bpf_printk("\tindex %x\n", index);
215#else
216	bpf_printk("\tdirection %d hwid %x timestamp %u\n",
217		   BPF_CORE_READ_BITFIELD(&md.u.md2, dir),
218		   (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) +
219		   BPF_CORE_READ_BITFIELD(&md.u.md2, hwid),
220		   bpf_ntohl(md.u.md2.timestamp));
221#endif
222
223	return TC_ACT_OK;
224}
225
226SEC("tc")
227int ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
228{
229	struct bpf_tunnel_key key;
230	struct erspan_metadata md;
231	int ret;
232
233	__builtin_memset(&key, 0x0, sizeof(key));
234	key.remote_ipv6[3] = bpf_htonl(0x11);
235	key.tunnel_id = 2;
236	key.tunnel_tos = 0;
237	key.tunnel_ttl = 64;
238
239	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
240				     BPF_F_TUNINFO_IPV6);
241	if (ret < 0) {
242		log_err(ret);
243		return TC_ACT_SHOT;
244	}
245
246	__builtin_memset(&md, 0, sizeof(md));
247
248#ifdef ERSPAN_V1
249	md.u.index = bpf_htonl(123);
250	md.version = 1;
251#else
252	__u8 direction = 0;
253	__u8 hwid = 17;
254
255	md.version = 2;
256	BPF_CORE_WRITE_BITFIELD(&md.u.md2, dir, direction);
257	BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid, (hwid & 0xf));
258	BPF_CORE_WRITE_BITFIELD(&md.u.md2, hwid_upper, (hwid >> 4) & 0x3);
259#endif
260
261	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
262	if (ret < 0) {
263		log_err(ret);
264		return TC_ACT_SHOT;
265	}
266
267	return TC_ACT_OK;
268}
269
270SEC("tc")
271int ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
272{
273	struct bpf_tunnel_key key;
274	struct erspan_metadata md;
275	int ret;
276
277	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
278				     BPF_F_TUNINFO_IPV6);
279	if (ret < 0) {
280		log_err(ret);
281		return TC_ACT_SHOT;
282	}
283
284	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
285	if (ret < 0) {
286		log_err(ret);
287		return TC_ACT_SHOT;
288	}
289
290	bpf_printk("ip6erspan get key %d remote ip6 ::%x erspan version %d\n",
291		   key.tunnel_id, key.remote_ipv4, md.version);
292
293#ifdef ERSPAN_V1
294	index = bpf_ntohl(md.u.index);
295	bpf_printk("\tindex %x\n", index);
296#else
297	bpf_printk("\tdirection %d hwid %x timestamp %u\n",
298		   BPF_CORE_READ_BITFIELD(&md.u.md2, dir),
299		   (BPF_CORE_READ_BITFIELD(&md.u.md2, hwid_upper) << 4) +
300		   BPF_CORE_READ_BITFIELD(&md.u.md2, hwid),
301		   bpf_ntohl(md.u.md2.timestamp));
302#endif
303
304	return TC_ACT_OK;
305}
306
307SEC("tc")
308int vxlan_set_tunnel_dst(struct __sk_buff *skb)
309{
310	struct bpf_tunnel_key key;
311	struct vxlan_metadata md;
312	__u32 index = 0;
313	__u32 *local_ip = NULL;
314	int ret = 0;
315
316	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
317	if (!local_ip) {
318		log_err(ret);
319		return TC_ACT_SHOT;
320	}
321
322	__builtin_memset(&key, 0x0, sizeof(key));
323	key.local_ipv4 = 0xac100164; /* 172.16.1.100 */
324	key.remote_ipv4 = *local_ip;
325	key.tunnel_id = 2;
326	key.tunnel_tos = 0;
327	key.tunnel_ttl = 64;
328
329	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
330				     BPF_F_ZERO_CSUM_TX);
331	if (ret < 0) {
332		log_err(ret);
333		return TC_ACT_SHOT;
334	}
335
336	md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
337	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
338	if (ret < 0) {
339		log_err(ret);
340		return TC_ACT_SHOT;
341	}
342
343	return TC_ACT_OK;
344}
345
346SEC("tc")
347int vxlan_set_tunnel_src(struct __sk_buff *skb)
348{
349	struct bpf_tunnel_key key;
350	struct vxlan_metadata md;
351	__u32 index = 0;
352	__u32 *local_ip = NULL;
353	int ret = 0;
354
355	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
356	if (!local_ip) {
357		log_err(ret);
358		return TC_ACT_SHOT;
359	}
360
361	__builtin_memset(&key, 0x0, sizeof(key));
362	key.local_ipv4 = *local_ip;
363	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
364	key.tunnel_id = 2;
365	key.tunnel_tos = 0;
366	key.tunnel_ttl = 64;
367
368	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
369				     BPF_F_ZERO_CSUM_TX);
370	if (ret < 0) {
371		log_err(ret);
372		return TC_ACT_SHOT;
373	}
374
375	md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
376	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
377	if (ret < 0) {
378		log_err(ret);
379		return TC_ACT_SHOT;
380	}
381
382	return TC_ACT_OK;
383}
384
385SEC("tc")
386int vxlan_get_tunnel_src(struct __sk_buff *skb)
387{
388	int ret;
389	struct bpf_tunnel_key key;
390	struct vxlan_metadata md;
391
392	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
393				     BPF_F_TUNINFO_FLAGS);
394	if (ret < 0) {
395		log_err(ret);
396		return TC_ACT_SHOT;
397	}
398
399	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
400	if (ret < 0) {
401		log_err(ret);
402		return TC_ACT_SHOT;
403	}
404
405	if (key.local_ipv4 != ASSIGNED_ADDR_VETH1 || md.gbp != 0x800FF ||
406	    !(key.tunnel_flags & TUNNEL_KEY) ||
407	    (key.tunnel_flags & TUNNEL_CSUM)) {
408		bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x flags 0x%x\n",
409			   key.tunnel_id, key.local_ipv4,
410			   key.remote_ipv4, md.gbp,
411			   bpf_ntohs(key.tunnel_flags));
412		log_err(ret);
413		return TC_ACT_SHOT;
414	}
415
416	return TC_ACT_OK;
417}
418
419SEC("tc")
420int veth_set_outer_dst(struct __sk_buff *skb)
421{
422	struct ethhdr *eth = (struct ethhdr *)(long)skb->data;
423	__u32 assigned_ip = bpf_htonl(ASSIGNED_ADDR_VETH1);
424	void *data_end = (void *)(long)skb->data_end;
425	struct udphdr *udph;
426	struct iphdr *iph;
427	int ret = 0;
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
472SEC("tc")
473int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb)
474{
475	struct bpf_tunnel_key key;
476	__u32 index = 0;
477	__u32 *local_ip;
478	int ret = 0;
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
503SEC("tc")
504int ip6vxlan_set_tunnel_src(struct __sk_buff *skb)
505{
506	struct bpf_tunnel_key key;
507	__u32 index = 0;
508	__u32 *local_ip;
509	int ret = 0;
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
534SEC("tc")
535int ip6vxlan_get_tunnel_src(struct __sk_buff *skb)
536{
537	struct bpf_tunnel_key key;
538	__u32 index = 0;
539	__u32 *local_ip;
540	int ret = 0;
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
570struct local_geneve_opt {
571	struct geneve_opt gopt;
572	int data;
573};
574
575SEC("tc")
576int geneve_set_tunnel(struct __sk_buff *skb)
577{
578	int ret;
579	struct bpf_tunnel_key key;
580	struct local_geneve_opt local_gopt;
581	struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt;
582
583	__builtin_memset(&key, 0x0, sizeof(key));
584	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
585	key.tunnel_id = 2;
586	key.tunnel_tos = 0;
587	key.tunnel_ttl = 64;
588
589	__builtin_memset(gopt, 0x0, sizeof(local_gopt));
590	gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
591	gopt->type = 0x08;
592	gopt->r1 = 0;
593	gopt->r2 = 0;
594	gopt->r3 = 0;
595	gopt->length = 2; /* 4-byte multiple */
596	*(int *) &gopt->opt_data = bpf_htonl(0xdeadbeef);
597
598	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
599				     BPF_F_ZERO_CSUM_TX);
600	if (ret < 0) {
601		log_err(ret);
602		return TC_ACT_SHOT;
603	}
604
605	ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(local_gopt));
606	if (ret < 0) {
607		log_err(ret);
608		return TC_ACT_SHOT;
609	}
610
611	return TC_ACT_OK;
612}
613
614SEC("tc")
615int geneve_get_tunnel(struct __sk_buff *skb)
616{
617	int ret;
618	struct bpf_tunnel_key key;
619	struct geneve_opt gopt;
620
621	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
622	if (ret < 0) {
623		log_err(ret);
624		return TC_ACT_SHOT;
625	}
626
627	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
628	if (ret < 0)
629		gopt.opt_class = 0;
630
631	bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",
632		   key.tunnel_id, key.remote_ipv4, gopt.opt_class);
633	return TC_ACT_OK;
634}
635
636SEC("tc")
637int ip6geneve_set_tunnel(struct __sk_buff *skb)
638{
639	struct bpf_tunnel_key key;
640	struct local_geneve_opt local_gopt;
641	struct geneve_opt *gopt = (struct geneve_opt *) &local_gopt;
642	int ret;
643
644	__builtin_memset(&key, 0x0, sizeof(key));
645	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
646	key.tunnel_id = 22;
647	key.tunnel_tos = 0;
648	key.tunnel_ttl = 64;
649
650	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
651				     BPF_F_TUNINFO_IPV6);
652	if (ret < 0) {
653		log_err(ret);
654		return TC_ACT_SHOT;
655	}
656
657	__builtin_memset(gopt, 0x0, sizeof(local_gopt));
658	gopt->opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
659	gopt->type = 0x08;
660	gopt->r1 = 0;
661	gopt->r2 = 0;
662	gopt->r3 = 0;
663	gopt->length = 2; /* 4-byte multiple */
664	*(int *) &gopt->opt_data = bpf_htonl(0xfeedbeef);
665
666	ret = bpf_skb_set_tunnel_opt(skb, gopt, sizeof(gopt));
667	if (ret < 0) {
668		log_err(ret);
669		return TC_ACT_SHOT;
670	}
671
672	return TC_ACT_OK;
673}
674
675SEC("tc")
676int ip6geneve_get_tunnel(struct __sk_buff *skb)
677{
678	struct bpf_tunnel_key key;
679	struct geneve_opt gopt;
680	int ret;
681
682	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
683				     BPF_F_TUNINFO_IPV6);
684	if (ret < 0) {
685		log_err(ret);
686		return TC_ACT_SHOT;
687	}
688
689	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
690	if (ret < 0)
691		gopt.opt_class = 0;
692
693	bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",
694		   key.tunnel_id, key.remote_ipv4, gopt.opt_class);
695
696	return TC_ACT_OK;
697}
698
699SEC("tc")
700int ipip_set_tunnel(struct __sk_buff *skb)
701{
702	struct bpf_tunnel_key key = {};
703	void *data = (void *)(long)skb->data;
704	struct iphdr *iph = data;
705	void *data_end = (void *)(long)skb->data_end;
706	int ret;
707
708	/* single length check */
709	if (data + sizeof(*iph) > data_end) {
710		log_err(1);
711		return TC_ACT_SHOT;
712	}
713
714	key.tunnel_ttl = 64;
715	if (iph->protocol == IPPROTO_ICMP) {
716		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
717	}
718
719	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
720	if (ret < 0) {
721		log_err(ret);
722		return TC_ACT_SHOT;
723	}
724
725	return TC_ACT_OK;
726}
727
728SEC("tc")
729int ipip_get_tunnel(struct __sk_buff *skb)
730{
731	int ret;
732	struct bpf_tunnel_key key;
733
734	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
735	if (ret < 0) {
736		log_err(ret);
737		return TC_ACT_SHOT;
738	}
739
740	bpf_printk("remote ip 0x%x\n", key.remote_ipv4);
741	return TC_ACT_OK;
742}
743
744SEC("tc")
745int ipip_gue_set_tunnel(struct __sk_buff *skb)
746{
747	struct bpf_tunnel_key key = {};
748	struct bpf_fou_encap encap = {};
749	void *data = (void *)(long)skb->data;
750	struct iphdr *iph = data;
751	void *data_end = (void *)(long)skb->data_end;
752	int ret;
753
754	if (data + sizeof(*iph) > data_end) {
755		log_err(1);
756		return TC_ACT_SHOT;
757	}
758
759	key.tunnel_ttl = 64;
760	if (iph->protocol == IPPROTO_ICMP)
761		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
762
763	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
764	if (ret < 0) {
765		log_err(ret);
766		return TC_ACT_SHOT;
767	}
768
769	encap.sport = 0;
770	encap.dport = bpf_htons(5555);
771
772	ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_GUE);
773	if (ret < 0) {
774		log_err(ret);
775		return TC_ACT_SHOT;
776	}
777
778	return TC_ACT_OK;
779}
780
781SEC("tc")
782int ipip_fou_set_tunnel(struct __sk_buff *skb)
783{
784	struct bpf_tunnel_key key = {};
785	struct bpf_fou_encap encap = {};
786	void *data = (void *)(long)skb->data;
787	struct iphdr *iph = data;
788	void *data_end = (void *)(long)skb->data_end;
789	int ret;
790
791	if (data + sizeof(*iph) > data_end) {
792		log_err(1);
793		return TC_ACT_SHOT;
794	}
795
796	key.tunnel_ttl = 64;
797	if (iph->protocol == IPPROTO_ICMP)
798		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
799
800	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
801	if (ret < 0) {
802		log_err(ret);
803		return TC_ACT_SHOT;
804	}
805
806	encap.sport = 0;
807	encap.dport = bpf_htons(5555);
808
809	ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_FOU);
810	if (ret < 0) {
811		log_err(ret);
812		return TC_ACT_SHOT;
813	}
814
815	return TC_ACT_OK;
816}
817
818SEC("tc")
819int ipip_encap_get_tunnel(struct __sk_buff *skb)
820{
821	int ret;
822	struct bpf_tunnel_key key = {};
823	struct bpf_fou_encap encap = {};
824
825	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
826	if (ret < 0) {
827		log_err(ret);
828		return TC_ACT_SHOT;
829	}
830
831	ret = bpf_skb_get_fou_encap(skb, &encap);
832	if (ret < 0) {
833		log_err(ret);
834		return TC_ACT_SHOT;
835	}
836
837	if (bpf_ntohs(encap.dport) != 5555)
838		return TC_ACT_SHOT;
839
840	bpf_printk("%d remote ip 0x%x, sport %d, dport %d\n", ret,
841		   key.remote_ipv4, bpf_ntohs(encap.sport),
842		   bpf_ntohs(encap.dport));
843	return TC_ACT_OK;
844}
845
846SEC("tc")
847int ipip6_set_tunnel(struct __sk_buff *skb)
848{
849	struct bpf_tunnel_key key = {};
850	void *data = (void *)(long)skb->data;
851	struct iphdr *iph = data;
852	void *data_end = (void *)(long)skb->data_end;
853	int ret;
854
855	/* single length check */
856	if (data + sizeof(*iph) > data_end) {
857		log_err(1);
858		return TC_ACT_SHOT;
859	}
860
861	__builtin_memset(&key, 0x0, sizeof(key));
862	key.tunnel_ttl = 64;
863	if (iph->protocol == IPPROTO_ICMP) {
864		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
865	}
866
867	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
868				     BPF_F_TUNINFO_IPV6);
869	if (ret < 0) {
870		log_err(ret);
871		return TC_ACT_SHOT;
872	}
873
874	return TC_ACT_OK;
875}
876
877SEC("tc")
878int ipip6_get_tunnel(struct __sk_buff *skb)
879{
880	int ret;
881	struct bpf_tunnel_key key;
882
883	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
884				     BPF_F_TUNINFO_IPV6);
885	if (ret < 0) {
886		log_err(ret);
887		return TC_ACT_SHOT;
888	}
889
890	bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),
891		   bpf_htonl(key.remote_ipv6[3]));
892	return TC_ACT_OK;
893}
894
895SEC("tc")
896int ip6ip6_set_tunnel(struct __sk_buff *skb)
897{
898	struct bpf_tunnel_key key = {};
899	void *data = (void *)(long)skb->data;
900	struct ipv6hdr *iph = data;
901	void *data_end = (void *)(long)skb->data_end;
902	int ret;
903
904	/* single length check */
905	if (data + sizeof(*iph) > data_end) {
906		log_err(1);
907		return TC_ACT_SHOT;
908	}
909
910	key.tunnel_ttl = 64;
911	if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
912		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
913	}
914
915	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
916				     BPF_F_TUNINFO_IPV6);
917	if (ret < 0) {
918		log_err(ret);
919		return TC_ACT_SHOT;
920	}
921
922	return TC_ACT_OK;
923}
924
925SEC("tc")
926int ip6ip6_get_tunnel(struct __sk_buff *skb)
927{
928	int ret;
929	struct bpf_tunnel_key key;
930
931	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
932				     BPF_F_TUNINFO_IPV6);
933	if (ret < 0) {
934		log_err(ret);
935		return TC_ACT_SHOT;
936	}
937
938	bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),
939		   bpf_htonl(key.remote_ipv6[3]));
940	return TC_ACT_OK;
941}
942
943volatile int xfrm_reqid = 0;
944volatile int xfrm_spi = 0;
945volatile int xfrm_remote_ip = 0;
946
947SEC("tc")
948int xfrm_get_state(struct __sk_buff *skb)
949{
950	struct bpf_xfrm_state x;
951	int ret;
952
953	ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
954	if (ret < 0)
955		return TC_ACT_OK;
956
957	xfrm_reqid = x.reqid;
958	xfrm_spi = bpf_ntohl(x.spi);
959	xfrm_remote_ip = bpf_ntohl(x.remote_ipv4);
960
961	return TC_ACT_OK;
962}
963
964volatile int xfrm_replay_window = 0;
965
966SEC("xdp")
967int xfrm_get_state_xdp(struct xdp_md *xdp)
968{
969	struct bpf_xfrm_state_opts opts = {};
970	struct xfrm_state *x = NULL;
971	struct ip_esp_hdr *esph;
972	struct bpf_dynptr ptr;
973	u8 esph_buf[8] = {};
974	u8 iph_buf[20] = {};
975	struct iphdr *iph;
976	u32 off;
977
978	if (bpf_dynptr_from_xdp(xdp, 0, &ptr))
979		goto out;
980
981	off = sizeof(struct ethhdr);
982	iph = bpf_dynptr_slice(&ptr, off, iph_buf, sizeof(iph_buf));
983	if (!iph || iph->protocol != IPPROTO_ESP)
984		goto out;
985
986	off += sizeof(struct iphdr);
987	esph = bpf_dynptr_slice(&ptr, off, esph_buf, sizeof(esph_buf));
988	if (!esph)
989		goto out;
990
991	opts.netns_id = BPF_F_CURRENT_NETNS;
992	opts.daddr.a4 = iph->daddr;
993	opts.spi = esph->spi;
994	opts.proto = IPPROTO_ESP;
995	opts.family = AF_INET;
996
997	x = bpf_xdp_get_xfrm_state(xdp, &opts, sizeof(opts));
998	if (!x)
999		goto out;
1000
1001	if (!x->replay_esn)
1002		goto out;
1003
1004	xfrm_replay_window = x->replay_esn->replay_window;
1005out:
1006	if (x)
1007		bpf_xdp_xfrm_state_release(x);
1008	return XDP_PASS;
1009}
1010
1011char _license[] SEC("license") = "GPL";
1012