Skip to content
84 changes: 84 additions & 0 deletions tests/everflow/everflow_test_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,90 @@ def validate_mirror_session_up(duthost, session_name):
return False


def validate_acl_rule_rids(duthost):
"""
Validate that the ACL rule RIDs are not empty.
For multi-ASIC DUTs, validates ACL rule RIDs in each frontend ASIC's ASIC_DB.

Args:
duthost: DUT host object

Returns:
bool: True if all ACL rule RIDs are valid in all frontend ASICs, False otherwise
"""
# Get all frontend ASIC instances
if duthost.is_multi_asic:
asic_instances = [duthost.asic_instance(asic_id) for asic_id in duthost.get_frontend_asic_ids()]
else:
asic_instances = [duthost]

# Validate ACL rule RIDs in each ASIC
for asic in asic_instances:
asicdb = AsicDbCli(asic)
acl_entry_table = asicdb.dump("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY")
entry_vids = []
for key, value in acl_entry_table.items():
if 'SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS' in value['value'] or \
'SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS' in value['value']:
# Extract OID from key format "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000abe"
oid = key.split(":")[-1] if "oid:" in key else None
if oid is not None:
entry_vids.append(oid)

# Validate VIDs for this ASIC
if entry_vids:
vidtorid_table = asicdb.dump("VIDTORID")["VIDTORID"]["value"]
for vid in entry_vids:
vid = "oid:" + vid
if vid not in vidtorid_table or vidtorid_table[vid] is None:
logging.error("ACL entry VID {} not found or has None RID in ASIC {}".format(
vid, asic.asic_index if duthost.is_multi_asic else "single"))
return False
return True


def validate_acl_rules_in_asic_db(duthost):
"""
Validate that the number of ACL rules in ASIC DB is the same as the number of ACL rules in CONFIG DB.
Also check that the ACL rule RIDs are not empty.
For multi-ASIC DUTs, validates ACL rules in each frontend ASIC's ASIC_DB and CONFIG_DB.

Args:
duthost: DUT host object

Returns:
bool: True if ACL rules count matches and RIDs are valid in all frontend ASICs, False otherwise
"""
# Get all frontend ASIC instances
if duthost.is_multi_asic:
asic_instances = [duthost.asic_instance(asic_id) for asic_id in duthost.get_frontend_asic_ids()]
else:
asic_instances = [duthost]

# Validate ACL rules in each ASIC
for asic in asic_instances:
# Get namespace-specific command prefix
if duthost.is_multi_asic:
namespace = asic.get_asic_namespace()
config_cmd = "sonic-db-cli -n {} CONFIG_DB KEYS *ACL_RULE*".format(namespace)
asic_cmd = "sonic-db-cli -n {} ASIC_DB KEYS *SAI_OBJECT_TYPE_ACL_ENTRY*".format(namespace)
else:
config_cmd = "sonic-db-cli CONFIG_DB KEYS *ACL_RULE*"
asic_cmd = "sonic-db-cli ASIC_DB KEYS *SAI_OBJECT_TYPE_ACL_ENTRY*"

config_rules = asic.shell(config_cmd)['stdout_lines']
asic_rules = asic.shell(asic_cmd)['stdout_lines']

if len(config_rules) != len(asic_rules):
logging.error("ACL rules count mismatch in ASIC {}: CONFIG_DB={}, ASIC_DB={}".format(
asic.asic_index if duthost.is_multi_asic else "single",
len(config_rules), len(asic_rules)))
return False

# Validate ACL rule RIDs across all ASICs
return validate_acl_rule_rids(duthost)


