You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.5 KiB
80 lines
2.5 KiB
#!/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])
|