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;
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 		gopt.opt_class = 0;
513 
514 	bpf_trace_printk(fmt, sizeof(fmt),
515 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
516 
517 	return TC_ACT_OK;
518 }
519 
520 SEC("ipip_set_tunnel")
521 int _ipip_set_tunnel(struct __sk_buff *skb)
522 {
523 	struct bpf_tunnel_key key = {};
524 	void *data = (void *)(long)skb->data;
525 	struct iphdr *iph = data;
526 	void *data_end = (void *)(long)skb->data_end;
527 	int ret;
528 
529 	/* single length check */
530 	if (data + sizeof(*iph) > data_end) {
531 		ERROR(1);
532 		return TC_ACT_SHOT;
533 	}
534 
535 	key.tunnel_ttl = 64;
536 	if (iph->protocol == IPPROTO_ICMP) {
537 		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
538 	}
539 
540 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
541 	if (ret < 0) {
542 		ERROR(ret);
543 		return TC_ACT_SHOT;
544 	}
545 
546 	return TC_ACT_OK;
547 }
548 
549 SEC("ipip_get_tunnel")
550 int _ipip_get_tunnel(struct __sk_buff *skb)
551 {
552 	int ret;
553 	struct bpf_tunnel_key key;
554 	char fmt[] = "remote ip 0x%x\n";
555 
556 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
557 	if (ret < 0) {
558 		ERROR(ret);
559 		return TC_ACT_SHOT;
560 	}
561 
562 	bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
563 	return TC_ACT_OK;
564 }
565 
566 SEC("ipip6_set_tunnel")
567 int _ipip6_set_tunnel(struct __sk_buff *skb)
568 {
569 	struct bpf_tunnel_key key = {};
570 	void *data = (void *)(long)skb->data;
571 	struct iphdr *iph = data;
572 	void *data_end = (void *)(long)skb->data_end;
573 	int ret;
574 
575 	/* single length check */
576 	if (data + sizeof(*iph) > data_end) {
577 		ERROR(1);
578 		return TC_ACT_SHOT;
579 	}
580 
581 	__builtin_memset(&key, 0x0, sizeof(key));
582 	key.tunnel_ttl = 64;
583 	if (iph->protocol == IPPROTO_ICMP) {
584 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
585 	}
586 
587 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
588 				     BPF_F_TUNINFO_IPV6);
589 	if (ret < 0) {
590 		ERROR(ret);
591 		return TC_ACT_SHOT;
592 	}
593 
594 	return TC_ACT_OK;
595 }
596 
597 SEC("ipip6_get_tunnel")
598 int _ipip6_get_tunnel(struct __sk_buff *skb)
599 {
600 	int ret;
601 	struct bpf_tunnel_key key;
602 	char fmt[] = "remote ip6 %x::%x\n";
603 
604 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
605 				     BPF_F_TUNINFO_IPV6);
606 	if (ret < 0) {
607 		ERROR(ret);
608 		return TC_ACT_SHOT;
609 	}
610 
611 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
612 			 bpf_htonl(key.remote_ipv6[3]));
613 	return TC_ACT_OK;
614 }
615 
616 SEC("ip6ip6_set_tunnel")
617 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
618 {
619 	struct bpf_tunnel_key key = {};
620 	void *data = (void *)(long)skb->data;
621 	struct ipv6hdr *iph = data;
622 	void *data_end = (void *)(long)skb->data_end;
623 	int ret;
624 
625 	/* single length check */
626 	if (data + sizeof(*iph) > data_end) {
627 		ERROR(1);
628 		return TC_ACT_SHOT;
629 	}
630 
631 	key.tunnel_ttl = 64;
632 	if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
633 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
634 	}
635 
636 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
637 				     BPF_F_TUNINFO_IPV6);
638 	if (ret < 0) {
639 		ERROR(ret);
640 		return TC_ACT_SHOT;
641 	}
642 
643 	return TC_ACT_OK;
644 }
645 
646 SEC("ip6ip6_get_tunnel")
647 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
648 {
649 	int ret;
650 	struct bpf_tunnel_key key;
651 	char fmt[] = "remote ip6 %x::%x\n";
652 
653 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
654 				     BPF_F_TUNINFO_IPV6);
655 	if (ret < 0) {
656 		ERROR(ret);
657 		return TC_ACT_SHOT;
658 	}
659 
660 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
661 			 bpf_htonl(key.remote_ipv6[3]));
662 	return TC_ACT_OK;
663 }
664 
665 SEC("xfrm_get_state")
666 int _xfrm_get_state(struct __sk_buff *skb)
667 {
668 	struct bpf_xfrm_state x;
669 	char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
670 	int ret;
671 
672 	ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
673 	if (ret < 0)
674 		return TC_ACT_OK;
675 
676 	bpf_trace_printk(fmt, sizeof(fmt), x.reqid, bpf_ntohl(x.spi),
677 			 bpf_ntohl(x.remote_ipv4));
678 	return TC_ACT_OK;
679 }
680 
681 char _license[] SEC("license") = "GPL";
682