selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / test_tunnel_kern.c
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/if_tunnel.h>
16 #include <linux/ip.h>
17 #include <linux/ipv6.h>
18 #include <linux/icmp.h>
19 #include <linux/types.h>
20 #include <linux/socket.h>
21 #include <linux/pkt_cls.h>
22 #include <linux/erspan.h>
23 #include <linux/udp.h>
24 #include <bpf/bpf_helpers.h>
25 #include <bpf/bpf_endian.h>
26
27 #define log_err(__ret) bpf_printk("ERROR line:%d ret:%d\n", __LINE__, __ret)
28
29 #define VXLAN_UDP_PORT 4789
30
31 /* Only IPv4 address assigned to veth1.
32  * 172.16.1.200
33  */
34 #define ASSIGNED_ADDR_VETH1 0xac1001c8
35
36 struct geneve_opt {
37         __be16  opt_class;
38         __u8    type;
39         __u8    length:5;
40         __u8    r3:1;
41         __u8    r2:1;
42         __u8    r1:1;
43         __u8    opt_data[8]; /* hard-coded to 8 byte */
44 };
45
46 struct vxlanhdr {
47         __be32 vx_flags;
48         __be32 vx_vni;
49 } __attribute__((packed));
50
51 struct vxlan_metadata {
52         __u32     gbp;
53 };
54
55 struct bpf_fou_encap {
56         __be16 sport;
57         __be16 dport;
58 };
59
60 enum bpf_fou_encap_type {
61         FOU_BPF_ENCAP_FOU,
62         FOU_BPF_ENCAP_GUE,
63 };
64
65 int bpf_skb_set_fou_encap(struct __sk_buff *skb_ctx,
66                           struct bpf_fou_encap *encap, int type) __ksym;
67 int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,
68                           struct bpf_fou_encap *encap) __ksym;
69
70 struct {
71         __uint(type, BPF_MAP_TYPE_ARRAY);
72         __uint(max_entries, 1);
73         __type(key, __u32);
74         __type(value, __u32);
75 } local_ip_map SEC(".maps");
76
77 SEC("tc")
78 int gre_set_tunnel(struct __sk_buff *skb)
79 {
80         int ret;
81         struct bpf_tunnel_key key;
82
83         __builtin_memset(&key, 0x0, sizeof(key));
84         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
85         key.tunnel_id = 2;
86         key.tunnel_tos = 0;
87         key.tunnel_ttl = 64;
88
89         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
90                                      BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);
91         if (ret < 0) {
92                 log_err(ret);
93                 return TC_ACT_SHOT;
94         }
95
96         return TC_ACT_OK;
97 }
98
99 SEC("tc")
100 int gre_set_tunnel_no_key(struct __sk_buff *skb)
101 {
102         int ret;
103         struct bpf_tunnel_key key;
104
105         __builtin_memset(&key, 0x0, sizeof(key));
106         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
107         key.tunnel_ttl = 64;
108
109         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
110                                      BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER |
111                                      BPF_F_NO_TUNNEL_KEY);
112         if (ret < 0) {
113                 log_err(ret);
114                 return TC_ACT_SHOT;
115         }
116
117         return TC_ACT_OK;
118 }
119
120 SEC("tc")
121 int gre_get_tunnel(struct __sk_buff *skb)
122 {
123         int ret;
124         struct bpf_tunnel_key key;
125
126         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
127         if (ret < 0) {
128                 log_err(ret);
129                 return TC_ACT_SHOT;
130         }
131
132         bpf_printk("key %d remote ip 0x%x\n", key.tunnel_id, key.remote_ipv4);
133         return TC_ACT_OK;
134 }
135
136 SEC("tc")
137 int ip6gretap_set_tunnel(struct __sk_buff *skb)
138 {
139         struct bpf_tunnel_key key;
140         int ret;
141
142         __builtin_memset(&key, 0x0, sizeof(key));
143         key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
144         key.tunnel_id = 2;
145         key.tunnel_tos = 0;
146         key.tunnel_ttl = 64;
147         key.tunnel_label = 0xabcde;
148
149         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
150                                      BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
151                                      BPF_F_SEQ_NUMBER);
152         if (ret < 0) {
153                 log_err(ret);
154                 return TC_ACT_SHOT;
155         }
156
157         return TC_ACT_OK;
158 }
159
160 SEC("tc")
161 int ip6gretap_get_tunnel(struct __sk_buff *skb)
162 {
163         struct bpf_tunnel_key key;
164         int ret;
165
166         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
167                                      BPF_F_TUNINFO_IPV6);
168         if (ret < 0) {
169                 log_err(ret);
170                 return TC_ACT_SHOT;
171         }
172
173         bpf_printk("key %d remote ip6 ::%x label %x\n",
174                    key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
175
176         return TC_ACT_OK;
177 }
178
179 SEC("tc")
180 int erspan_set_tunnel(struct __sk_buff *skb)
181 {
182         struct bpf_tunnel_key key;
183         struct erspan_metadata md;
184         int ret;
185
186         __builtin_memset(&key, 0x0, sizeof(key));
187         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
188         key.tunnel_id = 2;
189         key.tunnel_tos = 0;
190         key.tunnel_ttl = 64;
191
192         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
193                                      BPF_F_ZERO_CSUM_TX);
194         if (ret < 0) {
195                 log_err(ret);
196                 return TC_ACT_SHOT;
197         }
198
199         __builtin_memset(&md, 0, sizeof(md));
200 #ifdef ERSPAN_V1
201         md.version = 1;
202         md.u.index = bpf_htonl(123);
203 #else
204         __u8 direction = 1;
205         __u8 hwid = 7;
206
207         md.version = 2;
208         md.u.md2.dir = direction;
209         md.u.md2.hwid = hwid & 0xf;
210         md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
211 #endif
212
213         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
214         if (ret < 0) {
215                 log_err(ret);
216                 return TC_ACT_SHOT;
217         }
218
219         return TC_ACT_OK;
220 }
221
222 SEC("tc")
223 int erspan_get_tunnel(struct __sk_buff *skb)
224 {
225         struct bpf_tunnel_key key;
226         struct erspan_metadata md;
227         int ret;
228
229         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
230         if (ret < 0) {
231                 log_err(ret);
232                 return TC_ACT_SHOT;
233         }
234
235         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
236         if (ret < 0) {
237                 log_err(ret);
238                 return TC_ACT_SHOT;
239         }
240
241         bpf_printk("key %d remote ip 0x%x erspan version %d\n",
242                    key.tunnel_id, key.remote_ipv4, md.version);
243
244 #ifdef ERSPAN_V1
245         index = bpf_ntohl(md.u.index);
246         bpf_printk("\tindex %x\n", index);
247 #else
248         bpf_printk("\tdirection %d hwid %x timestamp %u\n",
249                    md.u.md2.dir,
250                    (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
251                    bpf_ntohl(md.u.md2.timestamp));
252 #endif
253
254         return TC_ACT_OK;
255 }
256
257 SEC("tc")
258 int ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
259 {
260         struct bpf_tunnel_key key;
261         struct erspan_metadata md;
262         int ret;
263
264         __builtin_memset(&key, 0x0, sizeof(key));
265         key.remote_ipv6[3] = bpf_htonl(0x11);
266         key.tunnel_id = 2;
267         key.tunnel_tos = 0;
268         key.tunnel_ttl = 64;
269
270         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
271                                      BPF_F_TUNINFO_IPV6);
272         if (ret < 0) {
273                 log_err(ret);
274                 return TC_ACT_SHOT;
275         }
276
277         __builtin_memset(&md, 0, sizeof(md));
278
279 #ifdef ERSPAN_V1
280         md.u.index = bpf_htonl(123);
281         md.version = 1;
282 #else
283         __u8 direction = 0;
284         __u8 hwid = 17;
285
286         md.version = 2;
287         md.u.md2.dir = direction;
288         md.u.md2.hwid = hwid & 0xf;
289         md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
290 #endif
291
292         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
293         if (ret < 0) {
294                 log_err(ret);
295                 return TC_ACT_SHOT;
296         }
297
298         return TC_ACT_OK;
299 }
300
301 SEC("tc")
302 int ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
303 {
304         struct bpf_tunnel_key key;
305         struct erspan_metadata md;
306         int ret;
307
308         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
309                                      BPF_F_TUNINFO_IPV6);
310         if (ret < 0) {
311                 log_err(ret);
312                 return TC_ACT_SHOT;
313         }
314
315         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
316         if (ret < 0) {
317                 log_err(ret);
318                 return TC_ACT_SHOT;
319         }
320
321         bpf_printk("ip6erspan get key %d remote ip6 ::%x erspan version %d\n",
322                    key.tunnel_id, key.remote_ipv4, md.version);
323
324 #ifdef ERSPAN_V1
325         index = bpf_ntohl(md.u.index);
326         bpf_printk("\tindex %x\n", index);
327 #else
328         bpf_printk("\tdirection %d hwid %x timestamp %u\n",
329                    md.u.md2.dir,
330                    (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
331                    bpf_ntohl(md.u.md2.timestamp));
332 #endif
333
334         return TC_ACT_OK;
335 }
336
337 SEC("tc")
338 int vxlan_set_tunnel_dst(struct __sk_buff *skb)
339 {
340         struct bpf_tunnel_key key;
341         struct vxlan_metadata md;
342         __u32 index = 0;
343         __u32 *local_ip = NULL;
344         int ret = 0;
345
346         local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
347         if (!local_ip) {
348                 log_err(ret);
349                 return TC_ACT_SHOT;
350         }
351
352         __builtin_memset(&key, 0x0, sizeof(key));
353         key.local_ipv4 = 0xac100164; /* 172.16.1.100 */
354         key.remote_ipv4 = *local_ip;
355         key.tunnel_id = 2;
356         key.tunnel_tos = 0;
357         key.tunnel_ttl = 64;
358
359         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
360                                      BPF_F_ZERO_CSUM_TX);
361         if (ret < 0) {
362                 log_err(ret);
363                 return TC_ACT_SHOT;
364         }
365
366         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
367         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
368         if (ret < 0) {
369                 log_err(ret);
370                 return TC_ACT_SHOT;
371         }
372
373         return TC_ACT_OK;
374 }
375
376 SEC("tc")
377 int vxlan_set_tunnel_src(struct __sk_buff *skb)
378 {
379         struct bpf_tunnel_key key;
380         struct vxlan_metadata md;
381         __u32 index = 0;
382         __u32 *local_ip = NULL;
383         int ret = 0;
384
385         local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
386         if (!local_ip) {
387                 log_err(ret);
388                 return TC_ACT_SHOT;
389         }
390
391         __builtin_memset(&key, 0x0, sizeof(key));
392         key.local_ipv4 = *local_ip;
393         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
394         key.tunnel_id = 2;
395         key.tunnel_tos = 0;
396         key.tunnel_ttl = 64;
397
398         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
399                                      BPF_F_ZERO_CSUM_TX);
400         if (ret < 0) {
401                 log_err(ret);
402                 return TC_ACT_SHOT;
403         }
404
405         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
406         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
407         if (ret < 0) {
408                 log_err(ret);
409                 return TC_ACT_SHOT;
410         }
411
412         return TC_ACT_OK;
413 }
414
415 SEC("tc")
416 int vxlan_get_tunnel_src(struct __sk_buff *skb)
417 {
418         int ret;
419         struct bpf_tunnel_key key;
420         struct vxlan_metadata md;
421
422         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
423                                      BPF_F_TUNINFO_FLAGS);
424         if (ret < 0) {
425                 log_err(ret);
426                 return TC_ACT_SHOT;
427         }
428
429         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
430         if (ret < 0) {
431                 log_err(ret);
432                 return TC_ACT_SHOT;
433         }
434
435         if (key.local_ipv4 != ASSIGNED_ADDR_VETH1 || md.gbp != 0x800FF ||
436             !(key.tunnel_flags & TUNNEL_KEY) ||
437             (key.tunnel_flags & TUNNEL_CSUM)) {
438                 bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x flags 0x%x\n",
439                            key.tunnel_id, key.local_ipv4,
440                            key.remote_ipv4, md.gbp,
441                            bpf_ntohs(key.tunnel_flags));
442                 log_err(ret);
443                 return TC_ACT_SHOT;
444         }
445
446         return TC_ACT_OK;
447 }
448
449 SEC("tc")
450 int veth_set_outer_dst(struct __sk_buff *skb)
451 {
452         struct ethhdr *eth = (struct ethhdr *)(long)skb->data;
453         __u32 assigned_ip = bpf_htonl(ASSIGNED_ADDR_VETH1);
454         void *data_end = (void *)(long)skb->data_end;
455         struct udphdr *udph;
456         struct iphdr *iph;
457         int ret = 0;
458         __s64 csum;
459
460         if ((void *)eth + sizeof(*eth) > data_end) {
461                 log_err(ret);
462                 return TC_ACT_SHOT;
463         }
464
465         if (eth->h_proto != bpf_htons(ETH_P_IP))
466                 return TC_ACT_OK;
467
468         iph = (struct iphdr *)(eth + 1);
469         if ((void *)iph + sizeof(*iph) > data_end) {
470                 log_err(ret);
471                 return TC_ACT_SHOT;
472         }
473         if (iph->protocol != IPPROTO_UDP)
474                 return TC_ACT_OK;
475
476         udph = (struct udphdr *)(iph + 1);
477         if ((void *)udph + sizeof(*udph) > data_end) {
478                 log_err(ret);
479                 return TC_ACT_SHOT;
480         }
481         if (udph->dest != bpf_htons(VXLAN_UDP_PORT))
482                 return TC_ACT_OK;
483
484         if (iph->daddr != assigned_ip) {
485                 csum = bpf_csum_diff(&iph->daddr, sizeof(__u32), &assigned_ip,
486                                      sizeof(__u32), 0);
487                 if (bpf_skb_store_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr),
488                                         &assigned_ip, sizeof(__u32), 0) < 0) {
489                         log_err(ret);
490                         return TC_ACT_SHOT;
491                 }
492                 if (bpf_l3_csum_replace(skb, ETH_HLEN + offsetof(struct iphdr, check),
493                                         0, csum, 0) < 0) {
494                         log_err(ret);
495                         return TC_ACT_SHOT;
496                 }
497                 bpf_skb_change_type(skb, PACKET_HOST);
498         }
499         return TC_ACT_OK;
500 }
501
502 SEC("tc")
503 int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb)
504 {
505         struct bpf_tunnel_key key;
506         __u32 index = 0;
507         __u32 *local_ip;
508         int ret = 0;
509
510         local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
511         if (!local_ip) {
512                 log_err(ret);
513                 return TC_ACT_SHOT;
514         }
515
516         __builtin_memset(&key, 0x0, sizeof(key));
517         key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */
518         key.remote_ipv6[3] = bpf_htonl(*local_ip);
519         key.tunnel_id = 22;
520         key.tunnel_tos = 0;
521         key.tunnel_ttl = 64;
522
523         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
524                                      BPF_F_TUNINFO_IPV6);
525         if (ret < 0) {
526                 log_err(ret);
527                 return TC_ACT_SHOT;
528         }
529
530         return TC_ACT_OK;
531 }
532
533 SEC("tc")
534 int ip6vxlan_set_tunnel_src(struct __sk_buff *skb)
535 {
536         struct bpf_tunnel_key key;
537         __u32 index = 0;
538         __u32 *local_ip;
539         int ret = 0;
540
541         local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
542         if (!local_ip) {
543                 log_err(ret);
544                 return TC_ACT_SHOT;
545         }
546
547         __builtin_memset(&key, 0x0, sizeof(key));
548         key.local_ipv6[3] = bpf_htonl(*local_ip);
549         key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
550         key.tunnel_id = 22;
551         key.tunnel_tos = 0;
552         key.tunnel_ttl = 64;
553
554         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
555                                      BPF_F_TUNINFO_IPV6);
556         if (ret < 0) {
557                 log_err(ret);
558                 return TC_ACT_SHOT;
559         }
560
561         return TC_ACT_OK;
562 }
563
564 SEC("tc")
565 int ip6vxlan_get_tunnel_src(struct __sk_buff *skb)
566 {
567         struct bpf_tunnel_key key;
568         __u32 index = 0;
569         __u32 *local_ip;
570         int ret = 0;
571
572         local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
573         if (!local_ip) {
574                 log_err(ret);
575                 return TC_ACT_SHOT;
576         }
577
578         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
579                                      BPF_F_TUNINFO_IPV6 | BPF_F_TUNINFO_FLAGS);
580         if (ret < 0) {
581                 log_err(ret);
582                 return TC_ACT_SHOT;
583         }
584
585         if (bpf_ntohl(key.local_ipv6[3]) != *local_ip ||
586             !(key.tunnel_flags & TUNNEL_KEY) ||
587             !(key.tunnel_flags & TUNNEL_CSUM)) {
588                 bpf_printk("ip6vxlan key %d local ip6 ::%x remote ip6 ::%x label 0x%x flags 0x%x\n",
589                            key.tunnel_id, bpf_ntohl(key.local_ipv6[3]),
590                            bpf_ntohl(key.remote_ipv6[3]), key.tunnel_label,
591                            bpf_ntohs(key.tunnel_flags));
592                 bpf_printk("local_ip 0x%x\n", *local_ip);
593                 log_err(ret);
594                 return TC_ACT_SHOT;
595         }
596
597         return TC_ACT_OK;
598 }
599
600 SEC("tc")
601 int geneve_set_tunnel(struct __sk_buff *skb)
602 {
603         int ret;
604         struct bpf_tunnel_key key;
605         struct geneve_opt gopt;
606
607         __builtin_memset(&key, 0x0, sizeof(key));
608         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
609         key.tunnel_id = 2;
610         key.tunnel_tos = 0;
611         key.tunnel_ttl = 64;
612
613         __builtin_memset(&gopt, 0x0, sizeof(gopt));
614         gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
615         gopt.type = 0x08;
616         gopt.r1 = 0;
617         gopt.r2 = 0;
618         gopt.r3 = 0;
619         gopt.length = 2; /* 4-byte multiple */
620         *(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef);
621
622         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
623                                      BPF_F_ZERO_CSUM_TX);
624         if (ret < 0) {
625                 log_err(ret);
626                 return TC_ACT_SHOT;
627         }
628
629         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
630         if (ret < 0) {
631                 log_err(ret);
632                 return TC_ACT_SHOT;
633         }
634
635         return TC_ACT_OK;
636 }
637
638 SEC("tc")
639 int geneve_get_tunnel(struct __sk_buff *skb)
640 {
641         int ret;
642         struct bpf_tunnel_key key;
643         struct geneve_opt gopt;
644
645         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
646         if (ret < 0) {
647                 log_err(ret);
648                 return TC_ACT_SHOT;
649         }
650
651         ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
652         if (ret < 0)
653                 gopt.opt_class = 0;
654
655         bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",
656                    key.tunnel_id, key.remote_ipv4, gopt.opt_class);
657         return TC_ACT_OK;
658 }
659
660 SEC("tc")
661 int ip6geneve_set_tunnel(struct __sk_buff *skb)
662 {
663         struct bpf_tunnel_key key;
664         struct geneve_opt gopt;
665         int ret;
666
667         __builtin_memset(&key, 0x0, sizeof(key));
668         key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
669         key.tunnel_id = 22;
670         key.tunnel_tos = 0;
671         key.tunnel_ttl = 64;
672
673         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
674                                      BPF_F_TUNINFO_IPV6);
675         if (ret < 0) {
676                 log_err(ret);
677                 return TC_ACT_SHOT;
678         }
679
680         __builtin_memset(&gopt, 0x0, sizeof(gopt));
681         gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
682         gopt.type = 0x08;
683         gopt.r1 = 0;
684         gopt.r2 = 0;
685         gopt.r3 = 0;
686         gopt.length = 2; /* 4-byte multiple */
687         *(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
688
689         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
690         if (ret < 0) {
691                 log_err(ret);
692                 return TC_ACT_SHOT;
693         }
694
695         return TC_ACT_OK;
696 }
697
698 SEC("tc")
699 int ip6geneve_get_tunnel(struct __sk_buff *skb)
700 {
701         struct bpf_tunnel_key key;
702         struct geneve_opt gopt;
703         int ret;
704
705         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
706                                      BPF_F_TUNINFO_IPV6);
707         if (ret < 0) {
708                 log_err(ret);
709                 return TC_ACT_SHOT;
710         }
711
712         ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
713         if (ret < 0)
714                 gopt.opt_class = 0;
715
716         bpf_printk("key %d remote ip 0x%x geneve class 0x%x\n",
717                    key.tunnel_id, key.remote_ipv4, gopt.opt_class);
718
719         return TC_ACT_OK;
720 }
721
722 SEC("tc")
723 int ipip_set_tunnel(struct __sk_buff *skb)
724 {
725         struct bpf_tunnel_key key = {};
726         void *data = (void *)(long)skb->data;
727         struct iphdr *iph = data;
728         void *data_end = (void *)(long)skb->data_end;
729         int ret;
730
731         /* single length check */
732         if (data + sizeof(*iph) > data_end) {
733                 log_err(1);
734                 return TC_ACT_SHOT;
735         }
736
737         key.tunnel_ttl = 64;
738         if (iph->protocol == IPPROTO_ICMP) {
739                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
740         }
741
742         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
743         if (ret < 0) {
744                 log_err(ret);
745                 return TC_ACT_SHOT;
746         }
747
748         return TC_ACT_OK;
749 }
750
751 SEC("tc")
752 int ipip_get_tunnel(struct __sk_buff *skb)
753 {
754         int ret;
755         struct bpf_tunnel_key key;
756
757         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
758         if (ret < 0) {
759                 log_err(ret);
760                 return TC_ACT_SHOT;
761         }
762
763         bpf_printk("remote ip 0x%x\n", key.remote_ipv4);
764         return TC_ACT_OK;
765 }
766
767 SEC("tc")
768 int ipip_gue_set_tunnel(struct __sk_buff *skb)
769 {
770         struct bpf_tunnel_key key = {};
771         struct bpf_fou_encap encap = {};
772         void *data = (void *)(long)skb->data;
773         struct iphdr *iph = data;
774         void *data_end = (void *)(long)skb->data_end;
775         int ret;
776
777         if (data + sizeof(*iph) > data_end) {
778                 log_err(1);
779                 return TC_ACT_SHOT;
780         }
781
782         key.tunnel_ttl = 64;
783         if (iph->protocol == IPPROTO_ICMP)
784                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
785
786         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
787         if (ret < 0) {
788                 log_err(ret);
789                 return TC_ACT_SHOT;
790         }
791
792         encap.sport = 0;
793         encap.dport = bpf_htons(5555);
794
795         ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_GUE);
796         if (ret < 0) {
797                 log_err(ret);
798                 return TC_ACT_SHOT;
799         }
800
801         return TC_ACT_OK;
802 }
803
804 SEC("tc")
805 int ipip_fou_set_tunnel(struct __sk_buff *skb)
806 {
807         struct bpf_tunnel_key key = {};
808         struct bpf_fou_encap encap = {};
809         void *data = (void *)(long)skb->data;
810         struct iphdr *iph = data;
811         void *data_end = (void *)(long)skb->data_end;
812         int ret;
813
814         if (data + sizeof(*iph) > data_end) {
815                 log_err(1);
816                 return TC_ACT_SHOT;
817         }
818
819         key.tunnel_ttl = 64;
820         if (iph->protocol == IPPROTO_ICMP)
821                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
822
823         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
824         if (ret < 0) {
825                 log_err(ret);
826                 return TC_ACT_SHOT;
827         }
828
829         encap.sport = 0;
830         encap.dport = bpf_htons(5555);
831
832         ret = bpf_skb_set_fou_encap(skb, &encap, FOU_BPF_ENCAP_FOU);
833         if (ret < 0) {
834                 log_err(ret);
835                 return TC_ACT_SHOT;
836         }
837
838         return TC_ACT_OK;
839 }
840
841 SEC("tc")
842 int ipip_encap_get_tunnel(struct __sk_buff *skb)
843 {
844         int ret;
845         struct bpf_tunnel_key key = {};
846         struct bpf_fou_encap encap = {};
847
848         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
849         if (ret < 0) {
850                 log_err(ret);
851                 return TC_ACT_SHOT;
852         }
853
854         ret = bpf_skb_get_fou_encap(skb, &encap);
855         if (ret < 0) {
856                 log_err(ret);
857                 return TC_ACT_SHOT;
858         }
859
860         if (bpf_ntohs(encap.dport) != 5555)
861                 return TC_ACT_SHOT;
862
863         bpf_printk("%d remote ip 0x%x, sport %d, dport %d\n", ret,
864                    key.remote_ipv4, bpf_ntohs(encap.sport),
865                    bpf_ntohs(encap.dport));
866         return TC_ACT_OK;
867 }
868
869 SEC("tc")
870 int ipip6_set_tunnel(struct __sk_buff *skb)
871 {
872         struct bpf_tunnel_key key = {};
873         void *data = (void *)(long)skb->data;
874         struct iphdr *iph = data;
875         void *data_end = (void *)(long)skb->data_end;
876         int ret;
877
878         /* single length check */
879         if (data + sizeof(*iph) > data_end) {
880                 log_err(1);
881                 return TC_ACT_SHOT;
882         }
883
884         __builtin_memset(&key, 0x0, sizeof(key));
885         key.tunnel_ttl = 64;
886         if (iph->protocol == IPPROTO_ICMP) {
887                 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
888         }
889
890         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
891                                      BPF_F_TUNINFO_IPV6);
892         if (ret < 0) {
893                 log_err(ret);
894                 return TC_ACT_SHOT;
895         }
896
897         return TC_ACT_OK;
898 }
899
900 SEC("tc")
901 int ipip6_get_tunnel(struct __sk_buff *skb)
902 {
903         int ret;
904         struct bpf_tunnel_key key;
905
906         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
907                                      BPF_F_TUNINFO_IPV6);
908         if (ret < 0) {
909                 log_err(ret);
910                 return TC_ACT_SHOT;
911         }
912
913         bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),
914                    bpf_htonl(key.remote_ipv6[3]));
915         return TC_ACT_OK;
916 }
917
918 SEC("tc")
919 int ip6ip6_set_tunnel(struct __sk_buff *skb)
920 {
921         struct bpf_tunnel_key key = {};
922         void *data = (void *)(long)skb->data;
923         struct ipv6hdr *iph = data;
924         void *data_end = (void *)(long)skb->data_end;
925         int ret;
926
927         /* single length check */
928         if (data + sizeof(*iph) > data_end) {
929                 log_err(1);
930                 return TC_ACT_SHOT;
931         }
932
933         key.tunnel_ttl = 64;
934         if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
935                 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
936         }
937
938         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
939                                      BPF_F_TUNINFO_IPV6);
940         if (ret < 0) {
941                 log_err(ret);
942                 return TC_ACT_SHOT;
943         }
944
945         return TC_ACT_OK;
946 }
947
948 SEC("tc")
949 int ip6ip6_get_tunnel(struct __sk_buff *skb)
950 {
951         int ret;
952         struct bpf_tunnel_key key;
953
954         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
955                                      BPF_F_TUNINFO_IPV6);
956         if (ret < 0) {
957                 log_err(ret);
958                 return TC_ACT_SHOT;
959         }
960
961         bpf_printk("remote ip6 %x::%x\n", bpf_htonl(key.remote_ipv6[0]),
962                    bpf_htonl(key.remote_ipv6[3]));
963         return TC_ACT_OK;
964 }
965
966 SEC("tc")
967 int xfrm_get_state(struct __sk_buff *skb)
968 {
969         struct bpf_xfrm_state x;
970         int ret;
971
972         ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
973         if (ret < 0)
974                 return TC_ACT_OK;
975
976         bpf_printk("reqid %d spi 0x%x remote ip 0x%x\n",
977                    x.reqid, bpf_ntohl(x.spi),
978                    bpf_ntohl(x.remote_ipv4));
979         return TC_ACT_OK;
980 }
981
982 char _license[] SEC("license") = "GPL";