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