GNU Linux-libre 4.14.251-gnu1
[releases.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 vxlan_metadata {
39         u32     gbp;
40 };
41
42 struct erspan_metadata {
43         __be32 index;
44 };
45
46 SEC("gre_set_tunnel")
47 int _gre_set_tunnel(struct __sk_buff *skb)
48 {
49         int ret;
50         struct bpf_tunnel_key key;
51
52         __builtin_memset(&key, 0x0, sizeof(key));
53         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
54         key.tunnel_id = 2;
55         key.tunnel_tos = 0;
56         key.tunnel_ttl = 64;
57
58         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
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("erspan_set_tunnel")
85 int _erspan_set_tunnel(struct __sk_buff *skb)
86 {
87         struct bpf_tunnel_key key;
88         struct erspan_metadata md;
89         int ret;
90
91         __builtin_memset(&key, 0x0, sizeof(key));
92         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
93         key.tunnel_id = 2;
94         key.tunnel_tos = 0;
95         key.tunnel_ttl = 64;
96
97         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
98         if (ret < 0) {
99                 ERROR(ret);
100                 return TC_ACT_SHOT;
101         }
102
103         md.index = htonl(123);
104         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
105         if (ret < 0) {
106                 ERROR(ret);
107                 return TC_ACT_SHOT;
108         }
109
110         return TC_ACT_OK;
111 }
112
113 SEC("erspan_get_tunnel")
114 int _erspan_get_tunnel(struct __sk_buff *skb)
115 {
116         char fmt[] = "key %d remote ip 0x%x erspan index 0x%x\n";
117         struct bpf_tunnel_key key;
118         struct erspan_metadata md;
119         u32 index;
120         int ret;
121
122         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
123         if (ret < 0) {
124                 ERROR(ret);
125                 return TC_ACT_SHOT;
126         }
127
128         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
129         if (ret < 0) {
130                 ERROR(ret);
131                 return TC_ACT_SHOT;
132         }
133
134         index = bpf_ntohl(md.index);
135         bpf_trace_printk(fmt, sizeof(fmt),
136                         key.tunnel_id, key.remote_ipv4, index);
137
138         return TC_ACT_OK;
139 }
140
141 SEC("vxlan_set_tunnel")
142 int _vxlan_set_tunnel(struct __sk_buff *skb)
143 {
144         int ret;
145         struct bpf_tunnel_key key;
146         struct vxlan_metadata md;
147
148         __builtin_memset(&key, 0x0, sizeof(key));
149         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
150         key.tunnel_id = 2;
151         key.tunnel_tos = 0;
152         key.tunnel_ttl = 64;
153
154         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
155         if (ret < 0) {
156                 ERROR(ret);
157                 return TC_ACT_SHOT;
158         }
159
160         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
161         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
162         if (ret < 0) {
163                 ERROR(ret);
164                 return TC_ACT_SHOT;
165         }
166
167         return TC_ACT_OK;
168 }
169
170 SEC("vxlan_get_tunnel")
171 int _vxlan_get_tunnel(struct __sk_buff *skb)
172 {
173         int ret;
174         struct bpf_tunnel_key key;
175         struct vxlan_metadata md;
176         char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
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.gbp);
192
193         return TC_ACT_OK;
194 }
195
196 SEC("geneve_set_tunnel")
197 int _geneve_set_tunnel(struct __sk_buff *skb)
198 {
199         int ret, ret2;
200         struct bpf_tunnel_key key;
201         struct geneve_opt gopt;
202
203         __builtin_memset(&key, 0x0, sizeof(key));
204         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
205         key.tunnel_id = 2;
206         key.tunnel_tos = 0;
207         key.tunnel_ttl = 64;
208
209         __builtin_memset(&gopt, 0x0, sizeof(gopt));
210         gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
211         gopt.type = 0x08;
212         gopt.r1 = 0;
213         gopt.r2 = 0;
214         gopt.r3 = 0;
215         gopt.length = 2; /* 4-byte multiple */
216         *(int *) &gopt.opt_data = 0xdeadbeef;
217
218         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
219         if (ret < 0) {
220                 ERROR(ret);
221                 return TC_ACT_SHOT;
222         }
223
224         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
225         if (ret < 0) {
226                 ERROR(ret);
227                 return TC_ACT_SHOT;
228         }
229
230         return TC_ACT_OK;
231 }
232
233 SEC("geneve_get_tunnel")
234 int _geneve_get_tunnel(struct __sk_buff *skb)
235 {
236         int ret;
237         struct bpf_tunnel_key key;
238         struct geneve_opt gopt;
239         char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
240
241         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
242         if (ret < 0) {
243                 ERROR(ret);
244                 return TC_ACT_SHOT;
245         }
246
247         ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
248         if (ret < 0) {
249                 ERROR(ret);
250                 return TC_ACT_SHOT;
251         }
252
253         bpf_trace_printk(fmt, sizeof(fmt),
254                         key.tunnel_id, key.remote_ipv4, gopt.opt_class);
255         return TC_ACT_OK;
256 }
257
258 SEC("ipip_set_tunnel")
259 int _ipip_set_tunnel(struct __sk_buff *skb)
260 {
261         struct bpf_tunnel_key key = {};
262         void *data = (void *)(long)skb->data;
263         struct iphdr *iph = data;
264         struct tcphdr *tcp = data + sizeof(*iph);
265         void *data_end = (void *)(long)skb->data_end;
266         int ret;
267
268         /* single length check */
269         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
270                 ERROR(1);
271                 return TC_ACT_SHOT;
272         }
273
274         key.tunnel_ttl = 64;
275         if (iph->protocol == IPPROTO_ICMP) {
276                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
277         } else {
278                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
279                         return TC_ACT_SHOT;
280
281                 if (tcp->dest == htons(5200))
282                         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
283                 else if (tcp->dest == htons(5201))
284                         key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
285                 else
286                         return TC_ACT_SHOT;
287         }
288
289         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
290         if (ret < 0) {
291                 ERROR(ret);
292                 return TC_ACT_SHOT;
293         }
294
295         return TC_ACT_OK;
296 }
297
298 SEC("ipip_get_tunnel")
299 int _ipip_get_tunnel(struct __sk_buff *skb)
300 {
301         int ret;
302         struct bpf_tunnel_key key;
303         char fmt[] = "remote ip 0x%x\n";
304
305         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
306         if (ret < 0) {
307                 ERROR(ret);
308                 return TC_ACT_SHOT;
309         }
310
311         bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
312         return TC_ACT_OK;
313 }
314
315 SEC("ipip6_set_tunnel")
316 int _ipip6_set_tunnel(struct __sk_buff *skb)
317 {
318         struct bpf_tunnel_key key = {};
319         void *data = (void *)(long)skb->data;
320         struct iphdr *iph = data;
321         struct tcphdr *tcp = data + sizeof(*iph);
322         void *data_end = (void *)(long)skb->data_end;
323         int ret;
324
325         /* single length check */
326         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
327                 ERROR(1);
328                 return TC_ACT_SHOT;
329         }
330
331         key.remote_ipv6[0] = _htonl(0x2401db00);
332         key.tunnel_ttl = 64;
333
334         if (iph->protocol == IPPROTO_ICMP) {
335                 key.remote_ipv6[3] = _htonl(1);
336         } else {
337                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
338                         ERROR(iph->protocol);
339                         return TC_ACT_SHOT;
340                 }
341
342                 if (tcp->dest == htons(5200)) {
343                         key.remote_ipv6[3] = _htonl(1);
344                 } else if (tcp->dest == htons(5201)) {
345                         key.remote_ipv6[3] = _htonl(2);
346                 } else {
347                         ERROR(tcp->dest);
348                         return TC_ACT_SHOT;
349                 }
350         }
351
352         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
353         if (ret < 0) {
354                 ERROR(ret);
355                 return TC_ACT_SHOT;
356         }
357
358         return TC_ACT_OK;
359 }
360
361 SEC("ipip6_get_tunnel")
362 int _ipip6_get_tunnel(struct __sk_buff *skb)
363 {
364         int ret;
365         struct bpf_tunnel_key key;
366         char fmt[] = "remote ip6 %x::%x\n";
367
368         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
369         if (ret < 0) {
370                 ERROR(ret);
371                 return TC_ACT_SHOT;
372         }
373
374         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
375                          _htonl(key.remote_ipv6[3]));
376         return TC_ACT_OK;
377 }
378
379 SEC("ip6ip6_set_tunnel")
380 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
381 {
382         struct bpf_tunnel_key key = {};
383         void *data = (void *)(long)skb->data;
384         struct ipv6hdr *iph = data;
385         struct tcphdr *tcp = data + sizeof(*iph);
386         void *data_end = (void *)(long)skb->data_end;
387         int ret;
388
389         /* single length check */
390         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
391                 ERROR(1);
392                 return TC_ACT_SHOT;
393         }
394
395         key.remote_ipv6[0] = _htonl(0x2401db00);
396         key.tunnel_ttl = 64;
397
398         if (iph->nexthdr == NEXTHDR_ICMP) {
399                 key.remote_ipv6[3] = _htonl(1);
400         } else {
401                 if (iph->nexthdr != NEXTHDR_TCP) {
402                         ERROR(iph->nexthdr);
403                         return TC_ACT_SHOT;
404                 }
405
406                 if (tcp->dest == htons(5200)) {
407                         key.remote_ipv6[3] = _htonl(1);
408                 } else if (tcp->dest == htons(5201)) {
409                         key.remote_ipv6[3] = _htonl(2);
410                 } else {
411                         ERROR(tcp->dest);
412                         return TC_ACT_SHOT;
413                 }
414         }
415
416         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
417         if (ret < 0) {
418                 ERROR(ret);
419                 return TC_ACT_SHOT;
420         }
421
422         return TC_ACT_OK;
423 }
424
425 SEC("ip6ip6_get_tunnel")
426 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
427 {
428         int ret;
429         struct bpf_tunnel_key key;
430         char fmt[] = "remote ip6 %x::%x\n";
431
432         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
433         if (ret < 0) {
434                 ERROR(ret);
435                 return TC_ACT_SHOT;
436         }
437
438         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
439                          _htonl(key.remote_ipv6[3]));
440         return TC_ACT_OK;
441 }
442
443 char _license[] SEC("license") = "GPL";