def test_brb2(self): try: b = BPF(src_file=arg1, debug=0) self.pem_fn = b.load_func("pem", BPF.SCHED_CLS) self.pem_dest= b.get_table("pem_dest") self.pem_stats = b.get_table("pem_stats") # set up the topology self.set_default_const() (ns1_ipdb, self.ns1_eth_out, _) = sim._create_ns(self.ns1, ipaddr=self.vm1_ip+'/24', fn=self.pem_fn, action='drop', disable_ipv6=True) (ns2_ipdb, self.ns2_eth_out, _) = sim._create_ns(self.ns2, ipaddr=self.vm2_ip+'/24', fn=self.pem_fn, action='drop', disable_ipv6=True) ns1_ipdb.routes.add({'dst': self.vm2_rtr_mask, 'gateway': self.vm1_rtr_ip}).commit() ns2_ipdb.routes.add({'dst': self.vm1_rtr_mask, 'gateway': self.vm2_rtr_ip}).commit() (_, self.nsrtr_eth0_out, _) = sim._create_ns(self.ns_router, ipaddr=self.vm1_rtr_ip+'/24', disable_ipv6=True) (rt_ipdb, self.nsrtr_eth1_out, _) = sim._ns_add_ifc(self.ns_router, "eth1", "ns_router2", ipaddr=self.vm2_rtr_ip+'/24', disable_ipv6=True) # enable ip forwarding in router ns nsp = NSPopen(rt_ipdb.nl.netns, ["sysctl", "-w", "net.ipv4.ip_forward=1"]) nsp.wait(); nsp.release() # for each VM connecting to pem, there will be a corresponding veth connecting to the bridge self.setup_br(self.br1, self.nsrtr_eth0_out.ifname, self.veth_pem_2_br1, self.veth_br1_2_pem) self.setup_br(self.br2, self.nsrtr_eth1_out.ifname, self.veth_pem_2_br2, self.veth_br2_2_pem) # load the program and configure maps self.config_maps() # ping nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"]); nsp.wait(); nsp.release() # one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total self.assertEqual(self.pem_stats[c_uint(0)].value, 12) nsp_server = NSPopenWithCheck(ns2_ipdb.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(ns1_ipdb.nl.netns, ["iperf", "-c", self.vm2_ip, "-t", "1", "-xSC"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release() nsp_server = NSPopenWithCheck(ns2_ipdb.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopenWithCheck(ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "--", "-m", "65160"]) nsp.wait(); nsp.release() nsp = NSPopen(ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "-t", "TCP_RR"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release() finally: if self.br1 in ipdb.interfaces: ipdb.interfaces[self.br1].remove().commit() if self.br2 in ipdb.interfaces: ipdb.interfaces[self.br2].remove().commit() if self.veth_pem_2_br1 in ipdb.interfaces: ipdb.interfaces[self.veth_pem_2_br1].remove().commit() if self.veth_pem_2_br2 in ipdb.interfaces: ipdb.interfaces[self.veth_pem_2_br2].remove().commit() sim.release() ipdb.release()
def test_release(self): require_user('root') nsid = self.alloc_nsname() nsp = NSPopen(nsid, ['true'], flags=os.O_CREAT, stdout=subprocess.PIPE) nsp.communicate() nsp.wait() nsp.release() try: print(nsp.returncode) except RuntimeError: pass
def add_values(self,subnet,VMs): x = 0 for sub in range(5,subnet+5): for mac in range(2,VMs+2): print 'ns_array[%d], ARP address: 192.168.%d.1' % (x,sub) cmd1 = ["route", "add", "default", "gw",'192.168.%d.1' % (sub)] nsp = NSPopen(self.ns_array[x].id.nl.netns, cmd1) nsp.wait(); nsp.release() cmd1 = ["arping", "-c", "1", "-I", "eth0", '192.168.%d.1' % (sub),"-q"] nsp = NSPopen(self.ns_array[x].id.nl.netns, cmd1) nsp.wait(); nsp.release() x+=1
def createEndpoint(name, svcName, endpointtype): if endpointtype == 'ns': ip_host = IPDB() ip_host.create(ifname=name, kind='veth', peer=name + '_' + svcName).commit() ip_ns = IPDB(nl=NetNS(name)) with ip_host.interfaces[name] as veth: veth.net_ns_fd = name veth.up() with ip_host.interfaces[name + '_' + svcName] as veth: veth.up() subprocess.call( ["ovs-vsctl", "add-port", "vs-" + svcName, name + '_' + svcName]) ip_host.release() ip_ns.release() nsp = NSPopen(name, ['dhclient', '-lf', '/tmp/' + name + '.lease', name], stdout=subprocess.PIPE) nsp.wait() nsp.release() if endpointtype == 'lxc': subprocess.call(['/usr/bin/lxc-clone', 'template', name]) lxcUpOvsScript = '#!/bin/bash\n' lxcUpOvsScript += 'BRIDGE="vs-' + svcName + '"\n' lxcUpOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' lxcUpOvsScript += 'ovs-vsctl add-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsup.sh', 'w+') f.write(lxcUpOvsScript) f.close() lxcDownOvsScript = '#!/bin/bash\n' lxcDownOvsScript += 'BRIDGE="vs-' + svcName + '"\n' lxcDownOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsdown.sh', 'w+') f.write(lxcDownOvsScript) f.close() os.chmod('/var/lib/lxc/' + name + '/ovsup.sh', stat.S_IRWXU) os.chmod('/var/lib/lxc/' + name + '/ovsdown.sh', stat.S_IRWXU) lxcConfig = 'lxc.include = /usr/share/lxc/config/ubuntu.common.conf\n' lxcConfig += 'lxc.arch = x86_64\n' lxcConfig += 'lxc.rootfs = /var/lib/lxc/' + name + '/rootfs\n' lxcConfig += 'lxc.utsname = ' + name + '\n' lxcConfig += 'lxc.network.type = veth\n' lxcConfig += 'lxc.network.veth.pair = ' + name + '\n' lxcConfig += 'lxc.network.script.up = /var/lib/lxc/' + name + '/ovsup.sh\n' lxcConfig += 'lxc.network.script.down = /var/lib/lxc/' + name + '/ovsdown.sh\n' lxcConfig += 'lxc.network.flags = up\n' f = open('/var/lib/lxc/' + name + '/config', 'w+') f.write(lxcConfig) f.close() subprocess.call(['/usr/bin/lxc-start', '-d', '-n', name]) pass return json.dumps({'status': 'created endpoint'})
def test_api_object(self): require_user('root') nsid = self.alloc_nsname() nsp = NSPopen(nsid, ['true'], flags=os.O_CREAT, stdout=subprocess.PIPE) smp = subprocess.Popen(['true'], stdout=subprocess.PIPE) nsp.communicate() smp.communicate() api_nspopen = set(dir(nsp)) api_popen = set(dir(smp)) minimal = set(('communicate', 'kill', 'wait')) assert minimal & (api_nspopen & api_popen) == minimal smp.wait() nsp.wait() assert nsp.returncode == smp.returncode == 0 nsp.release()
def createEndpoint(name, svcName, endpointtype): if endpointtype == 'ns': ip_host = IPDB() ip_host.create(ifname=name, kind='veth', peer=name + '_' + svcName).commit() ip_ns = IPDB(nl=NetNS(name)) with ip_host.interfaces[name] as veth: veth.net_ns_fd = name veth.up() with ip_host.interfaces[name + '_' + svcName] as veth: veth.up() subprocess.call(["ovs-vsctl", "add-port", "vs-" + svcName, name + '_' + svcName]) ip_host.release() ip_ns.release() nsp = NSPopen(name, ['dhclient', '-lf', '/tmp/' + name + '.lease', name], stdout=subprocess.PIPE) nsp.wait() nsp.release() if endpointtype == 'lxc': subprocess.call(['/usr/bin/lxc-clone','template',name]) lxcUpOvsScript = '#!/bin/bash\n' lxcUpOvsScript += 'BRIDGE="vs-'+ svcName + '"\n' lxcUpOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' lxcUpOvsScript += 'ovs-vsctl add-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsup.sh','w+') f.write(lxcUpOvsScript) f.close() lxcDownOvsScript = '#!/bin/bash\n' lxcDownOvsScript += 'BRIDGE="vs-'+ svcName + '"\n' lxcDownOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsdown.sh','w+') f.write(lxcDownOvsScript) f.close() os.chmod('/var/lib/lxc/' + name + '/ovsup.sh',stat.S_IRWXU) os.chmod('/var/lib/lxc/' + name + '/ovsdown.sh',stat.S_IRWXU) lxcConfig = 'lxc.include = /usr/share/lxc/config/ubuntu.common.conf\n' lxcConfig += 'lxc.arch = x86_64\n' lxcConfig += 'lxc.rootfs = /var/lib/lxc/' + name + '/rootfs\n' lxcConfig += 'lxc.utsname = ' + name + '\n' lxcConfig += 'lxc.network.type = veth\n' lxcConfig += 'lxc.network.veth.pair = ' + name + '\n' lxcConfig += 'lxc.network.script.up = /var/lib/lxc/' + name + '/ovsup.sh\n' lxcConfig += 'lxc.network.script.down = /var/lib/lxc/' + name + '/ovsdown.sh\n' lxcConfig += 'lxc.network.flags = up\n' f = open('/var/lib/lxc/' + name + '/config','w+') f.write(lxcConfig) f.close() subprocess.call(['/usr/bin/lxc-start','-d','-n',name]) pass return json.dumps({ 'status' : 'created endpoint'})
def deleteEndpoint(name, svcName, endpointtype): if endpointtype == 'ns': nsp = NSPopen(name, ['dhclient', '-r', name], stdout=subprocess.PIPE) nsp.wait() nsp.release() netns.remove(name) ip_host = IPDB() if name + '_' + svcName in ip_host.interfaces: with ip_host.interfaces[name + '_' + svcName] as veth: veth.remove() subprocess.call(["ovs-vsctl", "del-port", "vs-" + svcName, name + '_' + svcName]) if endpointtype == 'lxc': subprocess.call(['/usr/bin/lxc-stop','-n',name]) subprocess.call(['/usr/bin/lxc-destroy','-n',name]) pass return json.dumps({ 'status' : 'deleted endpoint'})
def test_topology(self): nsp = NSPopen(self.ns_array[0].id.nl.netns, ["ping", "192.168.6.2", "-c", "2"]); nsp.wait(); nsp.release() # one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total nsp_server = NSPopen(self.ns_array[2].id.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(self.ns_array[0].id.nl.netns, ["iperf", "-c", "192.168.6.2", "-t", "1", "-xSC"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release() nsp_server = NSPopen(self.ns_array[2].id.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopen(self.ns_array[0].id.nl.netns, ["netperf", "-l", "1", "-H", "192.168.6.2", "--", "-m", "65160"]) nsp.wait(); nsp.release() nsp = NSPopen(self.ns_array[0].id.nl.netns, ["netperf", "-l", "1", "-H", "192.168.6.2", "-t", "TCP_RR"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release()
def deleteEndpoint(name, svcName, endpointtype): if endpointtype == 'ns': nsp = NSPopen(name, ['dhclient', '-r', name], stdout=subprocess.PIPE) nsp.wait() nsp.release() netns.remove(name) ip_host = IPDB() if name + '_' + svcName in ip_host.interfaces: with ip_host.interfaces[name + '_' + svcName] as veth: veth.remove() subprocess.call( ["ovs-vsctl", "del-port", "vs-" + svcName, name + '_' + svcName]) if endpointtype == 'lxc': subprocess.call(['/usr/bin/lxc-stop', '-n', name]) subprocess.call(['/usr/bin/lxc-destroy', '-n', name]) pass return json.dumps({'status': 'deleted endpoint'})
def execute(self, command): # Run a command in the node's namespace # Return the command's exit code self.message(self.name, "Executing", command) nsn = self.get_ns_name() pipe = NSPopen(nsn, command) result = pipe.wait() pipe.release() return result
def _ns_add_ifc(self, name, ns_ifc, ifc_base_name=None, in_ifc=None, out_ifc=None, ipaddr=None, macaddr=None, fn=None, cmd=None, action="ok", disable_ipv6=False): if name in self.ipdbs: ns_ipdb = self.ipdbs[name] else: ns_ipdb = IPDB(nl=NetNS(name)) if disable_ipv6: cmd = ["sysctl", "-q", "-w", "net.ipv6.conf.default.disable_ipv6=1"] nsp = NSPopen(ns_ipdb.nl.netns, cmd) nsp.wait(); nsp.release() ns_ipdb.interfaces.lo.up().commit() if in_ifc: in_ifname = in_ifc.ifname else: out_ifc = self.ipdb.create(ifname="%sa" % ifc_base_name, kind="veth", peer="%sb" % ifc_base_name).commit() in_ifc = self.ipdb.interfaces[out_ifc.peer] in_ifname = in_ifc.ifname with in_ifc as v: # move half of veth into namespace v.net_ns_fd = ns_ipdb.nl.netns in_ifc = ns_ipdb.interfaces[in_ifname] if out_ifc: out_ifc.up().commit() ns_ipdb.interfaces.lo.up().commit() with in_ifc as v: v.ifname = ns_ifc if ipaddr: v.add_ip("%s" % ipaddr) if macaddr: v.address = macaddr v.up() if disable_ipv6: cmd = ["sysctl", "-q", "-w", "net.ipv6.conf.%s.disable_ipv6=1" % out_ifc.ifname] subprocess.call(cmd) if fn and out_ifc: self.ipdb.nl.tc("add", "ingress", out_ifc["index"], "ffff:") self.ipdb.nl.tc("add-filter", "bpf", out_ifc["index"], ":1", fd=fn.fd, name=fn.name, parent="ffff:", action=action, classid=1) if cmd: self.processes.append(NSPopen(ns_ipdb.nl.netns, cmd)) return (ns_ipdb, out_ifc, in_ifc)
def add_values(self, subnet, VMs): x = 0 for sub in range(5, subnet + 5): for mac in range(2, VMs + 2): print 'ns_array[%d], ARP address: 192.168.%d.1' % (x, sub) cmd1 = [ "route", "add", "default", "gw", '192.168.%d.1' % (sub) ] nsp = NSPopen(self.ns_array[x].id.nl.netns, cmd1) nsp.wait() nsp.release() cmd1 = [ "arping", "-c", "1", "-I", "eth0", '192.168.%d.1' % (sub), "-q" ] nsp = NSPopen(self.ns_array[x].id.nl.netns, cmd1) nsp.wait() nsp.release() x += 1
def test_basic(self): require_user('root') nsid = self.alloc_nsname() # create NS and run a child nsp = NSPopen(nsid, ['ip', '-o', 'link'], stdout=subprocess.PIPE, flags=os.O_CREAT) ret = nsp.communicate()[0].decode('utf-8') host_links = [x.get_attr('IFLA_IFNAME') for x in self.ip.get_links()] netns_links = [x.split(':')[1].split('@')[0].strip() for x in ret.split('\n') if len(x)] assert nsp.wait() == nsp.returncode == 0 assert set(host_links) & set(netns_links) == set(netns_links) assert set(netns_links) < set(host_links) assert not set(netns_links) > set(host_links) nsp.release()
def test_brb2(self): try: b = BPF(src_file=arg1, debug=0) self.pem_fn = b.load_func("pem", BPF.SCHED_CLS) self.pem_dest = b.get_table("pem_dest") self.pem_stats = b.get_table("pem_stats") # set up the topology self.set_default_const() (ns1_ipdb, self.ns1_eth_out, _) = sim._create_ns(self.ns1, ipaddr=self.vm1_ip + '/24', fn=self.pem_fn, action='drop', disable_ipv6=True) (ns2_ipdb, self.ns2_eth_out, _) = sim._create_ns(self.ns2, ipaddr=self.vm2_ip + '/24', fn=self.pem_fn, action='drop', disable_ipv6=True) ns1_ipdb.routes.add({ 'dst': self.vm2_rtr_mask, 'gateway': self.vm1_rtr_ip }).commit() ns2_ipdb.routes.add({ 'dst': self.vm1_rtr_mask, 'gateway': self.vm2_rtr_ip }).commit() (_, self.nsrtr_eth0_out, _) = sim._create_ns(self.ns_router, ipaddr=self.vm1_rtr_ip + '/24', disable_ipv6=True) (rt_ipdb, self.nsrtr_eth1_out, _) = sim._ns_add_ifc(self.ns_router, "eth1", "ns_router2", ipaddr=self.vm2_rtr_ip + '/24', disable_ipv6=True) # enable ip forwarding in router ns nsp = NSPopen(rt_ipdb.nl.netns, ["sysctl", "-w", "net.ipv4.ip_forward=1"]) nsp.wait() nsp.release() # for each VM connecting to pem, there will be a corresponding veth connecting to the bridge self.setup_br(self.br1, self.nsrtr_eth0_out.ifname, self.veth_pem_2_br1, self.veth_br1_2_pem) self.setup_br(self.br2, self.nsrtr_eth1_out.ifname, self.veth_pem_2_br2, self.veth_br2_2_pem) # load the program and configure maps self.config_maps() # ping nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"]) nsp.wait() nsp.release() # one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total self.assertEqual(self.pem_stats[c_uint(0)].value, 12) nsp_server = NSPopen(ns2_ipdb.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(ns1_ipdb.nl.netns, ["iperf", "-c", self.vm2_ip, "-t", "1", "-xSC"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release() nsp_server = NSPopen(ns2_ipdb.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopen( ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "--", "-m", "65160"]) nsp.wait() nsp.release() nsp = NSPopen( ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "-t", "TCP_RR"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release() finally: if self.br1 in ipdb.interfaces: ipdb.interfaces[self.br1].remove().commit() if self.br2 in ipdb.interfaces: ipdb.interfaces[self.br2].remove().commit() if self.veth_pem_2_br1 in ipdb.interfaces: ipdb.interfaces[self.veth_pem_2_br1].remove().commit() if self.veth_pem_2_br2 in ipdb.interfaces: ipdb.interfaces[self.veth_pem_2_br2].remove().commit() sim.release() ipdb.release()
def createService(data): print data name = data['name'] svcId = data['Id'] svcIdString = str(data['Id']) ip = data['dhcpip'] network = data['subnet'] customer = data['customer'] routetarget = data['routetarget'] terminal = data['terminal'] vr = data['virtualrouter'] if 'move' in data: move = data['move'] oldvr = data['oldvr'] oldId = data['oldId'] else: move = False if 'add' in data: add = data['add'] else: add = False print name if_svc_name = name + '_' + svcIdString if_svc_peer_name = name + '_' + svcIdString + '_v' ip_ns = IPDB(nl=NetNS(name + '_' + svcIdString)) ip_host = IPDB() ip_host.create(ifname=if_svc_name, kind='veth', peer=if_svc_peer_name).commit() subprocess.call(["ovs-vsctl", "add-port", "br0", if_svc_name]) subprocess.call(["ovs-vsctl", "set", "port", if_svc_name, "tag=" + str(svcId)]) netmask = network.split('/')[1] ip = ip + '/' + netmask createDhcpConfig(name, network, vr, customer, svcIdString) with ip_host.interfaces[if_svc_name] as veth: veth.up() with ip_host.interfaces[if_svc_peer_name] as veth: veth.net_ns_fd = name + '_' + svcIdString with ip_ns.interfaces[if_svc_peer_name] as veth: veth.address = 'de:ad:be:ef:ba:be' veth.add_ip(ip) veth.up() ip_host.release() ip_ns.release() nsp = NSPopen(name + '_' + svcIdString, ['dnsmasq', '-C', '/etc/dnsmasq.d/' + name + '.conf'], stdout=subprocess.PIPE) nsp.wait() nsp.release() if not move or add: try: vn = createVirtualNetwork(customer, name, network, routetarget) except: print 'failed to create VN' phInt = getPhysicalInterface(vr, serviceInterface) lif = createLogicalInterface(phInt, name + '_' + svcIdString, str(svcId)) if move: oldlif = getLogicalInterface(oldvr, name + '_' + str(oldId)) if oldlif.get_virtual_machine_interface_refs(): for vmInt in oldlif.get_virtual_machine_interface_refs(): vmIntObj = vnc_client.virtual_machine_interface_read(id = vmInt['uuid']) ''' if vmIntObj.get_instance_ip_back_refs(): for instIp in vmIntObj.get_instance_ip_back_refs(): instIpObj = vnc_client.instance_ip_read(id = instIp['uuid']) epIp = instIpObj.get_instance_ip_address() epMac = vmIntObj.get_virtual_machine_interface_mac_addresses().get_mac_address()[0] vn = getVirtualNetwork(customer, name) vmInterface = createVirtualMachineInterface(customer, name, epMac) createInstanceIp(epIp, vmInterface, vn) lif.add_virtual_machine_interface(vmInterface) ''' oldlif.del_virtual_machine_interface(vmIntObj) lif.add_virtual_machine_interface(vmIntObj) vnc_client.logical_interface_update(oldlif) vnc_client.logical_interface_update(lif) ''' if os.path.isfile('/mnt/' + name + '.lease'): f = open('/mnt/' + name + '.lease', 'r') leases = f.readlines() f.close() for lease in leases: epMac = lease.split(' ')[1] epIp = lease.split(' ')[2] vn = getVirtualNetwork(customer, name) vmInterface = createVirtualMachineInterface(customer, name, epMac) createInstanceIp(epIp, vmInterface, vn) lif.add_virtual_machine_interface(vmInterface) vnc_client.logical_interface_update(lif) ''' return json.dumps({ 'status' : 'created service'})
def execCmd(self, cmd): cmdList = cmd.split() nsp = NSPopen(self.nSname, cmdList, stdout=subprocess.PIPE) nsp.wait() nsp.release()
def test_brb(self): try: b = BPF(src_file=arg1, debug=0) self.pem_fn = b.load_func("pem", BPF.SCHED_CLS) self.br1_fn = b.load_func("br1", BPF.SCHED_CLS) self.br2_fn = b.load_func("br2", BPF.SCHED_CLS) self.get_table(b) # set up the topology self.set_default_const() (ns1_ipdb, self.ns1_eth_out, _) = sim._create_ns(self.ns1, ipaddr=self.vm1_ip + '/24', fn=self.pem_fn, action='drop', disable_ipv6=True) (ns2_ipdb, self.ns2_eth_out, _) = sim._create_ns(self.ns2, ipaddr=self.vm2_ip + '/24', fn=self.pem_fn, action='drop', disable_ipv6=True) ns1_ipdb.routes.add({ 'dst': self.vm2_rtr_mask, 'gateway': self.vm1_rtr_ip }).commit() ns2_ipdb.routes.add({ 'dst': self.vm1_rtr_mask, 'gateway': self.vm2_rtr_ip }).commit() self.vm1_mac = ns1_ipdb.interfaces['eth0'].address self.vm2_mac = ns2_ipdb.interfaces['eth0'].address (_, self.nsrtr_eth0_out, _) = sim._create_ns(self.ns_router, ipaddr=self.vm1_rtr_ip + '/24', fn=self.br1_fn, action='drop', disable_ipv6=True) (rt_ipdb, self.nsrtr_eth1_out, _) = sim._ns_add_ifc(self.ns_router, "eth1", "ns_router2", ipaddr=self.vm2_rtr_ip + '/24', fn=self.br2_fn, action='drop', disable_ipv6=True) nsp = NSPopen(rt_ipdb.nl.netns, ["sysctl", "-w", "net.ipv4.ip_forward=1"]) nsp.wait() nsp.release() # configure maps self.config_maps() # our bridge is not smart enough, so send arping for router learning to prevent router # from sending out arp request nsp = NSPopen(ns1_ipdb.nl.netns, [ "arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm1_rtr_ip ]) nsp.wait() nsp.release() nsp = NSPopen(ns2_ipdb.nl.netns, [ "arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm2_rtr_ip ]) nsp.wait() nsp.release() # ping nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"]) nsp.wait() nsp.release() # pem_stats only counts pem->bridge traffic, each VM has 4: arping/arp request/2 icmp request # total 8 packets should be counted self.assertEqual(self.pem_stats[c_uint(0)].value, 8) nsp_server = NSPopenWithCheck(ns2_ipdb.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(ns1_ipdb.nl.netns, ["iperf", "-c", self.vm2_ip, "-t", "1", "-xSC"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release() nsp_server = NSPopenWithCheck(ns2_ipdb.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopenWithCheck( ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "--", "-m", "65160"]) nsp.wait() nsp.release() nsp = NSPopen( ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "-t", "TCP_RR"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release() finally: sim.release() ipdb.release()
def _ns_add_ifc(self, name, ns_ifc, ifc_base_name=None, in_ifc=None, out_ifc=None, ipaddr=None, macaddr=None, fn=None, cmd=None, action="ok", disable_ipv6=False): if name in self.ipdbs: ns_ipdb = self.ipdbs[name] else: try: nl = NetNS(name) self.namespaces.append(nl) except KeyboardInterrupt: # remove the namespace if it has been created pyroute2.netns.remove(name) raise ns_ipdb = IPDB(nl) self.ipdbs[nl.netns] = ns_ipdb if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.default.disable_ipv6=1" ] nsp = NSPopen(ns_ipdb.nl.netns, cmd1) nsp.wait() nsp.release() try: ns_ipdb.interfaces.lo.up().commit() except pyroute2.ipdb.exceptions.CommitException: print( "Warning, commit for lo failed, operstate may be unknown") if in_ifc: in_ifname = in_ifc.ifname with in_ifc as v: # move half of veth into namespace v.net_ns_fd = ns_ipdb.nl.netns else: # delete the potentially leaf-over veth interfaces ipr = IPRoute() for i in ipr.link_lookup(ifname='%sa' % ifc_base_name): ipr.link("del", index=i) ipr.close() try: out_ifc = self.ipdb.create(ifname="%sa" % ifc_base_name, kind="veth", peer="%sb" % ifc_base_name).commit() in_ifc = self.ipdb.interfaces[out_ifc.peer] in_ifname = in_ifc.ifname with in_ifc as v: v.net_ns_fd = ns_ipdb.nl.netns except KeyboardInterrupt: # explicitly remove the interface out_ifname = "%sa" % ifc_base_name if out_ifname in self.ipdb.interfaces: self.ipdb.interfaces[out_ifname].remove().commit() raise if out_ifc: out_ifc.up().commit() try: # this is a workaround for fc31 and possible other disto's. # when interface 'lo' is already up, do another 'up().commit()' # has issues in fc31. # the workaround may become permanent if we upgrade pyroute2 # in all machines. if 'state' in ns_ipdb.interfaces.lo.keys(): if ns_ipdb.interfaces.lo['state'] != 'up': ns_ipdb.interfaces.lo.up().commit() else: ns_ipdb.interfaces.lo.up().commit() except pyroute2.ipdb.exceptions.CommitException: print("Warning, commit for lo failed, operstate may be unknown") ns_ipdb.initdb() in_ifc = ns_ipdb.interfaces[in_ifname] with in_ifc as v: v.ifname = ns_ifc if ipaddr: v.add_ip("%s" % ipaddr) if macaddr: v.address = macaddr v.up() if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.%s.disable_ipv6=1" % out_ifc.ifname ] subprocess.call(cmd1) if fn and out_ifc: self.ipdb.nl.tc("add", "ingress", out_ifc["index"], "ffff:") self.ipdb.nl.tc("add-filter", "bpf", out_ifc["index"], ":1", fd=fn.fd, name=fn.name, parent="ffff:", action=action, classid=1) if cmd: self.processes.append(NSPopen(ns_ipdb.nl.netns, cmd)) return (ns_ipdb, out_ifc, in_ifc)
def test_brb(self): try: b = BPF(src_file=arg1, debug=0) self.pem_fn = b.load_func("pem", BPF.SCHED_CLS) self.br1_fn = b.load_func("br1", BPF.SCHED_CLS) self.br2_fn = b.load_func("br2", BPF.SCHED_CLS) self.get_table(b) # set up the topology self.set_default_const() (ns1_ipdb, self.ns1_eth_out, _) = sim._create_ns(self.ns1, ipaddr=self.vm1_ip+'/24', fn=self.pem_fn, action='drop', disable_ipv6=True) (ns2_ipdb, self.ns2_eth_out, _) = sim._create_ns(self.ns2, ipaddr=self.vm2_ip+'/24', fn=self.pem_fn, action='drop', disable_ipv6=True) ns1_ipdb.routes.add({'dst': self.vm2_rtr_mask, 'gateway': self.vm1_rtr_ip}).commit() ns2_ipdb.routes.add({'dst': self.vm1_rtr_mask, 'gateway': self.vm2_rtr_ip}).commit() self.vm1_mac = ns1_ipdb.interfaces['eth0'].address self.vm2_mac = ns2_ipdb.interfaces['eth0'].address (_, self.nsrtr_eth0_out, _) = sim._create_ns(self.ns_router, ipaddr=self.vm1_rtr_ip+'/24', fn=self.br1_fn, action='drop', disable_ipv6=True) (rt_ipdb, self.nsrtr_eth1_out, _) = sim._ns_add_ifc(self.ns_router, "eth1", "ns_router2", ipaddr=self.vm2_rtr_ip+'/24', fn=self.br2_fn, action='drop', disable_ipv6=True) nsp = NSPopen(rt_ipdb.nl.netns, ["sysctl", "-w", "net.ipv4.ip_forward=1"]) nsp.wait(); nsp.release() # configure maps self.config_maps() # our bridge is not smart enough, so send arping for router learning to prevent router # from sending out arp request nsp = NSPopen(ns1_ipdb.nl.netns, ["arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm1_rtr_ip]) nsp.wait(); nsp.release() nsp = NSPopen(ns2_ipdb.nl.netns, ["arping", "-w", "1", "-c", "1", "-I", "eth0", self.vm2_rtr_ip]) nsp.wait(); nsp.release() # ping nsp = NSPopen(ns1_ipdb.nl.netns, ["ping", self.vm2_ip, "-c", "2"]) nsp.wait(); nsp.release() # pem_stats only counts pem->bridge traffic, each VM has 4: arping/arp request/2 icmp request # total 8 packets should be counted self.assertEqual(self.pem_stats[c_uint(0)].value, 8) nsp_server = NSPopen(ns2_ipdb.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(ns1_ipdb.nl.netns, ["iperf", "-c", self.vm2_ip, "-t", "1", "-xSC"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release() nsp_server = NSPopen(ns2_ipdb.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopen(ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "--", "-m", "65160"]) nsp.wait(); nsp.release() nsp = NSPopen(ns1_ipdb.nl.netns, ["netperf", "-l", "1", "-H", self.vm2_ip, "-t", "TCP_RR"]) nsp.wait(); nsp.release() nsp_server.kill(); nsp_server.wait(); nsp_server.release() finally: sim.release() ipdb.release()
def _ns_add_ifc(self, name, ns_ifc, ifc_base_name=None, in_ifc=None, out_ifc=None, ipaddr=None, macaddr=None, fn=None, cmd=None, action="ok", disable_ipv6=False): if name in self.ipdbs: ns_ipdb = self.ipdbs[name] else: try: nl=NetNS(name) self.namespaces.append(nl) except KeyboardInterrupt: # remove the namespace if it has been created pyroute2.netns.remove(name) raise ns_ipdb = IPDB(nl) self.ipdbs[nl.netns] = ns_ipdb if disable_ipv6: cmd1 = ["sysctl", "-q", "-w", "net.ipv6.conf.default.disable_ipv6=1"] nsp = NSPopen(ns_ipdb.nl.netns, cmd1) nsp.wait(); nsp.release() ns_ipdb.interfaces.lo.up().commit() if in_ifc: in_ifname = in_ifc.ifname with in_ifc as v: # move half of veth into namespace v.net_ns_fd = ns_ipdb.nl.netns else: # delete the potentially leaf-over veth interfaces ipr = IPRoute() for i in ipr.link_lookup(ifname='%sa' % ifc_base_name): ipr.link_remove(i) ipr.close() try: out_ifc = self.ipdb.create(ifname="%sa" % ifc_base_name, kind="veth", peer="%sb" % ifc_base_name).commit() in_ifc = self.ipdb.interfaces[out_ifc.peer] in_ifname = in_ifc.ifname with in_ifc as v: v.net_ns_fd = ns_ipdb.nl.netns except KeyboardInterrupt: # explicitly remove the interface out_ifname = "%sa" % ifc_base_name if out_ifname in self.ipdb.interfaces: self.ipdb.interfaces[out_ifname].remove().commit() raise if out_ifc: out_ifc.up().commit() ns_ipdb.interfaces.lo.up().commit() ns_ipdb.initdb() in_ifc = ns_ipdb.interfaces[in_ifname] with in_ifc as v: v.ifname = ns_ifc if ipaddr: v.add_ip("%s" % ipaddr) if macaddr: v.address = macaddr v.up() if disable_ipv6: cmd1 = ["sysctl", "-q", "-w", "net.ipv6.conf.%s.disable_ipv6=1" % out_ifc.ifname] subprocess.call(cmd1) if fn and out_ifc: self.ipdb.nl.tc("add", "ingress", out_ifc["index"], "ffff:") self.ipdb.nl.tc("add-filter", "bpf", out_ifc["index"], ":1", fd=fn.fd, name=fn.name, parent="ffff:", action=action, classid=1) if cmd: self.processes.append(NSPopen(ns_ipdb.nl.netns, cmd)) return (ns_ipdb, out_ifc, in_ifc)
def _ns_add_ifc(self, name, ns_ifc, ifc_base_name=None, in_ifc=None, out_ifc=None, ipaddr=None, macaddr=None, fn=None, cmd=None, action="ok", disable_ipv6=False): if name in self.ipdbs: ns_ipdb = self.ipdbs[name] else: try: nl = NetNS(name) self.namespaces.append(nl) except KeyboardInterrupt: # remove the namespace if it has been created pyroute2.netns.remove(name) raise ns_ipdb = IPDB(nl) self.ipdbs[nl.netns] = ns_ipdb if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.default.disable_ipv6=1" ] nsp = NSPopen(ns_ipdb.nl.netns, cmd1) nsp.wait() nsp.release() ns_ipdb.interfaces.lo.up().commit() if in_ifc: in_ifname = in_ifc.ifname with in_ifc as v: # move half of veth into namespace v.net_ns_fd = ns_ipdb.nl.netns else: # delete the potentially leaf-over veth interfaces ipr = IPRoute() for i in ipr.link_lookup(ifname='%sa' % ifc_base_name): ipr.link_remove(i) ipr.close() try: out_ifc = self.ipdb.create(ifname="%sa" % ifc_base_name, kind="veth", peer="%sb" % ifc_base_name).commit() in_ifc = self.ipdb.interfaces[out_ifc.peer] in_ifname = in_ifc.ifname with in_ifc as v: v.net_ns_fd = ns_ipdb.nl.netns except KeyboardInterrupt: # explicitly remove the interface out_ifname = "%sa" % ifc_base_name if out_ifname in self.ipdb.interfaces: self.ipdb.interfaces[out_ifname].remove().commit() raise if out_ifc: out_ifc.up().commit() ns_ipdb.interfaces.lo.up().commit() in_ifc = ns_ipdb.interfaces[in_ifname] with in_ifc as v: v.ifname = ns_ifc if ipaddr: v.add_ip("%s" % ipaddr) if macaddr: v.address = macaddr v.up() if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.%s.disable_ipv6=1" % out_ifc.ifname ] subprocess.call(cmd1) if fn and out_ifc: self.ipdb.nl.tc("add", "ingress", out_ifc["index"], "ffff:") self.ipdb.nl.tc("add-filter", "bpf", out_ifc["index"], ":1", fd=fn.fd, name=fn.name, parent="ffff:", action=action, classid=1) if cmd: self.processes.append(NSPopen(ns_ipdb.nl.netns, cmd)) return (ns_ipdb, out_ifc, in_ifc)
def test_topology(self): nsp = NSPopen(self.ns_array[0].id.nl.netns, ["ping", "192.168.6.2", "-c", "2"]) nsp.wait() nsp.release() # one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total nsp_server = NSPopen(self.ns_array[2].id.nl.netns, ["iperf", "-s", "-xSC"]) sleep(1) nsp = NSPopen(self.ns_array[0].id.nl.netns, ["iperf", "-c", "192.168.6.2", "-t", "1", "-xSC"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release() nsp_server = NSPopen(self.ns_array[2].id.nl.netns, ["netserver", "-D"]) sleep(1) nsp = NSPopen( self.ns_array[0].id.nl.netns, ["netperf", "-l", "1", "-H", "192.168.6.2", "--", "-m", "65160"]) nsp.wait() nsp.release() nsp = NSPopen( self.ns_array[0].id.nl.netns, ["netperf", "-l", "1", "-H", "192.168.6.2", "-t", "TCP_RR"]) nsp.wait() nsp.release() nsp_server.kill() nsp_server.wait() nsp_server.release()
def start(self): # Ingress = attached to tc ingress class on bridge # Egress = attached to tc engress class on namespace (outside) interface # Loading bpf functions/maps. brb_code = BPF(src_file="brb_topology_with_patch_pannel.c") pvm_fn = brb_code.load_func("pvm_function_p2v", BPF.SCHED_CLS) patchpanel_fn = brb_code.load_func("patch_panel_function", BPF.SCHED_CLS) broadcaster_fn = brb_code.load_func("broadcaster", BPF.SCHED_CLS) br1_fn = brb_code.load_func("br1_function", BPF.SCHED_CLS) print("loading router code") rt_fn = brb_code.load_func("router_function", BPF.SCHED_CLS) br2_fn = brb_code.load_func("br2_function", BPF.SCHED_CLS) vnf_prog = brb_code.get_table("vnf_prog") pvm_ifc2vi = brb_code.get_table("pvm_ifc2vi") forward_vi = brb_code.get_table("forwarder_vi") mac2host_br1 = brb_code.get_table("mac2host_br1") conf_br1 = brb_code.get_table("conf_br1") mac2host_br2 = brb_code.get_table("mac2host_br2") conf_br2 = brb_code.get_table("conf_br2") router_host = brb_code.get_table("router_host") #arp_table = brb_code.get_table("arp_table") vnf_prog[c_int(0)] = c_int(patchpanel_fn.fd) vnf_prog[c_int(1)] = c_int(pvm_fn.fd) vnf_prog[c_int(2)] = c_int(br1_fn.fd) vnf_prog[c_int(3)] = c_int(rt_fn.fd) vnf_prog[c_int(4)] = c_int(br2_fn.fd) #Need to add pem into this list. # Setup namespace and their interfaces for demostration of br1. host_info_br1 = [] for i in range(0, num_hosts): print("Launching host %i of %i in br1" % (i + 1, num_hosts)) ipaddr = "172.16.1.%d/24" % (100 + i) host_info_br1.append(self._create_ns("host%d" % i, ipaddr=ipaddr, disable_ipv6=True)) # Setup namespace and their interfaces for demostration of br2. host_info_br2 = [] for i in range(0, num_hosts): print("Launching host %i of %i in br2" % (i + 1, num_hosts)) ipaddr = "192.168.1.%d/24" % (100 + i) host_info_br2.append(self._create_ns("host%d" % (i+4), ipaddr=ipaddr, disable_ipv6=True)) # creating broadcaster, to help broadcast the unknown packets from bridge print("creating broadcaster interface") broadcaster = ipdb.create(ifname="bc", kind="dummy").up().commit() ipr.tc("add", "ingress", broadcaster.index, "ffff:") ipr.tc("add-filter", "bpf", broadcaster.index, ":1", fd=broadcaster_fn.fd, name=broadcaster_fn.name, parent="ffff:", action="drop", classid=1) print("adding it into bridges") conf_br1[c_uint(0)] = conf_br1.Leaf(c_uint(broadcaster.index)) conf_br2[c_uint(0)] = conf_br2.Leaf(c_uint(broadcaster.index)) print("attaching router between the bridges br1 and br2") conf_br1[c_uint(1)] = conf_br1.Leaf(c_uint(2000)) conf_br2[c_uint(1)] = conf_br2.Leaf(c_uint(4000)) forward_vi[c_int(2000)] = forward_vi.Leaf(1, c_uint(5000), c_uint(3) , 0) forward_vi[c_int(5000)] = forward_vi.Leaf(1, c_uint(2000), c_uint(2) , 0) forward_vi[c_int(4000)] = forward_vi.Leaf(1, c_uint(5001), c_uint(3) , 0) forward_vi[c_int(5001)] = forward_vi.Leaf(1, c_uint(4000), c_uint(4) , 0) #now tell router about it's interfaces router_host[c_int(5000)] = router_host.Leaf(self.ip2bin("172.16.1.1"), self.mac2bin("0d:b5:2f:b4:0b:1f"),0,0,0) router_host[c_int(5001)] = router_host.Leaf(self.ip2bin("192.168.1.1"), self.mac2bin("64:65:9c:b4:85:2d"),0,0,0) print("creating virutal topology for br1") # For each namespace that want to connect to the ebpf bridge index = 1 for host in host_info_br1: ipr.tc("add", "ingress", host[1].index, "ffff:") ipr.tc("add-filter", "bpf", host[1].index, ":1", fd=pvm_fn.fd, name=pvm_fn.name, parent="ffff:", action="drop", classid=1) # Passing namespace interface info to dataplane module. pvm_ifc2vi[c_uint(host[1].index)] = c_uint(index+1000) forward_vi[c_int(index+1000)] = forward_vi.Leaf(1, c_uint(index+2000), c_uint(2) , 0) forward_vi[c_int(index+2000)] = forward_vi.Leaf(0, c_uint(host[1].index), 0 , 0) conf_br1[c_uint(index+1)]= conf_br1.Leaf(c_uint(index+2000)) cmd1 = ["route", "add", "default", "gw","172.16.1.1"] nsp = NSPopen(host[0].nl.netns, cmd1) nsp.wait(); nsp.release() cmd1 = ["arping", "-c", "1", "172.16.1.1","-q"] nsp = NSPopen(host[0].nl.netns, cmd1) nsp.wait(); nsp.release() index = index+1 print("creating virtual topology for br2") # For each namespace that want to connect to the ebpf bridge index = 1 for host in host_info_br2: ipr.tc("add", "ingress", host[1].index, "ffff:") ipr.tc("add-filter", "bpf", host[1].index, ":1", fd=pvm_fn.fd, name=pvm_fn.name, parent="ffff:", action="drop", classid=1) # Passing namespace interface info to dataplane module. pvm_ifc2vi[c_uint(host[1].index)] = c_uint(index+3000) forward_vi[c_int(index+3000)] = forward_vi.Leaf(1, c_uint(index+4000), c_uint(4) , 0) forward_vi[c_int(index+4000)] = forward_vi.Leaf(0, c_uint(host[1].index), 0 , 0) conf_br2[c_uint(index+1)]= conf_br2.Leaf(c_uint(index+4000)) index = index+1 cmd1 = ["route", "add", "default", "gw","192.168.1.1"] nsp = NSPopen(host[0].nl.netns, cmd1) nsp.wait(); nsp.release() cmd1 = ["arping", "-c", "1", "192.168.1.1","-q"] nsp = NSPopen(host[0].nl.netns, cmd1) nsp.wait(); nsp.release() index = index+1
'add', 'dev', veth, 'root', 'netem', 'delay', f'{args.delay}ms', f'{int(args.delay)/2}ms', 'loss', f'{args.loss}%', '25%', ], stdout=subprocess.PIPE, ) nsp.communicate() nsp.wait() nsp.release() if args.verbose: print(f'netem: add {nsname}/{veth}, ' f'{args.delay}, {args.loss}') # create the tap # # for some reason we should create the tap inteface first, # and only then bring it up, thus two commit() calls (ndb.interfaces.create(kind='tuntap', ifname=tap_name, mode='tap').commit().set('state', 'up').commit()) if args.verbose: print(f'link: add main/{tap_name}')