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