samples/bpf: extend test_tunnel_bpf.sh with IPIP test
[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/in.h>
13 #include <uapi/linux/tcp.h>
14 #include <uapi/linux/filter.h>
15 #include <uapi/linux/pkt_cls.h>
16 #include "bpf_helpers.h"
17
18 #define ERROR(ret) do {\
19                 char fmt[] = "ERROR line:%d ret:%d\n";\
20                 bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
21         } while(0)
22
23 struct geneve_opt {
24         __be16  opt_class;
25         u8      type;
26         u8      length:5;
27         u8      r3:1;
28         u8      r2:1;
29         u8      r1:1;
30         u8      opt_data[8]; /* hard-coded to 8 byte */
31 };
32
33 struct vxlan_metadata {
34         u32     gbp;
35 };
36
37 SEC("gre_set_tunnel")
38 int _gre_set_tunnel(struct __sk_buff *skb)
39 {
40         int ret;
41         struct bpf_tunnel_key key;
42
43         __builtin_memset(&key, 0x0, sizeof(key));
44         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
45         key.tunnel_id = 2;
46         key.tunnel_tos = 0;
47         key.tunnel_ttl = 64;
48
49         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
50         if (ret < 0) {
51                 ERROR(ret);
52                 return TC_ACT_SHOT;
53         }
54
55         return TC_ACT_OK;
56 }
57
58 SEC("gre_get_tunnel")
59 int _gre_get_tunnel(struct __sk_buff *skb)
60 {
61         int ret;
62         struct bpf_tunnel_key key;
63         char fmt[] = "key %d remote ip 0x%x\n";
64
65         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
66         if (ret < 0) {
67                 ERROR(ret);
68                 return TC_ACT_SHOT;
69         }
70
71         bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
72         return TC_ACT_OK;
73 }
74
75 SEC("vxlan_set_tunnel")
76 int _vxlan_set_tunnel(struct __sk_buff *skb)
77 {
78         int ret;
79         struct bpf_tunnel_key key;
80         struct vxlan_metadata md;
81
82         __builtin_memset(&key, 0x0, sizeof(key));
83         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
84         key.tunnel_id = 2;
85         key.tunnel_tos = 0;
86         key.tunnel_ttl = 64;
87
88         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
89         if (ret < 0) {
90                 ERROR(ret);
91                 return TC_ACT_SHOT;
92         }
93
94         md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
95         ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
96         if (ret < 0) {
97                 ERROR(ret);
98                 return TC_ACT_SHOT;
99         }
100
101         return TC_ACT_OK;
102 }
103
104 SEC("vxlan_get_tunnel")
105 int _vxlan_get_tunnel(struct __sk_buff *skb)
106 {
107         int ret;
108         struct bpf_tunnel_key key;
109         struct vxlan_metadata md;
110         char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
111
112         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
113         if (ret < 0) {
114                 ERROR(ret);
115                 return TC_ACT_SHOT;
116         }
117
118         ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
119         if (ret < 0) {
120                 ERROR(ret);
121                 return TC_ACT_SHOT;
122         }
123
124         bpf_trace_printk(fmt, sizeof(fmt),
125                         key.tunnel_id, key.remote_ipv4, md.gbp);
126
127         return TC_ACT_OK;
128 }
129
130 SEC("geneve_set_tunnel")
131 int _geneve_set_tunnel(struct __sk_buff *skb)
132 {
133         int ret, ret2;
134         struct bpf_tunnel_key key;
135         struct geneve_opt gopt;
136
137         __builtin_memset(&key, 0x0, sizeof(key));
138         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
139         key.tunnel_id = 2;
140         key.tunnel_tos = 0;
141         key.tunnel_ttl = 64;
142
143         __builtin_memset(&gopt, 0x0, sizeof(gopt));
144         gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
145         gopt.type = 0x08;
146         gopt.r1 = 1;
147         gopt.r2 = 0;
148         gopt.r3 = 1;
149         gopt.length = 2; /* 4-byte multiple */
150         *(int *) &gopt.opt_data = 0xdeadbeef;
151
152         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
153         if (ret < 0) {
154                 ERROR(ret);
155                 return TC_ACT_SHOT;
156         }
157
158         ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
159         if (ret < 0) {
160                 ERROR(ret);
161                 return TC_ACT_SHOT;
162         }
163
164         return TC_ACT_OK;
165 }
166
167 SEC("geneve_get_tunnel")
168 int _geneve_get_tunnel(struct __sk_buff *skb)
169 {
170         int ret;
171         struct bpf_tunnel_key key;
172         struct geneve_opt gopt;
173         char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
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, &gopt, sizeof(gopt));
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, gopt.opt_class);
189         return TC_ACT_OK;
190 }
191
192 SEC("ipip_set_tunnel")
193 int _ipip_set_tunnel(struct __sk_buff *skb)
194 {
195         struct bpf_tunnel_key key = {};
196         void *data = (void *)(long)skb->data;
197         struct iphdr *iph = data;
198         struct tcphdr *tcp = data + sizeof(*iph);
199         void *data_end = (void *)(long)skb->data_end;
200         int ret;
201
202         /* single length check */
203         if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
204                 ERROR(1);
205                 return TC_ACT_SHOT;
206         }
207
208         key.tunnel_ttl = 64;
209         if (iph->protocol == IPPROTO_ICMP) {
210                 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
211         } else {
212                 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
213                         return TC_ACT_SHOT;
214
215                 if (tcp->dest == htons(5200))
216                         key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
217                 else if (tcp->dest == htons(5201))
218                         key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
219                 else
220                         return TC_ACT_SHOT;
221         }
222
223         ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
224         if (ret < 0) {
225                 ERROR(ret);
226                 return TC_ACT_SHOT;
227         }
228
229         return TC_ACT_OK;
230 }
231
232 SEC("ipip_get_tunnel")
233 int _ipip_get_tunnel(struct __sk_buff *skb)
234 {
235         int ret;
236         struct bpf_tunnel_key key;
237         char fmt[] = "remote ip 0x%x\n";
238
239         ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
240         if (ret < 0) {
241                 ERROR(ret);
242                 return TC_ACT_SHOT;
243         }
244
245         bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
246         return TC_ACT_OK;
247 }
248
249 char _license[] SEC("license") = "GPL";