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