def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, vlan_ports, ports_per_vlan): self.oper_type = '' self.memb_cnt = 0 self.cnt = 1 if 'routing' not in oper_type else len(vm_list) self.ip_cnt = 1 self.vm_list = vm_list self.portchannel_ports = portchannel_ports self.vm_dut_map = vm_dut_map self.test_args = test_args self.dut_connection = DeviceConnection(test_args['dut_hostname'], test_args['dut_username'], password=test_args['dut_password']) self.vlan_ports = vlan_ports self.ports_per_vlan = ports_per_vlan self.vlan_if_port = self.test_args['vlan_if_port'] self.neigh_vms = [] self.neigh_names = dict() self.vm_handles = dict() self.neigh_bgps = dict() self.dut_bgps = dict() self.log = [] self.fails = dict() self.fails['dut'] = set() self.tot_memb_cnt = 0 self.memb_index = 0 self.if_port = [] self.down_vlan_info = [] self.bp_ip = None self.bp_ip6 = None self.extract_oper_info(oper_type) self.extract_nexthops()
def setUp(self): self.dataplane = ptf.dataplane_instance config = self.get_param('config_file') self.ferret_ip = self.get_param('ferret_ip') self.dut_ssh = self.get_param('dut_ssh') self.dut_username = self.get_param('dut_username') self.dut_password = self.get_param('dut_password') self.dut_connection = DeviceConnection(self.dut_ssh, username=self.dut_username, password=self.dut_password) self.how_long = int( self.get_param('how_long', required=False, default=300)) if not os.path.isfile(config): raise Exception("the config file %s doesn't exist" % config) with open(config) as fp: graph = json.load(fp) self.tests = [] vni_base = 0 for name, data in graph['minigraph_vlans'].items(): test = {} test['acc_ports'] = [ graph['minigraph_port_indices'][member] for member in data['members'] ] vlan_id = int(name.replace('Vlan', '')) test['vni'] = vni_base + vlan_id gw = None prefixlen = None for d in graph['minigraph_vlan_interfaces']: if d['attachto'] == name: gw = d['addr'] prefixlen = int(d['prefixlen']) break else: raise Exception("Vlan '%s' is not found" % name) test['vlan_gw'] = gw test['vlan_ip_prefixes'] = self.generate_VlanPrefixes( gw, prefixlen, test['acc_ports']) self.tests.append(test) self.dut_mac = graph['dut_mac'] self.ptf_mac_addrs = self.readMacs() self.generatePackets() self.cmd(["supervisorctl", "restart", "ferret"]) self.dataplane.flush() return
def setUp(self): self.dataplane = ptf.dataplane_instance self.test_params = testutils.test_params_get() if 'vxlan_enabled' in self.test_params and self.test_params[ 'vxlan_enabled']: self.vxlan_enabled = True if 'count' in self.test_params: self.nr = int(self.test_params['count']) if 'config_file' not in self.test_params: raise Exception("required parameter 'config_file' is not present") config = self.test_params['config_file'] if 'dut_host' not in self.test_params: raise Exception("required parameter 'dut_host' is not present") self.dut_host = self.test_params['dut_host'] if 'sonic_admin_user' not in self.test_params: raise Exception( "required parameter 'sonic_admin_user' is not present") self.sonic_admin_user = self.test_params['sonic_admin_user'] if 'sonic_admin_password' not in self.test_params: raise Exception( "required parameter 'sonic_admin_password' is not present") self.sonic_admin_password = self.test_params['sonic_admin_password'] if not os.path.isfile(config): raise Exception("the config file %s doesn't exist" % config) with open(config) as fp: graph = json.load(fp) self.pc_info = [] self.net_ports = [] for name, val in graph['minigraph_portchannels'].items(): members = [ graph['minigraph_port_indices'][member] for member in val['members'] ] self.net_ports.extend(members) ip = None for d in graph['minigraph_portchannel_interfaces']: if d['attachto'] == name: ip = d['peer_addr'] break else: raise Exception("Portchannel '%s' ip address is not found" % name) self.pc_info.append((ip, members)) self.tests = [] vni_base = 336 for name, data in graph['minigraph_vlans'].items(): test = {} test['name'] = name test['intf_alias'] = data['members'] test['acc_ports'] = [ graph['minigraph_port_indices'][member] for member in data['members'] ] vlan_id = int(name.replace('Vlan', '')) test['vni'] = vni_base + vlan_id test['src_ip'] = "8.8.8.8" gw = None prefixlen = None for d in graph['minigraph_vlan_interfaces']: if d['attachto'] == name: gw = d['addr'] prefixlen = int(d['prefixlen']) break else: raise Exception("Vlan '%s' is not found" % name) test['vlan_gw'] = gw test['vlan_ip_prefixes'] = self.generate_VlanPrefixes( gw, prefixlen, test['acc_ports']) self.tests.append(test) self.log('Collected tests: {}'.format(pprint.pformat(self.tests))) self.dut_mac = graph['dut_mac'] ip = None for data in graph['minigraph_lo_interfaces']: if data['prefixlen'] == 32: ip = data['addr'] break else: raise Exception("ipv4 lo interface not found") self.loopback_ip = ip self.ptf_mac_addrs = self.readMacs() self.generate_ArpResponderConfig() self.cmd(["supervisorctl", "restart", "arp_responder"]) #Wait a short time for asp_reponder to be ready time.sleep(10) self.dataplane.flush() self.dut_connection = DeviceConnection( self.dut_host, self.sonic_admin_user, password=self.sonic_admin_password) return
class Vxlan(BaseTest): def __init__(self): BaseTest.__init__(self) self.vxlan_enabled = False self.random_mac = '8c:01:02:03:04:05' self.nr = 1 current_time = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") log_file_name = "/tmp/vxlan_decap_test.{}.log".format(current_time) self.log_fp = open(log_file_name, 'w') def cmd(self, cmds): process = subprocess.Popen(cmds, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() return_code = process.returncode return stdout, stderr, return_code def log(self, message): current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.log_fp.write("{} : {}\n".format(current_time, message)) self.log_fp.flush() def readMacs(self): addrs = {} for intf in os.listdir('/sys/class/net'): if os.path.isdir('/sys/class/net/%s' % intf): with open('/sys/class/net/%s/address' % intf) as fp: addrs[intf] = fp.read().strip() return addrs def generate_ArpResponderConfig(self): config = {} for test in self.tests: for port, ip in test['vlan_ip_prefixes'].items(): config['eth%d' % port] = [ip] with open('/tmp/vxlan_arpresponder.conf', 'w') as fp: json.dump(config, fp) return def generate_VlanPrefixes(self, gw, prefixlen, acc_ports): res = {} n_hosts = 2**(32 - prefixlen) - 3 nr_of_dataplane_ports = len(self.dataplane.ports) if nr_of_dataplane_ports > n_hosts: raise Exception("The prefix len size is too small for the test") gw_addr_n = struct.unpack(">I", socket.inet_aton(gw))[0] mask = (2**32 - 1) ^ (2**(32 - prefixlen) - 1) net_addr_n = gw_addr_n & mask addr = 1 for port in acc_ports: while True: host_addr_n = net_addr_n + addr host_ip = socket.inet_ntoa(struct.pack(">I", host_addr_n)) if host_ip != gw: break else: addr += 1 # skip gw res[port] = host_ip addr += 1 return res def setUp(self): self.dataplane = ptf.dataplane_instance self.test_params = testutils.test_params_get() if 'vxlan_enabled' in self.test_params and self.test_params[ 'vxlan_enabled']: self.vxlan_enabled = True if 'count' in self.test_params: self.nr = int(self.test_params['count']) if 'config_file' not in self.test_params: raise Exception("required parameter 'config_file' is not present") config = self.test_params['config_file'] if 'dut_host' not in self.test_params: raise Exception("required parameter 'dut_host' is not present") self.dut_host = self.test_params['dut_host'] if 'sonic_admin_user' not in self.test_params: raise Exception( "required parameter 'sonic_admin_user' is not present") self.sonic_admin_user = self.test_params['sonic_admin_user'] if 'sonic_admin_password' not in self.test_params: raise Exception( "required parameter 'sonic_admin_password' is not present") self.sonic_admin_password = self.test_params['sonic_admin_password'] if not os.path.isfile(config): raise Exception("the config file %s doesn't exist" % config) with open(config) as fp: graph = json.load(fp) self.pc_info = [] self.net_ports = [] for name, val in graph['minigraph_portchannels'].items(): members = [ graph['minigraph_port_indices'][member] for member in val['members'] ] self.net_ports.extend(members) ip = None for d in graph['minigraph_portchannel_interfaces']: if d['attachto'] == name: ip = d['peer_addr'] break else: raise Exception("Portchannel '%s' ip address is not found" % name) self.pc_info.append((ip, members)) self.tests = [] vni_base = 336 for name, data in graph['minigraph_vlans'].items(): test = {} test['name'] = name test['intf_alias'] = data['members'] test['acc_ports'] = [ graph['minigraph_port_indices'][member] for member in data['members'] ] vlan_id = int(name.replace('Vlan', '')) test['vni'] = vni_base + vlan_id test['src_ip'] = "8.8.8.8" gw = None prefixlen = None for d in graph['minigraph_vlan_interfaces']: if d['attachto'] == name: gw = d['addr'] prefixlen = int(d['prefixlen']) break else: raise Exception("Vlan '%s' is not found" % name) test['vlan_gw'] = gw test['vlan_ip_prefixes'] = self.generate_VlanPrefixes( gw, prefixlen, test['acc_ports']) self.tests.append(test) self.log('Collected tests: {}'.format(pprint.pformat(self.tests))) self.dut_mac = graph['dut_mac'] ip = None for data in graph['minigraph_lo_interfaces']: if data['prefixlen'] == 32: ip = data['addr'] break else: raise Exception("ipv4 lo interface not found") self.loopback_ip = ip self.ptf_mac_addrs = self.readMacs() self.generate_ArpResponderConfig() self.cmd(["supervisorctl", "restart", "arp_responder"]) #Wait a short time for asp_reponder to be ready time.sleep(10) self.dataplane.flush() self.dut_connection = DeviceConnection( self.dut_host, self.sonic_admin_user, password=self.sonic_admin_password) return def check_arp_table_on_dut(self, test): COMMAND = 'show arp' stdout, stderr, return_code = self.dut_connection.execCommand(COMMAND) for idx, port in enumerate(test['acc_ports']): intf_alias = test['intf_alias'][idx] ip_prefix = test['vlan_ip_prefixes'][port] for line in stdout: if re.match(r"{}.*{}.*".format(ip_prefix, intf_alias), line, re.IGNORECASE): break else: return False return True def check_fdb_on_dut(self, test): COMMAND = 'fdbshow' stdout, stderr, return_code = self.dut_connection.execCommand(COMMAND) for idx, port in enumerate(test['acc_ports']): mac_addr = self.ptf_mac_addrs['eth%d' % port] intf_alias = test['intf_alias'][idx] for line in stdout: if re.match(r".*{}.*{}.*".format(mac_addr, intf_alias), line, re.IGNORECASE): break else: return False return True def wait_dut(self, test, timeout): start_time = datetime.datetime.now() while True: if self.check_fdb_on_dut(test) and self.check_arp_table_on_dut( test): return True if (datetime.datetime.now() - start_time).seconds > timeout: return False time.sleep(3) def tearDown(self): self.cmd(["supervisorctl", "stop", "arp_responder"]) self.log_fp.close() return def warmup(self): self.log("Warming up") err = '' trace = '' ret = 0 TIMEOUT = 60 try: for test in self.tests: self.RegularLAGtoVLAN(test, True) #wait sometime for DUT to build FDB and ARP table res = self.wait_dut(test, TIMEOUT) self.log_dut_status() self.assertTrue( res, "DUT is not ready after {} seconds".format(TIMEOUT)) except Exception as e: err = str(e) trace = traceback.format_exc() ret = -1 if ret != 0: self.log("The warmup failed") self.log("Error: %s" % err) self.log(trace) else: self.log("Warmup successful") sys.stdout.flush() if ret != 0: raise AssertionError("Warmup failed") def log_dut_status(self): COMMAND = 'show arp' stdout, stderr, return_code = self.dut_connection.execCommand(COMMAND) self.log("ARP table on DUT \n{}".format(stdout)) COMMAND = 'fdbshow' stdout, stderr, return_code = self.dut_connection.execCommand(COMMAND) self.log("MAC table on DUT \n{}".format(stdout)) COMMAND = 'show vxlan tunnel' stdout, stderr, return_code = self.dut_connection.execCommand(COMMAND) self.log("vxlan config on DUT \n{}".format(stdout)) def work_test(self): self.log("Testing") err = '' trace = '' ret = 0 try: for test in self.tests: self.log(test['name']) res_f, out_f = self.RegularLAGtoVLAN(test) self.log("RegularLAGtoVLAN = {} {}".format(res_f, out_f)) if not res_f: self.log_dut_status() self.assertTrue( res_f, "RegularLAGtoVLAN test failed:\n %s\n" % (out_f)) res_t, out_t = self.RegularVLANtoLAG(test) self.log("RegularVLANtoLAG = {} {}".format(res_t, out_t)) if not res_t: self.log_dut_status() self.assertTrue( res_t, "RegularVLANtoLAG test failed:\n %s\n" % (out_t)) res_v, out_v = self.Vxlan(test) self.log("Vxlan = {} {}".format(res_v, out_v)) if self.vxlan_enabled: if not res_v: self.log_dut_status() self.assertTrue(res_v, "VxlanTest failed:\n %s\n" % (out_v)) else: if res_v: self.log_dut_status() self.assertFalse( res_v, "VxlanTest: vxlan works, but it must have been disabled!\n" ) except AssertionError as e: err = str(e) trace = traceback.format_exc() ret = -1 if ret != 0: self.log("The test failed") self.log("Error: {}".format(err)) self.log(trace) else: self.log("The test was successful") sys.stdout.flush() if ret != 0: raise AssertionError(err) def runTest(self): # Warm-up first self.warmup() # test itself self.work_test() def Vxlan(self, test): for i, n in enumerate(test['acc_ports']): for j, a in enumerate(test['acc_ports']): res, out = self.checkVxlan(a, n, test) if not res: return False, out + " | net_port_rel(acc)=%d acc_port_rel=%d" % ( i, j) for i, n in enumerate(self.net_ports): for j, a in enumerate(test['acc_ports']): res, out = self.checkVxlan(a, n, test) if not res: return False, out + " | net_port_rel=%d acc_port_rel=%d" % ( i, j) return True, "" def RegularLAGtoVLAN(self, test, wu=False): for i, n in enumerate(self.net_ports): for j, a in enumerate(test['acc_ports']): res, out = self.checkRegularRegularLAGtoVLAN(a, n, test, wu) if wu: #Wait a short time for building FDB and ARP table time.sleep(0.5) if not res and not wu: return False, out + " | net_port_rel=%d acc_port_rel=%d" % ( i, j) #We only loop all acc_ports in warmup if wu: break return True, "" def RegularVLANtoLAG(self, test): for i, (dst, ports) in enumerate(self.pc_info): for j, a in enumerate(test['acc_ports']): res, out = self.checkRegularRegularVLANtoLAG( a, ports, dst, test) if not res: return False, out + " | pc_info_rel=%d acc_port_rel=%d" % ( i, j) return True, "" def checkRegularRegularVLANtoLAG(self, acc_port, pc_ports, dst_ip, test): src_mac = self.ptf_mac_addrs['eth%d' % acc_port] dst_mac = self.dut_mac src_ip = test['vlan_ip_prefixes'][acc_port] packet = simple_tcp_packet( eth_dst=dst_mac, eth_src=src_mac, ip_src=src_ip, ip_dst=dst_ip, ) exp_packet = simple_tcp_packet( eth_dst=self.random_mac, eth_src=dst_mac, ip_src=src_ip, ip_dst=dst_ip, ip_ttl=63, ) exp_packet = Mask(exp_packet) exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") self.dataplane.flush() for i in xrange(self.nr): testutils.send_packet(self, acc_port, packet) nr_rcvd = count_matched_packets_all_ports_helper(self, exp_packet, self.nr, pc_ports, timeout=20) rv = nr_rcvd == self.nr out = "" if not rv: arg = self.nr, nr_rcvd, str(acc_port), str( pc_ports), src_mac, dst_mac, src_ip, dst_ip out = "sent = %d rcvd = %d | src_port=%s dst_ports=%s | src_mac=%s dst_mac=%s src_ip=%s dst_ip=%s" % arg return rv, out def checkRegularRegularLAGtoVLAN(self, acc_port, net_port, test, wu): src_mac = self.random_mac dst_mac = self.dut_mac src_ip = test['src_ip'] dst_ip = test['vlan_ip_prefixes'][acc_port] packet = simple_tcp_packet( eth_dst=dst_mac, eth_src=src_mac, ip_src=src_ip, ip_dst=dst_ip, ) exp_packet = simple_tcp_packet( eth_dst=self.ptf_mac_addrs['eth%d' % acc_port], eth_src=dst_mac, ip_src=src_ip, ip_dst=dst_ip, ip_ttl=63, ) self.dataplane.flush() for i in xrange(self.nr): testutils.send_packet(self, net_port, packet) # We don't care if expected packet is received during warming up if not wu: nr_rcvd = count_matched_packets_helper(self, exp_packet, self.nr, acc_port, timeout=20) else: nr_rcvd = 0 rv = nr_rcvd == self.nr out = "" if not rv: arg = self.nr, nr_rcvd, str(net_port), str( acc_port), src_mac, dst_mac, src_ip, dst_ip out = "sent = %d rcvd = %d | src_port=%s dst_port=%s | src_mac=%s dst_mac=%s src_ip=%s dst_ip=%s" % arg return rv, out def checkVxlan(self, acc_port, net_port, test): inner_dst_mac = self.ptf_mac_addrs['eth%d' % acc_port] inner_src_mac = self.dut_mac inner_src_ip = test['vlan_gw'] inner_dst_ip = test['vlan_ip_prefixes'][acc_port] dst_mac = self.dut_mac src_mac = self.random_mac ip_dst = self.loopback_ip inpacket = simple_arp_packet(eth_dst=inner_dst_mac, eth_src=inner_src_mac, arp_op=2, ip_snd=inner_src_ip, ip_tgt=inner_dst_ip, hw_snd=inner_src_mac, hw_tgt=inner_dst_mac) packet = simple_vxlan_packet(eth_dst=dst_mac, eth_src=src_mac, ip_src=test['src_ip'], ip_dst=ip_dst, vxlan_vni=test['vni'], inner_frame=inpacket) self.dataplane.flush() for i in xrange(self.nr): testutils.send_packet(self, net_port, packet) nr_rcvd = count_matched_packets_helper(self, inpacket, self.nr, acc_port, timeout=20) rv = nr_rcvd == self.nr out = "" if not rv: arg = self.nr, nr_rcvd, str(net_port), str( acc_port ), src_mac, dst_mac, test[ 'src_ip'], ip_dst, inner_src_mac, inner_dst_mac, inner_src_ip, inner_dst_ip, test[ 'vni'] out = "sent = %d rcvd = %d | src_port=%s dst_port=%s | src_mac=%s dst_mac=%s src_ip=%s dst_ip=%s | Inner: src_mac=%s dst_mac=%s src_ip=%s dst_ip=%s vni=%s" % arg return rv, out
def setUp(self): self.dataplane = ptf.dataplane_instance config = self.get_param('config_file') self.ferret_ip = self.get_param('ferret_ip') self.dut_ssh = self.get_param('dut_ssh') self.dut_username = self.get_param('dut_username') self.dut_password = self.get_param('dut_password') self.dut_alt_password = self.get_param('alt_password') self.dut_connection = DeviceConnection( self.dut_ssh, username=self.dut_username, password=self.dut_password, alt_password=self.dut_alt_password) self.how_long = int( self.get_param('how_long', required=False, default=300)) if not os.path.isfile(config): raise Exception("the config file %s doesn't exist" % config) with open(config) as fp: graph = json.load(fp) self.tests = [] vni_base = 0 for vlan, config in graph['vlan_facts'].items(): test = {} test['acc_ports'] = [] test['tagging_mode'] = {} for member, mode in config['members'].items(): ptf_port_idx = graph['minigraph_port_indices'][member] test['acc_ports'].append(ptf_port_idx) test['tagging_mode'].update( {ptf_port_idx: mode['tagging_mode']}) test['vlan_id'] = int(config['vlanid']) test['vni'] = vni_base + test['vlan_id'] prefixlen = None for d in config['interfaces']: if sys.version_info < (3, 0): ip = ipaddress.ip_address(d['addr'].decode('utf8')) else: ip = ipaddress.ip_address(d['addr']) if ip.version == 4: test['vlan_gw'] = d['addr'] prefixlen = int(d['prefixlen']) test['vlan_ip_prefixes'] = self.generate_VlanPrefixes( d['addr'], prefixlen, test['acc_ports']) break else: raise Exception("No invalid IPv4 address found for Vlan '%s'" % vlan) self.tests.append(test) self.dut_mac = graph['dut_mac'] self.ptf_mac_addrs = self.readMacs() self.generatePackets() self.cmd(["supervisorctl", "restart", "ferret"]) self.dataplane.flush() return