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 		gopt.opt_class = 0;
451 
452 	bpf_trace_printk(fmt, sizeof(fmt),
453 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
454 	return TC_ACT_OK;
455 }
456 
457 SEC("ip6geneve_set_tunnel")
458 int _ip6geneve_set_tunnel(struct __sk_buff *skb)
459 {
460 	struct bpf_tunnel_key key;
461 	struct geneve_opt gopt;
462 	int ret;
463 
464 	__builtin_memset(&key, 0x0, sizeof(key));
465 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
466 	key.tunnel_id = 22;
467 	key.tunnel_tos = 0;
468 	key.tunnel_ttl = 64;
469 
470 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
471 				     BPF_F_TUNINFO_IPV6);
472 	if (ret < 0) {
473 		ERROR(ret);
474 		return TC_ACT_SHOT;
475 	}
476 
477 	__builtin_memset(&gopt, 0x0, sizeof(gopt));
478 	gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
479 	gopt.type = 0x08;
480 	gopt.r1 = 0;
481 	gopt.r2 = 0;
482 	gopt.r3 = 0;
483 	gopt.length = 2; /* 4-byte multiple */
484 	*(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
485 
486 	ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
487 	if (ret < 0) {
488 		ERROR(ret);
489 		return TC_ACT_SHOT;
490 	}
491 
492 	return TC_ACT_OK;
493 }
494 
495 SEC("ip6geneve_get_tunnel")
496 int _ip6geneve_get_tunnel(struct __sk_buff *skb)
497 {
498 	char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
499 	struct bpf_tunnel_key key;
500 	struct geneve_opt gopt;
501 	int ret;
502 
503 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
504 				     BPF_F_TUNINFO_IPV6);
505 	if (ret < 0) {
506 		ERROR(ret);
507 		return TC_ACT_SHOT;
508 	}
509 
510 	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
511 	if (ret < 0) {
512 		ERROR(ret);
513 		return TC_ACT_SHOT;
514 	}
515 
516 	bpf_trace_printk(fmt, sizeof(fmt),
517 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
518 
519 	return TC_ACT_OK;
520 }
521 
522 SEC("ipip_set_tunnel")
523 int _ipip_set_tunnel(struct __sk_buff *skb)
524 {
525 	struct bpf_tunnel_key key = {};
526 	void *data = (void *)(long)skb->data;
527 	struct iphdr *iph = data;
528 	void *data_end = (void *)(long)skb->data_end;
529 	int ret;
530 
531 	/* single length check */
532 	if (data + sizeof(*iph) > data_end) {
533 		ERROR(1);
534 		return TC_ACT_SHOT;
535 	}
536 
537 	key.tunnel_ttl = 64;
538 	if (iph->protocol == IPPROTO_ICMP) {
539 		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
540 	}
541 
542 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
543 	if (ret < 0) {
544 		ERROR(ret);
545 		return TC_ACT_SHOT;
546 	}
547 
548 	return TC_ACT_OK;
549 }
550 
551 SEC("ipip_get_tunnel")
552 int _ipip_get_tunnel(struct __sk_buff *skb)
553 {
554 	int ret;
555 	struct bpf_tunnel_key key;
556 	char fmt[] = "remote ip 0x%x\n";
557 
558 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
559 	if (ret < 0) {
560 		ERROR(ret);
561 		return TC_ACT_SHOT;
562 	}
563 
564 	bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
565 	return TC_ACT_OK;
566 }
567 
568 SEC("ipip6_set_tunnel")
569 int _ipip6_set_tunnel(struct __sk_buff *skb)
570 {
571 	struct bpf_tunnel_key key = {};
572 	void *data = (void *)(long)skb->data;
573 	struct iphdr *iph = data;
574 	void *data_end = (void *)(long)skb->data_end;
575 	int ret;
576 
577 	/* single length check */
578 	if (data + sizeof(*iph) > data_end) {
579 		ERROR(1);
580 		return TC_ACT_SHOT;
581 	}
582 
583 	__builtin_memset(&key, 0x0, sizeof(key));
584 	key.tunnel_ttl = 64;
585 	if (iph->protocol == IPPROTO_ICMP) {
586 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
587 	}
588 
589 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
590 				     BPF_F_TUNINFO_IPV6);
591 	if (ret < 0) {
592 		ERROR(ret);
593 		return TC_ACT_SHOT;
594 	}
595 
596 	return TC_ACT_OK;
597 }
598 
599 SEC("ipip6_get_tunnel")
600 int _ipip6_get_tunnel(struct __sk_buff *skb)
601 {
602 	int ret;
603 	struct bpf_tunnel_key key;
604 	char fmt[] = "remote ip6 %x::%x\n";
605 
606 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
607 				     BPF_F_TUNINFO_IPV6);
608 	if (ret < 0) {
609 		ERROR(ret);
610 		return TC_ACT_SHOT;
611 	}
612 
613 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
614 			 bpf_htonl(key.remote_ipv6[3]));
615 	return TC_ACT_OK;
616 }
617 
618 SEC("ip6ip6_set_tunnel")
619 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
620 {
621 	struct bpf_tunnel_key key = {};
622 	void *data = (void *)(long)skb->data;
623 	struct ipv6hdr *iph = data;
624 	void *data_end = (void *)(long)skb->data_end;
625 	int ret;
626 
627 	/* single length check */
628 	if (data + sizeof(*iph) > data_end) {
629 		ERROR(1);
630 		return TC_ACT_SHOT;
631 	}
632 
633 	key.tunnel_ttl = 64;
634 	if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
635 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
636 	}
637 
638 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
639 				     BPF_F_TUNINFO_IPV6);
640 	if (ret < 0) {
641 		ERROR(ret);
642 		return TC_ACT_SHOT;
643 	}
644 
645 	return TC_ACT_OK;
646 }
647 
648 SEC("ip6ip6_get_tunnel")
649 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
650 {
651 	int ret;
652 	struct bpf_tunnel_key key;
653 	char fmt[] = "remote ip6 %x::%x\n";
654 
655 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
656 				     BPF_F_TUNINFO_IPV6);
657 	if (ret < 0) {
658 		ERROR(ret);
659 		return TC_ACT_SHOT;
660 	}
661 
662 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
663 			 bpf_htonl(key.remote_ipv6[3]));
664 	return TC_ACT_OK;
665 }
666 
667 SEC("xfrm_get_state")
668 int _xfrm_get_state(struct __sk_buff *skb)
669 {
670 	struct bpf_xfrm_state x;
671 	char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
672 	int ret;
673 
674 	ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
675 	if (ret < 0)
676 		return TC_ACT_OK;
677 
678 	bpf_trace_printk(fmt, sizeof(fmt), x.reqid, bpf_ntohl(x.spi),
679 			 bpf_ntohl(x.remote_ipv4));
680 	return TC_ACT_OK;
681 }
682 
683 char _license[] SEC("license") = "GPL";
684