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 #define KBUILD_MODNAME "foo"
9 #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>
13 #include <uapi/linux/ipv6.h>
14 #include <uapi/linux/in.h>
15 #include <uapi/linux/tcp.h>
16 #include <uapi/linux/filter.h>
17 #include <uapi/linux/pkt_cls.h>
19 #include "bpf_helpers.h"
21 #define _htonl __builtin_bswap32
22 #define ERROR(ret) do {\
23 char fmt[] = "ERROR line:%d ret:%d\n";\
24 bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
34 u8 opt_data[8]; /* hard-coded to 8 byte */
37 struct vxlan_metadata {
42 int _gre_set_tunnel(struct __sk_buff *skb)
45 struct bpf_tunnel_key key;
47 __builtin_memset(&key, 0x0, sizeof(key));
48 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
53 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
63 int _gre_get_tunnel(struct __sk_buff *skb)
66 struct bpf_tunnel_key key;
67 char fmt[] = "key %d remote ip 0x%x\n";
69 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
75 bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
79 SEC("vxlan_set_tunnel")
80 int _vxlan_set_tunnel(struct __sk_buff *skb)
83 struct bpf_tunnel_key key;
84 struct vxlan_metadata md;
86 __builtin_memset(&key, 0x0, sizeof(key));
87 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
92 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
98 md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
99 ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
108 SEC("vxlan_get_tunnel")
109 int _vxlan_get_tunnel(struct __sk_buff *skb)
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";
116 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
122 ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
128 bpf_trace_printk(fmt, sizeof(fmt),
129 key.tunnel_id, key.remote_ipv4, md.gbp);
134 SEC("geneve_set_tunnel")
135 int _geneve_set_tunnel(struct __sk_buff *skb)
138 struct bpf_tunnel_key key;
139 struct geneve_opt gopt;
141 __builtin_memset(&key, 0x0, sizeof(key));
142 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
147 __builtin_memset(&gopt, 0x0, sizeof(gopt));
148 gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
153 gopt.length = 2; /* 4-byte multiple */
154 *(int *) &gopt.opt_data = 0xdeadbeef;
156 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
162 ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
171 SEC("geneve_get_tunnel")
172 int _geneve_get_tunnel(struct __sk_buff *skb)
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";
179 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
185 ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
191 bpf_trace_printk(fmt, sizeof(fmt),
192 key.tunnel_id, key.remote_ipv4, gopt.opt_class);
196 SEC("ipip_set_tunnel")
197 int _ipip_set_tunnel(struct __sk_buff *skb)
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;
206 /* single length check */
207 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
213 if (iph->protocol == IPPROTO_ICMP) {
214 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
216 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
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 */
227 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
236 SEC("ipip_get_tunnel")
237 int _ipip_get_tunnel(struct __sk_buff *skb)
240 struct bpf_tunnel_key key;
241 char fmt[] = "remote ip 0x%x\n";
243 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
249 bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
253 SEC("ipip6_set_tunnel")
254 int _ipip6_set_tunnel(struct __sk_buff *skb)
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;
263 /* single length check */
264 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
269 key.remote_ipv6[0] = _htonl(0x2401db00);
272 if (iph->protocol == IPPROTO_ICMP) {
273 key.remote_ipv6[3] = _htonl(1);
275 if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
276 ERROR(iph->protocol);
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);
290 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
299 SEC("ipip6_get_tunnel")
300 int _ipip6_get_tunnel(struct __sk_buff *skb)
303 struct bpf_tunnel_key key;
304 char fmt[] = "remote ip6 %x::%x\n";
306 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
312 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
313 _htonl(key.remote_ipv6[3]));
317 SEC("ip6ip6_set_tunnel")
318 int _ip6ip6_set_tunnel(struct __sk_buff *skb)
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;
327 /* single length check */
328 if (data + sizeof(*iph) + sizeof(*tcp) > data_end) {
333 key.remote_ipv6[0] = _htonl(0x2401db00);
336 if (iph->nexthdr == NEXTHDR_ICMP) {
337 key.remote_ipv6[3] = _htonl(1);
339 if (iph->nexthdr != NEXTHDR_TCP) {
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);
354 ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
363 SEC("ip6ip6_get_tunnel")
364 int _ip6ip6_get_tunnel(struct __sk_buff *skb)
367 struct bpf_tunnel_key key;
368 char fmt[] = "remote ip6 %x::%x\n";
370 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
376 bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
377 _htonl(key.remote_ipv6[3]));
382 char _license[] SEC("license") = "GPL";