]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - samples/bpf/tcbpf2_kern.c
Merge tag 'fbdev-v4.13-rc5' of git://github.com/bzolnier/linux
[karo-tx-linux.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
21 #define _htonl __builtin_bswap32
22 #define ERROR(ret) do {\
23                 char fmt[] = "ERROR line:%d ret:%d\n";\
24                 bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
25         } while(0)
26
27 struct geneve_opt {
28         __be16  opt_class;
29         u8      type;
30         u8      length:5;
31         u8      r3:1;
32         u8      r2:1;
33         u8      r1:1;
34         u8      opt_data[8]; /* hard-coded to 8 byte */
35 };
36
37 struct vxlan_metadata {
38         u32     gbp;
39 };
40
41 SEC("gre_set_tunnel")
42 int _gre_set_tunnel(struct __sk_buff *skb)
43 {
44         int ret;
45         struct bpf_tunnel_key key;
46
47         __builtin_memset(&key, 0x0, sizeof(key));
48         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
49         key.tunnel_id = 2;
50         key.tunnel_tos = 0;
51         key.tunnel_ttl = 64;
52
53         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
54         if (ret < 0) {
55                 ERROR(ret);
56                 return TC_ACT_SHOT;
57         }
58
59         return TC_ACT_OK;
60 }
61
62 SEC("gre_get_tunnel")
63 int _gre_get_tunnel(struct __sk_buff *skb)
64 {
65         int ret;
66         struct bpf_tunnel_key key;
67         char fmt[] = "key %d remote ip 0x%x\n";
68
69         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
70         if (ret < 0) {
71                 ERROR(ret);
72                 return TC_ACT_SHOT;
73         }
74
75         bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
76         return TC_ACT_OK;
77 }
78
79 SEC("vxlan_set_tunnel")
80 int _vxlan_set_tunnel(struct __sk_buff *skb)
81 {
82         int ret;
83         struct bpf_tunnel_key key;
84         struct vxlan_metadata md;
85
86         __builtin_memset(&key, 0x0, sizeof(key));
87         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
88         key.tunnel_id = 2;
89         key.tunnel_tos = 0;
90         key.tunnel_ttl = 64;
91
92         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
93         if (ret < 0) {
94                 ERROR(ret);
95                 return TC_ACT_SHOT;
96         }
97
98         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
99         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
100         if (ret < 0) {
101                 ERROR(ret);
102                 return TC_ACT_SHOT;
103         }
104
105         return TC_ACT_OK;
106 }
107
108 SEC("vxlan_get_tunnel")
109 int _vxlan_get_tunnel(struct __sk_buff *skb)
110 {
111         int ret;
112         struct bpf_tunnel_key key;
113         struct vxlan_metadata md;
114         char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
115
116         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
117         if (ret < 0) {
118                 ERROR(ret);
119                 return TC_ACT_SHOT;
120         }
121
122         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
123         if (ret < 0) {
124                 ERROR(ret);
125                 return TC_ACT_SHOT;
126         }
127
128         bpf_trace_printk(fmt, sizeof(fmt),
129                         key.tunnel_id, key.remote_ipv4, md.gbp);
130
131         return TC_ACT_OK;
132 }
133
134 SEC("geneve_set_tunnel")
135 int _geneve_set_tunnel(struct __sk_buff *skb)
136 {
137         int ret, ret2;
138         struct bpf_tunnel_key key;
139         struct geneve_opt gopt;
140
141         __builtin_memset(&key, 0x0, sizeof(key));
142         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
143         key.tunnel_id = 2;
144         key.tunnel_tos = 0;
145         key.tunnel_ttl = 64;
146
147         __builtin_memset(&gopt, 0x0, sizeof(gopt));
148         gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
149         gopt.type = 0x08;
150         gopt.r1 = 0;
151         gopt.r2 = 0;
152         gopt.r3 = 0;
153         gopt.length = 2; /* 4-byte multiple */
154         *(int *) &gopt.opt_data = 0xdeadbeef;
155
156         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
157         if (ret < 0) {
158                 ERROR(ret);
159                 return TC_ACT_SHOT;
160         }
161
162         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
163         if (ret < 0) {
164                 ERROR(ret);
165                 return TC_ACT_SHOT;
166         }
167
168         return TC_ACT_OK;
169 }
170
171 SEC("geneve_get_tunnel")
172 int _geneve_get_tunnel(struct __sk_buff *skb)
173 {
174         int ret;
175         struct bpf_tunnel_key key;
176         struct geneve_opt gopt;
177         char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
178
179         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
180         if (ret < 0) {
181                 ERROR(ret);
182                 return TC_ACT_SHOT;
183         }
184
185         ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
186         if (ret < 0) {
187                 ERROR(ret);
188                 return TC_ACT_SHOT;
189         }
190
191         bpf_trace_printk(fmt, sizeof(fmt),
192                         key.tunnel_id, key.remote_ipv4, gopt.opt_class);
193         return TC_ACT_OK;
194 }
195
196 SEC("ipip_set_tunnel")
197 int _ipip_set_tunnel(struct __sk_buff *skb)
198 {
199         struct bpf_tunnel_key key = {};
200         void *data = (void *)(long)skb->data;
201         struct iphdr *iph = data;
202         struct tcphdr *tcp = data + sizeof(*iph);
203         void *data_end = (void *)(long)skb->data_end;
204         int ret;
205
206         /* single length check */
207         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
208                 ERROR(1);
209                 return TC_ACT_SHOT;
210         }
211
212         key.tunnel_ttl = 64;
213         if (iph->protocol == IPPROTO_ICMP) {
214                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
215         } else {
216                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
217                         return TC_ACT_SHOT;
218
219                 if (tcp->dest == htons(5200))
220                         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
221                 else if (tcp->dest == htons(5201))
222                         key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
223                 else
224                         return TC_ACT_SHOT;
225         }
226
227         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
228         if (ret < 0) {
229                 ERROR(ret);
230                 return TC_ACT_SHOT;
231         }
232
233         return TC_ACT_OK;
234 }
235
236 SEC("ipip_get_tunnel")
237 int _ipip_get_tunnel(struct __sk_buff *skb)
238 {
239         int ret;
240         struct bpf_tunnel_key key;
241         char fmt[] = "remote ip 0x%x\n";
242
243         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
244         if (ret < 0) {
245                 ERROR(ret);
246                 return TC_ACT_SHOT;
247         }
248
249         bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
250         return TC_ACT_OK;
251 }
252
253 SEC("ipip6_set_tunnel")
254 int _ipip6_set_tunnel(struct __sk_buff *skb)
255 {
256         struct bpf_tunnel_key key = {};
257         void *data = (void *)(long)skb->data;
258         struct iphdr *iph = data;
259         struct tcphdr *tcp = data + sizeof(*iph);
260         void *data_end = (void *)(long)skb->data_end;
261         int ret;
262
263         /* single length check */
264         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
265                 ERROR(1);
266                 return TC_ACT_SHOT;
267         }
268
269         key.remote_ipv6[0] = _htonl(0x2401db00);
270         key.tunnel_ttl = 64;
271
272         if (iph->protocol == IPPROTO_ICMP) {
273                 key.remote_ipv6[3] = _htonl(1);
274         } else {
275                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
276                         ERROR(iph->protocol);
277                         return TC_ACT_SHOT;
278                 }
279
280                 if (tcp->dest == htons(5200)) {
281                         key.remote_ipv6[3] = _htonl(1);
282                 } else if (tcp->dest == htons(5201)) {
283                         key.remote_ipv6[3] = _htonl(2);
284                 } else {
285                         ERROR(tcp->dest);
286                         return TC_ACT_SHOT;
287                 }
288         }
289
290         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
291         if (ret < 0) {
292                 ERROR(ret);
293                 return TC_ACT_SHOT;
294         }
295
296         return TC_ACT_OK;
297 }
298
299 SEC("ipip6_get_tunnel")
300 int _ipip6_get_tunnel(struct __sk_buff *skb)
301 {
302         int ret;
303         struct bpf_tunnel_key key;
304         char fmt[] = "remote ip6 %x::%x\n";
305
306         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
307         if (ret < 0) {
308                 ERROR(ret);
309                 return TC_ACT_SHOT;
310         }
311
312         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
313                          _htonl(key.remote_ipv6[3]));
314         return TC_ACT_OK;
315 }
316
317 SEC("ip6ip6_set_tunnel")
318 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
319 {
320         struct bpf_tunnel_key key = {};
321         void *data = (void *)(long)skb->data;
322         struct ipv6hdr *iph = data;
323         struct tcphdr *tcp = data + sizeof(*iph);
324         void *data_end = (void *)(long)skb->data_end;
325         int ret;
326
327         /* single length check */
328         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
329                 ERROR(1);
330                 return TC_ACT_SHOT;
331         }
332
333         key.remote_ipv6[0] = _htonl(0x2401db00);
334         key.tunnel_ttl = 64;
335
336         if (iph->nexthdr == NEXTHDR_ICMP) {
337                 key.remote_ipv6[3] = _htonl(1);
338         } else {
339                 if (iph->nexthdr != NEXTHDR_TCP) {
340                         ERROR(iph->nexthdr);
341                         return TC_ACT_SHOT;
342                 }
343
344                 if (tcp->dest == htons(5200)) {
345                         key.remote_ipv6[3] = _htonl(1);
346                 } else if (tcp->dest == htons(5201)) {
347                         key.remote_ipv6[3] = _htonl(2);
348                 } else {
349                         ERROR(tcp->dest);
350                         return TC_ACT_SHOT;
351                 }
352         }
353
354         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
355         if (ret < 0) {
356                 ERROR(ret);
357                 return TC_ACT_SHOT;
358         }
359
360         return TC_ACT_OK;
361 }
362
363 SEC("ip6ip6_get_tunnel")
364 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
365 {
366         int ret;
367         struct bpf_tunnel_key key;
368         char fmt[] = "remote ip6 %x::%x\n";
369
370         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
371         if (ret < 0) {
372                 ERROR(ret);
373                 return TC_ACT_SHOT;
374         }
375
376         bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
377                          _htonl(key.remote_ipv6[3]));
378         return TC_ACT_OK;
379 }
380
381
382 char _license[] SEC("license") = "GPL";