diff --git a/tests/conftest.py b/tests/conftest.py index af95f49794f0..261ad4eac839 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,6 +26,7 @@ from dvslib import dvs_lag from dvslib import dvs_mirror from dvslib import dvs_policer +from dvslib import dvs_hash from buffer_model import enable_dynamic_buffer @@ -151,6 +152,8 @@ def _populate_default_asic_db_values(self) -> None: self.default_acl_tables = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") self.default_acl_entries = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + self.default_hash_keys = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_HASH") + self.default_copp_policers = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_POLICER") @@ -1338,6 +1341,7 @@ def get_asic_db(self) -> AsicDbValidator: db = DVSDatabase(self.ASIC_DB_ID, self.redis_sock) db.default_acl_tables = self.asicdb.default_acl_tables db.default_acl_entries = self.asicdb.default_acl_entries + db.default_hash_keys = self.asicdb.default_hash_keys db.default_copp_policers = self.asicdb.default_copp_policers db.port_name_map = self.asicdb.portnamemap db.default_vlan_id = self.asicdb.default_vlan_id @@ -1916,6 +1920,11 @@ def dvs_policer_manager(request, dvs): request.cls.dvs_policer = dvs_policer.DVSPolicer(dvs.get_asic_db(), dvs.get_config_db()) +@pytest.fixture(scope="class") +def dvs_hash_manager(request, dvs): + request.cls.dvs_hash = dvs_hash.DVSHash(dvs.get_asic_db(), + dvs.get_config_db()) + ##################### DPB fixtures ########################################### def create_dpb_config_file(dvs): cmd = "sonic-cfggen -j /etc/sonic/init_cfg.json -j /tmp/ports.json --print-data > /tmp/dpb_config_db.json" diff --git a/tests/dvslib/dvs_hash.py b/tests/dvslib/dvs_hash.py new file mode 100644 index 000000000000..5ac896962c7f --- /dev/null +++ b/tests/dvslib/dvs_hash.py @@ -0,0 +1,80 @@ +"""Utilities for interacting with HASH objects when writing VS tests.""" +from typing import Dict, List + + +class DVSHash: + """Manage hash objects on the virtual switch.""" + + CDB_SWITCH_HASH = "SWITCH_HASH" + KEY_SWITCH_HASH_GLOBAL = "GLOBAL" + + ADB_HASH = "ASIC_STATE:SAI_OBJECT_TYPE_HASH" + + def __init__(self, asic_db, config_db): + """Create a new DVS hash manager.""" + self.asic_db = asic_db + self.config_db = config_db + + def update_switch_hash( + self, + qualifiers: Dict[str, str] + ) -> None: + """Update switch hash global in Config DB.""" + self.config_db.update_entry(self.CDB_SWITCH_HASH, self.KEY_SWITCH_HASH_GLOBAL, qualifiers) + + def get_hash_ids( + self, + expected: int = None + ) -> List[str]: + """Get all of the hash ids in ASIC DB. + + Args: + expected: The number of hash ids that are expected to be present in ASIC DB. + + Returns: + The list of hash ids in ASIC DB. + """ + if expected is None: + return self.asic_db.get_keys(self.ADB_HASH) + + num_keys = len(self.asic_db.default_hash_keys) + expected + keys = self.asic_db.wait_for_n_keys(self.ADB_HASH, num_keys) + + for k in self.asic_db.default_hash_keys: + assert k in keys + + return [k for k in keys if k not in self.asic_db.default_hash_keys] + + def verify_hash_count( + self, + expected: int + ) -> None: + """Verify that there are N hash objects in ASIC DB. + + Args: + expected: The number of hash ids that are expected to be present in ASIC DB. + """ + self.get_hash_ids(expected) + + def verify_hash_generic( + self, + sai_hash_id: str, + sai_qualifiers: Dict[str, str] + ) -> None: + """Verify that hash object has correct ASIC DB representation. + + Args: + sai_hash_id: The specific hash id to check in ASIC DB. + sai_qualifiers: The expected set of SAI qualifiers to be found in ASIC DB. + """ + entry = self.asic_db.wait_for_entry(self.ADB_HASH, sai_hash_id) + + for k, v in entry.items(): + if k == "NULL": + continue + elif k in sai_qualifiers: + if k == "SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST": + hfList = v[v.index(":")+1:].split(",") + assert set(sai_qualifiers[k]) == set(hfList) + else: + assert False, "Unknown SAI qualifier: key={}, value={}".format(k, v) diff --git a/tests/dvslib/dvs_pbh.py b/tests/dvslib/dvs_pbh.py index df612638ead1..2caf059adcb1 100644 --- a/tests/dvslib/dvs_pbh.py +++ b/tests/dvslib/dvs_pbh.py @@ -11,6 +11,7 @@ class DVSPbh: CDB_PBH_HASH_FIELD = "PBH_HASH_FIELD" ADB_PBH_HASH = "ASIC_STATE:SAI_OBJECT_TYPE_HASH" + ADB_PBH_HASH_FIELD = "ASIC_STATE:SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD" def __init__(self, asic_db, config_db): """Create a new DVS PBH Manager.""" @@ -110,13 +111,6 @@ def remove_pbh_hash( """Remove PBH hash from Config DB.""" self.config_db.delete_entry(self.CDB_PBH_HASH, hash_name) - def verify_pbh_hash_count( - self, - expected: int - ) -> None: - """Verify that there are N hash objects in ASIC DB.""" - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_HASH", expected) - def create_pbh_hash_field( self, hash_field_name: str, @@ -147,11 +141,4 @@ def verify_pbh_hash_field_count( expected: int ) -> None: """Verify that there are N hash field objects in ASIC DB.""" - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD", expected) - - def get_pbh_hash_ids( - self, - expected: int - ) -> List[str]: - """Get all of the PBH hash IDs in ASIC DB.""" - return self.asic_db.wait_for_n_keys(self.ADB_PBH_HASH, expected) + self.asic_db.wait_for_n_keys(self.ADB_PBH_HASH_FIELD, expected) diff --git a/tests/test_pbh.py b/tests/test_pbh.py index 270e59d429e0..65401a3ea970 100644 --- a/tests/test_pbh.py +++ b/tests/test_pbh.py @@ -130,6 +130,7 @@ def test_PbhTablePortChannelBinding(self, testlog): self.dvs_lag.get_and_verify_port_channel(0) +@pytest.mark.usefixtures("dvs_hash_manager") class TestPbhBasicFlows: def test_PbhHashFieldCreationDeletion(self, testlog): try: @@ -162,12 +163,12 @@ def test_PbhHashCreationDeletion(self, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) finally: # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -205,7 +206,7 @@ def test_PbhRuleCreationDeletion(self, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) # PBH table pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) @@ -247,7 +248,7 @@ def test_PbhRuleCreationDeletion(self, testlog): # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -255,6 +256,7 @@ def test_PbhRuleCreationDeletion(self, testlog): self.dvs_pbh.verify_pbh_hash_field_count(0) +@pytest.mark.usefixtures("dvs_hash_manager") class TestPbhBasicEditFlows: def test_PbhRuleUpdate(self, testlog): try: @@ -273,7 +275,7 @@ def test_PbhRuleUpdate(self, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) # PBH table pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) @@ -319,7 +321,7 @@ def test_PbhRuleUpdate(self, testlog): flow_counter="ENABLED" ) - hash_id = self.dvs_pbh.get_pbh_hash_ids(1)[0] + hash_id = self.dvs_hash.get_hash_ids(1)[0] counter_id = self.dvs_acl.get_acl_counter_ids(1)[0] sai_attr_dict = { @@ -352,7 +354,7 @@ def test_PbhRuleUpdate(self, testlog): # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -377,7 +379,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) # PBH table pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME)) @@ -463,7 +465,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog): # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -475,6 +477,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog): test_flex_counters.post_trap_flow_counter_test(meta_data) +@pytest.mark.usefixtures("dvs_hash_manager") @pytest.mark.usefixtures("dvs_lag_manager") class TestPbhExtendedFlows: class PbhRefCountHelper(object): @@ -596,13 +599,13 @@ def create_hash(self, meta_dict, pbh_ref_count): hash_field_list=meta_dict["hash_field_list"] ) pbh_ref_count.incPbhHashCount() - self.dvs_pbh.verify_pbh_hash_count(pbh_ref_count.getPbhHashCount()) + self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount()) def remove_hash(self, meta_dict, pbh_ref_count): pbhlogger.info("Remove PBH hash: {}".format(meta_dict["name"])) self.dvs_pbh.remove_pbh_hash(meta_dict["name"]) pbh_ref_count.decPbhHashCount() - self.dvs_pbh.verify_pbh_hash_count(pbh_ref_count.getPbhHashCount()) + self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount()) def create_table(self, meta_dict, pbh_ref_count): pbhlogger.info("Create PBH table: {}".format(meta_dict["name"])) @@ -909,6 +912,7 @@ def test_PbhNvgreVxlanConfiguration(self, testlog, pbh_nvgre, pbh_vxlan): pass +@pytest.mark.usefixtures("dvs_hash_manager") class TestPbhDependencyFlows: def test_PbhHashCreationDeletionWithDependencies(self, testlog): try: @@ -918,7 +922,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -928,7 +932,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog): sequence_id=PBH_HASH_FIELD_SEQUENCE_ID ) self.dvs_pbh.verify_pbh_hash_field_count(1) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) finally: # PBH hash field pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -938,7 +942,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog): # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) self.dvs_pbh.verify_pbh_hash_field_count(0) def test_PbhRuleCreationDeletionWithDependencies(self, testlog): @@ -949,7 +953,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog): hash_name=PBH_HASH_NAME, hash_field_list=PBH_HASH_HASH_FIELD_LIST ) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) # PBH hash field pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME)) @@ -959,7 +963,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog): sequence_id=PBH_HASH_FIELD_SEQUENCE_ID ) self.dvs_pbh.verify_pbh_hash_field_count(1) - self.dvs_pbh.verify_pbh_hash_count(1) + self.dvs_hash.verify_hash_count(1) # PBH rule attr_dict = { @@ -1009,7 +1013,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog): # PBH hash pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME)) self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME) - self.dvs_pbh.verify_pbh_hash_count(0) + self.dvs_hash.verify_hash_count(0) self.dvs_pbh.verify_pbh_hash_field_count(0)