# TODO: This should be refactored to some common area of sonic-mgmt.
def add_route(duthost, prefix, nexthop, namespace):
"""
Expand Down
64 changes: 54 additions & 10 deletions tests/everflow/test_everflow_testbed.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ def test_everflow_multi_binding_acl(self, setup_info, setup_mirror_session,
logger=logger
)



def test_everflow_basic_forwarding(self, setup_info, setup_mirror_session, # noqa F811
dest_port_type, ptfadapter, tbinfo, mux_config, # noqa F811
toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811
Expand Down Expand Up @@ -313,7 +315,10 @@ def test_everflow_basic_forwarding(self, setup_info, setup_mirror_session,
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip,
setup_info[dest_port_type]["remote_namespace"])

wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))

# Verify that mirrored traffic is sent along the route we installed
rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"]
Expand Down Expand Up @@ -358,7 +363,11 @@ def test_everflow_basic_forwarding(self, setup_info, setup_mirror_session,
peer_ip = everflow_utils.get_neighbor_info(remote_dut, tx_port, tbinfo, ip_version=erspan_ip_ver)
everflow_utils.add_route(remote_dut, session_prefixes[1], peer_ip,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[1])
pytest_assert(
wait_until(
120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[1]
)
)

# Verify that mirrored traffic uses the new route
tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][1]
Expand All @@ -377,7 +386,12 @@ def test_everflow_basic_forwarding(self, setup_info, setup_mirror_session,
# Remove the better route.
everflow_utils.remove_route(remote_dut, session_prefixes[1], peer_ip,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, lambda: not everflow_utils.validate_asic_route(remote_dut, session_prefixes[1]))
pytest_assert(
wait_until(
120, 10, 0,
lambda: not everflow_utils.validate_asic_route(remote_dut, session_prefixes[1])
)
)

# Verify that mirrored traffic switches back to the original route
tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][0]
Expand Down Expand Up @@ -414,7 +428,10 @@ def test_everflow_neighbor_mac_change(self, setup_info, setup_mirror_session,
else setup_mirror_session["session_prefixes_ipv6"]
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))

# Verify that mirrored traffic is sent along the route we installed
rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"]
Expand Down Expand Up @@ -499,7 +516,10 @@ def test_everflow_remove_unused_ecmp_next_hop(self, setup_info, setup_mirror_ses
else setup_mirror_session["session_prefixes_ipv6"]
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip_0,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))

tx_port = setup_info[dest_port_type]["dest_port"][1]
peer_ip_1 = everflow_utils.get_neighbor_info(remote_dut, tx_port, tbinfo, ip_version=erspan_ip_ver)
Expand Down Expand Up @@ -610,7 +630,10 @@ def test_everflow_remove_used_ecmp_next_hop(self, setup_info, setup_mirror_sessi
else setup_mirror_session["session_prefixes_ipv6"]
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip_0,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))

# Verify that mirrored traffic is sent along the route we installed
rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"]
Expand Down Expand Up @@ -804,6 +827,7 @@ def test_everflow_dscp_with_policer(
config_method,
rules=EVERFLOW_DSCP_RULES)

pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))
# Clear counters before test
clear_interface_counters(everflow_dut)
clear_queue_counters(everflow_dut, None)
Expand Down Expand Up @@ -865,7 +889,10 @@ def test_everflow_frwd_with_bkg_trf(self,
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip,
setup_info[dest_port_type]["remote_namespace"])

wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, everflow_dut))

# Verify that mirrored traffic is sent along the route we installed
rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"]
Expand Down Expand Up @@ -972,7 +999,11 @@ def background_traffic(run_count=None):
peer_ip = everflow_utils.get_neighbor_info(remote_dut, tx_port, tbinfo, ip_version=erspan_ip_ver)
everflow_utils.add_route(remote_dut, session_prefixes[1], peer_ip,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[1])
pytest_assert(
wait_until(
120, 10, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[1]
)
)
background_traffic(run_count=1)
# Verify that mirrored traffic uses the new route
tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][1]
Expand All @@ -991,7 +1022,12 @@ def background_traffic(run_count=None):
# Remove the better route.
everflow_utils.remove_route(remote_dut, session_prefixes[1], peer_ip,
setup_info[dest_port_type]["remote_namespace"])
wait_until(30, 5, 0, lambda: not everflow_utils.validate_asic_route(remote_dut, session_prefixes[1]))
pytest_assert(
wait_until(
120, 10, 0,
lambda: not everflow_utils.validate_asic_route(remote_dut, session_prefixes[1])
)
)
background_traffic(run_count=1)
# Verify that mirrored traffic switches back to the original route
tx_port_ptf_id = setup_info[dest_port_type]["dest_port_ptf_id"][0]
Expand Down Expand Up @@ -1097,7 +1133,13 @@ def configure_mirror_session_with_queue(mirror_session, queue_num, erspan_ip_ver
everflow_utils.add_route(remote_dut, session_prefixes[0], peer_ip,
setup_info[dest_port_type]["remote_namespace"])

wait_until(30, 5, 0, everflow_utils.validate_asic_route, remote_dut, session_prefixes[0])
pytest_assert(
wait_until(
120, 10, 0,
everflow_utils.validate_asic_route, remote_dut, session_prefixes[0]
)
)
pytest_assert(wait_until(120, 10, 0, everflow_utils.validate_acl_rules_in_asic_db, remote_dut))

# Verify that mirrored traffic is sent along the route we installed
rx_port_ptf_id = setup_info[dest_port_type]["src_port_ptf_id"]
Expand Down Expand Up @@ -1129,6 +1171,8 @@ def configure_mirror_session_with_queue(mirror_session, queue_num, erspan_ip_ver
valid_across_namespace=everflow_dut.is_multi_asic,
)
finally:
everflow_utils.remove_route(remote_dut, session_prefixes[0],
peer_ip, setup_info[dest_port_type]["remote_namespace"])
remote_dut.shell(remote_dut.get_vtysh_cmd_for_namespace(
"vtysh -c \"configure terminal\" -c \"ip nht resolve-via-default\"",
setup_info[dest_port_type]["remote_namespace"]))
Expand Down
Loading