Home | History | Annotate | Download | only in distributed_bridge
      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