blob: efdc16d195ff6e889f66104c60003a9801843831 [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>
William Tu9c33ca42018-02-05 13:35:36 -080018#include <uapi/linux/erspan.h>
Alexei Starovoitov173ca262016-09-15 13:00:32 -070019#include <net/ipv6.h>
William Tu6afb1e22016-08-19 11:55:44 -070020#include "bpf_helpers.h"
William Tuef88f892017-08-25 09:21:29 -070021#include "bpf_endian.h"
William Tu6afb1e22016-08-19 11:55:44 -070022
Alexei Starovoitov173ca262016-09-15 13:00:32 -070023#define _htonl __builtin_bswap32
William Tu6afb1e22016-08-19 11:55:44 -070024#define ERROR(ret) do {\
25 char fmt[] = "ERROR line:%d ret:%d\n";\
26 bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
27 } while(0)
28
29struct geneve_opt {
30 __be16 opt_class;
31 u8 type;
32 u8 length:5;
33 u8 r3:1;
34 u8 r2:1;
35 u8 r1:1;
36 u8 opt_data[8]; /* hard-coded to 8 byte */
37};
38
39struct vxlan_metadata {
40 u32 gbp;
41};
42
43SEC("gre_set_tunnel")
44int _gre_set_tunnel(struct __sk_buff *skb)
45{
46 int ret;
47 struct bpf_tunnel_key key;
48
49 __builtin_memset(&key, 0x0, sizeof(key));
50 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
51 key.tunnel_id = 2;
52 key.tunnel_tos = 0;
53 key.tunnel_ttl = 64;
54
55 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
56 if (ret < 0) {
57 ERROR(ret);
58 return TC_ACT_SHOT;
59 }
60
61 return TC_ACT_OK;
62}
63
64SEC("gre_get_tunnel")
65int _gre_get_tunnel(struct __sk_buff *skb)
66{
67 int ret;
68 struct bpf_tunnel_key key;
69 char fmt[] = "key %d remote ip 0x%x\n";
70
71 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
72 if (ret < 0) {
73 ERROR(ret);
74 return TC_ACT_SHOT;
75 }
76
77 bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
78 return TC_ACT_OK;
79}
80
William Tu56ddd302017-12-01 15:26:10 -080081SEC("ip6gretap_set_tunnel")
82int _ip6gretap_set_tunnel(struct __sk_buff *skb)
83{
84 struct bpf_tunnel_key key;
85 int ret;
86
87 __builtin_memset(&key, 0x0, sizeof(key));
88 key.remote_ipv6[3] = _htonl(0x11); /* ::11 */
89 key.tunnel_id = 2;
90 key.tunnel_tos = 0;
91 key.tunnel_ttl = 64;
92 key.tunnel_label = 0xabcde;
93
94 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
95 BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX);
96 if (ret < 0) {
97 ERROR(ret);
98 return TC_ACT_SHOT;
99 }
100
101 return TC_ACT_OK;
102}
103
104SEC("ip6gretap_get_tunnel")
105int _ip6gretap_get_tunnel(struct __sk_buff *skb)
106{
107 char fmt[] = "key %d remote ip6 ::%x label %x\n";
108 struct bpf_tunnel_key key;
109 int ret;
110
111 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
112 BPF_F_TUNINFO_IPV6);
113 if (ret < 0) {
114 ERROR(ret);
115 return TC_ACT_SHOT;
116 }
117
118 bpf_trace_printk(fmt, sizeof(fmt),
119 key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
120
121 return TC_ACT_OK;
122}
123
William Tuef88f892017-08-25 09:21:29 -0700124SEC("erspan_set_tunnel")
125int _erspan_set_tunnel(struct __sk_buff *skb)
126{
127 struct bpf_tunnel_key key;
128 struct erspan_metadata md;
129 int ret;
130
131 __builtin_memset(&key, 0x0, sizeof(key));
132 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
133 key.tunnel_id = 2;
134 key.tunnel_tos = 0;
135 key.tunnel_ttl = 64;
136
137 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
138 if (ret < 0) {
139 ERROR(ret);
140 return TC_ACT_SHOT;
141 }
142
William Tuac80c2a2017-12-13 16:38:58 -0800143 __builtin_memset(&md, 0, sizeof(md));
144#ifdef ERSPAN_V1
145 md.version = 1;
William Tu9c33ca42018-02-05 13:35:36 -0800146 md.u.index = bpf_htonl(123);
William Tuac80c2a2017-12-13 16:38:58 -0800147#else
148 u8 direction = 1;
William Tu9c33ca42018-02-05 13:35:36 -0800149 u8 hwid = 7;
William Tuac80c2a2017-12-13 16:38:58 -0800150
151 md.version = 2;
William Tu9c33ca42018-02-05 13:35:36 -0800152 md.u.md2.dir = direction;
153 md.u.md2.hwid = hwid & 0xf;
154 md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
William Tuac80c2a2017-12-13 16:38:58 -0800155#endif
156
William Tuef88f892017-08-25 09:21:29 -0700157 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
158 if (ret < 0) {
159 ERROR(ret);
160 return TC_ACT_SHOT;
161 }
162
163 return TC_ACT_OK;
164}
165
166SEC("erspan_get_tunnel")
167int _erspan_get_tunnel(struct __sk_buff *skb)
168{
William Tuac80c2a2017-12-13 16:38:58 -0800169 char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
William Tuef88f892017-08-25 09:21:29 -0700170 struct bpf_tunnel_key key;
171 struct erspan_metadata md;
172 u32 index;
173 int ret;
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, &md, sizeof(md));
182 if (ret < 0) {
183 ERROR(ret);
184 return TC_ACT_SHOT;
185 }
186
William Tuef88f892017-08-25 09:21:29 -0700187 bpf_trace_printk(fmt, sizeof(fmt),
William Tuac80c2a2017-12-13 16:38:58 -0800188 key.tunnel_id, key.remote_ipv4, md.version);
189
190#ifdef ERSPAN_V1
191 char fmt2[] = "\tindex %x\n";
192
193 index = bpf_ntohl(md.u.index);
194 bpf_trace_printk(fmt2, sizeof(fmt2), index);
195#else
196 char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
197
198 bpf_trace_printk(fmt2, sizeof(fmt2),
William Tu9c33ca42018-02-05 13:35:36 -0800199 md.u.md2.dir,
200 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
201 bpf_ntohl(md.u.md2.timestamp));
William Tuac80c2a2017-12-13 16:38:58 -0800202#endif
William Tuef88f892017-08-25 09:21:29 -0700203
204 return TC_ACT_OK;
205}
206
William Tud37e3bb2017-12-05 15:15:45 -0800207SEC("ip4ip6erspan_set_tunnel")
208int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
209{
210 struct bpf_tunnel_key key;
211 struct erspan_metadata md;
212 int ret;
213
214 __builtin_memset(&key, 0x0, sizeof(key));
215 key.remote_ipv6[3] = _htonl(0x11);
216 key.tunnel_id = 2;
217 key.tunnel_tos = 0;
218 key.tunnel_ttl = 64;
219
220 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
221 BPF_F_TUNINFO_IPV6);
222 if (ret < 0) {
223 ERROR(ret);
224 return TC_ACT_SHOT;
225 }
226
William Tuac80c2a2017-12-13 16:38:58 -0800227 __builtin_memset(&md, 0, sizeof(md));
228
229#ifdef ERSPAN_V1
230 md.u.index = htonl(123);
231 md.version = 1;
232#else
233 u8 direction = 0;
William Tu9c33ca42018-02-05 13:35:36 -0800234 u8 hwid = 17;
William Tuac80c2a2017-12-13 16:38:58 -0800235
236 md.version = 2;
William Tu9c33ca42018-02-05 13:35:36 -0800237 md.u.md2.dir = direction;
238 md.u.md2.hwid = hwid & 0xf;
239 md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
William Tuac80c2a2017-12-13 16:38:58 -0800240#endif
241
William Tud37e3bb2017-12-05 15:15:45 -0800242 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
243 if (ret < 0) {
244 ERROR(ret);
245 return TC_ACT_SHOT;
246 }
247
248 return TC_ACT_OK;
249}
250
251SEC("ip4ip6erspan_get_tunnel")
252int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
253{
William Tuac80c2a2017-12-13 16:38:58 -0800254 char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
William Tud37e3bb2017-12-05 15:15:45 -0800255 struct bpf_tunnel_key key;
256 struct erspan_metadata md;
257 u32 index;
258 int ret;
259
260 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
261 if (ret < 0) {
262 ERROR(ret);
263 return TC_ACT_SHOT;
264 }
265
266 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
267 if (ret < 0) {
268 ERROR(ret);
269 return TC_ACT_SHOT;
270 }
271
William Tud37e3bb2017-12-05 15:15:45 -0800272 bpf_trace_printk(fmt, sizeof(fmt),
William Tuac80c2a2017-12-13 16:38:58 -0800273 key.tunnel_id, key.remote_ipv4, md.version);
274
275#ifdef ERSPAN_V1
276 char fmt2[] = "\tindex %x\n";
277
278 index = bpf_ntohl(md.u.index);
279 bpf_trace_printk(fmt2, sizeof(fmt2), index);
280#else
281 char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
282
283 bpf_trace_printk(fmt2, sizeof(fmt2),
William Tu9c33ca42018-02-05 13:35:36 -0800284 md.u.md2.dir,
285 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
286 bpf_ntohl(md.u.md2.timestamp));
William Tuac80c2a2017-12-13 16:38:58 -0800287#endif
William Tud37e3bb2017-12-05 15:15:45 -0800288
289 return TC_ACT_OK;
290}
291
William Tu6afb1e22016-08-19 11:55:44 -0700292SEC("vxlan_set_tunnel")
293int _vxlan_set_tunnel(struct __sk_buff *skb)
294{
295 int ret;
296 struct bpf_tunnel_key key;
297 struct vxlan_metadata md;
298
299 __builtin_memset(&key, 0x0, sizeof(key));
300 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
301 key.tunnel_id = 2;
302 key.tunnel_tos = 0;
303 key.tunnel_ttl = 64;
304
305 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
306 if (ret < 0) {
307 ERROR(ret);
308 return TC_ACT_SHOT;
309 }
310
311 md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
312 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
313 if (ret < 0) {
314 ERROR(ret);
315 return TC_ACT_SHOT;
316 }
317
318 return TC_ACT_OK;
319}
320
321SEC("vxlan_get_tunnel")
322int _vxlan_get_tunnel(struct __sk_buff *skb)
323{
324 int ret;
325 struct bpf_tunnel_key key;
326 struct vxlan_metadata md;
327 char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
328
329 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
330 if (ret < 0) {
331 ERROR(ret);
332 return TC_ACT_SHOT;
333 }
334
335 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
336 if (ret < 0) {
337 ERROR(ret);
338 return TC_ACT_SHOT;
339 }
340
341 bpf_trace_printk(fmt, sizeof(fmt),
342 key.tunnel_id, key.remote_ipv4, md.gbp);
343
344 return TC_ACT_OK;
345}
346
347SEC("geneve_set_tunnel")
348int _geneve_set_tunnel(struct __sk_buff *skb)
349{
350 int ret, ret2;
351 struct bpf_tunnel_key key;
352 struct geneve_opt gopt;
353
354 __builtin_memset(&key, 0x0, sizeof(key));
355 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
356 key.tunnel_id = 2;
357 key.tunnel_tos = 0;
358 key.tunnel_ttl = 64;
359
360 __builtin_memset(&gopt, 0x0, sizeof(gopt));
361 gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
362 gopt.type = 0x08;
William Tucc75f852017-07-31 14:40:50 -0700363 gopt.r1 = 0;
William Tu6afb1e22016-08-19 11:55:44 -0700364 gopt.r2 = 0;
William Tucc75f852017-07-31 14:40:50 -0700365 gopt.r3 = 0;
William Tu6afb1e22016-08-19 11:55:44 -0700366 gopt.length = 2; /* 4-byte multiple */
367 *(int *) &gopt.opt_data = 0xdeadbeef;
368
369 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
370 if (ret < 0) {
371 ERROR(ret);
372 return TC_ACT_SHOT;
373 }
374
375 ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
376 if (ret < 0) {
377 ERROR(ret);
378 return TC_ACT_SHOT;
379 }
380
381 return TC_ACT_OK;
382}
383
384SEC("geneve_get_tunnel")
385int _geneve_get_tunnel(struct __sk_buff *skb)
386{
387 int ret;
388 struct bpf_tunnel_key key;
389 struct geneve_opt gopt;
390 char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
391
392 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
393 if (ret < 0) {
394 ERROR(ret);
395 return TC_ACT_SHOT;
396 }
397
398 ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
399 if (ret < 0) {
400 ERROR(ret);
401 return TC_ACT_SHOT;
402 }
403
404 bpf_trace_printk(fmt, sizeof(fmt),
405 key.tunnel_id, key.remote_ipv4, gopt.opt_class);
406 return TC_ACT_OK;
407}
408
Alexei Starovoitova1c82702016-09-15 13:00:31 -0700409SEC("ipip_set_tunnel")
410int _ipip_set_tunnel(struct __sk_buff *skb)
411{
412 struct bpf_tunnel_key key = {};
413 void *data = (void *)(long)skb->data;
414 struct iphdr *iph = data;
415 struct tcphdr *tcp = data + sizeof(*iph);
416 void *data_end = (void *)(long)skb->data_end;
417 int ret;
418
419 /* single length check */
420 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
421 ERROR(1);
422 return TC_ACT_SHOT;
423 }
424
425 key.tunnel_ttl = 64;
426 if (iph->protocol == IPPROTO_ICMP) {
427 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
428 } else {
429 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
430 return TC_ACT_SHOT;
431
432 if (tcp->dest == htons(5200))
433 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
434 else if (tcp->dest == htons(5201))
435 key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
436 else
437 return TC_ACT_SHOT;
438 }
439
440 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
441 if (ret < 0) {
442 ERROR(ret);
443 return TC_ACT_SHOT;
444 }
445
446 return TC_ACT_OK;
447}
448
449SEC("ipip_get_tunnel")
450int _ipip_get_tunnel(struct __sk_buff *skb)
451{
452 int ret;
453 struct bpf_tunnel_key key;
454 char fmt[] = "remote ip 0x%x\n";
455
456 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
457 if (ret < 0) {
458 ERROR(ret);
459 return TC_ACT_SHOT;
460 }
461
462 bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
463 return TC_ACT_OK;
464}
465
Alexei Starovoitov173ca262016-09-15 13:00:32 -0700466SEC("ipip6_set_tunnel")
467int _ipip6_set_tunnel(struct __sk_buff *skb)
468{
469 struct bpf_tunnel_key key = {};
470 void *data = (void *)(long)skb->data;
471 struct iphdr *iph = data;
472 struct tcphdr *tcp = data + sizeof(*iph);
473 void *data_end = (void *)(long)skb->data_end;
474 int ret;
475
476 /* single length check */
477 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
478 ERROR(1);
479 return TC_ACT_SHOT;
480 }
481
482 key.remote_ipv6[0] = _htonl(0x2401db00);
483 key.tunnel_ttl = 64;
484
485 if (iph->protocol == IPPROTO_ICMP) {
486 key.remote_ipv6[3] = _htonl(1);
487 } else {
488 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
489 ERROR(iph->protocol);
490 return TC_ACT_SHOT;
491 }
492
493 if (tcp->dest == htons(5200)) {
494 key.remote_ipv6[3] = _htonl(1);
495 } else if (tcp->dest == htons(5201)) {
496 key.remote_ipv6[3] = _htonl(2);
497 } else {
498 ERROR(tcp->dest);
499 return TC_ACT_SHOT;
500 }
501 }
502
503 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
504 if (ret < 0) {
505 ERROR(ret);
506 return TC_ACT_SHOT;
507 }
508
509 return TC_ACT_OK;
510}
511
512SEC("ipip6_get_tunnel")
513int _ipip6_get_tunnel(struct __sk_buff *skb)
514{
515 int ret;
516 struct bpf_tunnel_key key;
517 char fmt[] = "remote ip6 %x::%x\n";
518
519 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
520 if (ret < 0) {
521 ERROR(ret);
522 return TC_ACT_SHOT;
523 }
524
525 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
526 _htonl(key.remote_ipv6[3]));
527 return TC_ACT_OK;
528}
529
530SEC("ip6ip6_set_tunnel")
531int _ip6ip6_set_tunnel(struct __sk_buff *skb)
532{
533 struct bpf_tunnel_key key = {};
534 void *data = (void *)(long)skb->data;
535 struct ipv6hdr *iph = data;
536 struct tcphdr *tcp = data + sizeof(*iph);
537 void *data_end = (void *)(long)skb->data_end;
538 int ret;
539
540 /* single length check */
541 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
542 ERROR(1);
543 return TC_ACT_SHOT;
544 }
545
546 key.remote_ipv6[0] = _htonl(0x2401db00);
547 key.tunnel_ttl = 64;
548
549 if (iph->nexthdr == NEXTHDR_ICMP) {
550 key.remote_ipv6[3] = _htonl(1);
551 } else {
552 if (iph->nexthdr != NEXTHDR_TCP) {
553 ERROR(iph->nexthdr);
554 return TC_ACT_SHOT;
555 }
556
557 if (tcp->dest == htons(5200)) {
558 key.remote_ipv6[3] = _htonl(1);
559 } else if (tcp->dest == htons(5201)) {
560 key.remote_ipv6[3] = _htonl(2);
561 } else {
562 ERROR(tcp->dest);
563 return TC_ACT_SHOT;
564 }
565 }
566
567 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
568 if (ret < 0) {
569 ERROR(ret);
570 return TC_ACT_SHOT;
571 }
572
573 return TC_ACT_OK;
574}
575
576SEC("ip6ip6_get_tunnel")
577int _ip6ip6_get_tunnel(struct __sk_buff *skb)
578{
579 int ret;
580 struct bpf_tunnel_key key;
581 char fmt[] = "remote ip6 %x::%x\n";
582
583 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
584 if (ret < 0) {
585 ERROR(ret);
586 return TC_ACT_SHOT;
587 }
588
589 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
590 _htonl(key.remote_ipv6[3]));
591 return TC_ACT_OK;
592}
593
William Tu6afb1e22016-08-19 11:55:44 -0700594char _license[] SEC("license") = "GPL";