From 2127fb9a88cc8d26561b6051c5d91d03db4a4863 Mon Sep 17 00:00:00 2001 From: Vasant Patil <36455926+vasant17@users.noreply.github.com> Date: Wed, 10 Jun 2020 15:50:22 -0700 Subject: [PATCH] [DPB/VLAN] Add test VS cases and fix FDB flush issues (#1242) * Flush fdb entries when port/LAG is operational down (#14) Co-authored-by: zhenggen-xu --- orchagent/fdborch.cpp | 188 ++++++++++++++++--- orchagent/fdborch.h | 6 +- orchagent/observer.h | 1 + orchagent/portsorch.cpp | 50 +++-- orchagent/portsorch.h | 15 ++ tests/conftest.py | 23 ++- tests/dvslib/dvs_lag.py | 21 +++ tests/dvslib/dvs_vlan.py | 76 ++++++++ tests/port_dpb.py | 15 ++ tests/test_fdb_update.py | 68 ++++++- tests/test_port_dpb_vlan.py | 239 ++++++++++++++++++++++++ tests/test_vlan.py | 363 ++++++++++++++---------------------- 12 files changed, 784 insertions(+), 281 deletions(-) create mode 100644 tests/dvslib/dvs_lag.py create mode 100644 tests/dvslib/dvs_vlan.py create mode 100644 tests/test_port_dpb_vlan.py diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9a54ba98f1..c4923ef0a0 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -57,14 +57,13 @@ bool FdbOrch::bake() bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) { const FdbEntry& entry = update.entry; - const Port& port = update.port; const MacAddress& mac = entry.mac; - string portName = port.m_alias; Port vlan; if (!m_portsOrch->getPort(entry.bv_id, vlan)) { - SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate vlan port from bv_id 0x%" PRIx64, entry.bv_id); + SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate \ + vlan port from bv_id 0x%" PRIx64, entry.bv_id); return false; } @@ -73,6 +72,9 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) if (update.add) { + SWSS_LOG_INFO("Storing FDB entry: [%s, 0x%" PRIx64 "] [ port: %s ]", + entry.mac.to_string().c_str(), + entry.bv_id, entry.port_name.c_str()); auto inserted = m_entries.insert(entry); SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%" PRIx64, @@ -86,7 +88,7 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) // Write to StateDb std::vector fvs; - fvs.push_back(FieldValueTuple("port", portName)); + fvs.push_back(FieldValueTuple("port", entry.port_name)); fvs.push_back(FieldValueTuple("type", "dynamic")); m_fdbStateTable.set(key, fvs); @@ -111,7 +113,9 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) } } -void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_object_id_t bridge_port_id) +void FdbOrch::update(sai_fdb_event_t type, + const sai_fdb_entry_t* entry, + sai_object_id_t bridge_port_id) { SWSS_LOG_ENTER(); @@ -119,6 +123,19 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj update.entry.mac = entry->mac_address; update.entry.bv_id = entry->bv_id; + SWSS_LOG_INFO("FDB event:%d, MAC: %s , BVID: 0x%" PRIx64 " , \ + bridge port ID: 0x%" PRIx64 ".", + type, update.entry.mac.to_string().c_str(), + entry->bv_id, bridge_port_id); + + if (bridge_port_id && + !m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) + { + SWSS_LOG_ERROR("Failed to get port by bridge port ID 0x%" PRIx64 ".", + bridge_port_id); + return; + } + switch (type) { case SAI_FDB_EVENT_LEARNED: @@ -137,8 +154,10 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj } update.add = true; + update.entry.port_name = update.port.m_alias; storeFdbEntryState(update); + SWSS_LOG_INFO("Notifying observers of FDB entry LEARN"); for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -151,6 +170,7 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj update.add = false; storeFdbEntryState(update); + SWSS_LOG_INFO("Notifying observers of FDB entry removal on AGED/MOVED"); for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -159,8 +179,31 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj break; case SAI_FDB_EVENT_FLUSHED: - if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID) + + SWSS_LOG_INFO("FDB Flush event received: [ %s , 0x%" PRIx64 " ], \ + bridge port ID: 0x%" PRIx64 ".", + update.entry.mac.to_string().c_str(), entry->bv_id, + bridge_port_id); + + string vlanName = "-"; + if (entry->bv_id) { + Port vlan; + + if (!m_portsOrch->getPort(entry->bv_id, vlan)) + { + SWSS_LOG_ERROR("FdbOrch notification: Failed to locate vlan\ + port from bv_id 0x%" PRIx64, entry->bv_id); + return; + } + vlanName = "Vlan" + to_string(vlan.m_vlan_info.vlan_id); + } + + + if (bridge_port_id == SAI_NULL_OBJECT_ID && + entry->bv_id == SAI_NULL_OBJECT_ID) { + SWSS_LOG_INFO("FDB Flush: [ %s , %s ] = { port: - }", + update.entry.mac.to_string().c_str(), vlanName.c_str()); for (auto itr = m_entries.begin(); itr != m_entries.end();) { /* @@ -176,27 +219,50 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj storeFdbEntryState(update); - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed", update.entry.mac.to_string().c_str()); - for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); } } } - else if (bridge_port_id && entry->bv_id == SAI_NULL_OBJECT_ID) + else if (entry->bv_id == SAI_NULL_OBJECT_ID) { - /*this is a placeholder for flush port fdb case, not supported yet.*/ - SWSS_LOG_ERROR("FdbOrch notification: not supported flush port fdb action, port_id = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ".", bridge_port_id, entry->bv_id); + /* FLUSH based on port */ + SWSS_LOG_INFO("FDB Flush: [ %s , %s ] = { port: %s }", + update.entry.mac.to_string().c_str(), + vlanName.c_str(), update.port.m_alias.c_str()); + + for (const auto& itr : m_entries) + { + if (itr.port_name == update.port.m_alias) + { + update.entry.mac = itr.mac; + update.entry.bv_id = itr.bv_id; + update.add = false; + + storeFdbEntryState(update); + + for (auto observer: m_observers) + { + observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); + } + } + } } - else if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id != SAI_NULL_OBJECT_ID) + else if (bridge_port_id == SAI_NULL_OBJECT_ID) { - /*this is a placeholder for flush vlan fdb case, not supported yet.*/ - SWSS_LOG_ERROR("FdbOrch notification: not supported flush vlan fdb action, port_id = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ".", bridge_port_id, entry->bv_id); + /* FLUSH based on VLAN - unsupported */ + SWSS_LOG_ERROR("Unsupported FDB Flush: [ %s , %s ] = { port: - }", + update.entry.mac.to_string().c_str(), + vlanName.c_str()); + } else { - SWSS_LOG_ERROR("FdbOrch notification: not supported flush fdb action, port_id = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ".", bridge_port_id, entry->bv_id); + /* FLUSH based on port and VLAN - unsupported */ + SWSS_LOG_ERROR("Unsupported FDB Flush: [ %s , %s ] = { port: %s }", + update.entry.mac.to_string().c_str(), + vlanName.c_str(), update.port.m_alias.c_str()); } break; } @@ -217,6 +283,12 @@ void FdbOrch::update(SubjectType type, void *cntx) updateVlanMember(*update); break; } + case SUBJECT_TYPE_PORT_OPER_STATE_CHANGE: + { + PortOperStateUpdate *update = reinterpret_cast(cntx); + updatePortOperState(*update); + break; + } default: break; } @@ -307,10 +379,11 @@ void FdbOrch::doTask(Consumer& consumer) } } + entry.port_name = port; /* FDB type is either dynamic or static */ assert(type == "dynamic" || type == "static"); - if (addFdbEntry(entry, port, type)) + if (addFdbEntry(entry, type)) it = consumer.m_toSync.erase(it); else it++; @@ -416,13 +489,67 @@ void FdbOrch::doTask(NotificationConsumer& consumer) } } +void FdbOrch::flushFDBEntries(sai_object_id_t bridge_port_oid, + sai_object_id_t vlan_oid) +{ + vector attrs; + sai_attribute_t attr; + sai_status_t rv = SAI_STATUS_SUCCESS; + + SWSS_LOG_ENTER(); + + if (SAI_NULL_OBJECT_ID == bridge_port_oid && + SAI_NULL_OBJECT_ID == vlan_oid) + { + SWSS_LOG_WARN("Couldn't flush FDB. Bridge port OID: 0x%" PRIx64 " bvid:%" PRIx64 ",", + bridge_port_oid, vlan_oid); + return; + } + + if (SAI_NULL_OBJECT_ID != bridge_port_oid) + { + attr.id = SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID; + attr.value.oid = bridge_port_oid; + attrs.push_back(attr); + } + + if (SAI_NULL_OBJECT_ID != vlan_oid) + { + attr.id = SAI_FDB_FLUSH_ATTR_BV_ID; + attr.value.oid = vlan_oid; + attrs.push_back(attr); + } + + SWSS_LOG_INFO("Flushing FDB bridge_port_oid: 0x%" PRIx64 ", and bvid_oid:0x%" PRIx64 ".", bridge_port_oid, vlan_oid); + + rv = sai_fdb_api->flush_fdb_entries(gSwitchId, (uint32_t)attrs.size(), attrs.data()); + if (SAI_STATUS_SUCCESS != rv) + { + SWSS_LOG_ERROR("Flushing FDB failed. rv:%d", rv); + } +} + +void FdbOrch::updatePortOperState(const PortOperStateUpdate& update) +{ + SWSS_LOG_ENTER(); + if (update.operStatus == SAI_PORT_OPER_STATUS_DOWN) + { + swss::Port p = update.port; + flushFDBEntries(p.m_bridge_port_id, SAI_NULL_OBJECT_ID); + } + return; +} + void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) { SWSS_LOG_ENTER(); if (!update.add) { - return; // we need additions only + swss::Port vlan = update.vlan; + swss::Port port = update.member; + flushFDBEntries(port.m_bridge_port_id, vlan.m_vlan_info.vlan_oid); + return; } string port_name = update.member.m_alias; @@ -433,12 +560,12 @@ void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) { // try to insert an FDB entry. If the FDB entry is not ready to be inserted yet, // it would be added back to the saved_fdb_entries structure by addFDBEntry() - (void)addFdbEntry(fdb.entry, port_name, fdb.type); + (void)addFdbEntry(fdb.entry, fdb.type); } } } -bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const string& type) +bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& type) { SWSS_LOG_ENTER(); @@ -450,10 +577,11 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const Port port; /* Retry until port is created */ - if (!m_portsOrch->getPort(port_name, port)) + if (!m_portsOrch->getPort(entry.port_name, port)) { - SWSS_LOG_DEBUG("Saving a fdb entry until port %s becomes active", port_name.c_str()); - saved_fdb_entries[port_name].push_back({entry, type}); + SWSS_LOG_DEBUG("Saving a fdb entry until port %s becomes active", + entry. port_name.c_str()); + saved_fdb_entries[entry.port_name].push_back({entry, type}); return true; } @@ -461,8 +589,9 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const /* Retry until port is added to the VLAN */ if (!port.m_bridge_port_id) { - SWSS_LOG_DEBUG("Saving a fdb entry until port %s has got a bridge port ID", port_name.c_str()); - saved_fdb_entries[port_name].push_back({entry, type}); + SWSS_LOG_DEBUG("Saving a fdb entry until port %s has got a bridge port ID", + entry.port_name.c_str()); + saved_fdb_entries[entry.port_name].push_back({entry, type}); return true; } @@ -491,11 +620,14 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create %s FDB %s on %s, rv:%d", - type.c_str(), entry.mac.to_string().c_str(), port_name.c_str(), status); + type.c_str(), entry.mac.to_string().c_str(), + entry.port_name.c_str(), status); return false; //FIXME: it should be based on status. Some could be retried, some not } - SWSS_LOG_NOTICE("Create %s FDB %s on %s", type.c_str(), entry.mac.to_string().c_str(), port_name.c_str()); + SWSS_LOG_NOTICE("Storing FDB entry: [%s, 0x%" PRIx64 "] [ port: %s , type: %s]", + entry.mac.to_string().c_str(), + entry.bv_id, entry.port_name.c_str(), type.c_str()); (void) m_entries.insert(entry); @@ -516,7 +648,8 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) if (m_entries.count(entry) == 0) { - SWSS_LOG_ERROR("FDB entry isn't found. mac=%s bv_id=0x%" PRIx64, entry.mac.to_string().c_str(), entry.bv_id); + SWSS_LOG_ERROR("FDB entry isn't found. mac=%s bv_id=0x%" PRIx64 ".", + entry.mac.to_string().c_str(), entry.bv_id); return true; } @@ -541,6 +674,7 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) Port port; m_portsOrch->getPortByBridgePortId(entry.bv_id, port); + SWSS_LOG_INFO("Notifying observers of FDB entry removal"); FdbUpdate update = {entry, port, false}; for (auto observer: m_observers) { diff --git a/orchagent/fdborch.h b/orchagent/fdborch.h index 3125b3112d..83f3086a0a 100644 --- a/orchagent/fdborch.h +++ b/orchagent/fdborch.h @@ -9,6 +9,7 @@ struct FdbEntry { MacAddress mac; sai_object_id_t bv_id; + std::string port_name; bool operator<(const FdbEntry& other) const { @@ -60,8 +61,11 @@ class FdbOrch: public Orch, public Subject, public Observer void doTask(NotificationConsumer& consumer); void updateVlanMember(const VlanMemberUpdate&); - bool addFdbEntry(const FdbEntry&, const string&, const string&); + void updatePortOperState(const PortOperStateUpdate&); + bool addFdbEntry(const FdbEntry&, const string&); bool removeFdbEntry(const FdbEntry&); + void flushFDBEntries(sai_object_id_t bridge_port_oid, + sai_object_id_t vlan_oid); bool storeFdbEntryState(const FdbUpdate& update); }; diff --git a/orchagent/observer.h b/orchagent/observer.h index 2630ee992f..34b31e351c 100644 --- a/orchagent/observer.h +++ b/orchagent/observer.h @@ -16,6 +16,7 @@ enum SubjectType SUBJECT_TYPE_MIRROR_SESSION_CHANGE, SUBJECT_TYPE_INT_SESSION_CHANGE, SUBJECT_TYPE_PORT_CHANGE, + SUBJECT_TYPE_PORT_OPER_STATE_CHANGE, }; class Observer diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 90a0efb1b7..cdd28e4999 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -35,6 +35,7 @@ extern sai_hostif_api_t* sai_hostif_api; extern sai_acl_api_t* sai_acl_api; extern sai_queue_api_t *sai_queue_api; extern sai_object_id_t gSwitchId; +extern sai_fdb_api_t *sai_fdb_api; extern IntfsOrch *gIntfsOrch; extern NeighOrch *gNeighOrch; extern CrmOrch *gCrmOrch; @@ -1582,7 +1583,7 @@ sai_status_t PortsOrch::removePort(sai_object_id_t port_id) sai_status_t status = sai_port_api->remove_port(port_id); if (status != SAI_STATUS_SUCCESS) { - return status; + return status; } m_portCount--; @@ -2271,13 +2272,13 @@ void PortsOrch::doPortTask(Consumer &consumer) if (bridge_port_oid != SAI_NULL_OBJECT_ID) { // Bridge port OID is set on a port as long as - // port is part of at-least one VLAN. - // Ideally this should be tracked by SAI redis. + // port is part of at-least one VLAN. + // Ideally this should be tracked by SAI redis. // Until then, let this snippet be here. SWSS_LOG_WARN("Cannot remove port as bridge port OID is present %" PRIx64 , bridge_port_oid); it++; continue; - } + } if (m_portList[alias].m_init) { @@ -2292,7 +2293,7 @@ void PortsOrch::doPortTask(Consumer &consumer) Port p; if (getPort(port_id, p)) { - PortUpdate update = {p, false }; + PortUpdate update = {p, false}; notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); } } @@ -2548,6 +2549,8 @@ void PortsOrch::doLagTask(Consumer &consumer) // Retrieve attributes uint32_t mtu = 0; string learn_mode; + bool operation_status_changed = false; + string operation_status; for (auto i : kfvFieldsValues(t)) { @@ -2561,13 +2564,22 @@ void PortsOrch::doLagTask(Consumer &consumer) } else if (fvField(i) == "oper_status") { - if (fvValue(i) == "down") + operation_status = fvValue(i); + if (!string_oper_status.count(operation_status)) { - gNeighOrch->ifChangeInformNextHop(alias, false); + SWSS_LOG_ERROR("Invalid operation status value:%s", operation_status.c_str()); + it++; + continue; } - else + + gNeighOrch->ifChangeInformNextHop(alias, + (operation_status == "up")); + Port lag; + if (getPort(alias, lag)) { - gNeighOrch->ifChangeInformNextHop(alias, true); + operation_status_changed = + (string_oper_status.at(operation_status) != + lag.m_oper_status); } } } @@ -2590,6 +2602,19 @@ void PortsOrch::doLagTask(Consumer &consumer) } else { + + if (!operation_status.empty()) + { + l.m_oper_status = string_oper_status.at(operation_status); + m_portList[alias] = l; + } + if (operation_status_changed) + { + PortOperStateUpdate update; + update.port = l; + update.operStatus = string_oper_status.at(operation_status); + notify(SUBJECT_TYPE_PORT_OPER_STATE_CHANGE, static_cast(&update)); + } if (mtu != 0) { l.m_mtu = mtu; @@ -3144,10 +3169,6 @@ bool PortsOrch::removeBridgePort(Port &port) return false; } - /* Flush FDB entries pointing to this bridge port */ - // TODO: Remove all FDB entries associated with this bridge port before - // removing the bridge port itself - /* Remove bridge port */ status = sai_bridge_api->remove_bridge_port(port.m_bridge_port_id); if (status != SAI_STATUS_SUCCESS) @@ -3828,6 +3849,9 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status) { SWSS_LOG_WARN("Inform nexthop operation failed for interface %s", port.m_alias.c_str()); } + + PortOperStateUpdate update = {port, status}; + notify(SUBJECT_TYPE_PORT_OPER_STATE_CHANGE, static_cast(&update)); } /* diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 34d7dfd8bf..5b7662470a 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -30,12 +30,27 @@ static const map oper_status_strings = { SAI_PORT_OPER_STATUS_NOT_PRESENT, "not present" } }; +static const unordered_map string_oper_status = +{ + { "unknown", SAI_PORT_OPER_STATUS_UNKNOWN }, + { "up", SAI_PORT_OPER_STATUS_UP }, + { "down", SAI_PORT_OPER_STATUS_DOWN }, + { "testing", SAI_PORT_OPER_STATUS_TESTING }, + { "not present", SAI_PORT_OPER_STATUS_NOT_PRESENT } +}; + struct PortUpdate { Port port; bool add; }; +struct PortOperStateUpdate +{ + Port port; + sai_port_oper_status_t operStatus; +}; + struct LagMemberUpdate { Port lag; diff --git a/tests/conftest.py b/tests/conftest.py index f761d9d7b6..fac32b3217 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,6 +15,8 @@ from swsscommon import swsscommon from dvslib import dvs_database as dvs_db from dvslib import dvs_acl +from dvslib import dvs_vlan +from dvslib import dvs_lag def ensure_system(cmd): (rc, output) = commands.getstatusoutput(cmd) @@ -981,14 +983,6 @@ def get_state_db(self): return self.state_db - def get_dvs_acl(self): - if not self.dvs_acl: - self.dvs_acl = dvs_acl.DVSAcl(self.get_asic_db(), - self.get_config_db(), - self.get_state_db(), - self.get_counters_db()) - return self.dvs_acl - @pytest.yield_fixture(scope="module") def dvs(request): name = request.config.getoption("--dvsname") @@ -1009,6 +1003,8 @@ def testlog(request, dvs): yield testlog dvs.runcmd("logger === finish test %s ===" % request.node.name) + +################# DVSLIB module manager fixtures ############################# @pytest.yield_fixture(scope="class") def dvs_acl_manager(request, dvs): request.cls.dvs_acl = dvs_acl.DVSAcl(dvs.get_asic_db(), @@ -1016,6 +1012,17 @@ def dvs_acl_manager(request, dvs): dvs.get_state_db(), dvs.get_counters_db()) +@pytest.yield_fixture(scope="class") +def dvs_lag_manager(request, dvs): + request.cls.dvs_lag = dvs_lag.DVSLag(dvs.get_config_db()) + +@pytest.yield_fixture(scope="class") +def dvs_vlan_manager(request, dvs): + request.cls.dvs_vlan = dvs_vlan.DVSVlan(dvs.get_asic_db(), + dvs.get_config_db(), + dvs.get_state_db(), + dvs.get_counters_db(), + dvs.get_app_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_lag.py b/tests/dvslib/dvs_lag.py new file mode 100644 index 0000000000..6eafb084f8 --- /dev/null +++ b/tests/dvslib/dvs_lag.py @@ -0,0 +1,21 @@ +class DVSLag(object): + def __init__(self, cdb): + self.config_db = cdb + + 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) diff --git a/tests/dvslib/dvs_vlan.py b/tests/dvslib/dvs_vlan.py new file mode 100644 index 0000000000..b22ac9cf12 --- /dev/null +++ b/tests/dvslib/dvs_vlan.py @@ -0,0 +1,76 @@ +from dvs_database import DVSDatabase + +class DVSVlan(object): + def __init__(self, adb, cdb, sdb, cntrdb, appdb): + self.asic_db = adb + self.config_db = cdb + self.state_db = sdb + self.counters_db = cntrdb + self.app_db = appdb + + def create_vlan(self, vlan): + vlan = "Vlan{}".format(vlan) + vlan_entry = {"vlanid": vlan} + self.config_db.create_entry("VLAN", vlan, vlan_entry) + + def remove_vlan(self, vlan): + vlan = "Vlan{}".format(vlan) + self.config_db.delete_entry("VLAN", vlan) + + def create_vlan_member(self, vlan, interface, tagging_mode="untagged"): + 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): + member = "Vlan{}|{}".format(vlan, interface) + self.config_db.delete_entry("VLAN_MEMBER", member) + + def check_app_db_vlan_fields(self, fvs, admin_status="up", mtu="9100"): + assert fvs.get("admin_status") == admin_status + assert fvs.get("mtu") == mtu + + def check_app_db_vlan_member_fields(self, fvs, tagging_mode="untagged"): + assert fvs.get("tagging_mode") == tagging_mode + + def check_state_db_vlan_fields(self, fvs, state="ok"): + assert fvs.get("state") == state + + def check_state_db_vlan_member_fields(self, fvs, state="ok"): + 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) + #TBD: port_to_id_map may NOT be updated one in case port is deleted and re-created. + # Hence the map needs refreshed. Need to think trough and decide when and where + # to do it. + assert self.asic_db.port_to_id_map[bridge_port["SAI_BRIDGE_PORT_ATTR_PORT_ID"]] == expected_iface + return bridge_port_id + diff --git a/tests/port_dpb.py b/tests/port_dpb.py index 55fbb6cc9c..5a5217ca60 100644 --- a/tests/port_dpb.py +++ b/tests/port_dpb.py @@ -27,6 +27,7 @@ def __init__(self, dvs, name = None): self._asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) self._asic_db_ptbl = swsscommon.Table(self._asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") self._counters_db = redis.Redis(unix_socket_path=self._dvs.redis_sock, db=swsscommon.COUNTERS_DB) + self._dvs_asic_db = dvs.get_asic_db() def set_name(self, name): self._name = name @@ -173,6 +174,9 @@ def exists_in_app_db(self): def sync_oid(self): self._oid = self._counters_db.hget("COUNTERS_PORT_NAME_MAP", self.get_name()) + """ + Expectation of the caller is that the port does exist in ASIC DB. + """ def exists_in_asic_db(self): self.sync_oid() if self._oid is None: @@ -180,6 +184,17 @@ def exists_in_asic_db(self): (status, _) = self._asic_db_ptbl.get(self._oid) return status + """ + Expectation of the caller is that the port does NOT exists in ASIC DB. + """ + def not_exists_in_asic_db(self): + self.sync_oid() + if self._oid is None: + return True + + result = self._dvs_asic_db.wait_for_deleted_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", self._oid) + return (not bool(result)) + def verify_config_db(self): (status, fvs) = self._cfg_db_ptbl.get(self.get_name()) assert(status == True) diff --git a/tests/test_fdb_update.py b/tests/test_fdb_update.py index 7d6fdc153c..59e6cb9add 100644 --- a/tests/test_fdb_update.py +++ b/tests/test_fdb_update.py @@ -7,7 +7,6 @@ from swsscommon import swsscommon from distutils.version import StrictVersion - class TestFdbUpdate(object): def create_entry(self, tbl, key, pairs): fvs = swsscommon.FieldValuePairs(pairs) @@ -200,6 +199,7 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): dvs.servers[16].runcmd("ifconfig eth0 hw ether 00:00:00:00:00:11") dvs.servers[16].runcmd("ifconfig eth0 6.6.6.6/24 up") dvs.servers[16].runcmd("ip route add default via 6.6.6.1") + dvs.servers[17].runcmd("ifconfig eth0 hw ether 00:00:00:00:17:11") dvs.servers[17].runcmd("ifconfig eth0 6.6.6.7/24 up") dvs.servers[17].runcmd("ip route add default via 6.6.6.1") time.sleep(2) @@ -240,9 +240,10 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): # restore the default value of the servers dvs.servers[16].runcmd("ip route del default via 6.6.6.1") - dvs.servers[16].runcmd("ifconfig eth0 0") + dvs.servers[16].runcmd("ifconfig eth0 0 down") dvs.servers[17].runcmd("ip route del default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 0") + dvs.servers[17].runcmd("ifconfig eth0 0 down") + dvs.servers[18].runcmd("ifconfig eth0 0 down") # bring down port dvs.set_interface_status("Ethernet64", "down") @@ -250,8 +251,7 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): dvs.set_interface_status("Ethernet72", "down") # remove vlan ip - key = "Vlan6" + "|" + "6.6.6.1/24" - self.remove_entry_tbl(dvs.cdb, "VLAN_INTERFACE", key) + dvs.remove_ip_address("Vlan6", "6.6.6.1/24") # bring down vlan dvs.set_interface_status("Vlan6", "down") @@ -264,3 +264,61 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): # clear fdb dvs.runcmd("sonic-clear fdb all") + + def test_FDBLearnedAndFlushed(self, dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + + VLAN = "9" + VLAN_NAME = "Vlan9" + PORT = "Ethernet80" + server = 20 + server_mac = "00:00:00:00:20:11" + + # create vlan; create vlan member + dvs.create_vlan(VLAN) + dvs.create_vlan_member(VLAN, PORT) + time.sleep(2) + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # bring up vlan and member + dvs.set_interface_status(VLAN_NAME, "up") + dvs.add_ip_address(VLAN_NAME, "7.7.7.1/24") + dvs.set_interface_status(PORT, "up") + + dvs.servers[server].runcmd("ifconfig eth0 hw ether {}".format(server_mac)) + dvs.servers[server].runcmd("ifconfig eth0 7.7.7.7/24 up") + + # get neighbor and arp entry + rc = dvs.servers[server].runcmd("ping -c 1 7.7.7.1") + assert rc == 0 + time.sleep(2) + + # check that the FDB entries were inserted into ASIC DB + mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) + assert server_mac in mac + + # bring down port + dvs.servers[server].runcmd("ip link set down dev eth0") == 0 + #dvs.set_interface_status(PORT, "down") + time.sleep(2) + + # fdb should be flushed + mac = self.get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) + assert not mac + + # remove vlan ip + dvs.remove_ip_address(VLAN_NAME, "7.7.7.1/24") + + # bring down vlan + dvs.set_interface_status(VLAN_NAME, "down") + + # remove vlan member; remove vlan + dvs.remove_vlan_member(VLAN, PORT) + dvs.remove_vlan(VLAN) + + # restore the default value of the servers + dvs.servers[server].runcmd("ifconfig eth0 0 down") diff --git a/tests/test_port_dpb_vlan.py b/tests/test_port_dpb_vlan.py new file mode 100644 index 0000000000..a79060fe80 --- /dev/null +++ b/tests/test_port_dpb_vlan.py @@ -0,0 +1,239 @@ +import time +import pytest +from port_dpb import Port +from port_dpb import DPB + +@pytest.mark.usefixtures('dpb_setup_fixture') +@pytest.mark.usefixtures('dvs_vlan_manager') +class TestPortDPBVlan(object): + def check_syslog(self, dvs, marker, log, expected_cnt): + (exitcode, num) = dvs.runcmd(['sh', '-c', "awk \'/%s/,ENDFILE {print;}\' /var/log/syslog | grep \"%s\" | wc -l" % (marker, log)]) + assert num.strip() >= str(expected_cnt) + + def test_dependency(self, dvs): + vlan = "100" + p = Port(dvs, "Ethernet0") + p.sync_from_config_db() + + # 1. Create VLAN100 + self.dvs_vlan.create_vlan(vlan) + + # 2. Add Ethernet0 to VLAN100 + self.dvs_vlan.create_vlan_member(vlan, p.get_name()) + + # 3. Add log marker to syslog + marker = dvs.add_log_marker() + + # 4. Delete Ethernet0 from config DB. Sleep for 2 seconds. + p.delete_from_config_db() + time.sleep(2) + + # 5. Verify that we are waiting in portsorch for the port + # to be removed from VLAN, by looking at the log + self.check_syslog(dvs, marker, "Cannot remove port as bridge port OID is present", 1) + + # 6. Also verify that port is still present in ASIC DB. + assert(p.exists_in_asic_db() == True) + + # 7. Remove port from VLAN + self.dvs_vlan.remove_vlan_member(vlan, p.get_name()) + + # 8. Verify that port is removed from ASIC DB + assert(p.not_exists_in_asic_db() == True) + + # 9. Re-create port Ethernet0 and verify that it is + # present in CONFIG, APPL, and ASIC DBs + p.write_to_config_db() + p.verify_config_db() + p.verify_app_db() + p.verify_asic_db() + + # 10. Remove VLAN100 and verify that its removed. + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(0) + + def test_one_port_one_vlan(self, dvs): + dpb = DPB() + vlan = "100" + + # 1. Create VLAN100 and add Ethernet0 as member + self.dvs_vlan.create_vlan(vlan) + self.dvs_vlan.create_vlan_member(vlan, "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(1) + + # 2. Delete Ethernet0 from config DB. Verify that its deleted + # CONFIG and APPL DB and its still present in ASIC DB + p = Port(dvs, "Ethernet0") + p.sync_from_config_db() + p.delete_from_config_db() + assert(p.exists_in_config_db() == False) + assert(p.exists_in_app_db() == False) + assert(p.exists_in_asic_db() == True) + + # 3. Verify that Ethernet0 gets deleted from ASIC DB once + # its removed from VLAN100. + self.dvs_vlan.remove_vlan_member(vlan, "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(0) + assert(p.not_exists_in_asic_db() == True) + + # 4. To simulate port breakout, 1x100G --> 4x25G, create 4 ports + dpb.create_child_ports(dvs, p, 4) + + # 5. Add all 4 ports to VLAN100 + port_names = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] + vlan_member_count = 0 + for pname in port_names: + self.dvs_vlan.create_vlan_member(vlan, pname) + vlan_member_count = vlan_member_count + 1 + self.dvs_vlan.get_and_verify_vlan_member_ids(vlan_member_count) + + # 6. Delete 4 ports from CONFIG DB. Verify that they are all deleted + # from CONFIG and APPL DB but still present in ASIC DB + child_ports = [] + for pname in port_names: + cp = Port(dvs, pname) + cp.sync_from_config_db() + cp.delete_from_config_db() + assert(cp.exists_in_config_db() == False) + assert(cp.exists_in_app_db() == False) + assert(cp.exists_in_asic_db() == True) + child_ports.append(cp) + + # 7. Remove all 4 ports from VLAN100 and verify that they all get + # deleted from ASIC DB + for cp in child_ports: + self.dvs_vlan.remove_vlan_member(vlan, cp.get_name()) + vlan_member_count = vlan_member_count - 1 + self.dvs_vlan.get_and_verify_vlan_member_ids(vlan_member_count) + assert(cp.not_exists_in_asic_db() == True) + + # 8. Re-create Ethernet0 and verify that its created all 3 DBs + p.write_to_config_db() + p.verify_config_db() + p.verify_app_db() + p.verify_asic_db() + + # 9. Remove VLAN100 and verify the same + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(0) + + def test_one_port_multiple_vlan(self, dvs): + + dpb = DPB() + vlans = ["100", "101", "102"] + + # 1. Create 3 VLANs + for vlan in vlans: + self.dvs_vlan.create_vlan(vlan) + + # 2. Add Ethernet0 to all 3 VLANs and verify + for vlan in vlans: + self.dvs_vlan.create_vlan_member(vlan, "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)) + + # 3. Delete Ethernet0 from CONFIG DB. Verify that it is deleted + # from CONFIG and APPl DB, whereas still present in ASIC DB. + p = Port(dvs, "Ethernet0") + p.sync_from_config_db() + p.delete_from_config_db() + assert(p.exists_in_config_db() == False) + assert(p.exists_in_app_db() == False) + assert(p.exists_in_asic_db() == True) + + # 4. Remove Ethernet0 from one of the VLANs and verify that + # its still present in ASIC DB + self.dvs_vlan.remove_vlan_member(vlans[0], "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)-1) + assert(p.exists_in_asic_db() == True) + + # 5. Remove Ethernet0 from one more VLAN and verify that + # its still present in ASIC DB + self.dvs_vlan.remove_vlan_member(vlans[1], "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(len(vlans)-2) + assert(p.exists_in_asic_db() == True) + + # 6. Remove Ethernet0 from last VLAN as well and verify that + # its deleted from ASIC DB + self.dvs_vlan.remove_vlan_member(vlans[2], "Ethernet0") + self.dvs_vlan.get_and_verify_vlan_member_ids(0) + assert(p.not_exists_in_asic_db() == True) + + # 7. To Simulate 1x40G --> 4x10G, create 4 ports + dpb.create_child_ports(dvs, p, 4) + + # 8. To Simulate 4x10G --> 1x40G, delete all 4 ports and re-create Ethernet0 + port_names = ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] + for pname in port_names: + cp = Port(dvs, pname) + cp.sync_from_config_db() + cp.delete_from_config_db() + assert(cp.exists_in_config_db() == False) + assert(cp.exists_in_app_db() == False) + assert(cp.not_exists_in_asic_db() == True) + + p.write_to_config_db() + p.verify_config_db() + p.verify_app_db() + p.verify_asic_db() + + # 9. Remove all 3 VLANs and verify the same + self.dvs_vlan.remove_vlan("100") + self.dvs_vlan.remove_vlan("101") + self.dvs_vlan.remove_vlan("102") + self.dvs_vlan.get_and_verify_vlan_ids(0) + + def test_all_port_10_vlans(self, dvs): + num_vlans = 10 + start_vlan = 100 + num_ports = 32 + port_names = [] + vlan_names = [] + + dvs.setup_db() + for i in range(num_ports): + port_names.append("Ethernet" + str(i*4)) + + for i in range(num_vlans): + vlan_names.append(str(start_vlan + i)) + + # 1. Create 10 VLANs + for vlan_name in vlan_names: + self.dvs_vlan.create_vlan(vlan_name) + + # 2. Add all 32 ports to all 10 VLANs + for port_name in port_names: + for vlan_name in vlan_names: + self.dvs_vlan.create_vlan_member(vlan_name, port_name, tagging_mode = "tagged") + self.dvs_vlan.get_and_verify_vlan_member_ids(num_ports*num_vlans) + + # 3. Do the following for each port + # 3.1. Delete port from CONFIG DB and verify that its deleted from + # CONFIG DB and APPL DB but not from ASIC DB. + # 3.2. Remove the port from all 10 VLANs and verify that it + # gets deleted from ASIC DB + ports = [] + for port_name in port_names: + p = Port(dvs, port_name) + ports.append(p) + p.sync_from_config_db() + p.delete_from_config_db() + assert(p.exists_in_config_db() == False) + assert(p.exists_in_app_db() == False) + assert(p.exists_in_asic_db() == True) + for vlan_name in vlan_names: + self.dvs_vlan.remove_vlan_member(vlan_name, port_name) + + self.dvs_vlan.get_and_verify_vlan_member_ids((num_ports*num_vlans)-(len(ports)*num_vlans)) + assert(p.not_exists_in_asic_db() == True) + + # 4. Re-create all ports and verify the same + for p in ports: + p.write_to_config_db() + p.verify_config_db() + p.verify_app_db() + p.verify_asic_db() + + # 5. Remove all VLANs and verify the same + for vlan_name in vlan_names: + self.dvs_vlan.remove_vlan(vlan_name) + self.dvs_vlan.get_and_verify_vlan_ids(0) diff --git a/tests/test_vlan.py b/tests/test_vlan.py index 9124cb5d12..39b9bf7655 100644 --- a/tests/test_vlan.py +++ b/tests/test_vlan.py @@ -3,55 +3,11 @@ from distutils.version import StrictVersion from dvslib.dvs_common import PollingConfig -from dvslib.dvs_database import DVSDatabase @pytest.mark.usefixtures("testlog") +@pytest.mark.usefixtures('dvs_vlan_manager') +@pytest.mark.usefixtures('dvs_lag_manager') class TestVlan(object): - def setup_db(self, dvs): - 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): - vlan = "Vlan{}".format(vlan) - vlan_entry = {"vlanid": vlan} - self.config_db.create_entry("VLAN", vlan, vlan_entry) - - def remove_vlan(self, vlan): - vlan = "Vlan{}".format(vlan) - self.config_db.delete_entry("VLAN", vlan) - - def create_vlan_member(self, vlan, interface, tagging_mode="untagged"): - 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): - 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): (_, num) = dvs.runcmd( @@ -65,136 +21,93 @@ def check_syslog(self, dvs, marker, process, err_log, vlan_str, expected_cnt): assert num.strip() == str(expected_cnt) - def check_app_db_vlan_fields(self, fvs, admin_status="up", mtu="9100"): - assert fvs.get("admin_status") == admin_status - assert fvs.get("mtu") == mtu - - def check_app_db_vlan_member_fields(self, fvs, tagging_mode="untagged"): - assert fvs.get("tagging_mode") == tagging_mode - - def check_state_db_vlan_fields(self, fvs, state="ok"): - assert fvs.get("state") == state - - def check_state_db_vlan_member_fields(self, fvs, state="ok"): - 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) vlan = "2" interface = "Ethernet0" - self.create_vlan(vlan) - vlan_oid = self.get_and_verify_vlan_ids(1)[0] - self.verify_vlan(vlan_oid, vlan) + self.dvs_vlan.create_vlan(vlan) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.verify_vlan(vlan_oid, vlan) - self.create_vlan_member(vlan, interface) - self.verify_vlan_member(vlan_oid, interface) + self.dvs_vlan.create_vlan_member(vlan, interface) + self.dvs_vlan.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]) + member_port = self.dvs_vlan.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", + dvs.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]) + member_iface = self.dvs_vlan.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", + dvs.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.dvs_vlan.remove_vlan_member(vlan, interface) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.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) + self.dvs_vlan.create_vlan_member(vlan, member) def _remove_vlan_members(vlan, member_list): for member in member_list: - self.remove_vlan_member(vlan, member) + self.dvs_vlan.remove_vlan_member(vlan, member) vlan1 = "18" vlan1_members = ["Ethernet0", "Ethernet4", "Ethernet8"] vlan2 = "188" vlan2_members = ["Ethernet20", "Ethernet24", "Ethernet28"] - self.create_vlan(vlan1) + self.dvs_vlan.create_vlan(vlan1) _create_vlan_members(vlan1, vlan1_members) - self.get_and_verify_vlan_ids(1) - self.get_and_verify_vlan_member_ids(3) + self.dvs_vlan.get_and_verify_vlan_ids(1) + self.dvs_vlan.get_and_verify_vlan_member_ids(3) _remove_vlan_members(vlan1, vlan1_members) - self.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.create_vlan(vlan2) + self.dvs_vlan.create_vlan(vlan2) _create_vlan_members(vlan2, vlan2_members) - self.get_and_verify_vlan_ids(2) - self.get_and_verify_vlan_member_ids(3) + self.dvs_vlan.get_and_verify_vlan_ids(2) + self.dvs_vlan.get_and_verify_vlan_member_ids(3) _create_vlan_members(vlan1, vlan1_members) - self.get_and_verify_vlan_member_ids(6) + self.dvs_vlan.get_and_verify_vlan_member_ids(6) _remove_vlan_members(vlan1, vlan1_members) - self.get_and_verify_vlan_member_ids(3) + self.dvs_vlan.get_and_verify_vlan_member_ids(3) _remove_vlan_members(vlan2, vlan2_members) - self.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.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.dvs_vlan.remove_vlan(vlan1) + self.dvs_vlan.get_and_verify_vlan_ids(1) - self.remove_vlan(vlan2) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan2) + self.dvs_vlan.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) vlan = "2" vlan_interface = "Vlan{}".format(vlan) @@ -203,21 +116,21 @@ def test_VlanIncrementalConfig(self, dvs): initial_mtu = "9100" new_mtu = "8888" - self.create_vlan(vlan) + self.dvs_vlan.create_vlan(vlan) - vlan_oid = self.get_and_verify_vlan_ids(1)[0] - self.verify_vlan(vlan_oid, vlan) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.verify_vlan(vlan_oid, vlan) - self.create_vlan_member(vlan, interface) - self.verify_vlan_member(vlan_oid, interface) + self.dvs_vlan.create_vlan_member(vlan, interface) + self.dvs_vlan.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) + intf_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) for key in intf_entries: - fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", key) + fvs = self.dvs_vlan.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 @@ -226,24 +139,24 @@ def test_VlanIncrementalConfig(self, dvs): assert vlan_rif dvs.set_mtu(vlan_interface, new_mtu) - self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", + self.dvs_vlan.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"}) + self.dvs_vlan.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"}) + self.dvs_vlan.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.dvs_vlan.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.dvs_vlan.remove_vlan_member(vlan, interface) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.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") @@ -253,23 +166,24 @@ def test_VlanIncrementalConfig(self, dvs): (["vlan", "4"], 0), (["Vlan", "5"], 1), ]) + def test_AddVlanWithIncorrectKeyPrefix(self, dvs, test_input, expected): - self.setup_db(dvs) + marker = dvs.add_log_marker() 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) + self.dvs_vlan.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) + vlan_entries = self.dvs_vlan.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: - self.remove_vlan(vlan_id) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan_id) + self.dvs_vlan.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") @@ -280,14 +194,14 @@ def test_AddVlanWithIncorrectKeyPrefix(self, dvs, test_input, expected): (["Vlan", "5"], 1), ]) def test_AddVlanWithIncorrectValueType(self, dvs, test_input, expected): - self.setup_db(dvs) + marker = dvs.add_log_marker() 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) + self.dvs_vlan.config_db.create_entry("VLAN", vlan, {"vlanid": vlan_id}) + vlan_entries = self.dvs_vlan.get_and_verify_vlan_ids(expected) if not vlan_entries: # If no VLAN is created, we should see the error in the logs @@ -295,76 +209,73 @@ def test_AddVlanWithIncorrectValueType(self, dvs, test_input, expected): self.check_syslog(dvs, marker, "vlanmgrd", "Invalid key format. Not a number after \'Vlan\' prefix:", vlan, 1) else: - self.remove_vlan(vlan_id) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan_id) + self.dvs_vlan.get_and_verify_vlan_ids(0) def test_AddPortChannelToVlan(self, dvs): - self.setup_db(dvs) vlan = "2" lag_member = "Ethernet0" lag_id = "0001" lag_interface = "PortChannel{}".format(lag_id) - self.create_port_channel(lag_id) - lag_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel(lag_id) + lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) - self.create_port_channel_member(lag_id, lag_member) + self.dvs_lag.create_port_channel_member(lag_id, lag_member) # 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]) + lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) + fvs = self.dvs_vlan.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 + assert self.dvs_vlan.asic_db.port_to_id_map[fvs.get("SAI_LAG_MEMBER_ATTR_PORT_ID")] == lag_member - self.create_vlan(vlan) - self.get_and_verify_vlan_ids(1) + self.dvs_vlan.create_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(1) - self.create_vlan_member(vlan, lag_interface, "tagged") - self.get_and_verify_vlan_member_ids(1) + self.dvs_vlan.create_vlan_member(vlan, lag_interface, "tagged") + self.dvs_vlan.get_and_verify_vlan_member_ids(1) - self.remove_vlan_member(vlan, lag_interface) - self.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.remove_vlan_member(vlan, lag_interface) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(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) + self.dvs_lag.remove_port_channel_member(lag_id, lag_member) + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) - self.remove_port_channel(lag_id) - self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) + self.dvs_lag.remove_port_channel(lag_id) + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) def test_AddVlanMemberWithNonExistVlan(self, dvs): - self.setup_db(dvs) vlan = "2" interface = "Ethernet0" - self.create_vlan_member(vlan, interface) + self.dvs_vlan.create_vlan_member(vlan, interface) # Nothing should be created because there's no VLAN - self.get_and_verify_vlan_member_ids(0) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.get_and_verify_vlan_ids(0) - self.remove_vlan_member(vlan, interface) + self.dvs_vlan.remove_vlan_member(vlan, interface) def test_RemoveNonexistentVlan(self, dvs): - self.setup_db(dvs) vlan = "2" - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.get_and_verify_vlan_ids(0) - self.remove_vlan(vlan) + self.dvs_vlan.remove_vlan(vlan) # Verify that we're still able to create the VLAN after "deleting" it - self.create_vlan(vlan) - self.get_and_verify_vlan_ids(1) + self.dvs_vlan.create_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(1) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.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") @@ -375,8 +286,9 @@ def test_RemoveNonexistentVlan(self, dvs): (["tagging_mode", "unexpected_mode"], [0, ""]), (["no_tag_mode", ""], [1, "SAI_VLAN_TAGGING_MODE_UNTAGGED"]), ]) + def test_VlanMemberTaggingMode(self, dvs, test_input, expected): - self.setup_db(dvs) + marker = dvs.add_log_marker() if test_input[0] == "no_tag_mode": @@ -387,93 +299,91 @@ def test_VlanMemberTaggingMode(self, dvs, test_input, expected): vlan = "2" interface = "Ethernet0" - self.create_vlan(vlan) - vlan_oid = self.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.create_vlan(vlan) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[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]) + self.dvs_vlan.create_vlan_member(vlan, interface, tagging_mode) + vlan_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", expected[0]) if len(vlan_member_entries) == 1: - self.verify_vlan_member(vlan_oid, interface, expected[1]) + self.dvs_vlan.verify_vlan_member(vlan_oid, interface, expected[1]) else: # 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) - self.remove_vlan_member(vlan, interface) - self.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.remove_vlan_member(vlan, interface) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(0) @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 for vlan in range(min_vid, max_vid + 1): - self.create_vlan(str(vlan)) + self.dvs_vlan.create_vlan(str(vlan)) - self.get_and_verify_vlan_ids(max_vid - 1, polling_config=max_poll) + self.dvs_vlan.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.dvs_vlan.remove_vlan(str(vlan)) - self.get_and_verify_vlan_ids(0, polling_config=max_poll) + self.dvs_vlan.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() - 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) + self.dvs_vlan.create_vlan(vlan) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.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) + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 2) - self.remove_vlan(vlan) + self.dvs_vlan.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) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.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.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE", 1) - self.remove_vlan(vlan) + self.dvs_vlan.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.get_and_verify_vlan_ids(0) def test_VlanDbData(self, dvs): - self.setup_db(dvs) vlan = "2" - self.create_vlan(vlan) + self.dvs_vlan.create_vlan(vlan) - 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) + vlan_oid = self.dvs_vlan.app_db.wait_for_n_keys("VLAN_TABLE", 1)[0] + fvs = self.dvs_vlan.app_db.wait_for_entry("VLAN_TABLE", vlan_oid) + self.dvs_vlan.check_app_db_vlan_fields(fvs) - 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) + vlan_oid = self.dvs_vlan.state_db.wait_for_n_keys("VLAN_TABLE", 1)[0] + fvs = self.dvs_vlan.state_db.wait_for_entry("VLAN_TABLE", vlan_oid) + self.dvs_vlan.check_state_db_vlan_fields(fvs) - vlan_oid = self.get_and_verify_vlan_ids(1)[0] - self.verify_vlan(vlan_oid, vlan) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.verify_vlan(vlan_oid, vlan) - self.remove_vlan(vlan) + self.dvs_vlan.remove_vlan(vlan) @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") @@ -483,29 +393,28 @@ def test_VlanDbData(self, dvs): (["priority_tagged"], ["SAI_VLAN_TAGGING_MODE_PRIORITY_TAGGED"]), ]) def test_VlanMemberDbData(self, dvs, test_input, expected): - self.setup_db(dvs) vlan = "2" interface = "Ethernet0" tagging_mode = test_input[0] - self.create_vlan(vlan) + self.dvs_vlan.create_vlan(vlan) - self.create_vlan_member(vlan, interface, tagging_mode) + self.dvs_vlan.create_vlan_member(vlan, interface, tagging_mode) - 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) + vlan_oid = self.dvs_vlan.app_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] + fvs = self.dvs_vlan.app_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) + self.dvs_vlan.check_app_db_vlan_member_fields(fvs, tagging_mode) - 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) + vlan_oid = self.dvs_vlan.state_db.wait_for_n_keys("VLAN_MEMBER_TABLE", 1)[0] + fvs = self.dvs_vlan.state_db.wait_for_entry("VLAN_MEMBER_TABLE", vlan_oid) + self.dvs_vlan.check_state_db_vlan_member_fields(fvs) - vlan_oid = self.get_and_verify_vlan_ids(1)[0] - self.verify_vlan_member(vlan_oid, interface, expected[0]) + vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0] + self.dvs_vlan.verify_vlan_member(vlan_oid, interface, expected[0]) - self.remove_vlan_member(vlan, interface) - self.get_and_verify_vlan_member_ids(0) + self.dvs_vlan.remove_vlan_member(vlan, interface) + self.dvs_vlan.get_and_verify_vlan_member_ids(0) - self.remove_vlan(vlan) - self.get_and_verify_vlan_ids(0) + self.dvs_vlan.remove_vlan(vlan) + self.dvs_vlan.get_and_verify_vlan_ids(0)