Home | History | Annotate | Download | only in distributed_bridge
      1 #!/usr/bin/env python
      2 # Copyright (c) PLUMgrid, Inc.
      3 # Licensed under the Apache License, Version 2.0 (the "License")
      4 
      5 from sys import argv
      6 from bcc import BPF
      7 from builtins import input
      8 from ctypes import c_int, c_uint
      9 from http.server import HTTPServer, SimpleHTTPRequestHandler
     10 import json
     11 from netaddr import EUI, IPAddress
     12 from pyroute2 import IPRoute, NetNS, IPDB, NSPopen
     13 from socket import htons, AF_INET
     14 from threading import Thread
     15 from subprocess import call
     16 
     17 host_id = int(argv[1])
     18 
     19 b = BPF(src_file="tunnel.c")
     20 ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS)
     21 egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS)
     22 mac2host = b.get_table("mac2host")
     23 vni2if = b.get_table("vni2if")
     24 conf = b.get_table("conf")
     25 
     26 ipr = IPRoute()
     27 ipdb = IPDB(nl=ipr)
     28 
     29 ifc = ipdb.interfaces.eth0
     30 mcast = IPAddress("239.1.1.1")
     31 
     32 # ifcs to cleanup at the end
     33 ifc_gc = []
     34 
     35 def run():
     36     ipdb.routes.add({"dst": "224.0.0.0/4", "oif": ifc.index}).commit()
     37     with ipdb.create(ifname="vxlan0", kind="vxlan", vxlan_id=0,
     38                      vxlan_link=ifc, vxlan_port=4789,
     39                      vxlan_group=str(mcast), vxlan_flowbased=True,
     40                      vxlan_collect_metadata=True,
     41                      vxlan_learning=False) as vx:
     42         vx.up()
     43         ifc_gc.append(vx.ifname)
     44 
     45     conf[c_int(1)] = c_int(vx.index)
     46 
     47     ipr.tc("add", "ingress", vx.index, "ffff:")
     48     ipr.tc("add-filter", "bpf", vx.index, ":1", fd=ingress_fn.fd,
     49            name=ingress_fn.name, parent="ffff:", action="drop", classid=1)
     50 
     51     for i in range(0, 2):
     52         vni = 10000 + i
     53         with ipdb.create(ifname="br%d" % i, kind="bridge") as br:
     54             v = ipdb.create(ifname="dummy%d" % i, kind="dummy").up().commit()
     55             mcast_key = mac2host.Key(0xFFFFFFFFFFFF, v.index, 0)
     56             mcast_leaf = mac2host.Leaf(vni, mcast.value, 0, 0)
     57             mac2host[mcast_key] = mcast_leaf
     58 
     59             ipr.tc("add", "sfq", v.index, "1:")
     60             ipr.tc("add-filter", "bpf", v.index, ":1", fd=egress_fn.fd,
     61                    name=egress_fn.name, parent="1:", action="drop", classid=1)
     62             br.add_port(v)
     63             br.up()
     64             ifc_gc.append(v.ifname)
     65             ifc_gc.append(br.ifname)
     66             vni2if[c_uint(vni)] = c_int(v.index)
     67             ipaddr = "99.1.%d.%d/24" % (i, host_id + 1)
     68             br.add_ip(ipaddr)
     69 
     70 try:
     71     run()
     72     ipdb.release()
     73     input("")
     74     print("---")
     75     for k, v in mac2host.items():
     76         print(EUI(k.mac), k.ifindex, IPAddress(v.remote_ipv4),
     77               v.tunnel_id, v.rx_pkts, v.tx_pkts)
     78 finally:
     79     for v in ifc_gc: call(["ip", "link", "del", v])
     80