Brenden Blanco | 3f12ca2 | 2015-07-28 10:47:33 -0700 | [diff] [blame] | 1 | // Copyright (c) PLUMgrid, Inc. |
| 2 | // Licensed under the Apache License, Version 2.0 (the "License") |
| 3 | #include <bcc/proto.h> |
| 4 | |
| 5 | BPF_TABLE("hash", u32, int, vni2if, 1024); |
| 6 | |
| 7 | struct vni_key { |
| 8 | u64 mac; |
| 9 | int ifindex; |
| 10 | int pad; |
| 11 | }; |
| 12 | struct host { |
| 13 | u32 tunnel_id; |
| 14 | u32 remote_ipv4; |
| 15 | u64 rx_pkts; |
| 16 | u64 tx_pkts; |
| 17 | }; |
| 18 | BPF_TABLE("hash", struct vni_key, struct host, mac2host, 10240); |
| 19 | |
| 20 | struct config { |
| 21 | int tunnel_ifindex; |
| 22 | }; |
| 23 | BPF_TABLE("hash", int, struct config, conf, 1); |
| 24 | |
| 25 | // Handle packets from the encap device, demux into the dest tenant |
| 26 | int handle_ingress(struct __sk_buff *skb) { |
| 27 | u8 *cursor = 0; |
| 28 | |
| 29 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); |
| 30 | |
| 31 | struct bpf_tunnel_key tkey = {}; |
Alexei Starovoitov | b37f8a0 | 2015-07-30 14:14:09 -0700 | [diff] [blame] | 32 | bpf_skb_get_tunnel_key(skb, &tkey, sizeof(tkey), 0); |
Brenden Blanco | 3f12ca2 | 2015-07-28 10:47:33 -0700 | [diff] [blame] | 33 | |
| 34 | int *ifindex = vni2if.lookup(&tkey.tunnel_id); |
| 35 | if (ifindex) { |
| 36 | //bpf_trace_printk("ingress tunnel_id=%d ifindex=%d\n", tkey.tunnel_id, *ifindex); |
| 37 | struct vni_key vk = {ethernet->src, *ifindex, 0}; |
| 38 | struct host *src_host = mac2host.lookup_or_init(&vk, |
| 39 | &(struct host){tkey.tunnel_id, tkey.remote_ipv4, 0, 0}); |
| 40 | lock_xadd(&src_host->rx_pkts, 1); |
| 41 | bpf_clone_redirect(skb, *ifindex, 1/*ingress*/); |
| 42 | } else { |
| 43 | bpf_trace_printk("ingress invalid tunnel_id=%d\n", tkey.tunnel_id); |
| 44 | } |
| 45 | |
| 46 | return 1; |
| 47 | } |
| 48 | |
| 49 | // Handle packets from the tenant, mux into the encap device |
| 50 | int handle_egress(struct __sk_buff *skb) { |
| 51 | u8 *cursor = 0; |
| 52 | |
| 53 | int one = 1; |
| 54 | struct config *cfg = conf.lookup(&one); |
| 55 | if (!cfg) return 1; |
| 56 | |
| 57 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); |
| 58 | |
| 59 | struct vni_key vk = {ethernet->dst, skb->ifindex, 0}; |
| 60 | struct host *dst_host = mac2host.lookup(&vk); |
| 61 | struct bpf_tunnel_key tkey = {}; |
| 62 | if (dst_host) { |
| 63 | u32 zero = 0; |
| 64 | tkey.tunnel_id = dst_host->tunnel_id; |
| 65 | tkey.remote_ipv4 = dst_host->remote_ipv4; |
Alexei Starovoitov | b37f8a0 | 2015-07-30 14:14:09 -0700 | [diff] [blame] | 66 | bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), 0); |
Brenden Blanco | 3f12ca2 | 2015-07-28 10:47:33 -0700 | [diff] [blame] | 67 | lock_xadd(&dst_host->tx_pkts, 1); |
| 68 | } else { |
| 69 | struct bpf_tunnel_key tkey = {}; |
| 70 | vk.mac = 0xFFFFFFFFFFFFull; |
| 71 | dst_host = mac2host.lookup(&vk); |
| 72 | if (!dst_host) |
| 73 | return 1; |
| 74 | tkey.tunnel_id = dst_host->tunnel_id; |
| 75 | tkey.remote_ipv4 = dst_host->remote_ipv4; |
Alexei Starovoitov | b37f8a0 | 2015-07-30 14:14:09 -0700 | [diff] [blame] | 76 | bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), 0); |
Brenden Blanco | 3f12ca2 | 2015-07-28 10:47:33 -0700 | [diff] [blame] | 77 | } |
| 78 | bpf_clone_redirect(skb, cfg->tunnel_ifindex, 0/*egress*/); |
| 79 | return 1; |
| 80 | } |