| #!/usr/bin/env python |
| # Copyright (c) PLUMgrid, Inc. |
| # Licensed under the Apache License, Version 2.0 (the "License") |
| |
| from sys import argv |
| from bcc import BPF |
| from builtins import input |
| from ctypes import c_int, c_uint |
| from http.server import HTTPServer, SimpleHTTPRequestHandler |
| import json |
| from netaddr import EUI, IPAddress |
| from pyroute2 import IPRoute, NetNS, IPDB, NSPopen |
| from socket import htons, AF_INET |
| from threading import Thread |
| from subprocess import call |
| |
| host_id = int(argv[1]) |
| |
| b = BPF(src_file="tunnel.c") |
| ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) |
| egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS) |
| mac2host = b.get_table("mac2host") |
| vni2if = b.get_table("vni2if") |
| conf = b.get_table("conf") |
| |
| ipr = IPRoute() |
| ipdb = IPDB(nl=ipr) |
| |
| ifc = ipdb.interfaces.eth0 |
| mcast = IPAddress("239.1.1.1") |
| |
| # ifcs to cleanup at the end |
| ifc_gc = [] |
| |
| def run(): |
| ipdb.routes.add({"dst": "224.0.0.0/4", "oif": ifc.index}).commit() |
| with ipdb.create(ifname="vxlan0", kind="vxlan", vxlan_id=0, |
| vxlan_link=ifc, vxlan_port=4789, |
| vxlan_group=str(mcast), vxlan_flowbased=True, |
| vxlan_collect_metadata=True, |
| vxlan_learning=False) as vx: |
| vx.up() |
| ifc_gc.append(vx.ifname) |
| |
| conf[c_int(1)] = c_int(vx.index) |
| |
| ipr.tc("add", "ingress", vx.index, "ffff:") |
| ipr.tc("add-filter", "bpf", vx.index, ":1", fd=ingress_fn.fd, |
| name=ingress_fn.name, parent="ffff:", action="drop", classid=1) |
| |
| for i in range(0, 2): |
| vni = 10000 + i |
| with ipdb.create(ifname="br%d" % i, kind="bridge") as br: |
| v = ipdb.create(ifname="dummy%d" % i, kind="dummy").up().commit() |
| mcast_key = mac2host.Key(0xFFFFFFFFFFFF, v.index, 0) |
| mcast_leaf = mac2host.Leaf(vni, mcast.value, 0, 0) |
| mac2host[mcast_key] = mcast_leaf |
| |
| ipr.tc("add", "sfq", v.index, "1:") |
| ipr.tc("add-filter", "bpf", v.index, ":1", fd=egress_fn.fd, |
| name=egress_fn.name, parent="1:", action="drop", classid=1) |
| br.add_port(v) |
| br.up() |
| ifc_gc.append(v.ifname) |
| ifc_gc.append(br.ifname) |
| vni2if[c_uint(vni)] = c_int(v.index) |
| ipaddr = "99.1.%d.%d/24" % (i, host_id + 1) |
| br.add_ip(ipaddr) |
| |
| try: |
| run() |
| ipdb.release() |
| input("") |
| print("---") |
| for k, v in mac2host.items(): |
| print(EUI(k.mac), k.ifindex, IPAddress(v.remote_ipv4), |
| v.tunnel_id, v.rx_pkts, v.tx_pkts) |
| finally: |
| for v in ifc_gc: call(["ip", "link", "del", v]) |