blob: 9c823a609e75f8d66bbe1fa31a1ecebac7f65311 [file] [log] [blame]
William Tu6afb1e22016-08-19 11:55:44 -07001/* Copyright (c) 2016 VMware
Alexei Starovoitova1c82702016-09-15 13:00:31 -07002 * Copyright (c) 2016 Facebook
William Tu6afb1e22016-08-19 11:55:44 -07003 *
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 */
Daniel Borkmann96a8eb12016-10-26 00:37:53 +02008#define KBUILD_MODNAME "foo"
William Tu6afb1e22016-08-19 11:55:44 -07009#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>
Alexei Starovoitov173ca262016-09-15 13:00:32 -070013#include <uapi/linux/ipv6.h>
William Tu6afb1e22016-08-19 11:55:44 -070014#include <uapi/linux/in.h>
15#include <uapi/linux/tcp.h>
16#include <uapi/linux/filter.h>
17#include <uapi/linux/pkt_cls.h>
Alexei Starovoitov173ca262016-09-15 13:00:32 -070018#include <net/ipv6.h>
William Tu6afb1e22016-08-19 11:55:44 -070019#include "bpf_helpers.h"
20
Alexei Starovoitov173ca262016-09-15 13:00:32 -070021#define _htonl __builtin_bswap32
William Tu6afb1e22016-08-19 11:55:44 -070022#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
27struct 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
37struct vxlan_metadata {
38 u32 gbp;
39};
40
41SEC("gre_set_tunnel")
42int _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
62SEC("gre_get_tunnel")
63int _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
79SEC("vxlan_set_tunnel")
80int _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
108SEC("vxlan_get_tunnel")
109int _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
134SEC("geneve_set_tunnel")
135int _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 = 1;
151 gopt.r2 = 0;
152 gopt.r3 = 1;
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
171SEC("geneve_get_tunnel")
172int _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
Alexei Starovoitova1c82702016-09-15 13:00:31 -0700196SEC("ipip_set_tunnel")
197int _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
236SEC("ipip_get_tunnel")
237int _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
Alexei Starovoitov173ca262016-09-15 13:00:32 -0700253SEC("ipip6_set_tunnel")
254int _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
299SEC("ipip6_get_tunnel")
300int _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
317SEC("ip6ip6_set_tunnel")
318int _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
363SEC("ip6ip6_get_tunnel")
364int _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
William Tu6afb1e22016-08-19 11:55:44 -0700382char _license[] SEC("license") = "GPL";