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",