1 /* Copyright (c) 2016 VMware
2 * Copyright (c) 2016 Facebook
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.
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>
18 #include "bpf_helpers.h"
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); \
33 u8 opt_data[8]; /* hard-coded to 8 byte */
36 struct vxlan_metadata {
41 int _gre_set_tunnel(struct __sk_buff *skb)
44 struct bpf_tunnel_key key;
46 __builtin_memset(&key, 0x0, sizeof(key));
47 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
52 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
62 int _gre_get_tunnel(struct __sk_buff *skb)
65 struct bpf_tunnel_key key;
66 char fmt[] = "key %d remote ip 0x%x\n";
68 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
74 bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
78 SEC("vxlan_set_tunnel")
79 int _vxlan_set_tunnel(struct __sk_buff *skb)
82 struct bpf_tunnel_key key;
83 struct vxlan_metadata md;
85 __builtin_memset(&key, 0x0, sizeof(key));
86 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
91 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
97 md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
98 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
107 SEC("vxlan_get_tunnel")
108 int _vxlan_get_tunnel(struct __sk_buff *skb)
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";
115 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
121 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
127 bpf_trace_printk(fmt, sizeof(fmt),
128 key.tunnel_id, key.remote_ipv4, md.gbp);
133 SEC("geneve_set_tunnel")
134 int _geneve_set_tunnel(struct __sk_buff *skb)
137 struct bpf_tunnel_key key;
138 struct geneve_opt gopt;
140 __builtin_memset(&key, 0x0, sizeof(key));
141 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
146 __builtin_memset(&gopt, 0x0, sizeof(gopt));
147 gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
152 gopt.length = 2; /* 4-byte multiple */
153 *(int *) &gopt.opt_data = 0xdeadbeef;
155 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
161 ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
170 SEC("geneve_get_tunnel")
171 int _geneve_get_tunnel(struct __sk_buff *skb)
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";
178 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
184 ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
190 bpf_trace_printk(fmt, sizeof(fmt),
191 key.tunnel_id, key.remote_ipv4, gopt.opt_class);
195 SEC("ipip_set_tunnel")
196 int _ipip_set_tunnel(struct __sk_buff *skb)
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;
205 /* single length check */
206 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
212 if (iph->protocol == IPPROTO_ICMP) {
213 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
215 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
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 */
226 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
235 SEC("ipip_get_tunnel")
236 int _ipip_get_tunnel(struct __sk_buff *skb)
239 struct bpf_tunnel_key key;
240 char fmt[] = "remote ip 0x%x\n";
242 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
248 bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
252 SEC("ipip6_set_tunnel")
253 int _ipip6_set_tunnel(struct __sk_buff *skb)
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;
262 /* single length check */
263 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
268 key.remote_ipv6[0] = _htonl(0x2401db00);
271 if (iph->protocol == IPPROTO_ICMP) {
272 key.remote_ipv6[3] = _htonl(1);
274 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
275 ERROR(iph->protocol);
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);
289 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
298 SEC("ipip6_get_tunnel")
299 int _ipip6_get_tunnel(struct __sk_buff *skb)
302 struct bpf_tunnel_key key;
303 char fmt[] = "remote ip6 %x::%x\n";
305 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
311 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
312 _htonl(key.remote_ipv6[3]));
316 SEC("ip6ip6_set_tunnel")
317 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
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;
326 /* single length check */
327 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
332 key.remote_ipv6[0] = _htonl(0x2401db00);
335 if (iph->nexthdr == NEXTHDR_ICMP) {
336 key.remote_ipv6[3] = _htonl(1);
338 if (iph->nexthdr != NEXTHDR_TCP) {
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);
353 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
362 SEC("ip6ip6_get_tunnel")
363 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
366 struct bpf_tunnel_key key;
367 char fmt[] = "remote ip6 %x::%x\n";
369 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
375 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
376 _htonl(key.remote_ipv6[3]));
381 char _license[] SEC("license") = "GPL";