diff --git a/examples/distributed_bridge/main.py b/examples/distributed_bridge/main.py index 272ec98f77db..37db487b5bfa 100755 --- a/examples/distributed_bridge/main.py +++ b/examples/distributed_bridge/main.py @@ -7,11 +7,14 @@ from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from simulation import Simulation from subprocess import PIPE, call, Popen +import re +dhcp = 0 +multicast = 1 if len(argv) > 1 and argv[1] == "mesh": - multicast = 0 -else: - multicast = 1 + multicast = 0 + if len(argv) > 2 and argv[2] == "dhcp": + dhcp = 1 ipr = IPRoute() ipdb = IPDB(nl=ipr) @@ -34,12 +37,33 @@ def start(self): if multicast: cmd = ["python", "tunnel.py", str(i)] else: - cmd = ["python", "tunnel_mesh.py", str(num_hosts), str(i)] + cmd = ["python", "tunnel_mesh.py", str(num_hosts), str(i), str(dhcp)] p = NSPopen(host_info[i][0].nl.netns, cmd, stdin=PIPE) self.processes.append(p) with self.ipdb.create(ifname="br-fabric", kind="bridge") as br: for host in host_info: br.add_port(host[1]) br.up() + + # get host0 bridge ip's + host0_br_ips = [] + if dhcp == 1: + print("Waiting for host0 br1/br2 ip addresses available") + for j in range(0, 2): + retry = -1 + ip_out = None + while retry < 0: + check = Popen(["ip", "netns", "exec", "host0", + "ip", "addr", "show", "br%d" % j], stdout=PIPE, stderr=PIPE) + ip_out = check.stdout.read() + checkip = "99.1.%d" % j + retry = ip_out.find(checkip) + p = re.compile(("99.1.%d." % j) + "\d+") + host0_br_ips.append(p.findall(ip_out)[0]) + else: + host0_br_ips.append("99.1.0.1") + host0_br_ips.append("99.1.1.1") + + # traffic test print("Validating connectivity") for i in range(1, num_hosts): for j in range(0, 2): @@ -48,11 +72,11 @@ def start(self): check = Popen(["ip", "netns", "exec", "host%d" % i, "ip", "addr", "show", "br%d" % j], stdout=PIPE, stderr=PIPE) out = check.stdout.read() - checkip = "99.1.%d.%d" % (j, i+1) + checkip = "99.1.%d" % j retry = out.find(checkip) print("VNI%d between host0 and host%d" % (10000 + j, i)) call(["ip", "netns", "exec", "host%d" % i, - "ping", "99.1.%d.1" % j, "-c", "3", "-i", "0.2", "-q"]) + "ping", host0_br_ips[j], "-c", "3", "-i", "0.2", "-q"]) try: sim = TunnelSimulation(ipdb) diff --git a/examples/distributed_bridge/tunnel_mesh.py b/examples/distributed_bridge/tunnel_mesh.py index 9a6efa9d5135..05d3a5e024a3 100644 --- a/examples/distributed_bridge/tunnel_mesh.py +++ b/examples/distributed_bridge/tunnel_mesh.py @@ -12,10 +12,11 @@ from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from socket import htons, AF_INET from threading import Thread -from subprocess import call +from subprocess import call, Popen, PIPE num_hosts = int(argv[1]) host_id = int(argv[2]) +dhcp = int(argv[3]) b = BPF(src_file="tunnel_mesh.c") ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS) @@ -32,6 +33,10 @@ # ifcs to cleanup at the end ifc_gc = [] +# dhcp server and client processes +d_serv = [] +d_client = [] + def run(): with ipdb.create(ifname="vxlan0", kind="vxlan", vxlan_id=0, vxlan_link=ifc, vxlan_port=htons(4789), @@ -68,13 +73,58 @@ def run(): br.add_port(v) br.up() ifc_gc.append(v.ifname) - ipaddr = "99.1.%d.%d/24" % (j, host_id + 1) - br.add_ip(ipaddr) + if dhcp == 0: + ipaddr = "99.1.%d.%d/24" % (j, host_id + 1) + br.add_ip(ipaddr) ifc_gc.append(br.ifname) + # dhcp server only runs on host 0 + if dhcp == 1 and host_id == 0: + for j in range(0, 2): + v1 = "dhcp%d_v1" % j + v2 = "dhcp%d_v2" % j + br = ipdb.interfaces["br%d" % j] + with ipdb.create(ifname=v1, kind="veth", peer=v2) as v: + v.up() + br.add_port(ipdb.interfaces[v1]).commit() + dhcp_v2 = ipdb.interfaces[v2] + dhcp_v2.add_ip("99.1.%d.1/24" % j).up().commit() + + call(["/bin/rm", "-f", "/tmp/dnsmasq.%d.leases" % j]) + cmd = ["dnsmasq", "-d", "--bind-interfaces", "--strict-order", + "--conf-file=", + "--dhcp-range", "99.1.%d.2,99.1.%d.254,255.255.255.0,12h" % (j, j), + "--dhcp-no-override", "--except-interface=lo", + "--interface=dhcp%d_v2" % j, + "--dhcp-authoritative", + "--dhcp-leasefile=/tmp/dnsmasq.%d.leases" % j] + d_serv.append(Popen(cmd, stdout=PIPE, stderr=PIPE)) + + # dhcp client to assign ip address for each bridge + if dhcp == 1: + for j in range(0, 2): + call(["/bin/rm", "-rf", "/tmp/dhcp_%d_%d" % (host_id, j)]) + call(["mkdir", "/tmp/dhcp_%d_%d" % (host_id, j)]) + call(["touch", "/tmp/dhcp_%d_%d/dhclient.conf" % (host_id, j)]) + call(["touch", "/tmp/dhcp_%d_%d/dhclient.lease" % (host_id, j)]) + cmd = ["dhclient", "-d", "br%d" % j, + "-cf", "/tmp/dhcp_%d_%d/dhclient.conf" % (host_id, j), + "-lf", "/tmp/dhcp_%d_%d/dhclient.lease" % (host_id, j)] + d_client.append(Popen(cmd, stdout=PIPE, stderr=PIPE)) + + # make sure we get address for eth0 + retry = -1 + while retry < 0: + check = Popen(["ip", "addr", "show", "br%d" % j], stdout=PIPE, stderr=PIPE) + out = check.stdout.read() + checkip = "99.1.%d" % j + retry = out.find(checkip) + try: run() - ipdb.release() input("") finally: for v in ifc_gc: call(["ip", "link", "del", v]) + ipdb.release() + for p in d_client: p.kill() + for p in d_serv: p.kill()