diff --git a/tests/common/devices.py b/tests/common/devices.py index 81ade41f8a8..1f70844bbb0 100644 --- a/tests/common/devices.py +++ b/tests/common/devices.py @@ -2084,6 +2084,13 @@ def get_namespace_from_asic_id(self, asic_id): # Raise an error if we reach here raise ValueError("Invalid asic_id '{}' passed as input".format(asic_id)) + def get_vtysh_cmd_for_namespace(self, cmd, namespace): + asic_id = self.get_asic_id_from_namespace(namespace) + if asic_id == DEFAULT_ASIC_ID: + return cmd + ns_cmd = cmd.replace('vtysh', 'vtysh -n {}'.format(asic_id)) + return ns_cmd + def __getattr__(self, attr): """ To support calling an ansible module on a MultiAsicSonicHost. diff --git a/tests/everflow/everflow_test_utilities.py b/tests/everflow/everflow_test_utilities.py index bec2d320c7a..2d295622b53 100644 --- a/tests/everflow/everflow_test_utilities.py +++ b/tests/everflow/everflow_test_utilities.py @@ -46,8 +46,16 @@ def setup_info(duthosts, rand_one_dut_hostname, tbinfo): """ duthost = duthosts[rand_one_dut_hostname] - tor_ports = [] - spine_ports = [] + # { namespace : [tor ports] } + tor_ports_namespace_map = defaultdict(list) + # { namespace : [spine ports] } + spine_ports_namespace_map = defaultdict(list) + + # { set of namespace tor ports belongs } + tor_ports_namespace = set() + # { set of namespace spine ports belongs } + spine_ports_namespace = set() + # Gather test facts mg_facts = duthost.get_extended_minigraph_facts(tbinfo) @@ -57,9 +65,28 @@ def setup_info(duthosts, rand_one_dut_hostname, tbinfo): # TODO: The ACL tests do something really similar, I imagine we could refactor this bit. for dut_port, neigh in mg_facts["minigraph_neighbors"].items(): if "T0" in neigh["name"]: - tor_ports.append(dut_port) + # Add Tor ports to namespace + tor_ports_namespace_map[neigh['namespace']].append(dut_port) + tor_ports_namespace.add(neigh['namespace']) elif "T2" in neigh["name"]: - spine_ports.append(dut_port) + # Add Spine ports to namespace + spine_ports_namespace_map[neigh['namespace']].append(dut_port) + spine_ports_namespace.add(neigh['namespace']) + + # Set of TOR ports only Namespace + tor_only_namespace = tor_ports_namespace.difference(spine_ports_namespace) + # Set of Spine ports only Namespace + spine_only_namespace = spine_ports_namespace.difference(tor_ports_namespace) + + # Randomly choose from TOR_only Namespace if present else just use first one + tor_namespace = random.choice(tuple(tor_only_namespace)) if tor_only_namespace else tuple(tor_ports_namespace)[0] + # Randomly choose from Spine_only Namespace if present else just use first one + spine_namespace = random.choice(tuple(spine_only_namespace)) if spine_only_namespace else tuple(spine_ports_namespace)[0] + + # Get the corresponding namespace ports + tor_ports = tor_ports_namespace_map[tor_namespace] + spine_ports = spine_ports_namespace_map[spine_namespace] + switch_capabilities = switch_capability_facts["switch_capabilities"]["switch"] @@ -137,51 +164,46 @@ def get_port_info(in_port_list, out_port_list, out_port_ptf_id_list, out_port_la "src_port_ptf_id": str(mg_facts["minigraph_ptf_indices"][spine_ports[0]]), "dest_port": tor_dest_ports, "dest_port_ptf_id": tor_dest_ports_ptf_id, - "dest_port_lag_name": tor_dest_lag_name + "dest_port_lag_name": tor_dest_lag_name, + "namespace": tor_namespace }, "spine": { "src_port": tor_ports[0], "src_port_ptf_id": str(mg_facts["minigraph_ptf_indices"][tor_ports[0]]), "dest_port": spine_dest_ports, "dest_port_ptf_id": spine_dest_ports_ptf_id, - "dest_port_lag_name": spine_dest_lag_name + "dest_port_lag_name": spine_dest_lag_name, + "namespace": spine_namespace }, "port_index_map": { k: v for k, v in mg_facts["minigraph_ptf_indices"].items() if k in mg_facts["minigraph_ports"] + }, + # { ptf_port_id : namespace } + "port_index_namespace_map" : { + v: mg_facts["minigraph_neighbors"][k]['namespace'] + for k, v in mg_facts["minigraph_ptf_indices"].items() + if k in mg_facts["minigraph_ports"] } } - # NOTE: This is important to add since for the Policer test case regular packets - # and mirror packets can go to same interface, which causes tail drop of - # police packets and impacts test case cir/cbs calculation. - # - # We are making sure regular traffic has a dedicated route and does not use - # the default route. - - peer_ip, _ = get_neighbor_info(duthost, spine_dest_ports[3], tbinfo) - - # Disable recursive route resolution as we have test case where we check - # if better unresolved route is there then it should not be picked by Mirror state DB - # This change is triggeed by Sonic PR#https://github.com/Azure/sonic-buildimage/pull/5600 - duthost.shell("vtysh -c \"configure terminal\" -c \"no ip nht resolve-via-default\"") - - add_route(duthost, "30.0.0.1/24", peer_ip) - + # Disable BGP so that we don't keep on bouncing back mirror packets + # If we send TTL=1 packet we don't need this but in multi-asic TTL > 1 + duthost.command("sudo config bgp shutdown all") + time.sleep(60) duthost.command("mkdir -p {}".format(DUT_RUN_DIR)) - + yield setup_information - + + # Enable BGP again + duthost.command("sudo config bgp startup all") + time.sleep(60) duthost.command("rm -rf {}".format(DUT_RUN_DIR)) - - remove_route(duthost, "30.0.0.1/24", peer_ip) - - duthost.shell("vtysh -c \"configure terminal\" -c \"ip nht resolve-via-default\"") - + # TODO: This should be refactored to some common area of sonic-mgmt. -def add_route(duthost, prefix, nexthop): +def add_route(duthost, prefix, nexthop, namespace): """ Add a route to the DUT. @@ -189,13 +211,15 @@ def add_route(duthost, prefix, nexthop): duthost: DUT fixture prefix: IP prefix for the route nexthop: next hop for the route + namespace: namsespace/asic to add the route """ - duthost.shell("vtysh -c \"configure terminal\" -c \"ip route {} {}\"".format(prefix, nexthop)) + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"configure terminal\" -c \"ip route {} {}\"".format(prefix, nexthop), namespace)) + # TODO: This should be refactored to some common area of sonic-mgmt. -def remove_route(duthost, prefix, nexthop): +def remove_route(duthost, prefix, nexthop, namespace): """ Remove a route from the DUT. @@ -203,9 +227,10 @@ def remove_route(duthost, prefix, nexthop): duthost: DUT fixture prefix: IP prefix to remove nexthop: next hop to remove + namespace: namsespace/asic to remove the route """ - duthost.shell("vtysh -c \"configure terminal\" -c \"no ip route {} {}\"".format(prefix, nexthop)) + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"configure terminal\" -c \"no ip route {} {}\"".format(prefix, nexthop), namespace)) # TODO: This should be refactored to some common area of sonic-mgmt. @@ -220,7 +245,7 @@ def get_neighbor_info(duthost, dest_port, tbinfo, resolved=True): """ if not resolved: - return "20.20.20.100", None + return "20.20.20.100" mg_facts = duthost.get_extended_minigraph_facts(tbinfo) @@ -229,7 +254,7 @@ def get_neighbor_info(duthost, dest_port, tbinfo, resolved=True): peer_ip = bgp_peer["addr"] break - return peer_ip, duthost.shell("ip neigh show {} | awk -F\" \" \"{{print $5}}\"".format(peer_ip))["stdout"] + return peer_ip # TODO: This can probably be moved to a shared location in a later PR. @@ -475,7 +500,8 @@ def send_and_check_mirror_packets(self, mirror_packet, src_port=None, dest_ports=None, - expect_recv=True): + expect_recv=True, + valid_across_namespace=True): expected_mirror_packet = self._get_expected_mirror_packet(mirror_session, setup, duthost, @@ -487,42 +513,63 @@ def send_and_check_mirror_packets(self, if not dest_ports: dest_ports = [self._get_monitor_port(setup, mirror_session, duthost)] - ptfadapter.dataplane.flush() - testutils.send(ptfadapter, src_port, mirror_packet) - - if expect_recv: - _, received_packet = testutils.verify_packet_any_port( - ptfadapter, - expected_mirror_packet, - ports=dest_ports - ) - logging.info("Received packet: %s", packet.Ether(received_packet).summary()) - - inner_packet = self._extract_mirror_payload(received_packet, len(mirror_packet)) - logging.info("Received inner packet: %s", inner_packet.summary()) - - inner_packet = Mask(inner_packet) - - # For egress mirroring, we expect the DUT to have modified the packet - # before forwarding it. Specifically: - # - # - In L2 the SMAC and DMAC will change. - # - In L3 the TTL and checksum will change. - # - # We know what the TTL and SMAC should be after going through the pipeline, - # but DMAC and checksum are trickier. For now, update the TTL and SMAC, and - # mask off the DMAC and IP Checksum to verify the packet contents. - if self.mirror_type() == "egress": - mirror_packet[packet.IP].ttl -= 1 - mirror_packet[packet.Ether].src = setup["router_mac"] - - inner_packet.set_do_not_care_scapy(packet.Ether, "dst") - inner_packet.set_do_not_care_scapy(packet.IP, "chksum") - - logging.info("Expected inner packet: %s", mirror_packet.summary()) - pytest_assert(inner_packet.pkt_match(mirror_packet), "Mirror payload does not match received packet") - else: - testutils.verify_no_packet_any(ptfadapter, expected_mirror_packet, dest_ports) + # In Below logic idea is to send traffic in such a way so that mirror traffic + # will need to go across namespaces and within namespace. If source and mirror destination + # namespace are different then traffic mirror will go across namespace via (backend asic) + # else via same namespace(asic) + + src_port_namespace = self._get_port_namespace(setup, int(src_port)) + dest_ports_namespace = self._get_port_namespace(setup,int (dest_ports[0])) + + src_port_set = set() + + # Some of test scenario are not valid across namespaces so test will explicltly pass + # valid_across_namespace as False (default is True) + if valid_across_namespace == True or src_port_namespace == dest_ports_namespace: + src_port_set.add(src_port) + + # To verify same namespace mirroring we will add destination port also to the Source Port Set + if src_port_namespace != dest_ports_namespace: + src_port_set.add(dest_ports[0]) + + # Loop through Source Port Set and send traffic on each source port of the set + for src_port in src_port_set: + ptfadapter.dataplane.flush() + testutils.send(ptfadapter, src_port, mirror_packet) + + if expect_recv: + _, received_packet = testutils.verify_packet_any_port( + ptfadapter, + expected_mirror_packet, + ports=dest_ports + ) + logging.info("Received packet: %s", packet.Ether(received_packet).summary()) + + inner_packet = self._extract_mirror_payload(received_packet, len(mirror_packet)) + logging.info("Received inner packet: %s", inner_packet.summary()) + + inner_packet = Mask(inner_packet) + + # For egress mirroring, we expect the DUT to have modified the packet + # before forwarding it. Specifically: + # + # - In L2 the SMAC and DMAC will change. + # - In L3 the TTL and checksum will change. + # + # We know what the TTL and SMAC should be after going through the pipeline, + # but DMAC and checksum are trickier. For now, update the TTL and SMAC, and + # mask off the DMAC and IP Checksum to verify the packet contents. + if self.mirror_type() == "egress": + mirror_packet[packet.IP].ttl -= 1 + mirror_packet[packet.Ether].src = setup["router_mac"] + + inner_packet.set_do_not_care_scapy(packet.Ether, "dst") + inner_packet.set_do_not_care_scapy(packet.IP, "chksum") + + logging.info("Expected inner packet: %s", mirror_packet.summary()) + pytest_assert(inner_packet.pkt_match(mirror_packet), "Mirror payload does not match received packet") + else: + testutils.verify_no_packet_any(ptfadapter, expected_mirror_packet, dest_ports) def _get_expected_mirror_packet(self, mirror_session, setup, duthost, mirror_packet): payload = mirror_packet.copy() @@ -552,6 +599,7 @@ def _get_expected_mirror_packet(self, mirror_session, setup, duthost, mirror_pac expected_packet.set_do_not_care_scapy(packet.IP, "len") expected_packet.set_do_not_care_scapy(packet.IP, "flags") expected_packet.set_do_not_care_scapy(packet.IP, "chksum") + expected_packet.set_do_not_care_scapy(packet.IP, "ttl") # The fanout switch may modify this value en route to the PTF so we should ignore it, even # though the session does have a DSCP specified. @@ -573,7 +621,7 @@ def _mirror_session_info(self, session_name, asic_type): session_src_ip = "1.1.1.1" session_dst_ip = "2.2.2.2" session_dscp = "8" - session_ttl = "1" + session_ttl = "4" if "mellanox" == asic_type: session_gre = 0x8949 @@ -596,6 +644,9 @@ def _mirror_session_info(self, session_name, asic_type): "session_gre": session_gre, "session_prefixes": session_prefixes } + + def _get_port_namespace(self,setup, port): + return setup["port_index_namespace_map"][port] def _get_random_src_port(self, setup): return setup["port_index_map"][random.choice(setup["port_index_map"].keys())] diff --git a/tests/everflow/test_everflow_ipv6.py b/tests/everflow/test_everflow_ipv6.py index 87b65ed9f07..eee8d5b1288 100644 --- a/tests/everflow/test_everflow_ipv6.py +++ b/tests/everflow/test_everflow_ipv6.py @@ -38,13 +38,15 @@ def setup_mirror_session_dest_ip_route(self, duthosts, rand_one_dut_hostname, tb """ duthost = duthosts[rand_one_dut_hostname] + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"config\" -c \"router bgp\" -c \"address-family ipv4\" -c \"redistribute static\"",setup_info["tor"]["namespace"])) tx_port = setup_info["tor"]["dest_port"][0] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info["tor"]["namespace"]) self.tx_port_ids = self._get_tx_port_id_list([setup_info["tor"]["dest_port_ptf_id"][0]]) time.sleep(5) yield - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info["tor"]["namespace"]) + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"config\" -c \"router bgp\" -c \"address-family ipv4\" -c \"no redistribute static\"",setup_info["tor"]["namespace"])) def test_src_ipv6_mirroring(self, setup_info, setup_mirror_session, ptfadapter, duthosts, rand_one_dut_hostname): """Verify that we can match on Source IPv6 addresses.""" diff --git a/tests/everflow/test_everflow_testbed.py b/tests/everflow/test_everflow_testbed.py index c05e212f8bc..556b68aa796 100644 --- a/tests/everflow/test_everflow_testbed.py +++ b/tests/everflow/test_everflow_testbed.py @@ -74,15 +74,20 @@ def dest_port_type(self, duthosts, rand_one_dut_hostname, setup_info, setup_mirr This fixture parametrize dest_port_type and can perform action based on that. As of now cleanup is being done here. """ + duthost = duthosts[rand_one_dut_hostname] + + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"config\" -c \"router bgp\" -c \"address-family ipv4\" -c \"redistribute static\"",setup_info[request.param]["namespace"])) yield request.param - duthost = duthosts[rand_one_dut_hostname] for index in range(0, min(3, len(setup_info[request.param]["dest_port"]))): tx_port = setup_info[request.param]["dest_port"][index] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info[request.param]["namespace"]) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip, setup_info[request.param]["namespace"]) + + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"config\" -c \"router bgp\" -c \"address-family ipv4\" -c \"no redistribute static\"",setup_info[request.param]["namespace"])) + time.sleep(15) def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_info, setup_mirror_session, dest_port_type, ptfadapter, tbinfo): @@ -96,12 +101,13 @@ def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_ - Route creation and removal """ duthost = duthosts[rand_one_dut_hostname] + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"configure terminal\" -c \"no ip nht resolve-via-default\"", setup_info[dest_port_type]["namespace"])) # Add a route to the mirror session destination IP tx_port = setup_info[dest_port_type]["dest_port"][0] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) - time.sleep(3) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is sent along the route we installed rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"] @@ -116,9 +122,9 @@ def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_ ) # Add a (better) unresolved route to the mirror session destination IP - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo, resolved=False) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip) - time.sleep(3) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo, resolved=False) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is still sent along the original route self._run_everflow_test_scenarios( @@ -131,13 +137,13 @@ def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_ ) # Remove the unresolved route - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip, setup_info[dest_port_type]["namespace"]) # Add a better route to the mirror session destination IP tx_port = setup_info[dest_port_type]["dest_port"][1] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session['session_prefixes'][1], peer_ip) - time.sleep(3) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session['session_prefixes'][1], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic uses the new route tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][1] @@ -151,8 +157,8 @@ def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_ ) # Remove the better route. - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip) - time.sleep(3) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][1], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic switches back to the original route tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][0] @@ -164,15 +170,16 @@ def test_everflow_basic_forwarding(self, duthosts, rand_one_dut_hostname, setup_ rx_port_ptf_id, [tx_port_ptf_id] ) + duthost.shell(duthost.get_vtysh_cmd_for_namespace("vtysh -c \"configure terminal\" -c \"ip nht resolve-via-default\"", setup_info[dest_port_type]["namespace"])) def test_everflow_neighbor_mac_change(self, duthosts, rand_one_dut_hostname, setup_info, setup_mirror_session, dest_port_type, ptfadapter, tbinfo): """Verify that session destination MAC address is changed after neighbor MAC address update.""" duthost = duthosts[rand_one_dut_hostname] # Add a route to the mirror session destination IP tx_port = setup_info[dest_port_type]["dest_port"][0] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) - time.sleep(3) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is sent along the route we installed rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"] @@ -191,7 +198,7 @@ def test_everflow_neighbor_mac_change(self, duthosts, rand_one_dut_hostname, set tx_port = setup_info[dest_port_type]["dest_port_lag_name"][0] duthost.shell("ip neigh replace {} lladdr 00:11:22:33:44:55 nud permanent dev {}".format(peer_ip, tx_port)) - time.sleep(3) + time.sleep(15) try: # Verify that everything still works self._run_everflow_test_scenarios( @@ -223,14 +230,14 @@ def test_everflow_remove_unused_ecmp_next_hop(self, duthosts, rand_one_dut_hostn duthost = duthosts[rand_one_dut_hostname] # Create two ECMP next hops tx_port = setup_info[dest_port_type]["dest_port"][0] - peer_ip_0, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0) - time.sleep(3) + peer_ip_0 = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0, setup_info[dest_port_type]["namespace"]) + time.sleep(15) tx_port = setup_info[dest_port_type]["dest_port"][1] - peer_ip_1, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_1) - time.sleep(3) + peer_ip_1 = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_1, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is sent to one of the next hops rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"] @@ -249,9 +256,9 @@ def test_everflow_remove_unused_ecmp_next_hop(self, duthosts, rand_one_dut_hostn # Add another ECMP next hop tx_port = setup_info[dest_port_type]["dest_port"][2] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) - time.sleep(3) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is not sent to this new next hop tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][2] @@ -266,8 +273,8 @@ def test_everflow_remove_unused_ecmp_next_hop(self, duthosts, rand_one_dut_hostn ) # Remove the extra hop - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip) - time.sleep(3) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is not sent to the deleted next hop self._run_everflow_test_scenarios( @@ -295,9 +302,9 @@ def test_everflow_remove_used_ecmp_next_hop(self, duthosts, rand_one_dut_hostnam duthost = duthosts[rand_one_dut_hostname] # Add a route to the mirror session destination IP tx_port = setup_info[dest_port_type]["dest_port"][0] - peer_ip_0, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0) - time.sleep(3) + peer_ip_0 = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is sent along the route we installed rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"] @@ -313,13 +320,13 @@ def test_everflow_remove_used_ecmp_next_hop(self, duthosts, rand_one_dut_hostnam # Add two new ECMP next hops tx_port = setup_info[dest_port_type]["dest_port"][1] - peer_ip_1, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_1) + peer_ip_1 = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_1, setup_info[dest_port_type]["namespace"]) tx_port = setup_info[dest_port_type]["dest_port"][2] - peer_ip_2, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_2) - time.sleep(3) + peer_ip_2 = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_2, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that traffic is still sent along the original next hop self._run_everflow_test_scenarios( @@ -328,7 +335,8 @@ def test_everflow_remove_used_ecmp_next_hop(self, duthosts, rand_one_dut_hostnam setup_mirror_session, duthost, rx_port_ptf_id, - [tx_port_ptf_id] + [tx_port_ptf_id], + valid_across_namespace=False ) # Verify that traffic is not sent along either of the new next hops @@ -343,12 +351,13 @@ def test_everflow_remove_used_ecmp_next_hop(self, duthosts, rand_one_dut_hostnam duthost, rx_port_ptf_id, tx_port_ptf_ids, - expect_recv=False + expect_recv=False, + valid_across_namespace=False ) # Remove the original next hop - everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0) - time.sleep(3) + everflow_utils.remove_route(duthost, setup_mirror_session["session_prefixes"][0], peer_ip_0, setup_info[dest_port_type]["namespace"]) + time.sleep(15) # Verify that mirrored traffic is no longer sent along the original next hop self._run_everflow_test_scenarios( @@ -382,10 +391,21 @@ def test_everflow_dscp_with_policer( tbinfo ): """Verify that we can rate-limit mirrored traffic from the MIRROR_DSCP table.""" + # Add explicit for regular packet so that it's dest port is different then mirror port + # NOTE: This is important to add since for the Policer test case regular packets + # and mirror packets can go to same interface, which causes tail drop of + # police packets and impacts test case cir/cbs calculation. + default_tarffic_port_type = "tor" if dest_port_type == "spine" else "spine" + default_traffic_tx_port = setup_info[default_tarffic_port_type]["dest_port"][0] + default_traffic_peer_ip = everflow_utils.get_neighbor_info(duthost, default_traffic_tx_port, tbinfo) + everflow_utils.add_route(duthost, self.DEFAULT_DST_IP + "/32", default_traffic_peer_ip, setup_info[default_tarffic_port_type]["namespace"]) + time.sleep(15) + # Add explicit route for the mirror session tx_port = setup_info[dest_port_type]["dest_port"][0] - peer_ip, _ = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) - everflow_utils.add_route(duthost, policer_mirror_session["session_prefixes"][0], peer_ip) + peer_ip = everflow_utils.get_neighbor_info(duthost, tx_port, tbinfo) + everflow_utils.add_route(duthost, policer_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + time.sleep(15) try: # Add MIRROR_DSCP table for test @@ -421,18 +441,14 @@ def test_everflow_dscp_with_policer( # Clean up ACL rules and routes self.remove_acl_rule_config(duthost, table_name, config_method) self.remove_acl_table_config(duthost, table_name, config_method) - everflow_utils.remove_route(duthost, policer_mirror_session["session_prefixes"][0], peer_ip) + everflow_utils.remove_route(duthost, policer_mirror_session["session_prefixes"][0], peer_ip, setup_info[dest_port_type]["namespace"]) + everflow_utils.remove_route(duthost, self.DEFAULT_DST_IP + "/32", default_traffic_peer_ip, setup_info[default_tarffic_port_type]["namespace"]) - def _run_everflow_test_scenarios(self, ptfadapter, setup, mirror_session, duthost, rx_port, tx_ports, expect_recv=True): + def _run_everflow_test_scenarios(self, ptfadapter, setup, mirror_session, duthost, rx_port, tx_ports, expect_recv=True, valid_across_namespace=True): # FIXME: In the ptf_runner version of these tests, LAGs were passed down to the tests as comma-separated strings of # LAG member port IDs (e.g. portchannel0001 -> "2,3"). Because the DSCP test is still using ptf_runner we will preserve # this for now, but we should try to make the format a little more friendly once the DSCP test also gets converted. - tx_port_ids = [] - for port in tx_ports: - members = port.split(',') - for member in members: - tx_port_ids.append(int(member)) - + tx_port_ids = self._get_tx_port_id_list(tx_ports) pkt_dict = { "(src ip)": self._base_tcp_packet(ptfadapter, setup, src_ip="20.0.0.10"), "(dst ip)": self._base_tcp_packet(ptfadapter, setup, dst_ip="30.0.0.10"), @@ -455,7 +471,8 @@ def _run_everflow_test_scenarios(self, ptfadapter, setup, mirror_session, duthos pkt, src_port=rx_port, dest_ports=tx_port_ids, - expect_recv=expect_recv + expect_recv=expect_recv, + valid_across_namespace=valid_across_namespace ) def _base_tcp_packet(