• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright (c) PLUMgrid, Inc.
3# Licensed under the Apache License, Version 2.0 (the "License")
4
5from sys import argv
6from bcc import BPF
7from builtins import input
8from ctypes import c_int, c_uint
9from http.server import HTTPServer, SimpleHTTPRequestHandler
10import json
11from netaddr import EUI, IPAddress
12from pyroute2 import IPRoute, NetNS, IPDB, NSPopen
13from socket import htons, AF_INET
14from threading import Thread
15from subprocess import call
16
17host_id = int(argv[1])
18
19b = BPF(src_file="tunnel.c")
20ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS)
21egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS)
22mac2host = b.get_table("mac2host")
23vni2if = b.get_table("vni2if")
24conf = b.get_table("conf")
25
26ipr = IPRoute()
27ipdb = IPDB(nl=ipr)
28
29ifc = ipdb.interfaces.eth0
30mcast = IPAddress("239.1.1.1")
31
32# ifcs to cleanup at the end
33ifc_gc = []
34
35def 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
70try:
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)
78finally:
79    for v in ifc_gc: call(["ip", "link", "del", v])
80