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 ERROR(ret) do {\
25 		char fmt[] = "ERROR line:%d ret:%d\n";\
26 		bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
27 	} while (0)
28 
29 int _version SEC("version") = 1;
30 
31 struct geneve_opt {
32 	__be16	opt_class;
33 	__u8	type;
34 	__u8	length:5;
35 	__u8	r3:1;
36 	__u8	r2:1;
37 	__u8	r1:1;
38 	__u8	opt_data[8]; /* hard-coded to 8 byte */
39 };
40 
41 struct vxlan_metadata {
42 	__u32     gbp;
43 };
44 
45 SEC("gre_set_tunnel")
46 int _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 		ERROR(ret);
61 		return TC_ACT_SHOT;
62 	}
63 
64 	return TC_ACT_OK;
65 }
66 
67 SEC("gre_get_tunnel")
68 int _gre_get_tunnel(struct __sk_buff *skb)
69 {
70 	int ret;
71 	struct bpf_tunnel_key key;
72 	char fmt[] = "key %d remote ip 0x%x\n";
73 
74 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
75 	if (ret < 0) {
76 		ERROR(ret);
77 		return TC_ACT_SHOT;
78 	}
79 
80 	bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
81 	return TC_ACT_OK;
82 }
83 
84 SEC("ip6gretap_set_tunnel")
85 int _ip6gretap_set_tunnel(struct __sk_buff *skb)
86 {
87 	struct bpf_tunnel_key key;
88 	int ret;
89 
90 	__builtin_memset(&key, 0x0, sizeof(key));
91 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
92 	key.tunnel_id = 2;
93 	key.tunnel_tos = 0;
94 	key.tunnel_ttl = 64;
95 	key.tunnel_label = 0xabcde;
96 
97 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
98 				     BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
99 				     BPF_F_SEQ_NUMBER);
100 	if (ret < 0) {
101 		ERROR(ret);
102 		return TC_ACT_SHOT;
103 	}
104 
105 	return TC_ACT_OK;
106 }
107 
108 SEC("ip6gretap_get_tunnel")
109 int _ip6gretap_get_tunnel(struct __sk_buff *skb)
110 {
111 	char fmt[] = "key %d remote ip6 ::%x label %x\n";
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 		ERROR(ret);
119 		return TC_ACT_SHOT;
120 	}
121 
122 	bpf_trace_printk(fmt, sizeof(fmt),
123 			 key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
124 
125 	return TC_ACT_OK;
126 }
127 
128 SEC("erspan_set_tunnel")
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 		ERROR(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 		ERROR(ret);
165 		return TC_ACT_SHOT;
166 	}
167 
168 	return TC_ACT_OK;
169 }
170 
171 SEC("erspan_get_tunnel")
172 int _erspan_get_tunnel(struct __sk_buff *skb)
173 {
174 	char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
175 	struct bpf_tunnel_key key;
176 	struct erspan_metadata md;
177 	__u32 index;
178 	int ret;
179 
180 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
181 	if (ret < 0) {
182 		ERROR(ret);
183 		return TC_ACT_SHOT;
184 	}
185 
186 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
187 	if (ret < 0) {
188 		ERROR(ret);
189 		return TC_ACT_SHOT;
190 	}
191 
192 	bpf_trace_printk(fmt, sizeof(fmt),
193 			key.tunnel_id, key.remote_ipv4, md.version);
194 
195 #ifdef ERSPAN_V1
196 	char fmt2[] = "\tindex %x\n";
197 
198 	index = bpf_ntohl(md.u.index);
199 	bpf_trace_printk(fmt2, sizeof(fmt2), index);
200 #else
201 	char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
202 
203 	bpf_trace_printk(fmt2, sizeof(fmt2),
204 			 md.u.md2.dir,
205 			 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
206 			 bpf_ntohl(md.u.md2.timestamp));
207 #endif
208 
209 	return TC_ACT_OK;
210 }
211 
212 SEC("ip4ip6erspan_set_tunnel")
213 int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
214 {
215 	struct bpf_tunnel_key key;
216 	struct erspan_metadata md;
217 	int ret;
218 
219 	__builtin_memset(&key, 0x0, sizeof(key));
220 	key.remote_ipv6[3] = bpf_htonl(0x11);
221 	key.tunnel_id = 2;
222 	key.tunnel_tos = 0;
223 	key.tunnel_ttl = 64;
224 
225 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
226 				     BPF_F_TUNINFO_IPV6);
227 	if (ret < 0) {
228 		ERROR(ret);
229 		return TC_ACT_SHOT;
230 	}
231 
232 	__builtin_memset(&md, 0, sizeof(md));
233 
234 #ifdef ERSPAN_V1
235 	md.u.index = bpf_htonl(123);
236 	md.version = 1;
237 #else
238 	__u8 direction = 0;
239 	__u8 hwid = 17;
240 
241 	md.version = 2;
242 	md.u.md2.dir = direction;
243 	md.u.md2.hwid = hwid & 0xf;
244 	md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
245 #endif
246 
247 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
248 	if (ret < 0) {
249 		ERROR(ret);
250 		return TC_ACT_SHOT;
251 	}
252 
253 	return TC_ACT_OK;
254 }
255 
256 SEC("ip4ip6erspan_get_tunnel")
257 int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
258 {
259 	char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
260 	struct bpf_tunnel_key key;
261 	struct erspan_metadata md;
262 	__u32 index;
263 	int ret;
264 
265 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
266 				     BPF_F_TUNINFO_IPV6);
267 	if (ret < 0) {
268 		ERROR(ret);
269 		return TC_ACT_SHOT;
270 	}
271 
272 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
273 	if (ret < 0) {
274 		ERROR(ret);
275 		return TC_ACT_SHOT;
276 	}
277 
278 	bpf_trace_printk(fmt, sizeof(fmt),
279 			key.tunnel_id, key.remote_ipv4, md.version);
280 
281 #ifdef ERSPAN_V1
282 	char fmt2[] = "\tindex %x\n";
283 
284 	index = bpf_ntohl(md.u.index);
285 	bpf_trace_printk(fmt2, sizeof(fmt2), index);
286 #else
287 	char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
288 
289 	bpf_trace_printk(fmt2, sizeof(fmt2),
290 			 md.u.md2.dir,
291 			 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
292 			 bpf_ntohl(md.u.md2.timestamp));
293 #endif
294 
295 	return TC_ACT_OK;
296 }
297 
298 SEC("vxlan_set_tunnel")
299 int _vxlan_set_tunnel(struct __sk_buff *skb)
300 {
301 	int ret;
302 	struct bpf_tunnel_key key;
303 	struct vxlan_metadata md;
304 
305 	__builtin_memset(&key, 0x0, sizeof(key));
306 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
307 	key.tunnel_id = 2;
308 	key.tunnel_tos = 0;
309 	key.tunnel_ttl = 64;
310 
311 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
312 				     BPF_F_ZERO_CSUM_TX);
313 	if (ret < 0) {
314 		ERROR(ret);
315 		return TC_ACT_SHOT;
316 	}
317 
318 	md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
319 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
320 	if (ret < 0) {
321 		ERROR(ret);
322 		return TC_ACT_SHOT;
323 	}
324 
325 	return TC_ACT_OK;
326 }
327 
328 SEC("vxlan_get_tunnel")
329 int _vxlan_get_tunnel(struct __sk_buff *skb)
330 {
331 	int ret;
332 	struct bpf_tunnel_key key;
333 	struct vxlan_metadata md;
334 	char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
335 
336 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
337 	if (ret < 0) {
338 		ERROR(ret);
339 		return TC_ACT_SHOT;
340 	}
341 
342 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
343 	if (ret < 0) {
344 		ERROR(ret);
345 		return TC_ACT_SHOT;
346 	}
347 
348 	bpf_trace_printk(fmt, sizeof(fmt),
349 			key.tunnel_id, key.remote_ipv4, md.gbp);
350 
351 	return TC_ACT_OK;
352 }
353 
354 SEC("ip6vxlan_set_tunnel")
355 int _ip6vxlan_set_tunnel(struct __sk_buff *skb)
356 {
357 	struct bpf_tunnel_key key;
358 	int ret;
359 
360 	__builtin_memset(&key, 0x0, sizeof(key));
361 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
362 	key.tunnel_id = 22;
363 	key.tunnel_tos = 0;
364 	key.tunnel_ttl = 64;
365 
366 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
367 				     BPF_F_TUNINFO_IPV6);
368 	if (ret < 0) {
369 		ERROR(ret);
370 		return TC_ACT_SHOT;
371 	}
372 
373 	return TC_ACT_OK;
374 }
375 
376 SEC("ip6vxlan_get_tunnel")
377 int _ip6vxlan_get_tunnel(struct __sk_buff *skb)
378 {
379 	char fmt[] = "key %d remote ip6 ::%x label %x\n";
380 	struct bpf_tunnel_key key;
381 	int ret;
382 
383 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
384 				     BPF_F_TUNINFO_IPV6);
385 	if (ret < 0) {
386 		ERROR(ret);
387 		return TC_ACT_SHOT;
388 	}
389 
390 	bpf_trace_printk(fmt, sizeof(fmt),
391 			 key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
392 
393 	return TC_ACT_OK;
394 }
395 
396 SEC("geneve_set_tunnel")
397 int _geneve_set_tunnel(struct __sk_buff *skb)
398 {
399 	int ret, ret2;
400 	struct bpf_tunnel_key key;
401 	struct geneve_opt gopt;
402 
403 	__builtin_memset(&key, 0x0, sizeof(key));
404 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
405 	key.tunnel_id = 2;
406 	key.tunnel_tos = 0;
407 	key.tunnel_ttl = 64;
408 
409 	__builtin_memset(&gopt, 0x0, sizeof(gopt));
410 	gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
411 	gopt.type = 0x08;
412 	gopt.r1 = 0;
413 	gopt.r2 = 0;
414 	gopt.r3 = 0;
415 	gopt.length = 2; /* 4-byte multiple */
416 	*(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef);
417 
418 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
419 				     BPF_F_ZERO_CSUM_TX);
420 	if (ret < 0) {
421 		ERROR(ret);
422 		return TC_ACT_SHOT;
423 	}
424 
425 	ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
426 	if (ret < 0) {
427 		ERROR(ret);
428 		return TC_ACT_SHOT;
429 	}
430 
431 	return TC_ACT_OK;
432 }
433 
434 SEC("geneve_get_tunnel")
435 int _geneve_get_tunnel(struct __sk_buff *skb)
436 {
437 	int ret;
438 	struct bpf_tunnel_key key;
439 	struct geneve_opt gopt;
440 	char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
441 
442 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
443 	if (ret < 0) {
444 		ERROR(ret);
445 		return TC_ACT_SHOT;
446 	}
447 
448 	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
449 	if (ret < 0) {
450 		ERROR(ret);
451 		return TC_ACT_SHOT;
452 	}
453 
454 	bpf_trace_printk(fmt, sizeof(fmt),
455 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
456 	return TC_ACT_OK;
457 }
458 
459 SEC("ip6geneve_set_tunnel")
460 int _ip6geneve_set_tunnel(struct __sk_buff *skb)
461 {
462 	struct bpf_tunnel_key key;
463 	struct geneve_opt gopt;
464 	int ret;
465 
466 	__builtin_memset(&key, 0x0, sizeof(key));
467 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
468 	key.tunnel_id = 22;
469 	key.tunnel_tos = 0;
470 	key.tunnel_ttl = 64;
471 
472 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
473 				     BPF_F_TUNINFO_IPV6);
474 	if (ret < 0) {
475 		ERROR(ret);
476 		return TC_ACT_SHOT;
477 	}
478 
479 	__builtin_memset(&gopt, 0x0, sizeof(gopt));
480 	gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
481 	gopt.type = 0x08;
482 	gopt.r1 = 0;
483 	gopt.r2 = 0;
484 	gopt.r3 = 0;
485 	gopt.length = 2; /* 4-byte multiple */
486 	*(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
487 
488 	ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
489 	if (ret < 0) {
490 		ERROR(ret);
491 		return TC_ACT_SHOT;
492 	}
493 
494 	return TC_ACT_OK;
495 }
496 
497 SEC("ip6geneve_get_tunnel")
498 int _ip6geneve_get_tunnel(struct __sk_buff *skb)
499 {
500 	char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
501 	struct bpf_tunnel_key key;
502 	struct geneve_opt gopt;
503 	int ret;
504 
505 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
506 				     BPF_F_TUNINFO_IPV6);
507 	if (ret < 0) {
508 		ERROR(ret);
509 		return TC_ACT_SHOT;
510 	}
511 
512 	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
513 	if (ret < 0) {
514 		ERROR(ret);
515 		return TC_ACT_SHOT;
516 	}
517 
518 	bpf_trace_printk(fmt, sizeof(fmt),
519 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
520 
521 	return TC_ACT_OK;
522 }
523 
524 SEC("ipip_set_tunnel")
525 int _ipip_set_tunnel(struct __sk_buff *skb)
526 {
527 	struct bpf_tunnel_key key = {};
528 	void *data = (void *)(long)skb->data;
529 	struct iphdr *iph = data;
530 	void *data_end = (void *)(long)skb->data_end;
531 	int ret;
532 
533 	/* single length check */
534 	if (data + sizeof(*iph) > data_end) {
535 		ERROR(1);
536 		return TC_ACT_SHOT;
537 	}
538 
539 	key.tunnel_ttl = 64;
540 	if (iph->protocol == IPPROTO_ICMP) {
541 		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
542 	}
543 
544 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
545 	if (ret < 0) {
546 		ERROR(ret);
547 		return TC_ACT_SHOT;
548 	}
549 
550 	return TC_ACT_OK;
551 }
552 
553 SEC("ipip_get_tunnel")
554 int _ipip_get_tunnel(struct __sk_buff *skb)
555 {
556 	int ret;
557 	struct bpf_tunnel_key key;
558 	char fmt[] = "remote ip 0x%x\n";
559 
560 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
561 	if (ret < 0) {
562 		ERROR(ret);
563 		return TC_ACT_SHOT;
564 	}
565 
566 	bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
567 	return TC_ACT_OK;
568 }
569 
570 SEC("ipip6_set_tunnel")
571 int _ipip6_set_tunnel(struct __sk_buff *skb)
572 {
573 	struct bpf_tunnel_key key = {};
574 	void *data = (void *)(long)skb->data;
575 	struct iphdr *iph = data;
576 	void *data_end = (void *)(long)skb->data_end;
577 	int ret;
578 
579 	/* single length check */
580 	if (data + sizeof(*iph) > data_end) {
581 		ERROR(1);
582 		return TC_ACT_SHOT;
583 	}
584 
585 	__builtin_memset(&key, 0x0, sizeof(key));
586 	key.tunnel_ttl = 64;
587 	if (iph->protocol == IPPROTO_ICMP) {
588 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
589 	}
590 
591 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
592 				     BPF_F_TUNINFO_IPV6);
593 	if (ret < 0) {
594 		ERROR(ret);
595 		return TC_ACT_SHOT;
596 	}
597 
598 	return TC_ACT_OK;
599 }
600 
601 SEC("ipip6_get_tunnel")
602 int _ipip6_get_tunnel(struct __sk_buff *skb)
603 {
604 	int ret;
605 	struct bpf_tunnel_key key;
606 	char fmt[] = "remote ip6 %x::%x\n";
607 
608 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
609 				     BPF_F_TUNINFO_IPV6);
610 	if (ret < 0) {
611 		ERROR(ret);
612 		return TC_ACT_SHOT;
613 	}
614 
615 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
616 			 bpf_htonl(key.remote_ipv6[3]));
617 	return TC_ACT_OK;
618 }
619 
620 SEC("ip6ip6_set_tunnel")
621 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
622 {
623 	struct bpf_tunnel_key key = {};
624 	void *data = (void *)(long)skb->data;
625 	struct ipv6hdr *iph = data;
626 	void *data_end = (void *)(long)skb->data_end;
627 	int ret;
628 
629 	/* single length check */
630 	if (data + sizeof(*iph) > data_end) {
631 		ERROR(1);
632 		return TC_ACT_SHOT;
633 	}
634 
635 	key.tunnel_ttl = 64;
636 	if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
637 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
638 	}
639 
640 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
641 				     BPF_F_TUNINFO_IPV6);
642 	if (ret < 0) {
643 		ERROR(ret);
644 		return TC_ACT_SHOT;
645 	}
646 
647 	return TC_ACT_OK;
648 }
649 
650 SEC("ip6ip6_get_tunnel")
651 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
652 {
653 	int ret;
654 	struct bpf_tunnel_key key;
655 	char fmt[] = "remote ip6 %x::%x\n";
656 
657 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
658 				     BPF_F_TUNINFO_IPV6);
659 	if (ret < 0) {
660 		ERROR(ret);
661 		return TC_ACT_SHOT;
662 	}
663 
664 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
665 			 bpf_htonl(key.remote_ipv6[3]));
666 	return TC_ACT_OK;
667 }
668 
669 SEC("xfrm_get_state")
670 int _xfrm_get_state(struct __sk_buff *skb)
671 {
672 	struct bpf_xfrm_state x;
673 	char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
674 	int ret;
675 
676 	ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
677 	if (ret < 0)
678 		return TC_ACT_OK;
679 
680 	bpf_trace_printk(fmt, sizeof(fmt), x.reqid, bpf_ntohl(x.spi),
681 			 bpf_ntohl(x.remote_ipv4));
682 	return TC_ACT_OK;
683 }
684 
685 char _license[] SEC("license") = "GPL";
686