1 // Copyright (c) PLUMgrid, Inc. 2 // Licensed under the Apache License, Version 2.0 (the "License") 3 #include <bcc/proto.h> 4 5 BPF_HASH(vni2if, u32, int, 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_HASH(mac2host, struct vni_key, struct host); 19 20 struct config { 21 int tunnel_ifindex; 22 }; 23 BPF_HASH(conf, int, struct config, 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 = {}; 32 bpf_skb_get_tunnel_key(skb, &tkey, 33 offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0); 34 35 int *ifindex = vni2if.lookup(&tkey.tunnel_id); 36 if (ifindex) { 37 //bpf_trace_printk("ingress tunnel_id=%d ifindex=%d\n", tkey.tunnel_id, *ifindex); 38 struct vni_key vk = {ethernet->src, *ifindex, 0}; 39 struct host *src_host = mac2host.lookup_or_init(&vk, 40 &(struct host){tkey.tunnel_id, tkey.remote_ipv4, 0, 0}); 41 lock_xadd(&src_host->rx_pkts, 1); 42 bpf_clone_redirect(skb, *ifindex, 1/*ingress*/); 43 } else { 44 bpf_trace_printk("ingress invalid tunnel_id=%d\n", tkey.tunnel_id); 45 } 46 47 return 1; 48 } 49 50 // Handle packets from the tenant, mux into the encap device 51 int handle_egress(struct __sk_buff *skb) { 52 u8 *cursor = 0; 53 54 int one = 1; 55 struct config *cfg = conf.lookup(&one); 56 if (!cfg) return 1; 57 58 struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 59 60 struct vni_key vk = {ethernet->dst, skb->ifindex, 0}; 61 struct host *dst_host = mac2host.lookup(&vk); 62 struct bpf_tunnel_key tkey = {}; 63 if (dst_host) { 64 u32 zero = 0; 65 tkey.tunnel_id = dst_host->tunnel_id; 66 tkey.remote_ipv4 = dst_host->remote_ipv4; 67 bpf_skb_set_tunnel_key(skb, &tkey, 68 offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0); 69 lock_xadd(&dst_host->tx_pkts, 1); 70 } else { 71 struct bpf_tunnel_key tkey = {}; 72 vk.mac = 0xFFFFFFFFFFFFull; 73 dst_host = mac2host.lookup(&vk); 74 if (!dst_host) 75 return 1; 76 tkey.tunnel_id = dst_host->tunnel_id; 77 tkey.remote_ipv4 = dst_host->remote_ipv4; 78 bpf_skb_set_tunnel_key(skb, &tkey, 79 offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0); 80 } 81 bpf_clone_redirect(skb, cfg->tunnel_ifindex, 0/*egress*/); 82 return 1; 83 } 84