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
26struct 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
36struct vxlan_metadata {
37	__u32     gbp;
38};
39
40struct {
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
47SEC("tc")
48int 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
69SEC("tc")
70int 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
85SEC("tc")
86int 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
109SEC("tc")
110int 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
128SEC("tc")
129int 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
171SEC("tc")
172int 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
207SEC("tc")
208int 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
251SEC("tc")
252int 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
288SEC("tc")
289int 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
327SEC("tc")
328int 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
366SEC("tc")
367int 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
405SEC("tc")
406int 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
436SEC("tc")
437int 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
467SEC("tc")
468int 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
500SEC("tc")
501int 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
538SEC("tc")
539int 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
560SEC("tc")
561int 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
598SEC("tc")
599int 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
622SEC("tc")
623int 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
651SEC("tc")
652int 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
667SEC("tc")
668int 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
698SEC("tc")
699int 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
716SEC("tc")
717int 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
746SEC("tc")
747int 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
764SEC("tc")
765int 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
780char _license[] SEC("license") = "GPL";
781