From 691bd3000f10d167233bac3b37c7ce4e4c478072 Mon Sep 17 00:00:00 2001 From: vganesan-nokia <67648637+vganesan-nokia@users.noreply.github.com> Date: Wed, 31 Mar 2021 02:14:56 -0400 Subject: [PATCH] [voq/systemlag] Voq system lag functionality (#1605) * [voq/systemlag] VOQ System lag functionality Signed-off-by: vedganes Changes for voq system lag implementation (1) Portsorch changes for allocating unique lag id from chassis ap pdb and sending the id in system port aggregator id attribute while creating lag local LAG (2) Portsorch changes to synd local LAG and local LAG members to chassis app db. The sync-ing includes the allocated unique system lag id (3) Portsorch changes to process remote system lag from chassis app db and create lag entry in local asic db with received system lag id (4) Interface orch changes to identify local or remote interfaces (for both port and lag) (5) Orchdaemon changes in orchagent intialization to get hostname and asic_name attributes from DEVICE_METATDATA. These are used for unique system lag name derivation * [vog/systemlag] VS test for system lag --- orchagent/Makefile.am | 6 +- orchagent/intfsorch.cpp | 42 ++- orchagent/main.cpp | 30 ++ orchagent/neighorch.cpp | 37 +- orchagent/orchdaemon.cpp | 2 +- orchagent/port.h | 8 + orchagent/portsorch.cpp | 254 ++++++++++++- orchagent/portsorch.h | 14 +- tests/mock_tests/Makefile.am | 3 +- tests/mock_tests/aclorch_ut.cpp | 2 +- tests/mock_tests/mock_orchagent_main.cpp | 5 +- tests/mock_tests/portsorch_ut.cpp | 11 +- tests/test_virtual_chassis.py | 399 +++++++++++++++++++- tests/virtual_chassis/1/default_config.json | 1 + tests/virtual_chassis/2/default_config.json | 1 + tests/virtual_chassis/3/default_config.json | 1 + 16 files changed, 780 insertions(+), 36 deletions(-) diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index d1240cf9af2d..d2adf7a193e2 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -15,7 +15,8 @@ dist_swss_DATA = \ port_rates.lua \ watermark_queue.lua \ watermark_pg.lua \ - watermark_bufferpool.lua + watermark_bufferpool.lua \ + lagids.lua bin_PROGRAMS = orchagent routeresync orchagent_restart_check @@ -62,7 +63,8 @@ orchagent_SOURCES = \ debugcounterorch.cpp \ natorch.cpp \ muxorch.cpp \ - macsecorch.cpp + macsecorch.cpp \ + lagid.cpp orchagent_SOURCES += flex_counter/flex_counter_manager.cpp flex_counter/flex_counter_stat_manager.cpp orchagent_SOURCES += debug_counter/debug_counter.cpp debug_counter/drop_counter.cpp diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index babf874e7131..ffae3decacda 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -35,6 +35,7 @@ extern BufferOrch *gBufferOrch; extern bool gIsNatSupported; extern NeighOrch *gNeighOrch; extern string gMySwitchType; +extern int32_t gVoqMySwitchId; const int intfsorch_pri = 35; @@ -1410,9 +1411,14 @@ bool IntfsOrch::isRemoteSystemPortIntf(string alias) Port port; if(gPortsOrch->getPort(alias, port)) { + if (port.m_type == Port::LAG) + { + return(port.m_system_lag_info.switch_id != gVoqMySwitchId); + } + return(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE); } - //Given alias is system port alias of the local port + //Given alias is system port alias of the local port/LAG return false; } @@ -1423,11 +1429,22 @@ void IntfsOrch::voqSyncAddIntf(string &alias) Port port; if(gPortsOrch->getPort(alias, port)) { - if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + if (port.m_type == Port::LAG) { - return; + if (port.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + alias = port.m_system_lag_info.alias; + } + else + { + if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + { + return; + } + alias = port.m_system_port_info.alias; } - alias = port.m_system_port_info.alias; } else { @@ -1449,11 +1466,22 @@ void IntfsOrch::voqSyncDelIntf(string &alias) Port port; if(gPortsOrch->getPort(alias, port)) { - if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + if (port.m_type == Port::LAG) { - return; + if (port.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + alias = port.m_system_lag_info.alias; + } + else + { + if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + { + return; + } + alias = port.m_system_port_info.alias; } - alias = port.m_system_port_info.alias; } else { diff --git a/orchagent/main.cpp b/orchagent/main.cpp index 68e4d0a4b872..a4ac21fe82fa 100644 --- a/orchagent/main.cpp +++ b/orchagent/main.cpp @@ -67,6 +67,8 @@ string gMySwitchType = ""; int32_t gVoqMySwitchId = -1; int32_t gVoqMaxCores = 0; uint32_t gCfgSystemPorts = 0; +string gMyHostName = ""; +string gMyAsicName = ""; void usage() { @@ -212,6 +214,34 @@ bool getSystemPortConfigList(DBConnector *cfgDb, DBConnector *appDb, vector spKeys; cfgSystemPortTable.getKeys(spKeys); diff --git a/orchagent/neighorch.cpp b/orchagent/neighorch.cpp index dfc2ded2ec88..5e978bd039cc 100644 --- a/orchagent/neighorch.cpp +++ b/orchagent/neighorch.cpp @@ -18,6 +18,7 @@ extern RouteOrch *gRouteOrch; extern FgNhgOrch *gFgNhgOrch; extern Directory gDirectory; extern string gMySwitchType; +extern int32_t gVoqMySwitchId; const int neighorch_pri = 30; @@ -1116,7 +1117,6 @@ void NeighOrch::doVoqSystemNeighTask(Consumer &consumer) } else { - SWSS_LOG_ERROR("Failed to add voq neighbor %s to SAI", kfvKey(t).c_str()); it++; } } @@ -1141,7 +1141,6 @@ void NeighOrch::doVoqSystemNeighTask(Consumer &consumer) } else { - SWSS_LOG_ERROR("Failed to remove voq neighbor %s from SAI", kfvKey(t).c_str()); it++; } } @@ -1232,11 +1231,22 @@ void NeighOrch::voqSyncAddNeigh(string &alias, IpAddress &ip_address, const MacA Port port; if(gPortsOrch->getPort(alias, port)) { - if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + if (port.m_type == Port::LAG) { - return; + if (port.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + alias = port.m_system_lag_info.alias; + } + else + { + if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + { + return; + } + alias = port.m_system_port_info.alias; } - alias = port.m_system_port_info.alias; } else { @@ -1278,11 +1288,22 @@ void NeighOrch::voqSyncDelNeigh(string &alias, IpAddress &ip_address) Port port; if(gPortsOrch->getPort(alias, port)) { - if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + if (port.m_type == Port::LAG) { - return; + if (port.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + alias = port.m_system_lag_info.alias; + } + else + { + if(port.m_system_port_info.type == SAI_SYSTEM_PORT_TYPE_REMOTE) + { + return; + } + alias = port.m_system_port_info.alias; } - alias = port.m_system_port_info.alias; } else { diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 6e4c887f2a4b..f3c28d218fc0 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -102,7 +102,7 @@ bool OrchDaemon::init() }; gCrmOrch = new CrmOrch(m_configDb, CFG_CRM_TABLE_NAME); - gPortsOrch = new PortsOrch(m_applDb, ports_tables); + gPortsOrch = new PortsOrch(m_applDb, ports_tables, m_chassisAppDb); TableConnector stateDbFdb(m_stateDb, STATE_FDB_TABLE_NAME); gFdbOrch = new FdbOrch(m_applDb, app_fdb_tables, stateDbFdb, gPortsOrch); diff --git a/orchagent/port.h b/orchagent/port.h index 17131b6f4b61..86e84a16361f 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -51,6 +51,13 @@ struct SystemPortInfo uint32_t num_voq = 8; }; +struct SystemLagInfo +{ + std::string alias = ""; + int32_t switch_id = -1; + int32_t spa_id = 0; +}; + class Port { public: @@ -142,6 +149,7 @@ class Port sai_object_id_t m_system_port_oid = 0; SystemPortInfo m_system_port_info; + SystemLagInfo m_system_lag_info; }; diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index fb9817ec5bee..d776ee84e7e4 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -28,6 +28,7 @@ #include "countercheckorch.h" #include "notifier.h" #include "fdborch.h" +#include "subscriberstatetable.h" extern sai_switch_api_t *sai_switch_api; extern sai_bridge_api_t *sai_bridge_api; @@ -46,6 +47,10 @@ extern BufferOrch *gBufferOrch; extern FdbOrch *gFdbOrch; extern Directory gDirectory; extern sai_system_port_api_t *sai_system_port_api; +extern string gMySwitchType; +extern int32_t gVoqMySwitchId; +extern string gMyHostName; +extern string gMyAsicName; #define VLAN_PREFIX "Vlan" #define DEFAULT_VLAN_ID 1 @@ -225,7 +230,7 @@ static char* hostif_vlan_tag[] = { * bridge. By design, SONiC switch starts with all bridge ports removed from * default VLAN and all ports removed from .1Q bridge. */ -PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) : +PortsOrch::PortsOrch(DBConnector *db, vector &tableNames, DBConnector *chassisAppDb) : Orch(db, tableNames), port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true), port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, true), @@ -419,6 +424,22 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_portStatusNotificationConsumer = new swss::NotificationConsumer(notificationsDb, "NOTIFICATIONS"); auto portStatusNotificatier = new Notifier(m_portStatusNotificationConsumer, this, "PORT_STATUS_NOTIFICATIONS"); Orch::addExecutor(portStatusNotificatier); + + if (gMySwitchType == "voq") + { + string tableName; + //Add subscriber to process system LAG (System PortChannel) table + tableName = CHASSIS_APP_LAG_TABLE_NAME; + Orch::addExecutor(new Consumer(new SubscriberStateTable(chassisAppDb, tableName, TableConsumable::DEFAULT_POP_BATCH_SIZE, 0), this, tableName)); + m_tableVoqSystemLagTable = unique_ptr(new Table(chassisAppDb, CHASSIS_APP_LAG_TABLE_NAME)); + + //Add subscriber to process system LAG member (System PortChannelMember) table + tableName = CHASSIS_APP_LAG_MEMBER_TABLE_NAME; + Orch::addExecutor(new Consumer(new SubscriberStateTable(chassisAppDb, tableName, TableConsumable::DEFAULT_POP_BATCH_SIZE, 0), this, tableName)); + m_tableVoqSystemLagMemberTable = unique_ptr
(new Table(chassisAppDb, CHASSIS_APP_LAG_MEMBER_TABLE_NAME)); + + m_lagIdAllocator = unique_ptr (new LagIdAllocator(chassisAppDb)); + } } void PortsOrch::removeDefaultVlanMembers() @@ -1438,6 +1459,12 @@ bool PortsOrch::setPortPvid(Port &port, sai_uint32_t pvid) return true; } + if(port.m_type == Port::SYSTEM) + { + SWSS_LOG_INFO("pvid setting for system port %s is not applicable", port.m_alias.c_str()); + return true; + } + if (port.m_rif_id) { SWSS_LOG_ERROR("pvid setting for router interface %s is not allowed", port.m_alias.c_str()); @@ -3038,6 +3065,8 @@ void PortsOrch::doLagTask(Consumer &consumer) { SWSS_LOG_ENTER(); + string table_name = consumer.getTableName(); + auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) { @@ -3052,6 +3081,8 @@ void PortsOrch::doLagTask(Consumer &consumer) uint32_t mtu = 0; string learn_mode; string operation_status; + uint32_t lag_id = 0; + int32_t switch_id = -1; for (auto i : kfvFieldsValues(t)) { @@ -3073,12 +3104,37 @@ void PortsOrch::doLagTask(Consumer &consumer) continue; } } + else if (fvField(i) == "lag_id") + { + lag_id = (uint32_t)stoul(fvValue(i)); + } + else if (fvField(i) == "switch_id") + { + switch_id = stoi(fvValue(i)); + } + } + + if (table_name == CHASSIS_APP_LAG_TABLE_NAME) + { + if (switch_id == gVoqMySwitchId) + { + //Already created, syncd local lag from CHASSIS_APP_DB. Skip + it = consumer.m_toSync.erase(it); + continue; + } + } + else + { + // For local portchannel + + lag_id = 0; + switch_id = -1; } // Create a new LAG when the new alias comes if (m_portList.find(alias) == m_portList.end()) { - if (!addLag(alias)) + if (!addLag(alias, lag_id, switch_id)) { it++; continue; @@ -3168,6 +3224,8 @@ void PortsOrch::doLagMemberTask(Consumer &consumer) { SWSS_LOG_ENTER(); + string table_name = consumer.getTableName(); + auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) { @@ -3202,6 +3260,27 @@ void PortsOrch::doLagMemberTask(Consumer &consumer) continue; } + if (table_name == CHASSIS_APP_LAG_MEMBER_TABLE_NAME) + { + int32_t lag_switch_id = lag.m_system_lag_info.switch_id; + if (lag_switch_id == gVoqMySwitchId) + { + //Synced local member addition to local lag. Skip + it = consumer.m_toSync.erase(it); + continue; + } + + //Sanity check: The switch id-s of lag and member must match + int32_t port_switch_id = port.m_system_port_info.switch_id; + if (port_switch_id != lag_switch_id) + { + SWSS_LOG_ERROR("System lag switch id mismatch. Lag %s switch id: %d, Member %s switch id: %d", + lag_alias.c_str(), lag_switch_id, port_alias.c_str(), port_switch_id); + it = consumer.m_toSync.erase(it); + continue; + } + } + /* Update a LAG member */ if (op == SET_COMMAND) { @@ -3344,11 +3423,11 @@ void PortsOrch::doTask(Consumer &consumer) { doVlanMemberTask(consumer); } - else if (table_name == APP_LAG_TABLE_NAME) + else if (table_name == APP_LAG_TABLE_NAME || table_name == CHASSIS_APP_LAG_TABLE_NAME) { doLagTask(consumer); } - else if (table_name == APP_LAG_MEMBER_TABLE_NAME) + else if (table_name == APP_LAG_MEMBER_TABLE_NAME || table_name == CHASSIS_APP_LAG_MEMBER_TABLE_NAME) { doLagMemberTask(consumer); } @@ -3993,12 +4072,43 @@ bool PortsOrch::isVlanMember(Port &vlan, Port &port) return true; } -bool PortsOrch::addLag(string lag_alias) +bool PortsOrch::addLag(string lag_alias, uint32_t spa_id, int32_t switch_id) { SWSS_LOG_ENTER(); + vector lag_attrs; + string system_lag_alias = lag_alias; + + if (gMySwitchType == "voq") + { + if (switch_id < 0) + { + // Local PortChannel. Allocate unique lag id from central CHASSIS_APP_DB + // Use the chassis wide unique system lag name. + + // Get the local switch id and derive the system lag name. + + switch_id = gVoqMySwitchId; + system_lag_alias = gMyHostName + "|" + gMyAsicName + "|" + lag_alias; + + // Allocate unique lag id + spa_id = m_lagIdAllocator->lagIdAdd(system_lag_alias, 0); + + if ((int32_t)spa_id <= 0) + { + SWSS_LOG_ERROR("Failed to allocate unique LAG id for local lag %s rv:%d", lag_alias.c_str(), spa_id); + return false; + } + } + + sai_attribute_t attr; + attr.id = SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID; + attr.value.u32 = spa_id; + lag_attrs.push_back(attr); + } + sai_object_id_t lag_id; - sai_status_t status = sai_lag_api->create_lag(&lag_id, gSwitchId, 0, NULL); + sai_status_t status = sai_lag_api->create_lag(&lag_id, gSwitchId, static_cast(lag_attrs.size()), lag_attrs.data()); if (status != SAI_STATUS_SUCCESS) { @@ -4026,6 +4136,24 @@ bool PortsOrch::addLag(string lag_alias) fields.push_back(tuple); m_counterLagTable->set("", fields); + if (gMySwitchType == "voq") + { + // If this is voq switch, record system lag info + + lag.m_system_lag_info.alias = system_lag_alias; + lag.m_system_lag_info.switch_id = switch_id; + lag.m_system_lag_info.spa_id = spa_id; + + // This will update port list with local port channel name for local port channels + // and with system lag name for the system lags received from chassis app db + + m_portList[lag_alias] = lag; + + // Sync to SYSTEM_LAG_TABLE of CHASSIS_APP_DB + + voqSyncAddLag(lag); + } + return true; } @@ -4074,6 +4202,29 @@ bool PortsOrch::removeLag(Port lag) m_counterLagTable->hdel("", lag.m_alias); + if (gMySwitchType == "voq") + { + // Free the lag id, if this is local LAG + + if (lag.m_system_lag_info.switch_id == gVoqMySwitchId) + { + int32_t rv; + int32_t spa_id = lag.m_system_lag_info.spa_id; + + rv = m_lagIdAllocator->lagIdDel(lag.m_system_lag_info.alias); + + if (rv != spa_id) + { + SWSS_LOG_ERROR("Failed to delete LAG id %d of local lag %s rv:%d", spa_id, lag.m_alias.c_str(), rv); + return false; + } + + // Sync to SYSTEM_LAG_TABLE of CHASSIS_APP_DB + + voqSyncDelLag(lag); + } + } + return true; } @@ -4113,7 +4264,7 @@ bool PortsOrch::addLagMember(Port &lag, Port &port, bool enableForwarding) attr.value.oid = port.m_port_id; attrs.push_back(attr); - if (!enableForwarding) + if (!enableForwarding && port.m_type != Port::SYSTEM) { attr.id = SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE; attr.value.booldata = true; @@ -4161,6 +4312,12 @@ bool PortsOrch::addLagMember(Port &lag, Port &port, bool enableForwarding) LagMemberUpdate update = { lag, port, true }; notify(SUBJECT_TYPE_LAG_MEMBER_CHANGE, static_cast(&update)); + if (gMySwitchType == "voq") + { + //Sync to SYSTEM_LAG_MEMBER_TABLE of CHASSIS_APP_DB + voqSyncAddLagMember(lag, port); + } + return true; } @@ -4200,6 +4357,12 @@ bool PortsOrch::removeLagMember(Port &lag, Port &port) LagMemberUpdate update = { lag, port, false }; notify(SUBJECT_TYPE_LAG_MEMBER_CHANGE, static_cast(&update)); + if (gMySwitchType == "voq") + { + //Sync to SYSTEM_LAG_MEMBER_TABLE of CHASSIS_APP_DB + voqSyncDelLagMember(lag, port); + } + return true; } @@ -4208,6 +4371,12 @@ bool PortsOrch::setCollectionOnLagMember(Port &lagMember, bool enableCollection) /* Port must be LAG member */ assert(lagMember.m_lag_member_id); + // Collection is not applicable for system port lag members (i.e, members of remote LAGs) + if (lagMember.m_type == Port::SYSTEM) + { + return true; + } + sai_status_t status = SAI_STATUS_FAILURE; sai_attribute_t attr {}; @@ -4239,6 +4408,12 @@ bool PortsOrch::setDistributionOnLagMember(Port &lagMember, bool enableDistribut /* Port must be LAG member */ assert(lagMember.m_lag_member_id); + // Distribution is not applicable for system port lag members (i.e, members of remote LAGs) + if (lagMember.m_type == Port::SYSTEM) + { + return true; + } + sai_status_t status = SAI_STATUS_FAILURE; sai_attribute_t attr {}; @@ -5315,4 +5490,69 @@ bool PortsOrch::setVoqInbandIntf(string &alias, string &type) return true; } +void PortsOrch::voqSyncAddLag (Port &lag) +{ + int32_t switch_id = lag.m_system_lag_info.switch_id; + + // Sync only local lag add to CHASSIS_APP_DB + + if (switch_id != gVoqMySwitchId) + { + return; + } + + uint32_t spa_id = lag.m_system_lag_info.spa_id; + + vector attrs; + + FieldValueTuple li ("lag_id", to_string(spa_id)); + attrs.push_back(li); + + FieldValueTuple si ("switch_id", to_string(switch_id)); + attrs.push_back(si); + + string key = lag.m_system_lag_info.alias; + + m_tableVoqSystemLagTable->set(key, attrs); +} + +void PortsOrch::voqSyncDelLag(Port &lag) +{ + // Sync only local lag del to CHASSIS_APP_DB + if (lag.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + + string key = lag.m_system_lag_info.alias; + m_tableVoqSystemLagTable->del(key); +} + +void PortsOrch::voqSyncAddLagMember(Port &lag, Port &port) +{ + // Sync only local lag's member add to CHASSIS_APP_DB + if (lag.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + + vector attrs; + FieldValueTuple nullFv ("NULL", "NULL"); + attrs.push_back(nullFv); + + string key = lag.m_system_lag_info.alias + ":" + port.m_system_port_info.alias; + m_tableVoqSystemLagMemberTable->set(key, attrs); +} + +void PortsOrch::voqSyncDelLagMember(Port &lag, Port &port) +{ + // Sync only local lag's member del to CHASSIS_APP_DB + if (lag.m_system_lag_info.switch_id != gVoqMySwitchId) + { + return; + } + + string key = lag.m_system_lag_info.alias + ":" + port.m_system_port_info.alias; + m_tableVoqSystemLagMemberTable->del(key); +} diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 627a4f4b38b0..bcd5b5d38d56 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -12,6 +12,7 @@ #include "flex_counter_manager.h" #include "gearboxutils.h" #include "saihelper.h" +#include "lagid.h" #define FCS_LEN 4 @@ -73,7 +74,7 @@ struct VlanMemberUpdate class PortsOrch : public Orch, public Subject { public: - PortsOrch(DBConnector *db, vector &tableNames); + PortsOrch(DBConnector *db, vector &tableNames, DBConnector *chassisAppDb); bool allPortsReady(); bool isInitDone(); @@ -240,7 +241,7 @@ class PortsOrch : public Orch, public Subject bool addVlan(string vlan); bool removeVlan(Port vlan); - bool addLag(string lag); + bool addLag(string lag, uint32_t spa_id, int32_t switch_id); bool removeLag(Port lag); bool addLagMember(Port &lag, Port &port, bool enableForwarding); bool removeLagMember(Port &lag, Port &port); @@ -303,7 +304,14 @@ class PortsOrch : public Orch, public Subject sai_uint32_t m_systemPortCount; bool getSystemPorts(); bool addSystemPorts(); - + unique_ptr
m_tableVoqSystemLagTable; + unique_ptr
m_tableVoqSystemLagMemberTable; + void voqSyncAddLag(Port &lag); + void voqSyncDelLag(Port &lag); + void voqSyncAddLagMember(Port &lag, Port &port); + void voqSyncDelLagMember(Port &lag, Port &port); + unique_ptr m_lagIdAllocator; + }; #endif /* SWSS_PORTSORCH_H */ diff --git a/tests/mock_tests/Makefile.am b/tests/mock_tests/Makefile.am index 80f9e7173e4e..82ceaa2d6f7b 100644 --- a/tests/mock_tests/Makefile.am +++ b/tests/mock_tests/Makefile.am @@ -67,7 +67,8 @@ tests_SOURCES = aclorch_ut.cpp \ $(top_srcdir)/orchagent/debugcounterorch.cpp \ $(top_srcdir)/orchagent/natorch.cpp \ $(top_srcdir)/orchagent/muxorch.cpp \ - $(top_srcdir)/orchagent/macsecorch.cpp + $(top_srcdir)/orchagent/macsecorch.cpp \ + $(top_srcdir)/orchagent/lagid.cpp tests_SOURCES += $(FLEX_CTR_DIR)/flex_counter_manager.cpp $(FLEX_CTR_DIR)/flex_counter_stat_manager.cpp tests_SOURCES += $(DEBUG_CTR_DIR)/debug_counter.cpp $(DEBUG_CTR_DIR)/drop_counter.cpp diff --git a/tests/mock_tests/aclorch_ut.cpp b/tests/mock_tests/aclorch_ut.cpp index 5130dec2e987..5a3b7cff2683 100644 --- a/tests/mock_tests/aclorch_ut.cpp +++ b/tests/mock_tests/aclorch_ut.cpp @@ -317,7 +317,7 @@ namespace aclorch_test }; ASSERT_EQ(gPortsOrch, nullptr); - gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables); + gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables, m_chassis_app_db.get()); ASSERT_EQ(gCrmOrch, nullptr); gCrmOrch = new CrmOrch(m_config_db.get(), CFG_CRM_TABLE_NAME); diff --git a/tests/mock_tests/mock_orchagent_main.cpp b/tests/mock_tests/mock_orchagent_main.cpp index fb1ccc082cbf..62a03dc7700c 100644 --- a/tests/mock_tests/mock_orchagent_main.cpp +++ b/tests/mock_tests/mock_orchagent_main.cpp @@ -21,7 +21,10 @@ bool gLogRotate = false; bool gSaiRedisLogRotate = false; ofstream gRecordOfs; string gRecordFile; -string gMySwitchType = "voq"; +string gMySwitchType = "switch"; +int32_t gVoqMySwitchId = 0; +string gMyHostName = "Linecard1"; +string gMyAsicName = "Asic0"; VRFOrch *gVrfOrch; diff --git a/tests/mock_tests/portsorch_ut.cpp b/tests/mock_tests/portsorch_ut.cpp index a52b505b0669..778e290d6925 100644 --- a/tests/mock_tests/portsorch_ut.cpp +++ b/tests/mock_tests/portsorch_ut.cpp @@ -16,6 +16,7 @@ namespace portsorch_test shared_ptr m_config_db; shared_ptr m_state_db; shared_ptr m_counters_db; + shared_ptr m_chassis_app_db; PortsOrchTest() { @@ -28,6 +29,8 @@ namespace portsorch_test "CONFIG_DB", 0); m_state_db = make_shared( "STATE_DB", 0); + m_chassis_app_db = make_shared( + "CHASSIS_APP_DB", 0); } virtual void SetUp() override @@ -142,7 +145,7 @@ namespace portsorch_test }; ASSERT_EQ(gPortsOrch, nullptr); - gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables); + gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables, m_chassis_app_db.get()); vector buffer_tables = { APP_BUFFER_POOL_TABLE_NAME, APP_BUFFER_PROFILE_TABLE_NAME, APP_BUFFER_QUEUE_TABLE_NAME, @@ -271,7 +274,7 @@ namespace portsorch_test }; ASSERT_EQ(gPortsOrch, nullptr); - gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables); + gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables, m_chassis_app_db.get()); vector buffer_tables = { APP_BUFFER_POOL_TABLE_NAME, APP_BUFFER_PROFILE_TABLE_NAME, APP_BUFFER_QUEUE_TABLE_NAME, @@ -341,7 +344,7 @@ namespace portsorch_test }; ASSERT_EQ(gPortsOrch, nullptr); - gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables); + gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables, m_chassis_app_db.get()); vector buffer_tables = { APP_BUFFER_POOL_TABLE_NAME, APP_BUFFER_PROFILE_TABLE_NAME, APP_BUFFER_QUEUE_TABLE_NAME, @@ -486,7 +489,7 @@ namespace portsorch_test }; ASSERT_EQ(gPortsOrch, nullptr); - gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables); + gPortsOrch = new PortsOrch(m_app_db.get(), ports_tables, m_chassis_app_db.get()); vector buffer_tables = { APP_BUFFER_POOL_TABLE_NAME, APP_BUFFER_PROFILE_TABLE_NAME, APP_BUFFER_QUEUE_TABLE_NAME, diff --git a/tests/test_virtual_chassis.py b/tests/test_virtual_chassis.py index d1db2c6331b0..668e297e4197 100644 --- a/tests/test_virtual_chassis.py +++ b/tests/test_virtual_chassis.py @@ -2,8 +2,30 @@ from swsscommon import swsscommon from dvslib.dvs_database import DVSDatabase import ast +import time class TestVirtualChassis(object): + + def set_lag_id_boundaries(self, vct): + """This functions sets lag id boundaries in the chassis app db. + + In VOQ systems the lag id boundaries need to be set before configuring any PortChannels. + The lag id boundaries are used by lag id allocator while adding a PortChannel to the asic db. + Note: + In real systems, the lag id boundries are taken from a platform specific file. For testing + we assume the chassis capability with maximum 2 lags so that we can test the lag id allocator + table full error with less number of PortChannel configuration + """ + + dvss = vct.dvss + for name in dvss.keys(): + if name.startswith("supervisor"): + dvs = dvss[name] + chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) + chassis_app_db.db_connection.set("SYSTEM_LAG_ID_START", "1") + chassis_app_db.db_connection.set("SYSTEM_LAG_ID_END", "2") + break + def test_connectivity(self, vct): if vct is None: return @@ -37,6 +59,9 @@ def test_voq_switch(self, vct): configured system ports are avaiable in the asic db by checking the count. """ + if vct is None: + return + dvss = vct.dvss for name in dvss.keys(): dvs = dvss[name] @@ -88,6 +113,9 @@ def test_chassis_app_db_sync(self, vct): of syncing mechanism. """ + if vct is None: + return + dvss = vct.dvss for name in dvss.keys(): if name.startswith("supervisor"): @@ -106,6 +134,9 @@ def test_chassis_system_interface(self, vct): switch id. """ + if vct is None: + return + dvss = vct.dvss for name in dvss.keys(): dvs = dvss[name] @@ -157,6 +188,9 @@ def test_chassis_system_neigh(self, vct): (ii) Local neighbor is synced to chassis ap db with assigned encap index TODO: (iii) Remote neighbor entry is created in ASIC_DB with received encap index """ + + if vct is None: + return dvss = vct.dvss print("name {}".format(dvss.keys())) @@ -206,7 +240,6 @@ def test_chassis_system_neigh(self, vct): break # Verify neighbor record syncing with encap index - dvss = vct.dvss for name in dvss.keys(): if name.startswith("supervisor"): dvs = dvss[name] @@ -232,7 +265,371 @@ def test_chassis_system_neigh(self, vct): assert encap_index == sys_neigh_encap_index, "Encap index not sync-ed correctly" break + + def test_chassis_system_lag(self, vct): + """Test PortChannel in VOQ based chassis systems. + + This test validates that + (i) PortChannel is created in local asic with system port aggregator id (system lag id) + - Unique lag id is allocated from chassis app db in supervisor card + - The unique lag id is sent in system port aggregator id attribute + (ii) PortChannel members are successfully added in the PortChannel created + (iii) Local PortChannel is synced in chassis app db + (iv) PortChannel members addition is synced in the chassis app db + (v) System LAG is created for the remote PortChannel with system lag id. + (vi) System LAG of remote Portchannel has members with system port id + """ + + if vct is None: + return + + test_lag1_name = "PortChannel0001" + test_lag1_member = "Ethernet4" + + # Set the lag id boundaries in the chassis ap db + self.set_lag_id_boundaries(vct) + + # Create a PortChannel in a line card 1 (owner line card) + dvss = vct.dvss + for name in dvss.keys(): + dvs = dvss[name] + + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + # Get the host name and asic name for the system lag alias verification + cfg_hostname = metatbl.get("hostname") + assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" + + cfg_asic_name = metatbl.get("asic_name") + assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" + + cfg_switch_type = metatbl.get("switch_type") + + # Portchannel record verifiation done in line card + if cfg_switch_type == "voq": + lc_switch_id = metatbl.get("switch_id") + assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" + if lc_switch_id == "0": + + # Connect to app db: lag table and lag member table + app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") + psTbl_lagMember = swsscommon.ProducerStateTable(app_db, "LAG_MEMBER_TABLE") + + # Create PortChannel + fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) + psTbl_lag.set(f"{test_lag1_name}", fvs) + + time.sleep(1) + + # Add port channel member + fvs = swsscommon.FieldValuePairs([("status", "enabled")]) + psTbl_lagMember.set(f"{test_lag1_name}:{test_lag1_member}", fvs) + + time.sleep(1) + + # Verify creation of the PorChannel with voq system port aggregator id in asic db + asic_db = dvs.get_asic_db() + lagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(lagkeys) == 1, "The LAG entry for configured PortChannel is not available in asic db" + + # Check for the presence of voq system port aggregate id attribute + lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) + spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert spa_id != "", "VOQ System port aggregate id not present for the LAG" + + # Check for presence of lag member added + lagmemberkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") + assert len(lagmemberkeys) == 1, "The LAG member for configured PortChannel is not available in asic db" + + break + + # Check syncing of the PortChannel and PortChannel member in chasiss app db + for name in dvss.keys(): + if name.startswith("supervisor"): + dvs = dvss[name] + chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) + syslagkeys = chassis_app_db.get_keys("SYSTEM_LAG_TABLE") + assert len(syslagkeys) == 1, "System lag entry is not available in chassis app db" + + # system lag alias (key) should be unique across chassis. To ensure such uniqueness, + # the system lag name is derived from hostname, asic_name and PortChannel name + # Verify for correct name + assert f"{cfg_hostname}|{cfg_asic_name}|{test_lag1_name}" in syslagkeys[0], "Invalid unique system lag name" + + # Verify lag id of the system lag in chassis app db + syslag_entry = chassis_app_db.get_entry("SYSTEM_LAG_TABLE", syslagkeys[0]) + remote_lag_id = syslag_entry.get("lag_id") + assert remote_lag_id != "", "Lag id is not present in the sytem lag table in chassis app db" + # This id must be same as the id allocated in owner linecard. + assert remote_lag_id == spa_id, "System lag id in chassis app db is not same as allocated lag id" + + syslagmemberkeys = chassis_app_db.get_keys("SYSTEM_LAG_MEMBER_TABLE") + assert len(syslagmemberkeys) == 1, "No system lag member entries in chassis app db" + + break + + # Verify programming of remote system lag with received system lag id in non-owner line card + # Verify programming of lag menbers with system port id in non-owner line card + for name in dvss.keys(): + dvs = dvss[name] + + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + cfg_switch_type = metatbl.get("switch_type") + + # System LAG info verifiation done in non-owner line card + if cfg_switch_type == "voq": + lc_switch_id = metatbl.get("switch_id") + assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" + if lc_switch_id != "0": + # Linecard other than linecard 1 (owner line card) + asic_db = dvs.get_asic_db() + remotesyslagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(remotesyslagkeys) == 1, "No remote system lag entries in ASIC_DB" + + remotesyslag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", remotesyslagkeys[0]) + remote_lag_id = remotesyslag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert remote_lag_id != "", "Lag id not present in the remote syslag entry in asic db" + assert remote_lag_id == spa_id, "Remote system lag programmed with wrong lag id" + + # Verify remote system lag has system port as member + lagmemberkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") + assert len(lagmemberkeys) == 1, "The LAG member for remote system lag is not available in asic db" + + remotelagmember_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lagmemberkeys[0]) + member_port_id = remotelagmember_entry.get("SAI_LAG_MEMBER_ATTR_PORT_ID") + #Verify that the member is a system port + assert "oid:0x5d" in member_port_id, "System LAG member is not system port" + + break + + def test_chassis_system_lag_id_allocator_table_full(self, vct): + """Test lag id allocator table full. + + Pre-requisite: + (i) Test case: test_chassis_system_lag + This test validates that + (i) If PortChannel configuration goes beyond the platfrom capacitty boundary, lag id + allocator returns table full error + """ + + if vct is None: + return + + test_lag2_name = "PortChannel0002" + test_lag3_name = "PortChannel0003" + + # Create a PortChannel in a line card 1 (owner line card) + dvss = vct.dvss + for name in dvss.keys(): + dvs = dvss[name] + + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + # Get the host name and asic name for the system lag alias verification + cfg_hostname = metatbl.get("hostname") + assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" + + cfg_asic_name = metatbl.get("asic_name") + assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" + + cfg_switch_type = metatbl.get("switch_type") + + # Portchannel record verifiation done in line card + if cfg_switch_type == "voq": + lc_switch_id = metatbl.get("switch_id") + assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" + if lc_switch_id == "0": + + # Connect to app db: lag table + app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") + + # Create PortChannel 2. This should be successfully configured + fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) + psTbl_lag.set(f"{test_lag2_name}", fvs) + + time.sleep(1) + + # Verify creation of the PorChannels with voq system port aggregator id in asic db + asic_db = dvs.get_asic_db() + lagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(lagkeys) == 2, "Two configured LAG entries are not available in asic db" + + # Check for the presence of voq system port aggregate id attribute for 2 LAGs + lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) + spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert spa_id != "", "VOQ System port aggregate id not present for the LAG 1" + + lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[1]) + spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert spa_id != "", "VOQ System port aggregate id not present for the LAG 2" + + # Create PortChannel 3. This should not be configured since lag id limit reached + fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) + psTbl_lag.set(f"{test_lag3_name}", fvs) + + # Check syslog for the table full error + marker = "ERR #orchagent" + srch_str = f"addLag: Failed to allocate unique LAG id for local lag {test_lag3_name} rv:-1" + _, num = dvs.runcmd(["sh", "-c", "awk '/%s/,ENDFILE {print;}' /var/log/syslog \ + | grep \"%s\" | wc -l" % (marker, srch_str)]) + assert num.strip() == '1', "LAG ID allocator table full error is not returned" + + # Clean up the app db for the PortChannel creation failure + psTbl_lag.delete(f"{test_lag3_name}") + + break + + def test_chassis_system_lag_id_allocator_del_id(self, vct): + """Test lag id allocator's release id and re-use id processing. + + Pre-requisite: + (i) Test case: test_chassis_system_lag + (ii) Test case: test_chassis_system_lag_id_allocator_table_full + This test validates that + (i) Portchannel is deleted and id allocator does not return error + (ii) Should be able to add PortChannel to re-use released id + (iii) Deleted portchaneels are removed from chassis app db + (iv) Remote asics remove the system lag corresponding to the deleted PortChannels + """ + + if vct is None: + return + + test_lag1_name = "PortChannel0001" + test_lag1_member = "Ethernet4" + test_lag2_name = "PortChannel0002" + test_lag3_name = "PortChannel0003" + + # Create a PortChannel in a line card 1 (owner line card) + dvss = vct.dvss + for name in dvss.keys(): + dvs = dvss[name] + + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + # Get the host name and asic name for the system lag alias verification + cfg_hostname = metatbl.get("hostname") + assert cfg_hostname != "", "Got error in getting hostname from CONFIG_DB DEVICE_METADATA" + + cfg_asic_name = metatbl.get("asic_name") + assert cfg_asic_name != "", "Got error in getting asic_name from CONFIG_DB DEVICE_METADATA" + + cfg_switch_type = metatbl.get("switch_type") + + # Portchannel record verifiation done in line card + if cfg_switch_type == "voq": + lc_switch_id = metatbl.get("switch_id") + assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" + if lc_switch_id == "0": + + # At this point we have 2 port channels test_lag1_name and test_lag2_name. + # These were created by the above two test cases. Now delete the PortChannel + # test_lag1_name and verify that the lag is removed and add test_lag3_name to + # test for lag id allocator allocating newly available lag id + + # Connect to app db: lag table and lag member table + app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + psTbl_lag = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") + psTbl_lagMember = swsscommon.ProducerStateTable(app_db, "LAG_MEMBER_TABLE") + + # Delete port channel member of PortChannel test_lag1_name + psTbl_lagMember.delete(f"{test_lag1_name}:{test_lag1_member}") + + time.sleep(1) + + # Delete PortChannel test_lag1_name + psTbl_lag.delete(f"{test_lag1_name}") + + time.sleep(1) + + # Verify deletion of the PorChannel + asic_db = dvs.get_asic_db() + lagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(lagkeys) == 1, "Two LAG entries in asic db even after deleting a PortChannel" + + # Create PortChannel test_lag3_name. This should be addedd successfully since deleting + # PortChannel test_lag1_name made a lag id available for allocation + fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) + psTbl_lag.set(f"{test_lag3_name}", fvs) + + time.sleep(1) + + # Verify creation of the additional PortChannel after making space for more + # PortChannels by deleting some PortChannels + asic_db = dvs.get_asic_db() + lagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(lagkeys) == 2, "Two configured LAG entries are not available in asic db" + + # Check for the presence of voq system port aggregate id attribute for 2 LAGs + lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[0]) + spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert spa_id != "", "VOQ System port aggregate id not present for the LAG 1" + + lag_entry = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG", lagkeys[1]) + spa_id = lag_entry.get("SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") + assert spa_id != "", "VOQ System port aggregate id not present for the LAG 2" + + # Now delete all the PortChannels so that we can veify the chassis app db + # clearing and remote asics clearing + psTbl_lag.delete(f"{test_lag2_name}") + + psTbl_lag.delete(f"{test_lag3_name}") + + time.sleep(1) + + # Verify deletion of all PortChannels + asic_db = dvs.get_asic_db() + lagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(lagkeys) == 0, "LAG entries in asic db even after deleting all PortChannels" + + break + + # Check syncing deletion of the PortChannels and PortChannel member in chasiss app db + for name in dvss.keys(): + if name.startswith("supervisor"): + dvs = dvss[name] + chassis_app_db = DVSDatabase(swsscommon.CHASSIS_APP_DB, dvs.redis_chassis_sock) + syslagkeys = chassis_app_db.get_keys("SYSTEM_LAG_TABLE") + assert len(syslagkeys) == 0, "Stale system lag entries in chassis app db" + + syslagmemberkeys = chassis_app_db.get_keys("SYSTEM_LAG_MEMBER_TABLE") + assert len(syslagmemberkeys) == 0, "Stale system lag member entries in chassis app db" + + break + + # Verify removal of remote system lag in non-owner line card + # Verify removal of system lag menbers in non-owner line card + for name in dvss.keys(): + dvs = dvss[name] + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + cfg_switch_type = metatbl.get("switch_type") + + # System LAG info verifiation done in non-owner line card + if cfg_switch_type == "voq": + lc_switch_id = metatbl.get("switch_id") + assert lc_switch_id != "", "Got error in getting switch_id from CONFIG_DB DEVICE_METADATA" + if lc_switch_id != "0": + # Linecard other than linecard 1 (owner line card) + asic_db = dvs.get_asic_db() + remotesyslagkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG") + assert len(remotesyslagkeys) == 0, "Stale remote system lag entries in asic db" + + # Verify cleaning of system lag members + lagmemberkeys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") + assert len(lagmemberkeys) == 0, "Stale system lag member entries in asic db" + + break + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying def test_nonflaky_dummy(): diff --git a/tests/virtual_chassis/1/default_config.json b/tests/virtual_chassis/1/default_config.json index 8952380199c0..100d6561c4c0 100644 --- a/tests/virtual_chassis/1/default_config.json +++ b/tests/virtual_chassis/1/default_config.json @@ -2,6 +2,7 @@ "DEVICE_METADATA": { "localhost": { "hostname" : "lc1", + "asic_name" : "Asic0", "instance_name": "Linecard1", "connect_to_chassis_db" : 1, "chassis_db_address" : "10.8.1.200", diff --git a/tests/virtual_chassis/2/default_config.json b/tests/virtual_chassis/2/default_config.json index b4dc1a35a087..b4a1776cf380 100644 --- a/tests/virtual_chassis/2/default_config.json +++ b/tests/virtual_chassis/2/default_config.json @@ -2,6 +2,7 @@ "DEVICE_METADATA": { "localhost": { "hostname" : "lc2", + "asic_name" : "Asic0", "instance_name": "Linecard2", "connect_to_chassis_db" : 1, "chassis_db_address" : "10.8.1.200", diff --git a/tests/virtual_chassis/3/default_config.json b/tests/virtual_chassis/3/default_config.json index d1b91de7b49d..6ac0bbd17684 100644 --- a/tests/virtual_chassis/3/default_config.json +++ b/tests/virtual_chassis/3/default_config.json @@ -2,6 +2,7 @@ "DEVICE_METADATA": { "localhost": { "hostname" : "lc3", + "asic_name" : "Asic0", "instance_name": "Linecard3", "connect_to_chassis_db" : 1, "chassis_db_address" : "10.8.1.200",