From 4e7e77284a989cbc655af3a878281ae4fcbfa0dc Mon Sep 17 00:00:00 2001 From: Danny Allen Date: Wed, 8 Apr 2020 07:38:49 -0700 Subject: [PATCH] [dvs] Refactor VLAN tests to use dvslib (#1241) - Refactor tests to use polling interface - Refactor redundant testing methods - Reenable unstable tests Signed-off-by: Danny Allen --- tests/conftest.py | 3 + tests/dvslib/dvs_database.py | 39 +- tests/test_vlan.py | 1085 ++++++++++++---------------------- 3 files changed, 427 insertions(+), 700 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f8234240f401..753a333df5e9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -947,6 +947,9 @@ def get_asic_db(self): db.default_acl_tables = self.asicdb.default_acl_tables db.default_acl_entries = self.asicdb.default_acl_entries db.port_name_map = self.asicdb.portnamemap + db.default_vlan_id = self.asicdb.default_vlan_id + db.port_to_id_map = self.asicdb.portoidmap + db.hostif_name_map = self.asicdb.hostifnamemap self.asic_db = db return self.asic_db diff --git a/tests/dvslib/dvs_database.py b/tests/dvslib/dvs_database.py index ea667cd27c7f..9dd5493c530a 100644 --- a/tests/dvslib/dvs_database.py +++ b/tests/dvslib/dvs_database.py @@ -121,6 +121,43 @@ def _access_function(): return wait_for_result(_access_function, polling_config) + def wait_for_field_match(self, + table_name, + key, + expected_fields, + polling_config=DEFAULT_POLLING_CONFIG): + """ + Checks if the provided fields are contained in the entry stored + at `key` in the specified table. This method will wait for the + fields to exist. + + NOTE: We suggest you only use this function if: + 1) the entry already exists, and + 2) you expect certain fields to change + + Otherwise, it is more efficient to use `wait_for_entry` and check + for the expected fields after the entry has been retrieved. + + Args: + table_name (str): The name of the table where the entry is + stored. + key (str): The key that maps to the entry being checked. + expected_fields (dict): The fields and their values we expect + to see in the entry. + polling_config (PollingConfig): The parameters to use to poll + the db. + + Returns: + Dict[str, str]: The entry stored at `key`. If no entry is found, + then an empty Dict will be returned. + """ + + def _access_function(): + fv_pairs = self.get_entry(table_name, key) + return (expected_fields.items() <= fv_pairs.items(), fv_pairs) + + return wait_for_result(_access_function, polling_config) + def wait_for_empty_entry(self, table_name, key, @@ -141,7 +178,7 @@ def wait_for_empty_entry(self, def _access_function(): fv_pairs = self.get_entry(table_name, key) - return (not fv_pairs, fv_pairs) + return (not bool(fv_pairs), fv_pairs) return wait_for_result(_access_function, polling_config) diff --git a/tests/test_vlan.py b/tests/test_vlan.py index f7551ff66f59..9124cb5d1289 100644 --- a/tests/test_vlan.py +++ b/tests/test_vlan.py @@ -1,824 +1,511 @@ -import time -import re -import json -import pytest import platform +import pytest -from swsscommon import swsscommon from distutils.version import StrictVersion +from dvslib.dvs_common import PollingConfig +from dvslib.dvs_database import DVSDatabase - +@pytest.mark.usefixtures("testlog") class TestVlan(object): def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + self.app_db = dvs.get_app_db() + self.asic_db = dvs.get_asic_db() + self.config_db = dvs.get_config_db() + self.state_db = dvs.get_state_db() def create_vlan(self, vlan): - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) - tbl.set("Vlan" + vlan, fvs) - time.sleep(1) + vlan = "Vlan{}".format(vlan) + vlan_entry = {"vlanid": vlan} + self.config_db.create_entry("VLAN", vlan, vlan_entry) def remove_vlan(self, vlan): - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan" + vlan) - time.sleep(1) + vlan = "Vlan{}".format(vlan) + self.config_db.delete_entry("VLAN", vlan) def create_vlan_member(self, vlan, interface, tagging_mode="untagged"): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", tagging_mode)]) - tbl.set("Vlan" + vlan + "|" + interface, fvs) - time.sleep(1) + member = "Vlan{}|{}".format(vlan, interface) + if tagging_mode: + member_entry = {"tagging_mode": tagging_mode} + else: + member_entry = {"no_tag_mode": ""} + + self.config_db.create_entry("VLAN_MEMBER", member, member_entry) def remove_vlan_member(self, vlan, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan" + vlan + "|" + interface) - time.sleep(1) - - def create_port_channel(self, dvs, channel, admin_status="up", mtu="1500"): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", admin_status), ("mtu", mtu)]) - tbl.set("PortChannel" + channel, fvs) - dvs.runcmd("ip link add PortChannel" + channel + " type bond") - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("state", "ok")]) - tbl.set("PortChannel" + channel, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - dvs.runcmd("ip link del PortChannel" + channel) - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - time.sleep(1) - - def create_port_channel_member(self, channel, interface, status="enabled"): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - fvs = swsscommon.FieldValuePairs([("status", status)]) - tbl.set("PortChannel" + channel + ":" + interface, fvs) - time.sleep(1) - - def remove_port_channel_member(self, channel, interface): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - tbl._del("PortChannel" + channel + ":" + interface) - time.sleep(1) + member = "Vlan{}|{}".format(vlan, interface) + self.config_db.delete_entry("VLAN_MEMBER", member) + + def create_port_channel(self, lag_id, admin_status="up", mtu="1500"): + lag = "PortChannel{}".format(lag_id) + lag_entry = {"admin_status": admin_status, "mtu": mtu} + self.config_db.create_entry("PORTCHANNEL", lag, lag_entry) + + def remove_port_channel(self, lag_id): + lag = "PortChannel{}".format(lag_id) + self.config_db.delete_entry("PORTCHANNEL", lag) + + def create_port_channel_member(self, lag_id, interface): + member = "PortChannel{}|{}".format(lag_id, interface) + member_entry = {"NULL": "NULL"} + self.config_db.create_entry("PORTCHANNEL_MEMBER", member, member_entry) + + def remove_port_channel_member(self, lag_id, interface): + member = "PortChannel{}|{}".format(lag_id, interface) + self.config_db.delete_entry("PORTCHANNEL_MEMBER", member) def check_syslog(self, dvs, marker, process, err_log, vlan_str, expected_cnt): - (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep %s | grep \"%s\" | grep -i \"%s\" | wc -l" % (marker, process, err_log, vlan_str)]) + (_, num) = dvs.runcmd( + ["sh", + "-c", + "awk '/{}/,ENDFILE {{print;}}' /var/log/syslog \ + | grep {} \ + | grep \"{}\" \ + | grep -i \"{}\" \ + | wc -l".format(marker, process, err_log, vlan_str)]) + assert num.strip() == str(expected_cnt) def check_app_db_vlan_fields(self, fvs, admin_status="up", mtu="9100"): - for fv in fvs: - if fv[0] == "admin_status": - assert fv[1] == admin_status - elif fv[0] == "mtu": - assert fv[1] == mtu + assert fvs.get("admin_status") == admin_status + assert fvs.get("mtu") == mtu def check_app_db_vlan_member_fields(self, fvs, tagging_mode="untagged"): - for fv in fvs: - if fv[0] == "tagging_mode": - assert fv[1] == tagging_mode + assert fvs.get("tagging_mode") == tagging_mode def check_state_db_vlan_fields(self, fvs, state="ok"): - for fv in fvs: - if fv[0] == "state": - assert fv[1] == state + assert fvs.get("state") == state def check_state_db_vlan_member_fields(self, fvs, state="ok"): - for fv in fvs: - if fv[0] == "state": - assert fv[1] == state + assert fvs.get("state") == state + + def verify_vlan(self, vlan_oid, vlan_id): + vlan = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_VLAN", vlan_oid) + assert vlan.get("SAI_VLAN_ATTR_VLAN_ID") == vlan_id + + def get_and_verify_vlan_ids(self, + expected_num, + polling_config=DVSDatabase.DEFAULT_POLLING_CONFIG): + vlan_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN", + expected_num + 1, + polling_config) + return [v for v in vlan_entries if v != self.asic_db.default_vlan_id] + + def verify_vlan_member(self, vlan_oid, iface, tagging_mode="SAI_VLAN_TAGGING_MODE_UNTAGGED"): + member_ids = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", 1) + member = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", member_ids[0]) + assert member == {"SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE": tagging_mode, + "SAI_VLAN_MEMBER_ATTR_VLAN_ID": vlan_oid, + "SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID": self.get_bridge_port_id(iface)} + + def get_and_verify_vlan_member_ids(self, expected_num): + return self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", expected_num) + + def get_bridge_port_id(self, expected_iface): + bridge_port_id = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT", 1)[0] + bridge_port = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT", bridge_port_id) + assert self.asic_db.port_to_id_map[bridge_port["SAI_BRIDGE_PORT_ATTR_PORT_ID"]] == expected_iface + return bridge_port_id + + def test_VlanAddRemove(self, dvs): + self.setup_db(dvs) - def test_VlanAddRemove(self, dvs, testlog): - dvs.setup_db() + vlan = "2" + interface = "Ethernet0" - # create vlan - dvs.create_vlan("2") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fv[1] == "2" - - # create vlan member - dvs.create_vlan_member("2", "Ethernet0") - - # check asic database - bridge_port_map = {} - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - bridge_port_entries = tbl.getKeys() - for key in bridge_port_entries: - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_BRIDGE_PORT_ATTR_PORT_ID": - bridge_port_map[key] = fv[1] - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 - - (status, fvs) = tbl.get(vlan_member_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE": - assert fv[1] == "SAI_VLAN_TAGGING_MODE_UNTAGGED" - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID": - assert dvs.asicdb.portoidmap[bridge_port_map[fv[1]]] == "Ethernet0" - else: - assert False - - # check port pvid - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") - (status, fvs) = tbl.get(dvs.asicdb.portnamemap["Ethernet0"]) - assert status == True - assert "SAI_PORT_ATTR_PORT_VLAN_ID" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_PORT_ATTR_PORT_VLAN_ID": - assert fv[1] == "2" - - # check host interface vlan tag - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF") - (status, fvs) = tbl.get(dvs.asicdb.hostifnamemap["Ethernet0"]) - assert status == True - assert "SAI_HOSTIF_ATTR_VLAN_TAG" in [fv[0] for fv in fvs] - for fv in fvs: - if fv[0] == "SAI_HOSTIF_ATTR_VLAN_TAG": - assert fv[1] == "SAI_HOSTIF_VLAN_TAG_KEEP" - - # remove vlan member - dvs.remove_vlan_member("2", "Ethernet0") - - # remove vlan - dvs.remove_vlan("2") - - def test_MultipleVlan(self, dvs, testlog): - return - dvs.setup_db() + self.create_vlan(vlan) + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan(vlan_oid, vlan) + + self.create_vlan_member(vlan, interface) + self.verify_vlan_member(vlan_oid, interface) + + # Verify the physical port configuration + member_port = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", + self.asic_db.port_name_map[interface]) + assert member_port.get("SAI_PORT_ATTR_PORT_VLAN_ID") == vlan + + # Verify the host interface configuration + member_iface = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", + self.asic_db.hostif_name_map[interface]) + assert member_iface.get("SAI_HOSTIF_ATTR_VLAN_TAG") == "SAI_HOSTIF_VLAN_TAG_KEEP" + + self.remove_vlan_member(vlan, interface) + self.get_and_verify_vlan_member_ids(0) + + self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) + + def test_MultipleVlan(self, dvs): + self.setup_db(dvs) + + def _create_vlan_members(vlan, member_list): + for member in member_list: + self.create_vlan_member(vlan, member) + + def _remove_vlan_members(vlan, member_list): + for member in member_list: + self.remove_vlan_member(vlan, member) + + vlan1 = "18" + vlan1_members = ["Ethernet0", "Ethernet4", "Ethernet8"] + vlan2 = "188" + vlan2_members = ["Ethernet20", "Ethernet24", "Ethernet28"] + + self.create_vlan(vlan1) + _create_vlan_members(vlan1, vlan1_members) + + self.get_and_verify_vlan_ids(1) + self.get_and_verify_vlan_member_ids(3) + + _remove_vlan_members(vlan1, vlan1_members) + + self.get_and_verify_vlan_member_ids(0) - # create vlan and vlan members - dvs.create_vlan("18") - dvs.create_vlan_member("18", "Ethernet0") - dvs.create_vlan_member("18", "Ethernet4") - dvs.create_vlan_member("18", "Ethernet8") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 3 - - # remove vlan members - dvs.remove_vlan_member("18", "Ethernet0") - dvs.remove_vlan_member("18", "Ethernet4") - dvs.remove_vlan_member("18", "Ethernet8") - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 0 - - # create vlan and vlan members - dvs.create_vlan("188") - dvs.create_vlan_member("188", "Ethernet20") - dvs.create_vlan_member("188", "Ethernet24") - dvs.create_vlan_member("188", "Ethernet28") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 2 - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 3 - - # create vlan members - dvs.create_vlan_member("18", "Ethernet40") - dvs.create_vlan_member("18", "Ethernet44") - dvs.create_vlan_member("18", "Ethernet48") - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 6 - - # remove vlan members - dvs.remove_vlan_member("18", "Ethernet40") - dvs.remove_vlan_member("18", "Ethernet44") - dvs.remove_vlan_member("18", "Ethernet48") - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 3 - - # remove vlan members - dvs.remove_vlan_member("188", "Ethernet20") - dvs.remove_vlan_member("188", "Ethernet24") - dvs.remove_vlan_member("188", "Ethernet28") - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 0 - - # member ports should have been detached from bridge master properly - exitcode, output = dvs.runcmd(['sh', '-c', "ip link show Ethernet20 | grep -w master"]) - assert exitcode != 0 - exitcode, output = dvs.runcmd(['sh', '-c', "ip link show Ethernet24 | grep -w master"]) - assert exitcode != 0 - exitcode, output = dvs.runcmd(['sh', '-c', "ip link show Ethernet28 | grep -w master"]) - assert exitcode != 0 - - # remove vlans - dvs.remove_vlan("18") - dvs.remove_vlan("188") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 - - def test_VlanIncrementalConfig(self, dvs, testlog): + self.create_vlan(vlan2) + _create_vlan_members(vlan2, vlan2_members) + + self.get_and_verify_vlan_ids(2) + self.get_and_verify_vlan_member_ids(3) + + _create_vlan_members(vlan1, vlan1_members) + + self.get_and_verify_vlan_member_ids(6) + + _remove_vlan_members(vlan1, vlan1_members) + + self.get_and_verify_vlan_member_ids(3) + + _remove_vlan_members(vlan2, vlan2_members) + + self.get_and_verify_vlan_member_ids(0) + + # Member ports should have been detached from master bridge port + for member in vlan2_members: + _, output = dvs.runcmd(['sh', '-c', "ip link show {}".format(member)]) + assert "master" not in output + + self.remove_vlan(vlan1) + self.get_and_verify_vlan_ids(1) + + self.remove_vlan(vlan2) + self.get_and_verify_vlan_ids(0) + + def test_VlanIncrementalConfig(self, dvs): + # TODO: add_ip_address has a dependency on cdb within dvs, + # so we still need to setup the db. This should be refactored. dvs.setup_db() + self.setup_db(dvs) - # create vlan - dvs.create_vlan("2") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fv[1] == "2" - - # create vlan member - dvs.create_vlan_member("2", "Ethernet0") - - # check asic database - bridge_port_map = {} - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - bridge_port_entries = tbl.getKeys() - for key in bridge_port_entries: - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_BRIDGE_PORT_ATTR_PORT_ID": - bridge_port_map[key] = fv[1] - - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 - - (status, fvs) = tbl.get(vlan_member_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE": - assert fv[1] == "SAI_VLAN_TAGGING_MODE_UNTAGGED" - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID": - assert dvs.asicdb.portoidmap[bridge_port_map[fv[1]]] == "Ethernet0" - else: - assert False - - # assign IP to interface - dvs.add_ip_address("Vlan2", "20.0.0.8/29") - - # check ASIC router interface database for mtu changes. - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan based router interface - assert len(intf_entries) == 2 + vlan = "2" + vlan_interface = "Vlan{}".format(vlan) + interface = "Ethernet0" + ip = "20.0.0.8/29" + initial_mtu = "9100" + new_mtu = "8888" + self.create_vlan(vlan) + + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan(vlan_oid, vlan) + + self.create_vlan_member(vlan, interface) + self.verify_vlan_member(vlan_oid, interface) + + dvs.add_ip_address(vlan_interface, ip) + + # Separate the VLAN interface from the Loopback interface + vlan_rif = None + intf_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a Vlan based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - # assert the default value 9100 for the router interface - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "9100" - - # configure MTU to interface - dvs.set_mtu("Vlan2", "8888") - intf_entries = tbl.getKeys() - for key in intf_entries: - (status, fvs) = tbl.get(key) - assert status == True - # a Vlan based router interface has five field/value tuples - if len(fvs) == 5: - for fv in fvs: - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_TYPE": - assert fv[1] == "SAI_ROUTER_INTERFACE_TYPE_VLAN" - # assert the new value set to the router interface - if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_MTU": - assert fv[1] == "8888" - - # check appDB for VLAN admin_status change. - tbl = swsscommon.Table(dvs.pdb, "VLAN_TABLE") - dvs.set_interface_status("Vlan2", "down") - (status, fvs) = tbl.get("Vlan2") - assert status == True - for fv in fvs: - if fv[0] == "admin_status": - assert fv[1] == "down" - - dvs.set_interface_status("Vlan2", "up") - (status, fvs) = tbl.get("Vlan2") - assert status == True - for fv in fvs: - if fv[0] == "admin_status": - assert fv[1] == "up" - - # remove IP from interface - dvs.remove_ip_address("Vlan2", "20.0.0.8/29") - - # remove vlan member - dvs.remove_vlan_member("2", "Ethernet0") - - # remove vlan - dvs.remove_vlan("2") - - - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") + fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key) + + if fvs.get("SAI_ROUTER_INTERFACE_ATTR_TYPE") == "SAI_ROUTER_INTERFACE_TYPE_VLAN": + assert fvs.get("SAI_ROUTER_INTERFACE_ATTR_MTU") == initial_mtu + vlan_rif = key + + assert vlan_rif + + dvs.set_mtu(vlan_interface, new_mtu) + self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", + vlan_rif, + {"SAI_ROUTER_INTERFACE_ATTR_MTU": new_mtu}) + + dvs.set_interface_status(vlan_interface, "down") + self.app_db.wait_for_field_match("VLAN_TABLE", vlan_interface, {"admin_status": "down"}) + + dvs.set_interface_status(vlan_interface, "up") + self.app_db.wait_for_field_match("VLAN_TABLE", vlan_interface, {"admin_status": "up"}) + + dvs.remove_ip_address(vlan_interface, ip) + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) + + self.remove_vlan_member(vlan, interface) + self.get_and_verify_vlan_member_ids(0) + + self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) + + @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), + reason="Debian 8.9 or before has no support") @pytest.mark.parametrize("test_input, expected", [ - (["Vla", "2"], 0), + (["Vla", "2"], 0), (["VLAN", "3"], 0), (["vlan", "4"], 0), (["Vlan", "5"], 1), ]) - def test_AddVlanWithIncorrectKeyPrefix(self, dvs, testlog, test_input, expected): - dvs.setup_db() + def test_AddVlanWithIncorrectKeyPrefix(self, dvs, test_input, expected): + self.setup_db(dvs) marker = dvs.add_log_marker() - vlan_prefix = test_input[0] - vlan = test_input[1] - - # create vlan - tbl = swsscommon.Table(dvs.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) - tbl.set(vlan_prefix + vlan, fvs) - time.sleep(1) - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == expected - - if len(vlan_entries) == 0: - # check error log - self.check_syslog(dvs, marker, "vlanmgrd", "Invalid key format. No 'Vlan' prefix:", vlan_prefix+vlan, 1) + + vlan_id = test_input[1] + vlan = "{}{}".format(test_input[0], vlan_id) + + self.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) + vlan_entries = self.get_and_verify_vlan_ids(expected) + + if not vlan_entries: + # If no VLAN is created, we should see the error in the logs + # TODO: refactor to use loganalyzer + self.check_syslog(dvs, marker, "vlanmgrd", "Invalid key format. No 'Vlan' prefix:", vlan, 1) else: - #remove vlan - dvs.remove_vlan(vlan) + self.remove_vlan(vlan_id) + self.get_and_verify_vlan_ids(0) - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") + @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), + reason="Debian 8.9 or before has no support") @pytest.mark.parametrize("test_input, expected", [ (["Vlan", "abc"], 0), - (["Vlan", "a3"], 0), - (["Vlan", ""], 0), + (["Vlan", "a3"], 0), + (["Vlan", ""], 0), (["Vlan", "5"], 1), ]) - def test_AddVlanWithIncorrectValueType(self, dvs, testlog, test_input, expected): - dvs.setup_db() + def test_AddVlanWithIncorrectValueType(self, dvs, test_input, expected): + self.setup_db(dvs) marker = dvs.add_log_marker() - vlan_prefix = test_input[0] - vlan = test_input[1] - - # create vlan - tbl = swsscommon.Table(dvs.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) - tbl.set(vlan_prefix + vlan, fvs) - time.sleep(1) - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == expected - - if len(vlan_entries) == 0: - # check error log - self.check_syslog(dvs, marker, "vlanmgrd", "Invalid key format. Not a number after \'Vlan\' prefix:", vlan_prefix+vlan, 1) + + vlan_id = test_input[1] + vlan = "{}{}".format(test_input[0], vlan_id) + + self.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) + vlan_entries = self.get_and_verify_vlan_ids(expected) + + if not vlan_entries: + # If no VLAN is created, we should see the error in the logs + # TODO: refactor to use loganalyzer + self.check_syslog(dvs, marker, "vlanmgrd", + "Invalid key format. Not a number after \'Vlan\' prefix:", vlan, 1) else: - #remove vlan - dvs.remove_vlan(vlan) - - # FIXME: This test is extremely unstable and requires several retries - # for it to pass - we need to stabilize this test before putting it back - # into the pipeline. - @pytest.mark.xfail(reason="test case is unstable") - def test_AddPortChannelToVlan(self, dvs, testlog): + self.remove_vlan(vlan_id) + self.get_and_verify_vlan_ids(0) + + def test_AddPortChannelToVlan(self, dvs): self.setup_db(dvs) - marker = dvs.add_log_marker() - vlan = "2" - channel = "001" - - # create port channel - self.create_port_channel(dvs, channel) - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag_entries = tbl.getKeys() - assert len(lag_entries) == 1 - - # add port channel member - self.create_port_channel_member(channel, "Ethernet0") - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lag_member_entries = tbl.getKeys() - assert len(lag_member_entries) == 1 - - (status, fvs) = tbl.get(lag_member_entries[0]) - for fv in fvs: - if fv[0] == "SAI_LAG_MEMBER_ATTR_LAG_ID": - assert fv[1] == lag_entries[0] - elif fv[0] == "SAI_LAG_MEMBER_ATTR_PORT_ID": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet0" - else: - assert False - - # create vlan - self.create_vlan(vlan) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 + vlan = "2" + lag_member = "Ethernet0" + lag_id = "0001" + lag_interface = "PortChannel{}".format(lag_id) - # create vlan member - self.create_vlan_member(vlan, "PortChannel" + channel, "tagged") + self.create_port_channel(lag_id) + lag_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 + self.create_port_channel_member(lag_id, lag_member) - # remove vlan member - self.remove_vlan_member(vlan, "PortChannel" + channel) + # Verify the LAG has been initialized properly + lag_member_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) + fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lag_member_entries[0]) + assert len(fvs) == 4 + assert fvs.get("SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_entries[0] + assert self.asic_db.port_to_id_map[fvs.get("SAI_LAG_MEMBER_ATTR_PORT_ID")] == lag_member - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 0 + self.create_vlan(vlan) + self.get_and_verify_vlan_ids(1) - # remove vlan - self.remove_vlan(vlan) + self.create_vlan_member(vlan, lag_interface, "tagged") + self.get_and_verify_vlan_member_ids(1) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 + self.remove_vlan_member(vlan, lag_interface) + self.get_and_verify_vlan_member_ids(0) - # remove trunk member - self.remove_port_channel_member(channel, "Ethernet0") + self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") - lag_member_entries = tbl.getKeys() - assert len(lag_member_entries) == 0 + self.remove_port_channel_member(lag_id, lag_member) + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) - # remove trunk - self.remove_port_channel(dvs, channel) + self.remove_port_channel(lag_id) + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") - lag_entries = tbl.getKeys() - assert len(lag_entries) == 0 + def test_AddVlanMemberWithNonExistVlan(self, dvs): + self.setup_db(dvs) - def test_AddVlanMemberWithNonExistVlan(self, dvs, testlog): - dvs.setup_db() - marker = dvs.add_log_marker() vlan = "2" + interface = "Ethernet0" - # create vlan member - dvs.create_vlan_member(vlan, "Ethernet0") + self.create_vlan_member(vlan, interface) - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 + # Nothing should be created because there's no VLAN + self.get_and_verify_vlan_member_ids(0) + self.get_and_verify_vlan_ids(0) - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 0 + self.remove_vlan_member(vlan, interface) - # remove vlan member from cfgdb - dvs.remove_vlan_member(vlan, "Ethernet0") + def test_RemoveNonexistentVlan(self, dvs): + self.setup_db(dvs) - def test_RemoveNonexistentVlan(self, dvs, testlog): - dvs.setup_db() - marker = dvs.add_log_marker() vlan = "2" - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 - - # remove nonexistent vlan - dvs.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) - # create vlan - dvs.create_vlan(vlan) + self.remove_vlan(vlan) - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 + # Verify that we're still able to create the VLAN after "deleting" it + self.create_vlan(vlan) + self.get_and_verify_vlan_ids(1) - # remove vlan - dvs.remove_vlan(vlan) + self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") + @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), + reason="Debian 8.9 or before has no support") @pytest.mark.parametrize("test_input, expected", [ - (["tagging_mode", "untagged"], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), - (["tagging_mode", "tagged"], [1, "SAI_VLAN_TAGGING_MODE_TAGGED"]), + (["tagging_mode", "untagged"], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), + (["tagging_mode", "tagged"], [1, "SAI_VLAN_TAGGING_MODE_TAGGED"]), (["tagging_mode", "priority_tagged"], [1, "SAI_VLAN_TAGGING_MODE_PRIORITY_TAGGED"]), (["tagging_mode", "unexpected_mode"], [0, ""]), - (["no_tag_mode", ""], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), + (["no_tag_mode", ""], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), ]) - def test_VlanMemberTaggingMode(self, dvs, testlog, test_input, expected): + def test_VlanMemberTaggingMode(self, dvs, test_input, expected): self.setup_db(dvs) - tagging_mode_prefix = test_input[0] - tagging_mode = test_input[1] marker = dvs.add_log_marker() + + if test_input[0] == "no_tag_mode": + tagging_mode = None + else: + tagging_mode = test_input[1] + vlan = "2" + interface = "Ethernet0" - # create vlan self.create_vlan(vlan) + vlan_oid = self.get_and_verify_vlan_ids(1)[0] - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # add vlan member - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([(tagging_mode_prefix, tagging_mode)]) - tbl.set("Vlan" + vlan + "|" + "Ethernet0", fvs) - time.sleep(1) - - # check asic database - bridge_port_map = {} - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - bridge_port_entries = tbl.getKeys() - for key in bridge_port_entries: - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_BRIDGE_PORT_ATTR_PORT_ID": - bridge_port_map[key] = fv[1] - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == expected[0] + self.create_vlan_member(vlan, interface, tagging_mode) + vlan_member_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", expected[0]) if len(vlan_member_entries) == 1: - (status, fvs) = tbl.get(vlan_member_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE": - assert fv[1] == expected[1] - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID": - assert dvs.asicdb.portoidmap[bridge_port_map[fv[1]]] == "Ethernet0" - else: - assert False + self.verify_vlan_member(vlan_oid, interface, expected[1]) else: - # check error log + # If no VLAN is created, we should see the error in the logs + # TODO: refactor to use loganalyzer self.check_syslog(dvs, marker, "vlanmgrd", "Wrong tagging_mode", test_input, 1) - # remove vlan member - self.remove_vlan_member(vlan, "Ethernet0") + self.remove_vlan_member(vlan, interface) + self.get_and_verify_vlan_member_ids(0) - # remove vlan self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0) - @pytest.mark.skip(reason="AddMaxVlan take too long to execute") - def test_AddMaxVlan(self, dvs, testlog): - dvs.setup_db() + @pytest.mark.skip(reason="AddMaxVlan takes too long to execute") + def test_AddMaxVlan(self, dvs): + self.setup_db(dvs) + max_poll = PollingConfig(polling_interval=3, timeout=300, strict=True) min_vid = 2 max_vid = 4094 - # create max vlan - vlan = min_vid - while vlan <= max_vid: - dvs.create_vlan(str(vlan)) - vlan += 1 - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == (4094-1) - - # remove all vlan - vlan = min_vid - while vlan <= max_vid: - dvs.remove_vlan(str(vlan)) - vlan += 1 - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 - - # FIXME: This test is extremely unstable and requires several retries - # for it to pass - we need to stabilize this test before putting it back - # into the pipeline. - @pytest.mark.xfail(reason="test case is unstable") - def test_RemoveVlanWithRouterInterface(self, dvs, testlog): + for vlan in range(min_vid, max_vid + 1): + self.create_vlan(str(vlan)) + + self.get_and_verify_vlan_ids(max_vid - 1, polling_config=max_poll) + + for vlan in range(min_vid, max_vid + 1): + self.remove_vlan(str(vlan)) + + self.get_and_verify_vlan_ids(0, polling_config=max_poll) + + def test_RemoveVlanWithRouterInterface(self, dvs): + # TODO: add_ip_address has a dependency on cdb within dvs, + # so we still need to setup the db. This should be refactored. dvs.setup_db() - marker = dvs.add_log_marker() + self.setup_db(dvs) + + vlan = "100" + vlan_interface = "Vlan{}".format(vlan) + ip = "20.0.0.8/29" + + self.create_vlan(vlan) + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan(vlan_oid, vlan) + + dvs.add_ip_address(vlan_interface, ip) + + # Should see 1 VLAN interface and 1 Loopback interface + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - # create vlan - dvs.create_vlan("100") - - # check asic database - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fv[1] == "100" - - # assign IP to interface - dvs.add_ip_address("Vlan100", "20.0.0.8/29") - - # check ASIC router interface database for mtu changes. - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE") - intf_entries = tbl.getKeys() - # one loopback router interface one vlan based router interface - assert len(intf_entries) == 2 - - # remove vlan - dvs.remove_vlan("100") - - # check asic database still contains the vlan - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fv[1] == "100" - - # remove IP from interface - dvs.remove_ip_address("Vlan100", "20.0.0.8/29") - - # remove vlan - dvs.remove_vlan("100") - - # check asic database does not contain the vlan anymore - tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 0 - - def test_VlanDbData(self, dvs, testlog): + self.remove_vlan(vlan) + + # VLAN should still be preserved since the RIF depends on it + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan(vlan_oid, vlan) + + dvs.remove_ip_address(vlan_interface, ip) + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) + + self.remove_vlan(vlan) + + self.get_and_verify_vlan_ids(0) + + def test_VlanDbData(self, dvs): self.setup_db(dvs) vlan = "2" - # create vlan self.create_vlan(vlan) - # check app database - tbl = swsscommon.Table(self.pdb, "VLAN_TABLE") - vlan_entries = tbl.getKeys() - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) + vlan_oid = self.app_db.wait_for_n_keys("VLAN_TABLE", 1)[0] + fvs = self.app_db.wait_for_entry("VLAN_TABLE", vlan_oid) self.check_app_db_vlan_fields(fvs) - # check state database - tbl = swsscommon.Table(self.sdb, "VLAN_TABLE") - vlan_entries = tbl.getKeys() - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) + vlan_oid = self.state_db.wait_for_n_keys("VLAN_TABLE", 1)[0] + fvs = self.state_db.wait_for_entry("VLAN_TABLE", vlan_oid) self.check_state_db_vlan_fields(fvs) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - (status, fvs) = tbl.get(vlan_oid) - assert status == True - for fv in fvs: - if fv[0] == "SAI_VLAN_ATTR_VLAN_ID": - assert fv[1] == vlan + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan(vlan_oid, vlan) - # remove vlan self.remove_vlan(vlan) - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") + @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), + reason="Debian 8.9 or before has no support") @pytest.mark.parametrize("test_input, expected", [ - (["untagged"], ["SAI_VLAN_TAGGING_MODE_UNTAGGED"]), - (["tagged"], ["SAI_VLAN_TAGGING_MODE_TAGGED"]), + (["untagged"], ["SAI_VLAN_TAGGING_MODE_UNTAGGED"]), + (["tagged"], ["SAI_VLAN_TAGGING_MODE_TAGGED"]), (["priority_tagged"], ["SAI_VLAN_TAGGING_MODE_PRIORITY_TAGGED"]), ]) - def test_VlanMemberDbData(self, dvs, testlog, test_input, expected): + def test_VlanMemberDbData(self, dvs, test_input, expected): self.setup_db(dvs) + vlan = "2" interface = "Ethernet0" tagging_mode = test_input[0] - # create vlan self.create_vlan(vlan) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") - vlan_entries = [k for k in tbl.getKeys() if k != dvs.asicdb.default_vlan_id] - assert len(vlan_entries) == 1 - vlan_oid = vlan_entries[0] - - # create vlan member self.create_vlan_member(vlan, interface, tagging_mode) - # check app database - tbl = swsscommon.Table(self.pdb, "VLAN_MEMBER_TABLE") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 - vlan_member_oid = vlan_member_entries[0] - - (status, fvs) = tbl.get(vlan_member_oid) + vlan_oid = self.app_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] + fvs = self.app_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) self.check_app_db_vlan_member_fields(fvs, tagging_mode) - # check state database - tbl = swsscommon.Table(self.sdb, "VLAN_MEMBER_TABLE") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 - vlan_member_oid = vlan_member_entries[0] - - (status, fvs) = tbl.get(vlan_member_oid) + vlan_oid = self.state_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] + fvs = self.state_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) self.check_state_db_vlan_member_fields(fvs) - # check asic database - bridge_port_map = {} - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") - bridge_port_entries = tbl.getKeys() - for key in bridge_port_entries: - (status, fvs) = tbl.get(key) - assert status == True - for fv in fvs: - if fv[0] == "SAI_BRIDGE_PORT_ATTR_PORT_ID": - bridge_port_map[key] = fv[1] - - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") - vlan_member_entries = tbl.getKeys() - assert len(vlan_member_entries) == 1 - - (status, fvs) = tbl.get(vlan_member_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE": - assert fv[1] == expected[0] - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_VLAN_ID": - assert fv[1] == vlan_oid - elif fv[0] == "SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID": - assert dvs.asicdb.portoidmap[bridge_port_map[fv[1]]] == interface - else: - assert False - - # remove vlan member + vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.verify_vlan_member(vlan_oid, interface, expected[0]) + self.remove_vlan_member(vlan, interface) + self.get_and_verify_vlan_member_ids(0) - # remove vlan - self.remove_vlan(vlan) \ No newline at end of file + self.remove_vlan(vlan) + self.get_and_verify_vlan_ids(0)