def populate_vlan_arp_entries(setup, ptfhost, duthosts, rand_one_dut_hostname, ip_version): """Set up the ARP responder utility in the PTF container.""" duthost = duthosts[rand_one_dut_hostname] if setup["topo"] != "t0": def noop(): pass yield noop return # Don't fall through to t0 case addr_list = [ DOWNSTREAM_DST_IP[ip_version], DOWNSTREAM_IP_TO_ALLOW[ip_version], DOWNSTREAM_IP_TO_BLOCK[ip_version] ] vlan_host_map = defaultdict(dict) for i in range(len(addr_list)): mac = VLAN_BASE_MAC_PATTERN.format(i) port = random.choice(setup["vlan_ports"]) addr = addr_list[i] vlan_host_map[port][str(addr)] = mac arp_responder_conf = {} for port in vlan_host_map: arp_responder_conf['eth{}'.format(port)] = vlan_host_map[port] with open("/tmp/from_t1.json", "w") as ar_config: json.dump(arp_responder_conf, ar_config) ptfhost.copy(src="/tmp/from_t1.json", dest="/tmp/from_t1.json") ptfhost.host.options["variable_manager"].extra_vars.update( {"arp_responder_args": "-e"}) ptfhost.template(src="templates/arp_responder.conf.j2", dest="/etc/supervisor/conf.d/arp_responder.conf") ptfhost.shell("supervisorctl reread && supervisorctl update") ptfhost.shell("supervisorctl restart arp_responder") def populate_arp_table(): duthost.command("sonic-clear fdb all") duthost.command("sonic-clear arp") for addr in addr_list: duthost.command("ping {} -c 3".format(addr), module_ignore_errors=True) populate_arp_table() yield populate_arp_table logging.info("Stopping ARP responder") ptfhost.shell("supervisorctl stop arp_responder") duthost.command("sonic-clear fdb all") duthost.command("sonic-clear arp")
def check_rule_counters_internal(self, duthost): res = duthost.command('aclshow -a') num_of_lines = len(res['stdout'].split('\n')) if num_of_lines <= 2 or 'N/A' in res['stdout']: return False return True
def populate_arp_table(): duthost.command("sonic-clear fdb all") duthost.command("sonic-clear arp") for addr in addr_list: duthost.command("ping {} -c 3".format(addr), module_ignore_errors=True)
def acl_table(duthosts, rand_one_dut_hostname, setup, stage, ip_version, backup_and_restore_config_db_module): """Apply ACL table configuration and remove after tests. Args: duthosts: All DUTs belong to the testbed. rand_one_dut_hostname: hostname of a random chosen dut to run test. setup: Parameters for the ACL tests. stage: The ACL stage under test. ip_version: The IP version under test. backup_and_restore_config_db_module: A fixture that handles restoring Config DB after the tests are over. Yields: The ACL table configuration. """ duthost = duthosts[rand_one_dut_hostname] table_name = "DATA_{}_{}_TEST".format(stage.upper(), ip_version.upper()) acl_table_config = { "table_name": table_name, "table_ports": ",".join(setup["acl_table_ports"]), "table_stage": stage, "table_type": "L3" if ip_version == "ipv4" else "L3V6" } logger.info("Generated ACL table configuration:\n{}".format( pprint.pformat(acl_table_config))) loganalyzer = LogAnalyzer(ansible_host=duthost, marker_prefix="acl") loganalyzer.load_common_config() try: loganalyzer.expect_regex = [LOG_EXPECT_ACL_TABLE_CREATE_RE] with loganalyzer: logger.info("Creating ACL table: \"{}\"".format(table_name)) duthost.command("config acl add table {} {} -s {} -p {}".format( table_name, acl_table_config["table_type"], acl_table_config["table_stage"], acl_table_config["table_ports"])) except LogAnalyzerError as err: # Cleanup Config DB if table creation failed logger.error("ACL table creation failed, attempting to clean-up...") duthost.command("config acl remove table {}".format(table_name)) raise err try: yield acl_table_config finally: loganalyzer.expect_regex = [LOG_EXPECT_ACL_TABLE_REMOVE_RE] with loganalyzer: logger.info("Removing ACL table \"{}\"".format(table_name)) duthost.command("config acl remove table {}".format(table_name))
def acl_table(duthosts, rand_one_dut_hostname, acl_table_config, backup_and_restore_config_db_module): """Apply ACL table configuration and remove after tests. Args: duthosts: All DUTs belong to the testbed. rand_one_dut_hostname: hostname of a random chosen dut to run test. acl_table_config: A dictionary describing the ACL table configuration to apply. backup_and_restore_config_db_module: A fixture that handles restoring Config DB after the tests are over. Yields: The ACL table configuration. """ duthost = duthosts[rand_one_dut_hostname] table_name = acl_table_config["table_name"] config_file = acl_table_config["config_file"] loganalyzer = LogAnalyzer(ansible_host=duthost, marker_prefix="acl") loganalyzer.load_common_config() try: loganalyzer.expect_regex = [LOG_EXPECT_ACL_TABLE_CREATE_RE] with loganalyzer: logger.info("Creating ACL table from config file: \"{}\"".format( config_file)) # TODO: Use `config` CLI to create ACL table duthost.command( "sonic-cfggen -j {} --write-to-db".format(config_file)) except LogAnalyzerError as err: # Cleanup Config DB if table creation failed logger.error("ACL table creation failed, attempting to clean-up...") duthost.command("config acl remove table {}".format(table_name)) raise err try: yield acl_table_config finally: loganalyzer.expect_regex = [LOG_EXPECT_ACL_TABLE_REMOVE_RE] with loganalyzer: logger.info("Removing ACL table \"{}\"".format(table_name)) duthost.command("config acl remove table {}".format(table_name))
def setup(duthosts, rand_one_dut_hostname, tbinfo, ptfadapter): """Gather all required test information from DUT and tbinfo. Args: duthosts: All DUTs belong to the testbed. rand_one_dut_hostname: hostname of a random chosen dut to run test. tbinfo: A fixture to gather information about the testbed. Yields: A Dictionary with required test information. """ duthost = duthosts[rand_one_dut_hostname] mg_facts = duthost.get_extended_minigraph_facts(tbinfo) # Get the list of upstream/downstream ports downstream_ports = defaultdict(list) upstream_ports = defaultdict(list) downstream_port_ids = [] upstream_port_ids = [] topo = tbinfo["topo"]["type"] for interface, neighbor in mg_facts["minigraph_neighbors"].items(): port_id = mg_facts["minigraph_ptf_indices"][interface] if (topo == "t1" and "T0" in neighbor["name"]) or ( topo == "t0" and "Server" in neighbor["name"]): downstream_ports[neighbor['namespace']].append(interface) downstream_port_ids.append(port_id) elif (topo == "t1" and "T2" in neighbor["name"]) or (topo == "t0" and "T1" in neighbor["name"]): upstream_ports[neighbor['namespace']].append(interface) upstream_port_ids.append(port_id) # Get the list of LAGs port_channels = mg_facts["minigraph_portchannels"] # TODO: We should make this more robust (i.e. bind all active front-panel ports) acl_table_ports = defaultdict(list) if topo == "t0" or tbinfo["topo"]["name"] in ("t1", "t1-lag"): for namespace, port in downstream_ports.iteritems(): acl_table_ports[namespace] += port # In multi-asic we need config both in host and namespace. if namespace: acl_table_ports[''] += port if topo == "t0" or tbinfo["topo"]["name"] in ("t1-lag", "t1-64-lag", "t1-64-lag-clet"): for k, v in port_channels.iteritems(): acl_table_ports[v['namespace']].append(k) # In multi-asic we need config both in host and namespace. if v['namespace']: acl_table_ports[''].append(k) else: for namespace, port in upstream_ports.iteritems(): acl_table_ports[namespace] += port # In multi-asic we need config both in host and namespace. if namespace: acl_table_ports[''] += port vlan_ports = [] vlan_mac = duthost.facts["router_mac"] if topo == "t0": vlan_ports = [ mg_facts["minigraph_ptf_indices"][ifname] for ifname in mg_facts["minigraph_vlans"].values()[0]["members"] ] vlan_table = duthost.get_running_config_facts()['VLAN'] vlan_name = list(vlan_table.keys())[0] vlan_mac = duthost.get_dut_iface_mac(vlan_name) setup_information = { "router_mac": duthost.facts["router_mac"], "downstream_port_ids": downstream_port_ids, "upstream_port_ids": upstream_port_ids, "acl_table_ports": acl_table_ports, "vlan_ports": vlan_ports, "topo": topo, "vlan_mac": vlan_mac } logger.info("Gathered variables for ACL test:\n{}".format( pprint.pformat(setup_information))) logger.info( "Creating temporary folder \"{}\" for ACL test".format(DUT_TMP_DIR)) duthost.command("mkdir -p {}".format(DUT_TMP_DIR)) yield setup_information logger.info("Removing temporary directory \"{}\"".format(DUT_TMP_DIR)) duthost.command("rm -rf {}".format(DUT_TMP_DIR))
def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptfadapter): """Gather all required test information from DUT and tbinfo. Args: duthosts: All DUTs belong to the testbed. rand_one_dut_hostname: hostname of a random chosen dut to run test. tbinfo: A fixture to gather information about the testbed. Yields: A Dictionary with required test information. """ mg_facts = rand_selected_dut.get_extended_minigraph_facts(tbinfo) topo = tbinfo["topo"]["type"] vlan_ports = [] vlan_mac = None if topo == "t0": vlan_ports = [ mg_facts["minigraph_ptf_indices"][ifname] for ifname in mg_facts["minigraph_vlans"].values()[0]["members"] ] config_facts = rand_selected_dut.get_running_config_facts() vlan_table = config_facts["VLAN"] vlan_name = list(vlan_table.keys())[0] if "mac" in vlan_table[vlan_name]: vlan_mac = vlan_table[vlan_name]["mac"] # Get the list of upstream/downstream ports downstream_ports = defaultdict(list) upstream_ports = defaultdict(list) downstream_port_ids = [] upstream_port_ids = [] upstream_port_id_to_router_mac_map = {} downstream_port_id_to_router_mac_map = {} # For T0/dual ToR testbeds, we need to use the VLAN MAC to interact with downstream ports # For T1 testbeds, no VLANs are present so using the router MAC is acceptable downlink_dst_mac = vlan_mac if vlan_mac is not None else rand_selected_dut.facts[ "router_mac"] for interface, neighbor in mg_facts["minigraph_neighbors"].items(): port_id = mg_facts["minigraph_ptf_indices"][interface] if (topo == "t1" and "T0" in neighbor["name"]) or ( topo == "t0" and "Server" in neighbor["name"]): downstream_ports[neighbor['namespace']].append(interface) downstream_port_ids.append(port_id) downstream_port_id_to_router_mac_map[port_id] = downlink_dst_mac elif (topo == "t1" and "T2" in neighbor["name"]) or (topo == "t0" and "T1" in neighbor["name"]): upstream_ports[neighbor['namespace']].append(interface) upstream_port_ids.append(port_id) upstream_port_id_to_router_mac_map[ port_id] = rand_selected_dut.facts["router_mac"] # stop garp service for single tor if 'dualtor' not in tbinfo['topo']['name']: logging.info("Stopping GARP service on single tor") ptfhost.shell("supervisorctl stop garp_service", module_ignore_errors=True) # If running on a dual ToR testbed, any uplink for either ToR is an acceptable # source or destination port if 'dualtor' in tbinfo['topo']['name'] and rand_unselected_dut is not None: peer_mg_facts = rand_unselected_dut.get_extended_minigraph_facts( tbinfo) for interface, neighbor in peer_mg_facts['minigraph_neighbors'].items( ): if (topo == "t1" and "T2" in neighbor["name"]) or ( topo == "t0" and "T1" in neighbor["name"]): port_id = peer_mg_facts["minigraph_ptf_indices"][interface] upstream_port_ids.append(port_id) upstream_port_id_to_router_mac_map[ port_id] = rand_unselected_dut.facts["router_mac"] # Get the list of LAGs port_channels = mg_facts["minigraph_portchannels"] # TODO: We should make this more robust (i.e. bind all active front-panel ports) acl_table_ports = defaultdict(list) if topo == "t0" or tbinfo["topo"]["name"] in ("t1", "t1-lag"): for namespace, port in downstream_ports.iteritems(): acl_table_ports[namespace] += port # In multi-asic we need config both in host and namespace. if namespace: acl_table_ports[''] += port if topo == "t0" or tbinfo["topo"]["name"] in ("t1-lag", "t1-64-lag", "t1-64-lag-clet"): for k, v in port_channels.iteritems(): acl_table_ports[v['namespace']].append(k) # In multi-asic we need config both in host and namespace. if v['namespace']: acl_table_ports[''].append(k) else: for namespace, port in upstream_ports.iteritems(): acl_table_ports[namespace] += port # In multi-asic we need config both in host and namespace. if namespace: acl_table_ports[''] += port dest_mac_mapping = { "downlink->uplink": downstream_port_id_to_router_mac_map, "uplink->downlink": upstream_port_id_to_router_mac_map } setup_information = { "destination_mac": dest_mac_mapping, "downstream_port_ids": downstream_port_ids, "upstream_port_ids": upstream_port_ids, "acl_table_ports": acl_table_ports, "vlan_ports": vlan_ports, "topo": topo, "vlan_mac": vlan_mac } logger.info("Gathered variables for ACL test:\n{}".format( pprint.pformat(setup_information))) logger.info( "Creating temporary folder \"{}\" for ACL test".format(DUT_TMP_DIR)) for duthost in duthosts: duthost.command("mkdir -p {}".format(DUT_TMP_DIR)) yield setup_information logger.info("Removing temporary directory \"{}\"".format(DUT_TMP_DIR)) for duthost in duthosts: duthost.command("rm -rf {}".format(DUT_TMP_DIR))