Merge tag 'wireless-drivers-next-for-davem-2018-02-08' of git://git.kernel.org/pub...
[linux-2.6-microblaze.git] / samples / bpf / tcbpf2_kern.c
1 /* Copyright (c) 2016 VMware
2  * Copyright (c) 2016 Facebook
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  */
8 #define KBUILD_MODNAME "foo"
9 #include <uapi/linux/bpf.h>
10 #include <uapi/linux/if_ether.h>
11 #include <uapi/linux/if_packet.h>
12 #include <uapi/linux/ip.h>
13 #include <uapi/linux/ipv6.h>
14 #include <uapi/linux/in.h>
15 #include <uapi/linux/tcp.h>
16 #include <uapi/linux/filter.h>
17 #include <uapi/linux/pkt_cls.h>
18 #include <uapi/linux/erspan.h>
19 #include <net/ipv6.h>
20 #include "bpf_helpers.h"
21 #include "bpf_endian.h"
22
23 #define _htonl __builtin_bswap32
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), BPF_F_ZERO_CSUM_TX);
56         if (ret < 0) {
57                 ERROR(ret);
58                 return TC_ACT_SHOT;
59         }
60
61         return TC_ACT_OK;
62 }
63
64 SEC("gre_get_tunnel")
65 int _gre_get_tunnel(struct __sk_buff *skb)
66 {
67         int ret;
68         struct bpf_tunnel_key key;
69         char fmt[] = "key %d remote ip 0x%x\n";
70
71         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
72         if (ret < 0) {
73                 ERROR(ret);
74                 return TC_ACT_SHOT;
75         }
76
77         bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
78         return TC_ACT_OK;
79 }
80
81 SEC("ip6gretap_set_tunnel")
82 int _ip6gretap_set_tunnel(struct __sk_buff *skb)
83 {
84         struct bpf_tunnel_key key;
85         int ret;
86
87         __builtin_memset(&key, 0x0, sizeof(key));
88         key.remote_ipv6[3] = _htonl(0x11); /* ::11 */
89         key.tunnel_id = 2;
90         key.tunnel_tos = 0;
91         key.tunnel_ttl = 64;
92         key.tunnel_label = 0xabcde;
93
94         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
95                                      BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX);
96         if (ret < 0) {
97                 ERROR(ret);
98                 return TC_ACT_SHOT;
99         }
100
101         return TC_ACT_OK;
102 }
103
104 SEC("ip6gretap_get_tunnel")
105 int _ip6gretap_get_tunnel(struct __sk_buff *skb)
106 {
107         char fmt[] = "key %d remote ip6 ::%x label %x\n";
108         struct bpf_tunnel_key key;
109         int ret;
110
111         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
112                                      BPF_F_TUNINFO_IPV6);
113         if (ret < 0) {
114                 ERROR(ret);
115                 return TC_ACT_SHOT;
116         }
117
118         bpf_trace_printk(fmt, sizeof(fmt),
119                          key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
120
121         return TC_ACT_OK;
122 }
123
124 SEC("erspan_set_tunnel")
125 int _erspan_set_tunnel(struct __sk_buff *skb)
126 {
127         struct bpf_tunnel_key key;
128         struct erspan_metadata md;
129         int ret;
130
131         __builtin_memset(&key, 0x0, sizeof(key));
132         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
133         key.tunnel_id = 2;
134         key.tunnel_tos = 0;
135         key.tunnel_ttl = 64;
136
137         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
138         if (ret < 0) {
139                 ERROR(ret);
140                 return TC_ACT_SHOT;
141         }
142
143         __builtin_memset(&md, 0, sizeof(md));
144 #ifdef ERSPAN_V1
145         md.version = 1;
146         md.u.index = bpf_htonl(123);
147 #else
148         u8 direction = 1;
149         u8 hwid = 7;
150
151         md.version = 2;
152         md.u.md2.dir = direction;
153         md.u.md2.hwid = hwid & 0xf;
154         md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
155 #endif
156
157         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
158         if (ret < 0) {
159                 ERROR(ret);
160                 return TC_ACT_SHOT;
161         }
162
163         return TC_ACT_OK;
164 }
165
166 SEC("erspan_get_tunnel")
167 int _erspan_get_tunnel(struct __sk_buff *skb)
168 {
169         char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
170         struct bpf_tunnel_key key;
171         struct erspan_metadata md;
172         u32 index;
173         int ret;
174
175         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
176         if (ret < 0) {
177                 ERROR(ret);
178                 return TC_ACT_SHOT;
179         }
180
181         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
182         if (ret < 0) {
183                 ERROR(ret);
184                 return TC_ACT_SHOT;
185         }
186
187         bpf_trace_printk(fmt, sizeof(fmt),
188                         key.tunnel_id, key.remote_ipv4, md.version);
189
190 #ifdef ERSPAN_V1
191         char fmt2[] = "\tindex %x\n";
192
193         index = bpf_ntohl(md.u.index);
194         bpf_trace_printk(fmt2, sizeof(fmt2), index);
195 #else
196         char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
197
198         bpf_trace_printk(fmt2, sizeof(fmt2),
199                          md.u.md2.dir,
200                          (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
201                          bpf_ntohl(md.u.md2.timestamp));
202 #endif
203
204         return TC_ACT_OK;
205 }
206
207 SEC("ip4ip6erspan_set_tunnel")
208 int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
209 {
210         struct bpf_tunnel_key key;
211         struct erspan_metadata md;
212         int ret;
213
214         __builtin_memset(&key, 0x0, sizeof(key));
215         key.remote_ipv6[3] = _htonl(0x11);
216         key.tunnel_id = 2;
217         key.tunnel_tos = 0;
218         key.tunnel_ttl = 64;
219
220         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
221                                      BPF_F_TUNINFO_IPV6);
222         if (ret < 0) {
223                 ERROR(ret);
224                 return TC_ACT_SHOT;
225         }
226
227         __builtin_memset(&md, 0, sizeof(md));
228
229 #ifdef ERSPAN_V1
230         md.u.index = htonl(123);
231         md.version = 1;
232 #else
233         u8 direction = 0;
234         u8 hwid = 17;
235
236         md.version = 2;
237         md.u.md2.dir = direction;
238         md.u.md2.hwid = hwid & 0xf;
239         md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
240 #endif
241
242         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
243         if (ret < 0) {
244                 ERROR(ret);
245                 return TC_ACT_SHOT;
246         }
247
248         return TC_ACT_OK;
249 }
250
251 SEC("ip4ip6erspan_get_tunnel")
252 int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
253 {
254         char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
255         struct bpf_tunnel_key key;
256         struct erspan_metadata md;
257         u32 index;
258         int ret;
259
260         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
261         if (ret < 0) {
262                 ERROR(ret);
263                 return TC_ACT_SHOT;
264         }
265
266         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
267         if (ret < 0) {
268                 ERROR(ret);
269                 return TC_ACT_SHOT;
270         }
271
272         bpf_trace_printk(fmt, sizeof(fmt),
273                         key.tunnel_id, key.remote_ipv4, md.version);
274
275 #ifdef ERSPAN_V1
276         char fmt2[] = "\tindex %x\n";
277
278         index = bpf_ntohl(md.u.index);
279         bpf_trace_printk(fmt2, sizeof(fmt2), index);
280 #else
281         char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
282
283         bpf_trace_printk(fmt2, sizeof(fmt2),
284                          md.u.md2.dir,
285                          (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
286                          bpf_ntohl(md.u.md2.timestamp));
287 #endif
288
289         return TC_ACT_OK;
290 }
291
292 SEC("vxlan_set_tunnel")
293 int _vxlan_set_tunnel(struct __sk_buff *skb)
294 {
295         int ret;
296         struct bpf_tunnel_key key;
297         struct vxlan_metadata md;
298
299         __builtin_memset(&key, 0x0, sizeof(key));
300         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
301         key.tunnel_id = 2;
302         key.tunnel_tos = 0;
303         key.tunnel_ttl = 64;
304
305         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
306         if (ret < 0) {
307                 ERROR(ret);
308                 return TC_ACT_SHOT;
309         }
310
311         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
312         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
313         if (ret < 0) {
314                 ERROR(ret);
315                 return TC_ACT_SHOT;
316         }
317
318         return TC_ACT_OK;
319 }
320
321 SEC("vxlan_get_tunnel")
322 int _vxlan_get_tunnel(struct __sk_buff *skb)
323 {
324         int ret;
325         struct bpf_tunnel_key key;
326         struct vxlan_metadata md;
327         char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
328
329         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
330         if (ret < 0) {
331                 ERROR(ret);
332                 return TC_ACT_SHOT;
333         }
334
335         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
336         if (ret < 0) {
337                 ERROR(ret);
338                 return TC_ACT_SHOT;
339         }
340
341         bpf_trace_printk(fmt, sizeof(fmt),
342                         key.tunnel_id, key.remote_ipv4, md.gbp);
343
344         return TC_ACT_OK;
345 }
346
347 SEC("geneve_set_tunnel")
348 int _geneve_set_tunnel(struct __sk_buff *skb)
349 {
350         int ret, ret2;
351         struct bpf_tunnel_key key;
352         struct geneve_opt gopt;
353
354         __builtin_memset(&key, 0x0, sizeof(key));
355         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
356         key.tunnel_id = 2;
357         key.tunnel_tos = 0;
358         key.tunnel_ttl = 64;
359
360         __builtin_memset(&gopt, 0x0, sizeof(gopt));
361         gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
362         gopt.type = 0x08;
363         gopt.r1 = 0;
364         gopt.r2 = 0;
365         gopt.r3 = 0;
366         gopt.length = 2; /* 4-byte multiple */
367         *(int *) &gopt.opt_data = 0xdeadbeef;
368
369         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
370         if (ret < 0) {
371                 ERROR(ret);
372                 return TC_ACT_SHOT;
373         }
374
375         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
376         if (ret < 0) {
377                 ERROR(ret);
378                 return TC_ACT_SHOT;
379         }
380
381         return TC_ACT_OK;
382 }
383
384 SEC("geneve_get_tunnel")
385 int _geneve_get_tunnel(struct __sk_buff *skb)
386 {
387         int ret;
388         struct bpf_tunnel_key key;
389         struct geneve_opt gopt;
390         char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
391
392         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
393         if (ret < 0) {
394                 ERROR(ret);
395                 return TC_ACT_SHOT;
396         }
397
398         ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
399         if (ret < 0) {
400                 ERROR(ret);
401                 return TC_ACT_SHOT;
402         }
403
404         bpf_trace_printk(fmt, sizeof(fmt),
405                         key.tunnel_id, key.remote_ipv4, gopt.opt_class);
406         return TC_ACT_OK;
407 }
408
409 SEC("ipip_set_tunnel")
410 int _ipip_set_tunnel(struct __sk_buff *skb)
411 {
412         struct bpf_tunnel_key key = {};
413         void *data = (void *)(long)skb->data;
414         struct iphdr *iph = data;
415         struct tcphdr *tcp = data + sizeof(*iph);
416         void *data_end = (void *)(long)skb->data_end;
417         int ret;
418
419         /* single length check */
420         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
421                 ERROR(1);
422                 return TC_ACT_SHOT;
423         }
424
425         key.tunnel_ttl = 64;
426         if (iph->protocol == IPPROTO_ICMP) {
427                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
428         } else {
429                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
430                         return TC_ACT_SHOT;
431
432                 if (tcp->dest == htons(5200))
433                         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
434                 else if (tcp->dest == htons(5201))
435                         key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
436                 else
437                         return TC_ACT_SHOT;
438         }
439
440         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
441         if (ret < 0) {
442                 ERROR(ret);
443                 return TC_ACT_SHOT;
444         }
445
446         return TC_ACT_OK;
447 }
448
449 SEC("ipip_get_tunnel")
450 int _ipip_get_tunnel(struct __sk_buff *skb)
451 {
452         int ret;
453         struct bpf_tunnel_key key;
454         char fmt[] = "remote ip 0x%x\n";
455
456         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
457         if (ret < 0) {
458                 ERROR(ret);
459                 return TC_ACT_SHOT;
460         }
461
462         bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
463         return TC_ACT_OK;
464 }
465
466 SEC("ipip6_set_tunnel")
467 int _ipip6_set_tunnel(struct __sk_buff *skb)
468 {
469         struct bpf_tunnel_key key = {};
470         void *data = (void *)(long)skb->data;
471         struct iphdr *iph = data;
472         struct tcphdr *tcp = data + sizeof(*iph);
473         void *data_end = (void *)(long)skb->data_end;
474         int ret;
475
476         /* single length check */
477         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
478                 ERROR(1);
479                 return TC_ACT_SHOT;
480         }
481
482         key.remote_ipv6[0] = _htonl(0x2401db00);
483         key.tunnel_ttl = 64;
484
485         if (iph->protocol == IPPROTO_ICMP) {
486                 key.remote_ipv6[3] = _htonl(1);
487         } else {
488                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
489                         ERROR(iph->protocol);
490                         return TC_ACT_SHOT;
491                 }
492
493                 if (tcp->dest == htons(5200)) {
494                         key.remote_ipv6[3] = _htonl(1);
495                 } else if (tcp->dest == htons(5201)) {
496                         key.remote_ipv6[3] = _htonl(2);
497                 } else {
498                         ERROR(tcp->dest);
499                         return TC_ACT_SHOT;
500                 }
501         }
502
503         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
504         if (ret < 0) {
505                 ERROR(ret);
506                 return TC_ACT_SHOT;
507         }
508
509         return TC_ACT_OK;
510 }
511
512 SEC("ipip6_get_tunnel")
513 int _ipip6_get_tunnel(struct __sk_buff *skb)
514 {
515         int ret;
516         struct bpf_tunnel_key key;
517         char fmt[] = "remote ip6 %x::%x\n";
518
519         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
520         if (ret < 0) {
521                 ERROR(ret);
522                 return TC_ACT_SHOT;
523         }
524
525         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
526                          _htonl(key.remote_ipv6[3]));
527         return TC_ACT_OK;
528 }
529
530 SEC("ip6ip6_set_tunnel")
531 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
532 {
533         struct bpf_tunnel_key key = {};
534         void *data = (void *)(long)skb->data;
535         struct ipv6hdr *iph = data;
536         struct tcphdr *tcp = data + sizeof(*iph);
537         void *data_end = (void *)(long)skb->data_end;
538         int ret;
539
540         /* single length check */
541         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
542                 ERROR(1);
543                 return TC_ACT_SHOT;
544         }
545
546         key.remote_ipv6[0] = _htonl(0x2401db00);
547         key.tunnel_ttl = 64;
548
549         if (iph->nexthdr == NEXTHDR_ICMP) {
550                 key.remote_ipv6[3] = _htonl(1);
551         } else {
552                 if (iph->nexthdr != NEXTHDR_TCP) {
553                         ERROR(iph->nexthdr);
554                         return TC_ACT_SHOT;
555                 }
556
557                 if (tcp->dest == htons(5200)) {
558                         key.remote_ipv6[3] = _htonl(1);
559                 } else if (tcp->dest == htons(5201)) {
560                         key.remote_ipv6[3] = _htonl(2);
561                 } else {
562                         ERROR(tcp->dest);
563                         return TC_ACT_SHOT;
564                 }
565         }
566
567         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
568         if (ret < 0) {
569                 ERROR(ret);
570                 return TC_ACT_SHOT;
571         }
572
573         return TC_ACT_OK;
574 }
575
576 SEC("ip6ip6_get_tunnel")
577 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
578 {
579         int ret;
580         struct bpf_tunnel_key key;
581         char fmt[] = "remote ip6 %x::%x\n";
582
583         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
584         if (ret < 0) {
585                 ERROR(ret);
586                 return TC_ACT_SHOT;
587         }
588
589         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
590                          _htonl(key.remote_ipv6[3]));
591         return TC_ACT_OK;
592 }
593
594 char _license[] SEC("license") = "GPL";