From 9afa98163cee9b589dbc40cc7b921f0375042ad3 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 10 May 2019 17:13:05 -0700 Subject: [PATCH 01/24] add LAG name map to counter table Issue: fdbshow does not show the portchannel name Fix: 1.Added port channel port oid to name mapping in COUNTERS_PORT_NAME_MAP table so that a given portchannel port oid will give port channel name 2. made fix to add add portchannel port oid to name mapping when addLag is done from portsorch. similarly removed the mapping when removeLag is done --- .DS_Store | Bin 0 -> 8196 bytes orchagent/portsorch.cpp | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e4c3d5ec04b37f34faed2af415b1760dd7edf917 GIT binary patch literal 8196 zcmeHMU1%It6h3E@HuolNGl^-NxUShYCd4!~KPDupY25rYHcexTn>0U7o6PP^lflVM zx-+}mHb#PIRZtOs5L!{BZ&m~!M8qfmr6LrmXptiL=9Bm)qT;!8XG5ExCqV<93-^Ba z-gC~KIp=L?DPj5P={98zBO8XN$ttx%Z_sXoCm@5x6ZQAkK#=dmn3>e2Q^*_KqyiG zuTY=z0M91sW6Z}TiJmE~DYFOkP0>#=P@0oGD%1&MJ}ya==77>1(0?-e847w&C%dSp z4j7Xdv_S-d2&|5P_Vkn~Do-ZUJyvGIEh<>hbMT)tcO$p{cQ*25oK4i;JA?tZv#rFgy1Fx^ z6g%YfK+?93rt}OsIGVK0^qfVKlB8-T)1<6-n`YcNr#oY=e#RBO3CB*ky`JKjLAGLU zN+}igN9J9_wwz;n$|2zeW`crdxyC6&Pw|pa4Ij4DIsKZlV`q8Ao#F6G?c6G3>4b4QZMbKZD#qk9D#N?D z@;;l?=)E2nvFxQ;6-8+OPOxx`-Hz!irNKT10*O`CZO zQ#3westMhcQ*FG1DT918Bi)sgoxF>cU_Bp8+H-T{k0YnM!@W%Tik%eCKCC+Kk$K&s z#|!TcREERjV!m6`bd51q6|0pS??s?0)+k4cxMC`x9=f0(CW!79WZ^k@9$tV8a0xEM zd+-r_0bjxu_!_Rlb@&N>f#2W{_!Ituzp(%r7Ge>W<1XBdRoH;-*ntmVCwAi@9K<1f z7~?pJCvXa<@f6xPk12F;0iVRD@ELp-U&4#{I=+E#;=A|(evF^sr}!CugWuwh@(n{d z;tt7iuEiVFTjL`o;`$$H=;T_&jr2csu;+gv?)5E#ttF**lx@Ges&;R4TW9z3hOXGd zo9W~+NK(Y3PL3MhM&8OtNoyV%A%^K^)?>F)Ah^V?3GK>gB%%ls$>BZKGz<~X-nW!^CxY z_!hhkAHwIvz^m{b+<>3qSNNT{myg?U2Qe>^&|8w|nNZ`U(); m_portList[lag_alias] = lag; + /* Add lag name map to counter table */ + FieldValueTuple tuple(lag_alias, sai_serialize_object_id(lag_id)); + vector fields; + fields.push_back(tuple); + m_counterTable->set("",fields); + PortUpdate update = { lag, true }; notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); @@ -2856,6 +2862,9 @@ bool PortsOrch::removeLag(Port lag) SWSS_LOG_NOTICE("Remove LAG %s lid:%lx", lag.m_alias.c_str(), lag.m_lag_id); + /* Remove LAG name map from counter table */ + m_counterTable->hdel("",lag.m_alias.c_str()); + m_portList.erase(lag.m_alias); PortUpdate update = { lag, false }; From 9f9935d1e2c36368a2d1256378f85d80af75d828 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Wed, 12 Jun 2019 12:06:44 -0700 Subject: [PATCH 02/24] Delete .DS_Store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e4c3d5ec04b37f34faed2af415b1760dd7edf917..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMU1%It6h3E@HuolNGl^-NxUShYCd4!~KPDupY25rYHcexTn>0U7o6PP^lflVM zx-+}mHb#PIRZtOs5L!{BZ&m~!M8qfmr6LrmXptiL=9Bm)qT;!8XG5ExCqV<93-^Ba z-gC~KIp=L?DPj5P={98zBO8XN$ttx%Z_sXoCm@5x6ZQAkK#=dmn3>e2Q^*_KqyiG zuTY=z0M91sW6Z}TiJmE~DYFOkP0>#=P@0oGD%1&MJ}ya==77>1(0?-e847w&C%dSp z4j7Xdv_S-d2&|5P_Vkn~Do-ZUJyvGIEh<>hbMT)tcO$p{cQ*25oK4i;JA?tZv#rFgy1Fx^ z6g%YfK+?93rt}OsIGVK0^qfVKlB8-T)1<6-n`YcNr#oY=e#RBO3CB*ky`JKjLAGLU zN+}igN9J9_wwz;n$|2zeW`crdxyC6&Pw|pa4Ij4DIsKZlV`q8Ao#F6G?c6G3>4b4QZMbKZD#qk9D#N?D z@;;l?=)E2nvFxQ;6-8+OPOxx`-Hz!irNKT10*O`CZO zQ#3westMhcQ*FG1DT918Bi)sgoxF>cU_Bp8+H-T{k0YnM!@W%Tik%eCKCC+Kk$K&s z#|!TcREERjV!m6`bd51q6|0pS??s?0)+k4cxMC`x9=f0(CW!79WZ^k@9$tV8a0xEM zd+-r_0bjxu_!_Rlb@&N>f#2W{_!Ituzp(%r7Ge>W<1XBdRoH;-*ntmVCwAi@9K<1f z7~?pJCvXa<@f6xPk12F;0iVRD@ELp-U&4#{I=+E#;=A|(evF^sr}!CugWuwh@(n{d z;tt7iuEiVFTjL`o;`$$H=;T_&jr2csu;+gv?)5E#ttF**lx@Ges&;R4TW9z3hOXGd zo9W~+NK(Y3PL3MhM&8OtNoyV%A%^K^)?>F)Ah^V?3GK>gB%%ls$>BZKGz<~X-nW!^CxY z_!hhkAHwIvz^m{b+<>3qSNNT{myg?U2Qe>^&|8w|nNZ`U Date: Sat, 7 Sep 2019 16:30:10 -0700 Subject: [PATCH 03/24] Layer 2 Forwarding Enhancements Layer 2 Forwarding Enhancements --- cfgmgr/vlanmgr.cpp | 220 ++++++++++++- cfgmgr/vlanmgr.h | 7 + cfgmgr/vlanmgrd.cpp | 2 + orchagent/fdborch.cpp | 630 +++++++++++++++++++++++++++++------- orchagent/fdborch.h | 27 +- orchagent/notifications.cpp | 24 +- orchagent/port.h | 4 + orchagent/portsorch.cpp | 473 +++++++++++++++++++-------- orchagent/portsorch.h | 16 +- 9 files changed, 1131 insertions(+), 272 deletions(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index fc5949252e..2a69862f92 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -13,6 +13,7 @@ using namespace swss; #define DOT1Q_BRIDGE_NAME "Bridge" #define VLAN_PREFIX "Vlan" +#define SWITCH_STR "switch" #define LAG_PREFIX "PortChannel" #define DEFAULT_VLAN_ID "1" #define DEFAULT_MTU_STR "9100" @@ -28,6 +29,8 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME), m_stateVlanMemberTable(stateDb, STATE_VLAN_MEMBER_TABLE_NAME), + m_appFdbTableProducer(appDb, APP_FDB_TABLE_NAME), + m_appSwitchTableProducer(appDb, APP_SWITCH_TABLE_NAME), m_appVlanTableProducer(appDb, APP_VLAN_TABLE_NAME), m_appVlanMemberTableProducer(appDb, APP_VLAN_MEMBER_TABLE_NAME) { @@ -86,6 +89,10 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c EXEC_WITH_ERROR_THROW(echo_cmd_backup, res); } + /* vlan state notification from portsorch */ + m_VlanStateNotificationConsumer = new swss::NotificationConsumer(appDb, "VLANSTATE"); + auto vlanStatusNotificatier = new Notifier(m_VlanStateNotificationConsumer, this, "VLANSTATE"); + Orch::addExecutor(vlanStatusNotificatier); } bool VlanMgr::addHostVlan(int vlan_id) @@ -99,7 +106,7 @@ bool VlanMgr::addHostVlan(int vlan_id) + BASH_CMD + " -c \"" + BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + DOT1Q_BRIDGE_NAME + " self && " + IP_CMD + " link add link " + DOT1Q_BRIDGE_NAME - + " up" + + " down" + " name " + VLAN_PREFIX + std::to_string(vlan_id) + " address " + gMacAddress.to_string() + " type vlan id " + std::to_string(vlan_id) + "\""; @@ -177,14 +184,27 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str // /bin/bash -c "/sbin/ip link set {{port_alias}} master Bridge && // /sbin/bridge vlan del vid 1 dev {{ port_alias }} && // /sbin/bridge vlan add vid {{vlan_id}} dev {{port_alias}} {{tagging_mode}}" - const std::string cmds = std::string("") - + BASH_CMD + " -c \"" - + IP_CMD + " link set " + port_alias + " master " + DOT1Q_BRIDGE_NAME + " && " - + BRIDGE_CMD + " vlan del vid " + DEFAULT_VLAN_ID + " dev " + port_alias + " && " - + BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + port_alias + " " + tagging_cmd + "\""; + + const std::string key = std::string("") + "Vlan1|" + port_alias; - std::string res; - EXEC_WITH_ERROR_THROW(cmds, res); + if (isVlanMemberStateOk(key)) { + const std::string cmds = std::string("") + + BASH_CMD + " -c \"" + + IP_CMD + " link set " + port_alias + " master " + DOT1Q_BRIDGE_NAME + " && " + + BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + port_alias + " " + tagging_cmd + "\""; + std::string res; + EXEC_WITH_ERROR_THROW(cmds, res); + } + else + { + const std::string cmds = std::string("") + + BASH_CMD + " -c \"" + + IP_CMD + " link set " + port_alias + " master " + DOT1Q_BRIDGE_NAME + " && " + + BRIDGE_CMD + " vlan del vid " + DEFAULT_VLAN_ID + " dev " + port_alias + " && " + + BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + port_alias + " " + tagging_cmd + "\""; + std::string res; + EXEC_WITH_ERROR_THROW(cmds, res); + } return true; } @@ -222,6 +242,144 @@ bool VlanMgr::isVlanMacOk() return !!gMacAddress; } +void VlanMgr::doSwitchTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + auto it = consumer.m_toSync.begin(); + + while (it != consumer.m_toSync.end()) + { + KeyOpFieldsValuesTuple t = it->second; + + string key = kfvKey(t); + string op = kfvOp(t); + + /* Ensure the key starts with "switch" otherwise ignore */ + if (key != SWITCH_STR) + { + SWSS_LOG_INFO("Ignoring SWITCH key %s", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + SWSS_LOG_DEBUG("key:switch"); + + for (auto i : kfvFieldsValues(t)) + { + if (fvField(i) == "fdb_aging_time") + { + int agingTime = 0; + SWSS_LOG_DEBUG("attribute:fdb_aging_time"); + if (op == SET_COMMAND) + { + SWSS_LOG_DEBUG("operation:set"); + agingTime = atoi(fvValue(i).c_str()); + if(agingTime < 0) + { + SWSS_LOG_ERROR("Invalid fdb_aging_time %s", fvValue(i).c_str()); + break; + } + SWSS_LOG_DEBUG("value:%s",fvValue(i).c_str()); + } + else if (op == DEL_COMMAND) + { + SWSS_LOG_DEBUG("operation:del"); + agingTime=0; + } + else + { + SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); + break; + } + + vector fvVector; + FieldValueTuple aging_time("fdb_aging_time", to_string(agingTime)); + fvVector.push_back(aging_time); + m_appSwitchTableProducer.set(key, fvVector); + break; + } + } + + it = consumer.m_toSync.erase(it); + } +} + +void VlanMgr::doFdbTask(Consumer &consumer) +{ + if (!isVlanMacOk()) + { + SWSS_LOG_DEBUG("VLAN mac not ready, delaying FDB task"); + SWSS_LOG_DEBUG("VLAN mac not ready, delaying VLAN task"); + return; + } + + auto it = consumer.m_toSync.begin(); + + while (it != consumer.m_toSync.end()) + { + KeyOpFieldsValuesTuple t = it->second; + + /* format: | */ + vector keys = tokenize(kfvKey(t), config_db_key_delimiter, 1); + /* keys[0] is vlan as (Vlan10) and keys[1] is mac as (00-00-00-00-00-00) */ + string op = kfvOp(t); + + /* Ensure the key starts with "Vlan" otherwise ignore */ + if (strncmp(keys[0].c_str(), VLAN_PREFIX, 4)) + { + SWSS_LOG_ERROR("Invalid key format. No 'Vlan' prefix: %s", keys[0].c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + int vlan_id; + vlan_id = stoi(keys[0].substr(4)); + + if ((vlan_id <= 0) || (vlan_id > 4095)) + { + SWSS_LOG_ERROR("Invalid key format. Vlan is out of range: %s", keys[0].c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + MacAddress mac = MacAddress(keys[1]); + + string key = VLAN_PREFIX + to_string(vlan_id); + key += DEFAULT_KEY_SEPARATOR; + key += mac.to_string(); + + if (op == SET_COMMAND) + { + string port; + for (auto i : kfvFieldsValues(t)) + { + if (fvField(i) == "port") + { + port = fvValue(i); + break; + } + } + + vector fvVector; + FieldValueTuple p("port", port); + fvVector.push_back(p); + FieldValueTuple t("type", "static"); + fvVector.push_back(t); + + m_appFdbTableProducer.set(key, fvVector); + } + else if (op == DEL_COMMAND) + { + m_appFdbTableProducer.del(key); + } + else + { + SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); + } + it = consumer.m_toSync.erase(it); + } +} + void VlanMgr::doVlanTask(Consumer &consumer) { if (!isVlanMacOk()) @@ -292,15 +450,7 @@ void VlanMgr::doVlanTask(Consumer &consumer) /* set up host env .... */ for (auto i : kfvFieldsValues(t)) { - /* Set vlan admin status */ - if (fvField(i) == "admin_status") - { - admin_status = fvValue(i); - setHostVlanAdminState(vlan_id, admin_status); - fvVector.push_back(i); - } - /* Set vlan mtu */ - else if (fvField(i) == "mtu") + if (fvField(i) == "mtu") { mtu = fvValue(i); /* @@ -590,9 +740,45 @@ void VlanMgr::doTask(Consumer &consumer) { doVlanMemberTask(consumer); } + else if (table_name == CFG_FDB_TABLE_NAME) + { + doFdbTask(consumer); + } + else if (table_name == CFG_SWITCH_TABLE_NAME) + { + SWSS_LOG_DEBUG("Table:SWITCH"); + doSwitchTask(consumer); + } else { SWSS_LOG_ERROR("Unknown config table %s ", table_name.c_str()); throw runtime_error("VlanMgr doTask failure."); } } + +void VlanMgr::doTask(NotificationConsumer &consumer) +{ + std::string op; + std::string data; + std::vector values; + + if (&consumer != m_VlanStateNotificationConsumer) + { + return; + } + + consumer.pop(op, data, values); + + int vlan_id = stoi(data.substr(4)); + + SWSS_LOG_NOTICE("vlanmgr received port status notification state %s vlan %s id %d", + op.c_str(), data.c_str(), vlan_id); + + if (isVlanStateOk(data)) { + setHostVlanAdminState(vlan_id, op); + } + else + { + SWSS_LOG_ERROR("received state update for vlan %s not existing", data.c_str()); + } +} diff --git a/cfgmgr/vlanmgr.h b/cfgmgr/vlanmgr.h index aff14999c2..40847f346d 100644 --- a/cfgmgr/vlanmgr.h +++ b/cfgmgr/vlanmgr.h @@ -4,6 +4,7 @@ #include "dbconnector.h" #include "producerstatetable.h" #include "orch.h" +#include "notifier.h" #include #include @@ -19,14 +20,20 @@ class VlanMgr : public Orch private: ProducerStateTable m_appVlanTableProducer, m_appVlanMemberTableProducer; + ProducerStateTable m_appFdbTableProducer; + ProducerStateTable m_appSwitchTableProducer; Table m_cfgVlanTable, m_cfgVlanMemberTable; Table m_statePortTable, m_stateLagTable; Table m_stateVlanTable, m_stateVlanMemberTable; std::set m_vlans; + NotificationConsumer* m_VlanStateNotificationConsumer; void doTask(Consumer &consumer); + void doTask(NotificationConsumer &consumer); void doVlanTask(Consumer &consumer); void doVlanMemberTask(Consumer &consumer); + void doFdbTask(Consumer &consumer); + void doSwitchTask(Consumer &consumer); void processUntaggedVlanMembers(string vlan, const string &members); bool addHostVlan(int vlan_id); diff --git a/cfgmgr/vlanmgrd.cpp b/cfgmgr/vlanmgrd.cpp index a2bafe0284..db71a127e5 100644 --- a/cfgmgr/vlanmgrd.cpp +++ b/cfgmgr/vlanmgrd.cpp @@ -51,6 +51,8 @@ int main(int argc, char **argv) vector cfg_vlan_tables = { CFG_VLAN_TABLE_NAME, CFG_VLAN_MEMBER_TABLE_NAME, + CFG_FDB_TABLE_NAME, + CFG_SWITCH_TABLE_NAME, }; DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 2c0ff988df..6ed11e02aa 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -57,6 +57,7 @@ bool FdbOrch::bake() bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) { const FdbEntry& entry = update.entry; + const FdbData fdbdata = {update.port.m_bridge_port_id, update.type}; const Port& port = update.port; const MacAddress& mac = entry.mac; string portName = port.m_alias; @@ -73,30 +74,39 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) if (update.add) { - auto inserted = m_entries.insert(entry); - - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%" PRIx64, - entry.mac.to_string().c_str(), entry.bv_id); - - if (!inserted.second) + bool mac_move=false; + auto it = m_entries.find(entry); + if(it != m_entries.end()) { - SWSS_LOG_INFO("FdbOrch notification: mac %s is duplicate", entry.mac.to_string().c_str()); - return false; + if(port.m_bridge_port_id == it->second.bridge_port_id) + { + SWSS_LOG_INFO("FdbOrch notification: mac %s is duplicate", entry.mac.to_string().c_str()); + return false; + } + mac_move=true; } + m_entries[entry] = fdbdata; + SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%lx", + entry.mac.to_string().c_str(), entry.bv_id); + SWSS_LOG_DEBUG("m_entries size=%lu mac=%s port=%lx", m_entries.size(), entry.mac.to_string().c_str(), m_entries[entry].bridge_port_id); + // Write to StateDb std::vector fvs; fvs.push_back(FieldValueTuple("port", portName)); - fvs.push_back(FieldValueTuple("type", "dynamic")); + fvs.push_back(FieldValueTuple("type", update.type)); m_fdbStateTable.set(key, fvs); - gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + if(!mac_move) + { + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + } return true; } else { size_t erased = m_entries.erase(entry); - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed from bv_id 0x%" PRIx64, entry.mac.to_string().c_str(), entry.bv_id); + SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed from bv_id 0x%lx", entry.mac.to_string().c_str(), entry.bv_id); if (erased == 0) { @@ -118,26 +128,43 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj FdbUpdate update; update.entry.mac = entry->mac_address; update.entry.bv_id = entry->bv_id; + update.type = "dynamic"; + Port vlan; switch (type) { case SAI_FDB_EVENT_LEARNED: + { + SWSS_LOG_INFO("Received LEARN event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + + if (!m_portsOrch->getPort(entry->bv_id, vlan)) + { + SWSS_LOG_NOTICE("FdbOrch LEARN notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); + return; + } + if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) { - SWSS_LOG_ERROR("Failed to get port by bridge port ID 0x%" PRIx64, bridge_port_id); + SWSS_LOG_NOTICE("FdbOrch LEARN notification: Failed to get port by bridge port ID 0x%lx", bridge_port_id); return; } // we already have such entries - if (m_entries.find(update.entry) != m_entries.end()) + auto existing_entry = m_entries.find(update.entry); + if (existing_entry != m_entries.end()) { - SWSS_LOG_INFO("FdbOrch notification: mac %s is already in bv_id 0x%" PRIx64, - update.entry.mac.to_string().c_str(), entry->bv_id); + SWSS_LOG_INFO("FdbOrch LEARN notification: mac %s is already in bv_id 0x%lx existing-bp 0x%lx new-bp:0x%lx", + update.entry.mac.to_string().c_str(), entry->bv_id, existing_entry->second.bridge_port_id, bridge_port_id); break; } update.add = true; + update.type = "dynamic"; storeFdbEntryState(update); + update.port.m_fdb_count++; + m_portsOrch->setPort(update.port.m_alias, update.port); + vlan.m_fdb_count++; + m_portsOrch->setPort(vlan.m_alias, vlan); for (auto observer: m_observers) { @@ -145,58 +172,162 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj } break; - + } case SAI_FDB_EVENT_AGED: - case SAI_FDB_EVENT_MOVE: + { + SWSS_LOG_INFO("Received AGE event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + + if (!m_portsOrch->getPort(entry->bv_id, vlan)) + { + SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); + return; + } + + auto existing_entry = m_entries.find(update.entry); + // we don't have such entries + if (existing_entry == m_entries.end()) + { + SWSS_LOG_INFO("FdbOrch AGE notification: mac %s is not present in bv_id 0x%lx bp 0x%lx", + update.entry.mac.to_string().c_str(), entry->bv_id, bridge_port_id); + break; + } + + if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) + { + SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to get port by bridge port ID 0x%lx", bridge_port_id); + return; + } + + if (existing_entry->second.bridge_port_id != bridge_port_id) + { + SWSS_LOG_NOTICE("FdbOrch AGE notification: Stale aging event received for mac-bv_id %s-0x%lx with bp=0x%lx existing bp=0x%lx", update.entry.mac.to_string().c_str(), entry->bv_id, bridge_port_id, existing_entry->second.bridge_port_id); + // We need to get the port for bridge-port in existing fdb + if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, update.port)) + { + SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to get port by bridge port ID 0x%lx", existing_entry->second.bridge_port_id); + return; + } + // dont return, let it delete just to bring SONiC and SAI in sync + // return; + } + + if (existing_entry->second.type == "static") + { + update.type = "static"; + saved_fdb_entries[update.port.m_alias].push_back({existing_entry->first.mac, vlan.m_vlan_info.vlan_id, "static"}); + } update.add = false; storeFdbEntryState(update); + update.port.m_fdb_count--; + m_portsOrch->setPort(update.port.m_alias, update.port); + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); } - break; + } + case SAI_FDB_EVENT_MOVE: + { + Port port_old; + auto existing_entry = m_entries.find(update.entry); + SWSS_LOG_INFO("Received MOVE event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + update.add = true; + + if (!m_portsOrch->getPort(entry->bv_id, vlan)) + { + SWSS_LOG_NOTICE("FdbOrch MOVE notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); + return; + } + + if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) + { + SWSS_LOG_ERROR("FdbOrch MOVE notification: Failed to get port by bridge port ID 0x%lx", bridge_port_id); + return; + } + + // We should already have such entry + if (existing_entry == m_entries.end()) + { + SWSS_LOG_INFO("FdbOrch MOVE notification: mac %s is not found in bv_id 0x%lx", + update.entry.mac.to_string().c_str(), entry->bv_id); + break; + } + if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, port_old)) + { + SWSS_LOG_ERROR("FdbOrch MOVE notification: Failed to get port by bridge port ID 0x%lx", existing_entry->second.bridge_port_id); + return; + } + port_old.m_fdb_count--; + m_portsOrch->setPort(port_old.m_alias, port_old); + update.port.m_fdb_count++; + m_portsOrch->setPort(update.port.m_alias, update.port); + + storeFdbEntryState(update); + + for (auto observer: m_observers) + { + observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); + } + break; + } case SAI_FDB_EVENT_FLUSHED: - if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID) + SWSS_LOG_INFO("Received FLUSH event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + for (auto itr = m_entries.begin(); itr != m_entries.end();) { - for (auto itr = m_entries.begin(); itr != m_entries.end();) + if (itr->second.type == "static") { - /* - TODO: here should only delete the dynamic fdb entries, - but unfortunately in structure FdbEntry currently have - no member to indicate the fdb entry type, - if there is static mac added, here will have issue. - */ - update.entry.mac = itr->mac; - update.entry.bv_id = itr->bv_id; + itr++; + continue; + } + + if (((bridge_port_id == SAI_NULL_OBJECT_ID) && (entry->bv_id == SAI_NULL_OBJECT_ID)) // Flush all DYNAMIC + || ((bridge_port_id == itr->second.bridge_port_id) && (entry->bv_id == SAI_NULL_OBJECT_ID)) // flush all DYN on a port + || ((bridge_port_id == SAI_NULL_OBJECT_ID) && (entry->bv_id == itr->first.bv_id))) // flush all DYN on a vlan + { + + if (!m_portsOrch->getPortByBridgePortId(itr->second.bridge_port_id, update.port)) + { + SWSS_LOG_ERROR("FdbOrch FLUSH notification: Failed to get port by bridge port ID 0x%lx", itr->second.bridge_port_id); + itr++; + continue; + } + + if (!m_portsOrch->getPort(itr->first.bv_id, vlan)) + { + SWSS_LOG_NOTICE("FdbOrch FLUSH notification: Failed to locate vlan port from bv_id 0x%lx", itr->first.bv_id); + itr++; + continue; + } + + update.entry.mac = itr->first.mac; + update.entry.bv_id = itr->first.bv_id; update.add = false; itr++; + + /* This will invalidate the current iterator hence itr++ is done before */ storeFdbEntryState(update); - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed", update.entry.mac.to_string().c_str()); + update.port.m_fdb_count--; + m_portsOrch->setPort(update.port.m_alias, update.port); + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); + + SWSS_LOG_DEBUG("FdbOrch FLUSH 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) - { - /*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); - } - else if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_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); - } - 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); + else + { + itr++; + } } break; } @@ -281,7 +412,24 @@ void FdbOrch::doTask(Consumer& consumer) if (!m_portsOrch->getPort(keys[0], vlan)) { SWSS_LOG_INFO("Failed to locate %s", keys[0].c_str()); - it++; + if(op == DEL_COMMAND) + { + /* Delete if it is in saved_fdb_entry */ + unsigned short vlan_id; + try { + vlan_id = (unsigned short) stoi(keys[0].substr(4)); + } catch(exception &e) { + it = consumer.m_toSync.erase(it); + continue; + } + deleteFdbEntryFromSavedFDB(MacAddress(keys[1]), vlan_id, ""); + + it = consumer.m_toSync.erase(it); + } + else + { + it++; + } continue; } @@ -348,7 +496,6 @@ void FdbOrch::doTask(NotificationConsumer& consumer) return; } - sai_status_t status; std::string op; std::string data; std::vector values; @@ -359,28 +506,17 @@ void FdbOrch::doTask(NotificationConsumer& consumer) { if (op == "ALL") { - /* - * so far only support flush all the FDB entris - * flush per port and flush per vlan will be added later. - */ - status = sai_fdb_api->flush_fdb_entries(gSwitchId, 0, NULL); - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); - } - + flushFdbAll(0); return; } else if (op == "PORT") { - /*place holder for flush port fdb*/ - SWSS_LOG_ERROR("Received unsupported flush port fdb request"); + flushFdbByPort(data, 0); return; } else if (op == "VLAN") { - /*place holder for flush vlan fdb*/ - SWSS_LOG_ERROR("Received unsupported flush vlan fdb request"); + flushFdbByVlan(data, 0); return; } else @@ -389,43 +525,21 @@ void FdbOrch::doTask(NotificationConsumer& consumer) return; } } - else if (&consumer == m_fdbNotificationConsumer && op == "fdb_event") - { - uint32_t count; - sai_fdb_event_notification_data_t *fdbevent = nullptr; - - sai_deserialize_fdb_event_ntf(data, count, &fdbevent); - - for (uint32_t i = 0; i < count; ++i) - { - sai_object_id_t oid = SAI_NULL_OBJECT_ID; - - for (uint32_t j = 0; j < fdbevent[i].attr_count; ++j) - { - if (fdbevent[i].attr[j].id == SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID) - { - oid = fdbevent[i].attr[j].value.oid; - break; - } - } - - this->update(fdbevent[i].event_type, &fdbevent[i].fdb_entry, oid); - } - - sai_deserialize_free_fdb_event_ntf(count, fdbevent); - } } void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) { + string port_name = update.member.m_alias; + string vlan_name = update.vlan.m_alias; + SWSS_LOG_ENTER(); if (!update.add) { - return; // we need additions only + flushFdbByPortVlan(port_name, vlan_name, 1); + return; } - string port_name = update.member.m_alias; auto fdb_list = std::move(saved_fdb_entries[port_name]); if(!fdb_list.empty()) { @@ -433,40 +547,85 @@ 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); + if(fdb.vlanId == update.vlan.m_vlan_info.vlan_id) + { + FdbEntry entry; + entry.mac = fdb.mac; + entry.bv_id = update.vlan.m_vlan_info.vlan_oid; + (void)addFdbEntry(entry, port_name, fdb.type); + } + else + { + saved_fdb_entries[port_name].push_back(fdb); + } } } } bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const string& type) { - SWSS_LOG_ENTER(); + Port vlan; + Port port; - sai_fdb_entry_t fdb_entry; + SWSS_LOG_ENTER(); + SWSS_LOG_INFO("mac=%s bv_id=0x%lx port_name %s type %s", entry.mac.to_string().c_str(), entry.bv_id, port_name.c_str(), type.c_str()); - fdb_entry.switch_id = gSwitchId; - memcpy(fdb_entry.mac_address, entry.mac.getMac(), sizeof(sai_mac_t)); - fdb_entry.bv_id = entry.bv_id; + if (!m_portsOrch->getPort(entry.bv_id, vlan)) + { + SWSS_LOG_NOTICE("addFdbEntry: Failed to locate vlan port from bv_id 0x%lx", entry.bv_id); + return false; + } - Port port; /* Retry until port is created */ - if (!m_portsOrch->getPort(port_name, port)) + if (!m_portsOrch->getPort(port_name, port) || (port.m_bridge_port_id == SAI_NULL_OBJECT_ID)) { - 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_INFO("Saving a fdb entry until port %s becomes active", port_name.c_str()); + saved_fdb_entries[port_name].push_back({entry.mac, vlan.m_vlan_info.vlan_id, type}); return true; } - /* Retry until port is added to the VLAN */ - if (!port.m_bridge_port_id) + /* Retry until port is member of vlan*/ + if (vlan.m_members.find(port_name) == vlan.m_members.end()) { - 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_INFO("Saving a fdb entry until port %s becomes vlan %s member", port_name.c_str(), vlan.m_alias.c_str()); + saved_fdb_entries[port_name].push_back({entry.mac, vlan.m_vlan_info.vlan_id, type}); return true; } + sai_status_t status; + sai_fdb_entry_t fdb_entry; + fdb_entry.switch_id = gSwitchId; + memcpy(fdb_entry.mac_address, entry.mac.getMac(), sizeof(sai_mac_t)); + fdb_entry.bv_id = entry.bv_id; + + Port oldPort; + string oldType; + bool macUpdate = false; + auto it = m_entries.find(entry); + if(it != m_entries.end()) + { + if(port.m_bridge_port_id == it->second.bridge_port_id) + { + if((it->second.type == type)) + { + SWSS_LOG_INFO("FdbOrch: mac=%s %s port=%s type=%s is duplicate", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str(), type.c_str()); + return true; + } + } + + /* get existing port and type */ + oldType = it->second.type; + if (!m_portsOrch->getPortByBridgePortId(it->second.bridge_port_id, oldPort)) + { + SWSS_LOG_ERROR("Existing port 0x%lx details not found", it->second.bridge_port_id); + return false; + } + + macUpdate = true; + } + sai_attribute_t attr; vector attrs; @@ -482,26 +641,61 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const attr.value.s32 = SAI_PACKET_ACTION_FORWARD; attrs.push_back(attr); - if (m_entries.count(entry) != 0) // we already have such entries + if(macUpdate) { - removeFdbEntry(entry); + SWSS_LOG_NOTICE("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); + for(auto itr : attrs) + { + status = sai_fdb_api->set_fdb_entry_attribute(&fdb_entry, &itr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("macUpdate-Failed for attr.id=0x%x for FDB %s in %s on %s, rv:%d", + itr.id, entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str(), status); + return false; + } + } + if (oldPort.m_bridge_port_id != port.m_bridge_port_id) + { + oldPort.m_fdb_count--; + m_portsOrch->setPort(oldPort.m_alias, oldPort); + port.m_fdb_count++; + m_portsOrch->setPort(port.m_alias, port); + } } - - sai_status_t status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); - if (status != SAI_STATUS_SUCCESS) + else { - 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); - return false; //FIXME: it should be based on status. Some could be retried, some not + SWSS_LOG_INFO("MAC-Create %s FDB %s in %s on %s", type.c_str(), entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str()); + + status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); + 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); + return false; //FIXME: it should be based on status. Some could be retried, some not + } + port.m_fdb_count++; + m_portsOrch->setPort(port.m_alias, port); + vlan.m_fdb_count++; + m_portsOrch->setPort(vlan.m_alias, vlan); } - SWSS_LOG_NOTICE("Create %s FDB %s on %s", type.c_str(), entry.mac.to_string().c_str(), port_name.c_str()); + const FdbData fdbdata = {port.m_bridge_port_id, type}; + m_entries[entry] = fdbdata; + + string key = "Vlan" + to_string(vlan.m_vlan_info.vlan_id) + ":" + entry.mac.to_string(); - (void) m_entries.insert(entry); + // Write to StateDb + std::vector fvs; + fvs.push_back(FieldValueTuple("port", port_name)); + fvs.push_back(FieldValueTuple("type", type)); + m_fdbStateTable.set(key, fvs); - gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + if(!macUpdate) + { + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + } - FdbUpdate update = {entry, port, true}; + FdbUpdate update = {entry, port, type, true}; for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -512,14 +706,36 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const bool FdbOrch::removeFdbEntry(const FdbEntry& entry) { + Port vlan; + Port port; + SWSS_LOG_ENTER(); - if (m_entries.count(entry) == 0) + if (!m_portsOrch->getPort(entry.bv_id, vlan)) { - 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_NOTICE("FdbOrch notification: Failed to locate vlan port from bv_id 0x%lx", entry.bv_id); + return false; + } + + auto it= m_entries.find(entry); + if(it == m_entries.end()) + { + SWSS_LOG_INFO("FdbOrch RemoveFDBEntry: FDB entry isn't found. mac=%s bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); + + /* check whether the entry is in the saved fdb, if so delete it from there. */ + deleteFdbEntryFromSavedFDB(entry.mac, vlan.m_vlan_info.vlan_id, ""); return true; } + FdbData fdbData = it->second; + if (!m_portsOrch->getPortByBridgePortId(fdbData.bridge_port_id, port)) + { + SWSS_LOG_NOTICE("FdbOrch RemoveFDBEntry: Failed to locate port from bridge_port_id 0x%lx", fdbData.bridge_port_id); + return false; + } + + string key = "Vlan" + to_string(vlan.m_vlan_info.vlan_id) + ":" + entry.mac.to_string(); + sai_status_t status; sai_fdb_entry_t fdb_entry; fdb_entry.switch_id = gSwitchId; @@ -529,19 +745,22 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) status = sai_fdb_api->remove_fdb_entry(&fdb_entry); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to remove FDB entry. mac=%s, bv_id=0x%" PRIx64, + SWSS_LOG_ERROR("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); return true; //FIXME: it should be based on status. Some could be retried. some not } - + port.m_fdb_count--; + m_portsOrch->setPort(port.m_alias, port); + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); (void)m_entries.erase(entry); - gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + // Remove in StateDb + m_fdbStateTable.del(key); - Port port; - m_portsOrch->getPortByBridgePortId(entry.bv_id, port); + gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); - FdbUpdate update = {entry, port, false}; + FdbUpdate update = {entry, port, fdbData.type, false}; for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -549,3 +768,174 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) return true; } + +int FdbOrch::flushFdbAll(bool flush_static) +{ + sai_status_t status; + sai_attribute_t port_attr; + + if (!flush_static) + { + port_attr.id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + port_attr.value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC; + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 1, &port_attr); + } + else + { + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 0, NULL); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + } + return 0; +} + +int FdbOrch::flushFdbByPort(const string &alias, bool flush_static) +{ + sai_status_t status; + Port port; + sai_attribute_t port_attr[2]; + + if (!m_portsOrch->getPort(alias, port)) + { + SWSS_LOG_ERROR("could not locate port from alias %s", alias.c_str()); + return false; + } + + if ((port.m_bridge_port_id == SAI_NULL_OBJECT_ID) || !port.m_fdb_count) + { + /* port is not an L2 port or no macs to flush */ + return true; + } + + SWSS_LOG_NOTICE("m_bridge_port_id 0x%lx flush_static %d m_fdb_count %u", port.m_bridge_port_id, flush_static, port.m_fdb_count); + + port_attr[0].id = SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID; + port_attr[0].value.oid = port.m_bridge_port_id; + if (!flush_static) + { + port_attr[1].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + port_attr[1].value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC; + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 2, port_attr); + } + else + { + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 1, port_attr); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + } + return 0; +} + +int FdbOrch::flushFdbByVlan(const string &alias, bool flush_static) +{ + sai_status_t status; + Port vlan; + sai_attribute_t vlan_attr[2]; + + if (!m_portsOrch->getPort(alias, vlan)) + { + SWSS_LOG_ERROR("could not locate vlan from alias %s", alias.c_str()); + return false; + } + SWSS_LOG_NOTICE("vlan_oid 0x%lx flush_static %d", vlan.m_vlan_info.vlan_oid, flush_static); + + vlan_attr[0].id = SAI_FDB_FLUSH_ATTR_BV_ID; + vlan_attr[0].value.oid = vlan.m_vlan_info.vlan_oid; + if (!flush_static) + { + vlan_attr[1].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + vlan_attr[1].value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC; + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 2, vlan_attr); + } + else + { + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 1, vlan_attr); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + } + + return 0; +} + +int FdbOrch::flushFdbByPortVlan(const string &port_alias, const string &vlan_alias, bool flush_static) +{ + + sai_status_t status; + Port vlan; + Port port; + sai_attribute_t port_vlan_attr[3]; + + SWSS_LOG_NOTICE("port %s vlan %s", port_alias.c_str(), vlan_alias.c_str()); + + if (!m_portsOrch->getPort(port_alias, port)) + { + SWSS_LOG_ERROR("could not locate port from alias %s", port_alias.c_str()); + return false; + } + if (!m_portsOrch->getPort(vlan_alias, vlan)) + { + SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate vlan %s", vlan_alias.c_str()); + return false; + } + + if ((port.m_bridge_port_id == SAI_NULL_OBJECT_ID) || !port.m_fdb_count) + { + /* port is not an L2 port or no macs to flush */ + return true; + } + + SWSS_LOG_NOTICE("vlan_oid 0x%lx m_bridge_port_id 0x%lx flush_static %d m_fdb_count %u", vlan.m_vlan_info.vlan_oid, port.m_bridge_port_id, flush_static, port.m_fdb_count); + + port_vlan_attr[0].id = SAI_FDB_FLUSH_ATTR_BV_ID; + port_vlan_attr[0].value.oid = vlan.m_vlan_info.vlan_oid; + port_vlan_attr[1].id = SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID; + port_vlan_attr[1].value.oid = port.m_bridge_port_id; + if (!flush_static) + { + port_vlan_attr[2].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + port_vlan_attr[2].value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC; + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 3, port_vlan_attr); + } + else + { + status = sai_fdb_api->flush_fdb_entries(gSwitchId, 2, port_vlan_attr); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + } + + return 0; +} + +void FdbOrch::deleteFdbEntryFromSavedFDB(const MacAddress &mac, const unsigned short &vlanId, const string portName) +{ + bool found=false; + SavedFdbEntry entry = {mac, vlanId, "static"}; + for (auto& itr: saved_fdb_entries) + { + if(portName.empty() || (portName == itr.first)) + { + auto iter = saved_fdb_entries[itr.first].begin(); + while(iter != saved_fdb_entries[itr.first].end()) + { + if (*iter == entry) + { + SWSS_LOG_INFO("FDB entry found in saved fdb. deleting... mac=%s vlan_id=0x%x", mac.to_string().c_str(), vlanId); + saved_fdb_entries[itr.first].erase(iter); + found=true; + break; + } + iter++; + } + } + if(found) + break; + } +} diff --git a/orchagent/fdborch.h b/orchagent/fdborch.h index 3125b3112d..6348218a86 100644 --- a/orchagent/fdborch.h +++ b/orchagent/fdborch.h @@ -14,19 +14,35 @@ struct FdbEntry { return tie(mac, bv_id) < tie(other.mac, other.bv_id); } + bool operator==(const FdbEntry& other) const + { + return tie(mac, bv_id) == tie(other.mac, other.bv_id); + } }; struct FdbUpdate { FdbEntry entry; Port port; + string type; bool add; }; +struct FdbData +{ + sai_object_id_t bridge_port_id; + string type; +}; + struct SavedFdbEntry { - FdbEntry entry; + MacAddress mac; + unsigned short vlanId; string type; + bool operator==(const SavedFdbEntry& other) const + { + return tie(mac, vlanId) == tie(other.mac, other.vlanId); + } }; typedef unordered_map> fdb_entries_by_port_t; @@ -46,10 +62,15 @@ class FdbOrch: public Orch, public Subject, public Observer void update(sai_fdb_event_t, const sai_fdb_entry_t *, sai_object_id_t); void update(SubjectType type, void *cntx); bool getPort(const MacAddress&, uint16_t, Port&); + int flushFdbByPortVlan(const string &, const string &, bool flush_static); + int flushFdbByVlan(const string &, bool flush_static); + int flushFdbByPort(const string &, bool flush_static); + int flushFdbAll(bool flush_static); + bool removeFdbEntry(const FdbEntry&); private: PortsOrch *m_portsOrch; - set m_entries; + map m_entries; fdb_entries_by_port_t saved_fdb_entries; Table m_table; Table m_fdbStateTable; @@ -61,7 +82,7 @@ class FdbOrch: public Orch, public Subject, public Observer void updateVlanMember(const VlanMemberUpdate&); bool addFdbEntry(const FdbEntry&, const string&, const string&); - bool removeFdbEntry(const FdbEntry&); + void deleteFdbEntryFromSavedFDB(const MacAddress &mac, const unsigned short &vlanId, const string portName=""); bool storeFdbEntryState(const FdbUpdate& update); }; diff --git a/orchagent/notifications.cpp b/orchagent/notifications.cpp index 209c03d83b..daad09b837 100644 --- a/orchagent/notifications.cpp +++ b/orchagent/notifications.cpp @@ -4,11 +4,29 @@ extern "C" { #include "logger.h" #include "notifications.h" +#include "fdborch.h" -void on_fdb_event(uint32_t count, sai_fdb_event_notification_data_t *data) +extern FdbOrch *gFdbOrch; + +void on_fdb_event(uint32_t count, sai_fdb_event_notification_data_t *fdbevent) { - // don't use this event handler, because it runs by libsairedis in a separate thread - // which causes concurrency access to the DB + //std::lock_guard lock(g_orchmutex); + + for (uint32_t i = 0; i < count; ++i) + { + sai_object_id_t oid = SAI_NULL_OBJECT_ID; + + for (uint32_t j = 0; j < fdbevent[i].attr_count; ++j) + { + if (fdbevent[i].attr[j].id == SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID) + { + oid = fdbevent[i].attr[j].value.oid; + break; + } + } + + gFdbOrch->update(fdbevent[i].event_type, &fdbevent[i].fdb_entry, oid); + } } void on_port_state_change(uint32_t count, sai_port_oper_status_notification_t *data) diff --git a/orchagent/port.h b/orchagent/port.h index 34b72aa8c2..6d7ceb0cdb 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -22,6 +22,7 @@ namespace swss { struct VlanMemberEntry { + std::string alias; sai_object_id_t vlan_member_id; sai_vlan_tagging_mode_t vlan_mode; }; @@ -77,6 +78,7 @@ class Port sai_port_fec_mode_t m_fec_mode = SAI_PORT_FEC_MODE_NONE; VlanInfo m_vlan_info; sai_object_id_t m_bridge_port_id = 0; // TODO: port could have multiple bridge port IDs + sai_object_id_t m_bridge_port_admin_state = 0; // TODO: port could have multiple bridge port IDs sai_vlan_id_t m_port_vlan_id = DEFAULT_PORT_VLAN_ID; // Port VLAN ID sai_object_id_t m_rif_id = 0; sai_object_id_t m_vr_id = 0; @@ -92,6 +94,8 @@ class Port std::vector m_priority_group_ids; sai_port_priority_flow_control_mode_t m_pfc_asym = SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_COMBINED; uint8_t m_pfc_bitmask = 0; + uint32_t m_fdb_count = 0; + uint32_t m_up_member_count = 0; }; } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 30b2d26269..f0d9cccc8c 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -23,6 +23,7 @@ #include "crmorch.h" #include "countercheckorch.h" #include "notifier.h" +#include "fdborch.h" extern sai_switch_api_t *sai_switch_api; extern sai_bridge_api_t *sai_bridge_api; @@ -37,6 +38,9 @@ extern IntfsOrch *gIntfsOrch; extern NeighOrch *gNeighOrch; extern CrmOrch *gCrmOrch; extern BufferOrch *gBufferOrch; +extern FdbOrch *gFdbOrch; +std::recursive_mutex g_orchmutex; + #define VLAN_PREFIX "Vlan" #define DEFAULT_VLAN_ID 1 @@ -148,8 +152,9 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_counter_db = shared_ptr(new DBConnector(COUNTERS_DB, DBConnector::DEFAULT_UNIXSOCKET, 0)); m_counterTable = unique_ptr(new Table(m_counter_db.get(), COUNTERS_PORT_NAME_MAP)); - /* Initialize port table */ + /* Initialize port and vlan table */ m_portTable = unique_ptr
(new Table(db, APP_PORT_TABLE_NAME)); + m_vlanTable = unique_ptr
(new Table(db, APP_VLAN_TABLE_NAME)); /* Initialize queue tables */ m_queueTable = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_QUEUE_NAME_MAP)); @@ -166,6 +171,8 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_flexCounterTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_TABLE)); m_flexCounterGroupTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_GROUP_TABLE)); + notifications = new swss::NotificationProducer(db, "VLANSTATE"); + vector fields; fields.emplace_back(POLL_INTERVAL_FIELD, PORT_FLEX_STAT_COUNTER_POLL_MSECS); fields.emplace_back(STATS_MODE_FIELD, STATS_MODE_READ); @@ -298,7 +305,19 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) } m_default1QBridge = attrs[0].value.oid; - m_defaultVlan = attrs[1].value.oid; + m_defaultVlan_ObjId = attrs[1].value.oid; + + memset(&attr, 0x00, sizeof(attr)); + attr.id = SAI_VLAN_ATTR_VLAN_ID; + + status = sai_vlan_api->get_vlan_attribute(m_defaultVlan_ObjId, 1, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get default VLAN ID, rv:%d", status); + throw runtime_error("PortsOrch initialization failure"); + } + + m_defaultVlan_Id = attr.value.u16; removeDefaultVlanMembers(); removeDefaultBridgePorts(); @@ -320,7 +339,7 @@ void PortsOrch::removeDefaultVlanMembers() attr.value.objlist.count = (uint32_t)vlan_member_list.size(); attr.value.objlist.list = vlan_member_list.data(); - sai_status_t status = sai_vlan_api->get_vlan_attribute(m_defaultVlan, 1, &attr); + sai_status_t status = sai_vlan_api->get_vlan_attribute(m_defaultVlan_ObjId, 1, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to get VLAN member list in default VLAN, rv:%d", status); @@ -410,13 +429,16 @@ bool PortsOrch::getPort(string alias, Port &p) { SWSS_LOG_ENTER(); + std::unique_lock lock(g_orchmutex); if (m_portList.find(alias) == m_portList.end()) { + std::unique_lock unlock(g_orchmutex); return false; } else { p = m_portList[alias]; + std::unique_lock unlock(g_orchmutex); return true; } } @@ -425,34 +447,12 @@ bool PortsOrch::getPort(sai_object_id_t id, Port &port) { SWSS_LOG_ENTER(); - for (const auto& portIter: m_portList) - { - switch (portIter.second.m_type) - { - case Port::PHY: - if(portIter.second.m_port_id == id) - { - port = portIter.second; - return true; - } - break; - case Port::LAG: - if(portIter.second.m_lag_id == id) - { - port = portIter.second; - return true; - } - break; - case Port::VLAN: - if (portIter.second.m_vlan_info.vlan_oid == id) - { - port = portIter.second; - return true; - } - break; - default: - continue; - } + auto itr = portOidToName.find(id); + if (itr == portOidToName.end()) + return false; + else { + getPort(itr->second, port); + return true; } return false; @@ -474,13 +474,12 @@ bool PortsOrch::getPortByBridgePortId(sai_object_id_t bridge_port_id, Port &port { SWSS_LOG_ENTER(); - for (auto &it: m_portList) - { - if (it.second.m_bridge_port_id == bridge_port_id) - { - port = it.second; - return true; - } + auto itr = portOidToName.find(bridge_port_id); + if (itr == portOidToName.end()) + return false; + else { + getPort(itr->second, port); + return true; } return false; @@ -528,7 +527,16 @@ bool PortsOrch::getAclBindPortId(string alias, sai_object_id_t &port_id) void PortsOrch::setPort(string alias, Port p) { + std::unique_lock lock(g_orchmutex); m_portList[alias] = p; + std::unique_lock unlock(g_orchmutex); +} + +void PortsOrch::erasePort(string alias) +{ + std::unique_lock lock(g_orchmutex); + m_portList.erase(alias); + std::unique_lock unlock(g_orchmutex); } void PortsOrch::getCpuPort(Port &port) @@ -671,7 +679,7 @@ bool PortsOrch::setPortPfc(sai_object_id_t portId, uint8_t pfc_bitmask) if (p.m_pfc_bitmask != pfc_bitmask) { p.m_pfc_bitmask = pfc_bitmask; - m_portList[p.m_alias] = p; + setPort(p.m_alias, p); } return true; @@ -704,7 +712,7 @@ bool PortsOrch::setPortPfcAsym(Port &port, string pfc_asym) } port.m_pfc_asym = new_pfc_asym; - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); attr.id = SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_MODE; attr.value.s32 = (int32_t) port.m_pfc_asym; @@ -1263,6 +1271,22 @@ void PortsOrch::updateDbPortOperStatus(const Port& port, sai_port_oper_status_t m_portTable->set(port.m_alias, tuples); } +void PortsOrch::updateDbVlanOperStatus(const Port& vlan, string status) const +{ + SWSS_LOG_NOTICE("vlan %s status %s", vlan.m_alias.c_str(), status.c_str()); + + vector tuples; + FieldValueTuple tuple("oper_status", status); + tuples.push_back(tuple); + m_vlanTable->set(vlan.m_alias, tuples); + + std::vector entry; + + SWSS_LOG_NOTICE("sending oper state notification to VlanMgr"); + + notifications->send(status, vlan.m_alias, entry); +} + bool PortsOrch::addPort(const set &lane_set, uint32_t speed, int an, string fec_mode) { SWSS_LOG_ENTER(); @@ -1360,26 +1384,31 @@ bool PortsOrch::initPort(const string &alias, const set &lane_set) /* Determine if the lane combination exists in switch */ if (m_portListLaneMap.find(lane_set) != m_portListLaneMap.end()) { + Port port; sai_object_id_t id = m_portListLaneMap[lane_set]; /* Determine if the port has already been initialized before */ - if (m_portList.find(alias) != m_portList.end() && m_portList[alias].m_port_id == id) - { + auto port_found = getPort(alias, port); + if (port_found && (port.m_port_id == id)) { SWSS_LOG_INFO("Port has already been initialized before alias:%s", alias.c_str()); } else { Port p(alias, Port::PHY); - - p.m_index = static_cast(m_portList.size()); // TODO: Assume no deletion of physical port - p.m_port_id = id; + { + std::unique_lock lock(g_orchmutex); + p.m_index = static_cast(m_portList.size()); // TODO: Assume no deletion of physical port + std::unique_lock unlock(g_orchmutex); + p.m_port_id = id; + } /* Initialize the port and create corresponding host interface */ if (initializePort(p)) { /* Add port to port list */ - m_portList[alias] = p; - m_port_ref_count[alias] = 0; + setPort(alias, p); + portOidToName[id] = alias; + m_port_ref_count[alias] = 0; /* Add port name map to counter table */ FieldValueTuple tuple(p.m_alias, sai_serialize_object_id(p.m_port_id)); vector fields; @@ -1430,8 +1459,7 @@ bool PortsOrch::bake() vector tuples; string value; bool foundPortConfigDone = m_portTable->hget("PortConfigDone", "count", value); - uintmax_t portCount; - char* endPtr = NULL; + unsigned long portCount; SWSS_LOG_NOTICE("foundPortConfigDone = %d", foundPortConfigDone); bool foundPortInitDone = m_portTable->get("PortInitDone", tuples); @@ -1448,12 +1476,12 @@ bool PortsOrch::bake() return false; } - portCount = strtoumax(value.c_str(), &endPtr, 0); - SWSS_LOG_NOTICE("portCount = %" PRIuMAX ", m_portCount = %u", portCount, m_portCount); + portCount = stoul(value); + SWSS_LOG_NOTICE("portCount = %" PRIu64 ", m_portCount = %u", portCount, m_portCount); if (portCount != keys.size() - 2) { // Invalid port table - SWSS_LOG_ERROR("Invalid port table: portCount, expecting %" PRIuMAX ", got %zu", + SWSS_LOG_ERROR("Invalid port table: portCount, expecting %" PRIu64 ", got %" PRIu64, portCount, keys.size() - 2); cleanPortTable(keys); @@ -1716,7 +1744,7 @@ void PortsOrch::doPortTask(Consumer &consumer) { SWSS_LOG_NOTICE("Set port %s AutoNeg to %u", alias.c_str(), an); p.m_autoneg = an; - m_portList[alias] = p; + setPort(alias, p); // Once AN is changed // - no speed specified: need to reapply the port speed or port adv speed accordingly @@ -1752,7 +1780,7 @@ void PortsOrch::doPortTask(Consumer &consumer) */ if (speed != 0 && speed != p.m_speed) { - m_portList[alias] = p; + setPort(alias, p); if (p.m_autoneg) { @@ -1786,7 +1814,7 @@ void PortsOrch::doPortTask(Consumer &consumer) } p.m_admin_state_up = false; - m_portList[alias] = p; + setPort(alias, p); if (!setPortSpeed(p.m_port_id, speed)) { @@ -1808,7 +1836,7 @@ void PortsOrch::doPortTask(Consumer &consumer) SWSS_LOG_NOTICE("Set port %s speed to %u", alias.c_str(), speed); } p.m_speed = speed; - m_portList[alias] = p; + setPort(alias, p); } if (mtu != 0 && mtu != p.m_mtu) @@ -1816,7 +1844,7 @@ void PortsOrch::doPortTask(Consumer &consumer) if (setPortMtu(p.m_port_id, mtu)) { p.m_mtu = mtu; - m_portList[alias] = p; + setPort(alias, p); SWSS_LOG_NOTICE("Set port %s MTU to %u", alias.c_str(), mtu); if (p.m_rif_id) { @@ -1841,7 +1869,7 @@ void PortsOrch::doPortTask(Consumer &consumer) p.m_fec_mode = fec_mode_map[fec_mode]; if (setPortFec(p.m_port_id, p.m_fec_mode)) { - m_portList[alias] = p; + setPort(alias, p); SWSS_LOG_NOTICE("Set port %s fec to %s", alias.c_str(), fec_mode.c_str()); } else @@ -1923,7 +1951,7 @@ void PortsOrch::doPortTask(Consumer &consumer) if (setPortAdminStatus(p.m_port_id, admin_status == "up")) { p.m_admin_state_up = (admin_status == "up"); - m_portList[alias] = p; + setPort(alias, p); SWSS_LOG_NOTICE("Set port %s admin status to %s", alias.c_str(), admin_status.c_str()); } else @@ -1972,6 +2000,7 @@ void PortsOrch::doVlanTask(Consumer &consumer) if (op == SET_COMMAND) { + Port vlan; // Retrieve attributes uint32_t mtu = 0; for (auto i : kfvFieldsValues(t)) @@ -1987,7 +2016,7 @@ void PortsOrch::doVlanTask(Consumer &consumer) * We may add support for VLAN mac learning enable/disable, * VLAN flooding control setting and etc. in the future. */ - if (m_portList.find(vlan_alias) == m_portList.end()) + if (!getPort(vlan_alias, vlan)) { if (!addVlan(vlan_alias)) { @@ -2007,7 +2036,7 @@ void PortsOrch::doVlanTask(Consumer &consumer) if (mtu != 0) { vl.m_mtu = mtu; - m_portList[vlan_alias] = vl; + setPort(vlan_alias, vl); if (vl.m_rif_id) { gIntfsOrch->setRouterIntfsMtu(vl); @@ -2125,24 +2154,23 @@ void PortsOrch::doVlanMemberTask(Consumer &consumer) } else if (op == DEL_COMMAND) { + int ret = true; if (vlan.m_members.find(port_alias) != vlan.m_members.end()) { - if (removeVlanMember(vlan, port)) - { - if (port.m_vlan_members.empty()) - { - removeBridgePort(port); - } - it = consumer.m_toSync.erase(it); - } - else - { - it++; - } + ret = removeVlanMember(vlan, port); } - else - /* Cannot locate the VLAN */ + if ((ret == true) && port.m_vlan_members.empty()) + { + ret = removeBridgePort(port); + } + if (ret == true) + { it = consumer.m_toSync.erase(it); + } + else + { + it++; + } } else { @@ -2168,24 +2196,22 @@ void PortsOrch::doLagTask(Consumer &consumer) { // Retrieve attributes uint32_t mtu = 0; + string oper_status; + for (auto i : kfvFieldsValues(t)) { if (fvField(i) == "mtu") { mtu = (uint32_t)stoul(fvValue(i)); } - } - - // Create a new LAG when the new alias comes - if (m_portList.find(alias) == m_portList.end()) - { - if (!addLag(alias)) + if (fvField(i) == "oper_status") { - it++; - continue; + oper_status = fvValue(i); } } + auto status = addLag(alias); + // Process attributes Port l; if (!getPort(alias, l)) @@ -2194,18 +2220,31 @@ void PortsOrch::doLagTask(Consumer &consumer) } else { - if (mtu != 0) + if ((mtu != 0) && (mtu != l.m_mtu)) { l.m_mtu = mtu; - m_portList[alias] = l; + setPort(alias, l); if (l.m_rif_id) { gIntfsOrch->setRouterIntfsMtu(l); } } + if (!oper_status.empty() && (oper_status != "up")) + { + gFdbOrch->flushFdbByPort(alias, 0); + } + sai_port_oper_status_t status = (oper_status == "up") ? SAI_PORT_OPER_STATUS_UP : SAI_PORT_OPER_STATUS_DOWN; + updateLagOperStatus(l, status); + } + if (!status) + { + it++; + continue; + } + else + { + it = consumer.m_toSync.erase(it); } - - it = consumer.m_toSync.erase(it); } else if (op == DEL_COMMAND) { @@ -2581,8 +2620,44 @@ bool PortsOrch::addBridgePort(Port &port) { SWSS_LOG_ENTER(); + if (port.m_rif_id) + { + SWSS_LOG_ERROR("Adding router interface %s as bridge port is not allowed", port.m_alias.c_str()); + return false; + } if (port.m_bridge_port_id != SAI_NULL_OBJECT_ID) { + /* If the port is being added to the first VLAN, + * set bridge port admin status to UP. + * This can happen if the port was just removed from + * last VLAN and fdb flush is still in progress. + */ + if (port.m_vlan_members.empty()) + { + if (port.m_fdb_count > 0) + { + return false; + } + sai_attribute_t attr; + attr.id = SAI_BRIDGE_PORT_ATTR_ADMIN_STATE; + attr.value.booldata = true; + + sai_status_t status = sai_bridge_api->set_bridge_port_attribute(port.m_bridge_port_id, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set bridge port %s admin status to UP, rv:%d", + port.m_alias.c_str(), status); + return false; + } + port.m_bridge_port_admin_state = true; + setPort(port.m_alias, port); + if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_KEEP)) + { + SWSS_LOG_ERROR("Failed to set %s for hostif of port %s", + hostif_vlan_tag[SAI_HOSTIF_VLAN_TAG_KEEP], port.m_alias.c_str()); + return false; + } + } return true; } @@ -2627,6 +2702,13 @@ bool PortsOrch::addBridgePort(Port &port) port.m_alias.c_str(), status); return false; } + if (!setPortPvid(port, 0)) + { + SWSS_LOG_ERROR("Failed to set pvid for port %s, rv:%d", + port.m_alias.c_str(), status); + return false; + } + port.m_bridge_port_admin_state = true; if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_KEEP)) { @@ -2634,12 +2716,14 @@ bool PortsOrch::addBridgePort(Port &port) hostif_vlan_tag[SAI_HOSTIF_VLAN_TAG_KEEP], port.m_alias.c_str()); return false; } - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); + portOidToName[port.m_bridge_port_id] = port.m_alias; SWSS_LOG_NOTICE("Add bridge port %s to default 1Q bridge", port.m_alias.c_str()); return true; } + bool PortsOrch::removeBridgePort(Port &port) { SWSS_LOG_ENTER(); @@ -2648,43 +2732,50 @@ bool PortsOrch::removeBridgePort(Port &port) { return true; } - /* Set bridge port admin status to DOWN */ - sai_attribute_t attr; - attr.id = SAI_BRIDGE_PORT_ATTR_ADMIN_STATE; - attr.value.booldata = false; - - sai_status_t status = sai_bridge_api->set_bridge_port_attribute(port.m_bridge_port_id, &attr); - if (status != SAI_STATUS_SUCCESS) + if (port.m_bridge_port_admin_state) { - SWSS_LOG_ERROR("Failed to set bridge port %s admin status to DOWN, rv:%d", - port.m_alias.c_str(), status); - return false; + /* Set bridge port admin status to DOWN */ + sai_attribute_t attr; + attr.id = SAI_BRIDGE_PORT_ATTR_ADMIN_STATE; + attr.value.booldata = false; + + sai_status_t status = sai_bridge_api->set_bridge_port_attribute(port.m_bridge_port_id, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set bridge port %s admin status to DOWN, rv:%d", + port.m_alias.c_str(), status); + return false; + } + port.m_bridge_port_admin_state = false; + setPort(port.m_alias, port); + + if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_STRIP)) + { + SWSS_LOG_ERROR("Failed to set %s for hostif of port %s", + hostif_vlan_tag[SAI_HOSTIF_VLAN_TAG_STRIP], port.m_alias.c_str()); + return false; + } } - if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_STRIP)) - { - SWSS_LOG_ERROR("Failed to set %s for hostif of port %s", - hostif_vlan_tag[SAI_HOSTIF_VLAN_TAG_STRIP], port.m_alias.c_str()); + if (port.m_fdb_count != 0) { + //SWSS_LOG_NOTICE("Port still has fdb entries, will not remove bridge port for %s", port.m_alias.c_str()); 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); + sai_status_t status = sai_bridge_api->remove_bridge_port(port.m_bridge_port_id); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to remove bridge port %s from default 1Q bridge, rv:%d", port.m_alias.c_str(), status); return false; } + portOidToName.erase(port.m_bridge_port_id); port.m_bridge_port_id = SAI_NULL_OBJECT_ID; SWSS_LOG_NOTICE("Remove bridge port %s from default 1Q bridge", port.m_alias.c_str()); - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); return true; } @@ -2698,7 +2789,17 @@ bool PortsOrch::addVlan(string vlan_alias) sai_attribute_t attr; attr.id = SAI_VLAN_ATTR_VLAN_ID; attr.value.u16 = vlan_id; - sai_status_t status = sai_vlan_api->create_vlan(&vlan_oid, gSwitchId, 1, &attr); + sai_status_t status = SAI_STATUS_SUCCESS; + + /* Do not create default VLAN. It is already created by default */ + if (vlan_id != m_defaultVlan_Id) + { + status = sai_vlan_api->create_vlan(&vlan_oid, gSwitchId, 1, &attr); + } + else + { + vlan_oid = m_defaultVlan_ObjId; /* use the default VLAN object id instead */ + } if (status != SAI_STATUS_SUCCESS) { @@ -2712,7 +2813,8 @@ bool PortsOrch::addVlan(string vlan_alias) vlan.m_vlan_info.vlan_oid = vlan_oid; vlan.m_vlan_info.vlan_id = vlan_id; vlan.m_members = set(); - m_portList[vlan_alias] = vlan; + setPort(vlan_alias, vlan); + portOidToName[vlan_oid] = vlan_alias; m_port_ref_count[vlan_alias] = 0; return true; @@ -2721,6 +2823,7 @@ bool PortsOrch::addVlan(string vlan_alias) bool PortsOrch::removeVlan(Port vlan) { SWSS_LOG_ENTER(); + if (m_port_ref_count[vlan.m_alias] > 0) { SWSS_LOG_ERROR("Failed to remove ref count %d VLAN %s", @@ -2728,6 +2831,12 @@ bool PortsOrch::removeVlan(Port vlan) vlan.m_alias.c_str()); return false; } + /* If there are still fdb entries associated with the VLAN, + return false for retry */ + if (vlan.m_fdb_count > 0) + { + return false; + } /* Vlan removing is not allowed when the VLAN still has members */ if (vlan.m_members.size() > 0) @@ -2736,12 +2845,16 @@ bool PortsOrch::removeVlan(Port vlan) return false; } - sai_status_t status = sai_vlan_api->remove_vlan(vlan.m_vlan_info.vlan_oid); - if (status != SAI_STATUS_SUCCESS) + /* Do not delete default VLAN from driver, but clear internal state */ + if (vlan.m_vlan_info.vlan_id != m_defaultVlan_Id) { + sai_status_t status = sai_vlan_api->remove_vlan(vlan.m_vlan_info.vlan_oid); + if (status != SAI_STATUS_SUCCESS) + { SWSS_LOG_ERROR("Failed to remove VLAN %s vid:%hu", vlan.m_alias.c_str(), vlan.m_vlan_info.vlan_id); return false; + } } removeAclTableGroup(vlan); @@ -2749,7 +2862,8 @@ bool PortsOrch::removeVlan(Port vlan) SWSS_LOG_NOTICE("Remove VLAN %s vid:%hu", vlan.m_alias.c_str(), vlan.m_vlan_info.vlan_id); - m_portList.erase(vlan.m_alias); + portOidToName.erase(vlan.m_vlan_info.vlan_oid); + erasePort(vlan.m_alias); m_port_ref_count.erase(vlan.m_alias); return true; @@ -2759,14 +2873,17 @@ bool PortsOrch::getVlanByVlanId(sai_vlan_id_t vlan_id, Port &vlan) { SWSS_LOG_ENTER(); + std::unique_lock lock(g_orchmutex); for (auto &it: m_portList) { if (it.second.m_type == Port::VLAN && it.second.m_vlan_info.vlan_id == vlan_id) { vlan = it.second; + std::unique_lock unlock(g_orchmutex); return true; } } + std::unique_lock unlock(g_orchmutex); return false; } @@ -2819,11 +2936,20 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode) } /* a physical port may join multiple vlans */ - VlanMemberEntry vme = {vlan_member_id, sai_tagging_mode}; + VlanMemberEntry vme = {vlan.m_alias, vlan_member_id, sai_tagging_mode}; port.m_vlan_members[vlan.m_vlan_info.vlan_id] = vme; - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); vlan.m_members.insert(port.m_alias); - m_portList[vlan.m_alias] = vlan; + if (port.m_oper_status == SAI_PORT_OPER_STATUS_UP) + { + auto old_count = vlan.m_up_member_count; + vlan.m_up_member_count++; + if (old_count == 0) + { + updateDbVlanOperStatus(vlan, "up"); + } + } + setPort(vlan.m_alias, vlan); VlanMemberUpdate update = { vlan, port, true }; notify(SUBJECT_TYPE_VLAN_MEMBER_CHANGE, static_cast(&update)); @@ -2858,15 +2984,23 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port) /* Restore to default pvid if this port joined this VLAN in untagged mode previously */ if (sai_tagging_mode == SAI_VLAN_TAGGING_MODE_UNTAGGED) { - if (!setPortPvid(port, DEFAULT_PORT_VLAN_ID)) + if (!setPortPvid(port, 0)) { return false; } } - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); vlan.m_members.erase(port.m_alias); - m_portList[vlan.m_alias] = vlan; + if (port.m_oper_status == SAI_PORT_OPER_STATUS_UP) + { + vlan.m_up_member_count--; + if (vlan.m_up_member_count == 0) + { + updateDbVlanOperStatus(vlan, "down"); + } + } + setPort(vlan.m_alias, vlan); VlanMemberUpdate update = { vlan, port, false }; notify(SUBJECT_TYPE_VLAN_MEMBER_CHANGE, static_cast(&update)); @@ -2878,6 +3012,17 @@ bool PortsOrch::addLag(string lag_alias) { SWSS_LOG_ENTER(); + Port lagport; + if (getPort(lag_alias, lagport)) + { + if ((lagport.m_bridge_port_id != SAI_NULL_OBJECT_ID) && + (lagport.m_vlan_members.empty())) + { + return false; + } + return true; + } + sai_object_id_t lag_id; sai_status_t status = sai_lag_api->create_lag(&lag_id, gSwitchId, 0, NULL); @@ -2892,7 +3037,8 @@ bool PortsOrch::addLag(string lag_alias) Port lag(lag_alias, Port::LAG); lag.m_lag_id = lag_id; lag.m_members = set(); - m_portList[lag_alias] = lag; + setPort(lag_alias, lag); + portOidToName[lag_id] = lag_alias; m_port_ref_count[lag_alias] = 0; /* Add lag name map to counter table */ @@ -2930,6 +3076,10 @@ bool PortsOrch::removeLag(Port lag) SWSS_LOG_ERROR("Failed to remove LAG %s, it is still in VLAN", lag.m_alias.c_str()); return false; } + if (lag.m_bridge_port_id != SAI_NULL_OBJECT_ID) + { + return false; + } sai_status_t status = sai_lag_api->remove_lag(lag.m_lag_id); if (status != SAI_STATUS_SUCCESS) @@ -2940,12 +3090,13 @@ bool PortsOrch::removeLag(Port lag) removeAclTableGroup(lag); - SWSS_LOG_NOTICE("Remove LAG %s lid:%" PRIx64, lag.m_alias.c_str(), lag.m_lag_id); + SWSS_LOG_NOTICE("Remove LAG %s lid:%lx", lag.m_alias.c_str(), lag.m_lag_id); /* Remove LAG name map from counter table */ m_counterTable->hdel("",lag.m_alias.c_str()); - m_portList.erase(lag.m_alias); + portOidToName.erase(lag.m_lag_id); + erasePort(lag.m_alias); m_port_ref_count.erase(lag.m_alias); PortUpdate update = { lag, false }; @@ -3005,10 +3156,10 @@ bool PortsOrch::addLagMember(Port &lag, Port &port) port.m_lag_id = lag.m_lag_id; port.m_lag_member_id = lag_member_id; - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); lag.m_members.insert(port.m_alias); - m_portList[lag.m_alias] = lag; + setPort(lag.m_alias, lag); if (lag.m_bridge_port_id > 0) { @@ -3042,9 +3193,9 @@ bool PortsOrch::removeLagMember(Port &lag, Port &port) port.m_lag_id = 0; port.m_lag_member_id = 0; - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); lag.m_members.erase(port.m_alias); - m_portList[lag.m_alias] = lag; + setPort(lag.m_alias, lag); if (lag.m_bridge_port_id > 0) { @@ -3068,6 +3219,7 @@ void PortsOrch::generateQueueMap() return; } + std::unique_lock lock(g_orchmutex); for (const auto& it: m_portList) { if (it.second.m_type == Port::PHY) @@ -3075,6 +3227,7 @@ void PortsOrch::generateQueueMap() generateQueueMapPerPort(it.second); } } + std::unique_lock unlock(g_orchmutex); m_isQueueMapGenerated = true; } @@ -3154,6 +3307,7 @@ void PortsOrch::generatePriorityGroupMap() return; } + std::unique_lock lock(g_orchmutex); for (const auto& it: m_portList) { if (it.second.m_type == Port::PHY) @@ -3161,6 +3315,7 @@ void PortsOrch::generatePriorityGroupMap() generatePriorityGroupMapPerPort(it.second); } } + std::unique_lock unlock(g_orchmutex); m_isPriorityGroupMapGenerated = true; } @@ -3254,7 +3409,7 @@ void PortsOrch::doTask(NotificationConsumer &consumer) updatePortOperStatus(port, status); /* update m_portList */ - m_portList[port.m_alias] = port; + setPort(port.m_alias, port); } sai_deserialize_free_port_oper_status_ntf(count, portoperstatus); @@ -3275,6 +3430,26 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status) port.m_oper_status = status; bool isUp = status == SAI_PORT_OPER_STATUS_UP; + + for(auto vlan_member: port.m_vlan_members) + { + Port Vlan; + getPort(vlan_member.second.alias, Vlan); + auto old_count = Vlan.m_up_member_count; + isUp ? Vlan.m_up_member_count++ : Vlan.m_up_member_count--; + if (Vlan.m_up_member_count == 0) + { + updateDbVlanOperStatus(Vlan, "down"); + } + else if ((old_count == 0) && (Vlan.m_up_member_count == 1)) + { + updateDbVlanOperStatus(Vlan, "up"); + } + SWSS_LOG_NOTICE("Vlan %s Port %s state %s m_up_member_count %d", + vlan_member.second.alias.c_str(), port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), Vlan.m_up_member_count); + + setPort(Vlan.m_alias, Vlan); + } if (!setHostIntfsOperStatus(port, isUp)) { SWSS_LOG_ERROR("Failed to set host interface %s operational status %s", port.m_alias.c_str(), @@ -3284,6 +3459,47 @@ 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()); } + /* flush all dynamic FDB on this port */ + if (status == SAI_PORT_OPER_STATUS_DOWN) + { + gFdbOrch->flushFdbByPort(port.m_alias, 0); + } +} + +void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) +{ + if (status == port.m_oper_status) + { + return ; + } + SWSS_LOG_NOTICE("Port %s oper state set from %s to %s", + port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), + oper_status_strings.at(status).c_str()); + + port.m_oper_status = status; + setPort(port.m_alias, port); + + bool isUp = status == SAI_PORT_OPER_STATUS_UP; + + for(auto vlan_member: port.m_vlan_members) + { + Port Vlan; + getPort(vlan_member.second.alias, Vlan); + auto old_count = Vlan.m_up_member_count; + isUp ? Vlan.m_up_member_count++ : Vlan.m_up_member_count--; + if (Vlan.m_up_member_count == 0) + { + updateDbVlanOperStatus(Vlan, "down"); + } + else if ((old_count == 0) && (Vlan.m_up_member_count == 1)) + { + updateDbVlanOperStatus(Vlan, "up"); + } + SWSS_LOG_NOTICE("Vlan %s Port %s state %s m_up_member_count %d", + vlan_member.second.alias.c_str(), port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), Vlan.m_up_member_count); + + setPort(Vlan.m_alias, Vlan); + } } /* @@ -3301,6 +3517,7 @@ void PortsOrch::refreshPortStatus() { SWSS_LOG_ENTER(); + std::unique_lock lock(g_orchmutex); for (auto &it: m_portList) { auto &port = it.second; @@ -3312,12 +3529,14 @@ void PortsOrch::refreshPortStatus() sai_port_oper_status_t status; if (!getPortOperStatus(port, status)) { + std::unique_lock unlock(g_orchmutex); throw runtime_error("PortsOrch get port oper status failure"); } SWSS_LOG_INFO("%s oper status is %s", port.m_alias.c_str(), oper_status_strings.at(status).c_str()); updatePortOperStatus(port, status); } + std::unique_lock unlock(g_orchmutex); } bool PortsOrch::getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index d2819e62ea..fc2182bb58 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -9,6 +9,7 @@ #include "observer.h" #include "macaddress.h" #include "producertable.h" +#include "notificationproducer.h" #define FCS_LEN 4 #define VLAN_TAG_LEN 4 @@ -69,12 +70,14 @@ class PortsOrch : public Orch, public Subject void decreasePortRefCount(const string &alias); bool getPortByBridgePortId(sai_object_id_t bridge_port_id, Port &port); void setPort(string alias, Port port); + void erasePort(string alias); void getCpuPort(Port &port); bool getVlanByVlanId(sai_vlan_id_t vlan_id, Port &vlan); bool getAclBindPortId(string alias, sai_object_id_t &port_id); bool setHostIntfsOperStatus(const Port& port, bool up) const; void updateDbPortOperStatus(const Port& port, sai_port_oper_status_t status) const; + void updateDbVlanOperStatus(const Port& port, string status) const; bool createBindAclTableGroup(sai_object_id_t id, sai_object_id_t &group_oid, acl_stage_type_t acl_stage = ACL_STAGE_EGRESS); bool bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_object_id_t &group_member_oid, acl_stage_type_t acl_stage = ACL_STAGE_INGRESS); @@ -89,6 +92,7 @@ class PortsOrch : public Orch, public Subject private: unique_ptr
m_counterTable; unique_ptr
m_portTable; + unique_ptr
m_vlanTable; unique_ptr
m_queueTable; unique_ptr
m_queuePortTable; unique_ptr
m_queueIndexTable; @@ -98,6 +102,7 @@ class PortsOrch : public Orch, public Subject unique_ptr
m_pgIndexTable; unique_ptr m_flexCounterTable; unique_ptr m_flexCounterGroupTable; + NotificationProducer* notifications; std::string getQueueFlexCounterTableKey(std::string s); std::string getQueueWatermarkFlexCounterTableKey(std::string s); @@ -113,15 +118,21 @@ class PortsOrch : public Orch, public Subject Port m_cpuPort; // TODO: Add Bridge/Vlan class sai_object_id_t m_default1QBridge; - sai_object_id_t m_defaultVlan; + sai_object_id_t m_defaultVlan_ObjId; + sai_vlan_id_t m_defaultVlan_Id; bool m_portConfigDone = false; sai_uint32_t m_portCount; map, sai_object_id_t> m_portListLaneMap; map, tuple> m_lanesAliasSpeedMap; map m_portList; - map m_port_ref_count; + /* mapping from SAI object ID to Name for faster + retrieval of Port/VLAN from object ID for events + coming from SAI + */ + unordered_map portOidToName; + map m_port_ref_count; unordered_set m_pendingPortSet; NotificationConsumer* m_portStatusNotificationConsumer; @@ -197,6 +208,7 @@ class PortsOrch : public Orch, public Subject bool setPortSerdesAttribute(sai_object_id_t port_id, sai_attr_id_t attr_id, vector &serdes_val); + void updateLagOperStatus(Port &port, sai_port_oper_status_t status); }; #endif /* SWSS_PORTSORCH_H */ From 80a91a5d7b3567d7dd3ca533326d8252876d1bf3 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 7 Sep 2019 19:01:33 -0700 Subject: [PATCH 04/24] Layer 2 Forwarding Enhancements Layer 2 Forwarding Enhancements --- orchagent/portsorch.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index f0d9cccc8c..32ef4ff858 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -1459,7 +1459,8 @@ bool PortsOrch::bake() vector tuples; string value; bool foundPortConfigDone = m_portTable->hget("PortConfigDone", "count", value); - unsigned long portCount; + uintmax_t portCount; + char* endPtr = NULL; SWSS_LOG_NOTICE("foundPortConfigDone = %d", foundPortConfigDone); bool foundPortInitDone = m_portTable->get("PortInitDone", tuples); @@ -1476,12 +1477,12 @@ bool PortsOrch::bake() return false; } - portCount = stoul(value); - SWSS_LOG_NOTICE("portCount = %" PRIu64 ", m_portCount = %u", portCount, m_portCount); + portCount = strtoumax(value.c_str(), &endPtr, 0); + SWSS_LOG_NOTICE("portCount = %" PRIuMAX ", m_portCount = %u", portCount, m_portCount); if (portCount != keys.size() - 2) { // Invalid port table - SWSS_LOG_ERROR("Invalid port table: portCount, expecting %" PRIu64 ", got %" PRIu64, + SWSS_LOG_ERROR("Invalid port table: portCount, expecting %" PRIuMAX ", got %zu", portCount, keys.size() - 2); cleanPortTable(keys); From 0398cc881267cf05ee4dd8a48edc9787b77e5dda Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 7 Sep 2019 21:01:33 -0700 Subject: [PATCH 05/24] Layer 2 Forwarding Enhancements Layer 2 Forwarding Enhancements --- tests/test_fdb_clear_all.py | 92 +++ tests/test_fdb_clear_port.py | 92 +++ tests/test_fdb_clear_vlan.py | 92 +++ tests/test_fdb_dynamic_mac_add.py | 90 +++ tests/test_fdb_dynamic_mac_del.py | 93 +++ tests/test_fdb_flush_port_vlan_remove.py | 91 +++ tests/test_fdb_mac_readd_port_vlan_add.py | 86 +++ tests/test_fdb_negative.py | 627 ++++++++++++++++++++ tests/test_fdb_no_flush_static_port_down.py | 92 +++ tests/test_fdb_static_mac_add.py | 72 +++ tests/test_fdb_static_mac_del.py | 76 +++ 11 files changed, 1503 insertions(+) create mode 100644 tests/test_fdb_clear_all.py create mode 100644 tests/test_fdb_clear_port.py create mode 100644 tests/test_fdb_clear_vlan.py create mode 100644 tests/test_fdb_dynamic_mac_add.py create mode 100644 tests/test_fdb_dynamic_mac_del.py create mode 100644 tests/test_fdb_flush_port_vlan_remove.py create mode 100644 tests/test_fdb_mac_readd_port_vlan_add.py create mode 100644 tests/test_fdb_negative.py create mode 100644 tests/test_fdb_no_flush_static_port_down.py create mode 100644 tests/test_fdb_static_mac_add.py create mode 100644 tests/test_fdb_static_mac_del.py diff --git a/tests/test_fdb_clear_all.py b/tests/test_fdb_clear_all.py new file mode 100644 index 0000000000..d32db2185c --- /dev/null +++ b/tests/test_fdb_clear_all.py @@ -0,0 +1,92 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBClearAll(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + # check that the FDB entry was flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not flushed" + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_clear_port.py b/tests/test_fdb_clear_port.py new file mode 100644 index 0000000000..c8568c6c36 --- /dev/null +++ b/tests/test_fdb_clear_port.py @@ -0,0 +1,92 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBClearPort(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.runcmd("sonic-clear fdb port Ethernet0") + time.sleep(2) + # check that the FDB entry was flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not flushed" + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_clear_vlan.py b/tests/test_fdb_clear_vlan.py new file mode 100644 index 0000000000..0bb99ae1ee --- /dev/null +++ b/tests/test_fdb_clear_vlan.py @@ -0,0 +1,92 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBClearVlan(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.runcmd("sonic-clear fdb vlan Vlan2") + time.sleep(2) + # check that the FDB entry was flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not flushed" + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_dynamic_mac_add.py b/tests/test_fdb_dynamic_mac_add.py new file mode 100644 index 0000000000..83898e5304 --- /dev/null +++ b/tests/test_fdb_dynamic_mac_add.py @@ -0,0 +1,90 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion +import pytest + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +@pytest.mark.dev_sanity +def test_FDBAddDynamic(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_dynamic_mac_del.py b/tests/test_fdb_dynamic_mac_del.py new file mode 100644 index 0000000000..c4ce510022 --- /dev/null +++ b/tests/test_fdb_dynamic_mac_del.py @@ -0,0 +1,93 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion +import pytest + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +@pytest.mark.dev_sanity +def test_FDBDelDynamic(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + time.sleep(2) + # check that the FDB entry was deleted from ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not deleted" + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_flush_port_vlan_remove.py b/tests/test_fdb_flush_port_vlan_remove.py new file mode 100644 index 0000000000..21fa3d5a43 --- /dev/null +++ b/tests/test_fdb_flush_port_vlan_remove.py @@ -0,0 +1,91 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBFlushPortRemoveVlan(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.remove_vlan_member("2", "Ethernet0") + time.sleep(2) + # check that the FDB entry was flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not flushed" + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_mac_readd_port_vlan_add.py b/tests/test_fdb_mac_readd_port_vlan_add.py new file mode 100644 index 0000000000..4e5fda4a5b --- /dev/null +++ b/tests/test_fdb_mac_readd_port_vlan_add.py @@ -0,0 +1,86 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBReaddPortAddedBackToVlan(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a static FDB entry + dvs.runcmd("config mac add 52:54:00:25:06:E9 2 Ethernet0") + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.remove_vlan_member("2", "Ethernet0") + time.sleep(2) + # check that the FDB entry was flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry was not flushed" + dvs.create_vlan_member("2", "Ethernet0") + time.sleep(2) + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") != 0, "The fdb entry wasn't inserted to ASIC" + dvs.runcmd("config mac del 52:54:00:25:06:E9 2") + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_negative.py b/tests/test_fdb_negative.py new file mode 100644 index 0000000000..15a4a5d5b8 --- /dev/null +++ b/tests/test_fdb_negative.py @@ -0,0 +1,627 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +import pytest +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def remove_entry_tbl(db, table, key): + tbl = swsscommon.Table(db, table) + tbl._del(key) + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_negativeFDB(dvs, testlog): + dvs.setup_db() + + #dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + #Find switch_id + switch_id = dvs.getSwitchOid() + print("Switch_id="+str(switch_id)) + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + dvs.create_vlan_member("2", "Ethernet4") + # Find the vlan_oid_2 to be used in DB communications + vlan_oid_2 = dvs.getVlanOid("2") + assert vlan_oid_2 is not None, "Could not find Vlan_oid" + print("VLan-2 vlan_oid="+str(vlan_oid_2)) + + + # create vlan + dvs.create_vlan("4") + dvs.create_vlan_member("4", "Ethernet8") + # Find the vlan_oid_4 to be used in DB communications + vlan_oid_4 = dvs.getVlanOid("4") + assert vlan_oid_4 is not None, "Could not find Vlan_oid" + print("VLan-4 vlan_oid="+str(vlan_oid_4)) + + + dvs.create_vlan("10") + dvs.create_vlan_member("10", "Ethernet12") + # Find the vlan_oid_10 to be used in DB communications + vlan_oid_10 = dvs.getVlanOid("10") + assert vlan_oid_10 is not None, "Could not find Vlan_oid" + print("VLan-10 vlan_oid="+str(vlan_oid_10)) + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 3, "The Vlan2/Vlan4 wasn't created" + assert bp_after - bp_before == 4, "The bridge port wasn't created" + assert vm_after - vm_before == 4, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + #dvs.runcmd("swssloglevel -l DEBUG -c orchagent") + #dvs.runcmd("swssloglevel -l DEBUG -c vlanmgrd") + + print("NEG1 - Add MAC address to an out of range vlan and later delete it") + mac = "52:54:00:25:06:E9" + #dvs.runcmd("config mac add " + mac.lower() + " 3 Ethernet0") + print("ACTION: Creating static FDB Vlan33333|"+mac.lower()+"|Ethernet0 in CONFIG-DB") + create_entry_tbl( + dvs.cdb, + "FDB", "Vlan33333|"+mac.lower(), + [ + ("port", "Ethernet0"), + ] + ) + time.sleep(2) + + # check that the FDB entry was added in Config DB + print("CHECK: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is created in Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan33333\|"+mac.lower(), + [("port", "Ethernet0")] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is created in Config-DB") + + # check that the FDB entry was not added in APP DB + print("CHECK: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is not created in APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan33333:"+mac.lower(), + [("port", "Ethernet0"), + ("type", "static"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is not created in APP-DB") + + print("ACTION: Deleting Static FDB Vlan33333:"+mac.lower()+":Ethernet0") + remove_entry_tbl(dvs.cdb, "FDB", "Vlan33333|"+mac.lower()) + time.sleep(2) + + #Check the mac is removed from config-db + print("CHECK: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is deleted from Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan33333\|"+mac.lower(), + [("port", "Ethernet0")] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan33333:"+mac.lower()+":Ethernet0 is deleted from Config-DB") + + print("NEG2 - Add MAC address to a vlan which does not exist and later delete it") + mac = "52:54:00:25:06:E9" + #dvs.runcmd("config mac add " + mac.lower() + " 3 Ethernet0") + print("ACTION: Creating static FDB Vlan3:"+mac.lower()+":Ethernet0 in CONFIG-DB") + create_entry_tbl( + dvs.cdb, + "FDB", "Vlan3|"+mac.lower(), + [ + ("port", "Ethernet0"), + ] + ) + time.sleep(2) + + # check that the FDB entry was added in Config DB + print("CHECK: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is created in Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan3\|"+mac.lower(), + [("port", "Ethernet0")] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is created in Config-DB") + + # check that the FDB entry was added in APP DB + print("CHECK: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is created in APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan3:"+mac.lower(), + [("port", "Ethernet0"), + ("type", "static"), + ] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is created in APP-DB") + + # check that the FDB entry is not inserted into ASIC DB + print("CHECK: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is not created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", mac.lower())], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] + ) + assert ok == False, str(extra) + print("CONFIRM: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is not created in ASIC-DB") + + print("ACTION: Deleting Static FDB Vlan3:"+mac.lower()+"Ethernet0") + remove_entry_tbl(dvs.cdb, "FDB", "Vlan3|"+mac.lower()) + time.sleep(2) + + #Check the mac is removed from config-db + print("CHECK: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is deleted from Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan3\|"+mac.lower(), + [("port", "Ethernet0")] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is deleted from Config-DB") + + # check that the FDB entry is removed from APP DB + print("CHECK: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is deleted from APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan3:"+mac.lower(), + [("port", "Ethernet0"), + ("type", "static"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan3:"+mac.lower()+":Ethernet0 is deleted from APP-DB") + + + print("NEG3 - Add MAC address to an invalid port which does not exist and later delete it") + mac = "52:54:00:25:06:E9" + #dvs.runcmd("config mac add " + mac.lower() + " 3 Ethernet0") + print("ACTION: Creating static FDB Vlan2:"+mac.lower()+":Port0 in CONFIG-DB") + create_entry_tbl( + dvs.cdb, + "FDB", "Vlan2|"+mac.lower(), + [ + ("port", "Port0"), + ] + ) + time.sleep(2) + + + # check that the FDB entry was added in Config DB + print("CHECK: Static FDB Vlan2:"+mac.lower()+":Port0 is created in Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan2\|"+mac.lower(), + [("port", "Port0")] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan2:"+mac.lower()+":Port0 is created in Config-DB") + + # check that the FDB entry was added in APP DB + print("CHECK: Static FDB Vlan2:"+mac.lower()+":Port0 is created in APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan2:"+mac.lower(), + [("port", "Port0"), + ("type", "static"), + ] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan2:"+mac.lower()+"Port0 is created in APP-DB") + + # check that the FDB entry is not inserted into ASIC DB + print("CHECK: Static FDB Vlan2:"+mac.lower()+":Port0 is not created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", mac.lower())], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] + ) + assert ok == False, str(extra) + print("CONFIRM: Static FDB Vlan2:"+mac.lower()+":Port0 is not created in ASIC-DB") + + print("ACTION: Removing static FDB Vlan2:"+mac.lower()+":Port0 from CONFIG-DB") + remove_entry_tbl(dvs.cdb, "FDB", "Vlan2|"+mac.lower()) + time.sleep(2) + + + #Check the mac is removed from config-db + print("CHECK: Static FDB Vlan2:"+mac.lower()+":Port0 is deleted from Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan2\|"+mac.lower(), + [("port", "Port0")] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan2:"+mac.lower()+":Port0 is deleted from Config-DB") + + # check that the FDB entry is removed from APP DB + print("CHECK: Static FDB Vlan2:"+mac.lower()+":Port0 is deleted from APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan2:"+mac.lower(), + [("port", "Port0"), + ("type", "static"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan2:"+mac.lower()+":Port0 is deleted from APP-DB") + + print("NEG4 - simulate mac learn event for a port which is not part of vlan") + bp_eth8 = iface_2_bridge_port_id["Ethernet8"] + dvs.remove_vlan_member("4", "Ethernet8") + + print("ACTION Creating FDB Vlan4:52-54-00-25-06-E9:Ethernet8 in ASIC-DB") + create_entry_tbl( + dvs.adb, + "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_4+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}", + [ + ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth8), + ] + ) + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_4+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth8+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + # check that the FDB entry was added in ASIC DB + print("CHECK: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_4)], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth8)] + ) + assert ok, str(extra) + print("CONFIRM: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is created in ASIC-DB") + + # check that the FDB entry was not added in STATE DB + print("CHECK: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not created in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan4:52:54:00:25:06:e9", + [("port", "Ethernet8"), + ("type", "dynamic"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not created in STATE-DB") + + print("NEG5 - simulate mac learn event for a vlan which does not exist") + bp_eth12 = iface_2_bridge_port_id["Ethernet12"] + dvs.remove_vlan_member("10", "Ethernet12") + dvs.remove_vlan("10") + + print("ACTION: Creating FDB Vlan10:52-54-00-25-06-E9:Ethernet12 in ASIC-DB") + create_entry_tbl( + dvs.adb, + "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_10+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}", + [ + ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth12), + ] + ) + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_10+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + # check that the FDB entry was added in ASIC DB + print("CHECK: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_10)], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth12)] + ) + assert ok, str(extra) + print("CONFIRM: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is created in ASIC-DB") + + # check that the FDB entry was not added in STATE DB + print("CHECK: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not created in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan10:52:54:00:25:06:e9", + [("port", "Ethernet12"), + ("type", "dynamic"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not created in STATE-DB") + + + print("NEG6 - simulate mac age event for a vlan which does not exist") + + print("ACTION: Deleting FDB Vlan10:52-54-00-25-06-E9:Ethernet12 from ASIC-DB") + remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_10+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_10+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + # check that the FDB entry is not present ASIC DB + print("CHECK: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not found in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_10)], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth12)] + ) + assert ok == False, str(extra) + print("CONFIRM: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not found in ASIC-DB") + + # check that the FDB entry was not found in STATE DB + print("CHECK: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not found in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan10:52:54:00:25:06:e9", + [("port", "Ethernet12"), + ("type", "dynamic"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: FDB Vlan10:52-54-00-25-06-E9:Ethernet12 is not found in STATE-DB") + + print("NEG7 - simulate mac age event for a port which is not part of vlan") + + print("ACTION: Deleting FDB Vlan4:52-54-00-25-06-E9:Ethernet8 from ASIC-DB") + remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_4+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_4+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth8+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + # check that the FDB entry is not present ASIC DB + print("CHECK: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not found in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_4)], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth8)] + ) + assert ok == False, str(extra) + print("CONFIRM: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not found in ASIC-DB") + + # check that the FDB entry was not found in STATE DB + print("CHECK: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not found in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan4:52:54:00:25:06:e9", + [("port", "Ethernet8"), + ("type", "dynamic"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: FDB Vlan4:52-54-00-25-06-E9:Ethernet8 is not found in STATE-DB") + + + print("NEG8 - simulate mac age event for a mac which does not exist") + + bp_eth0 = iface_2_bridge_port_id["Ethernet0"] + print("ACTION: Deleting FDB Vlan2:52-54-00-25-06-E9:Ethernet0 from ASIC-DB") + remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_2+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth0+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + # check that the FDB entry is not present ASIC DB + print("CHECK: FDB Vlan2:52-54-00-25-06-E9:Ethernet0 is not found in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_2)], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth0)] + ) + assert ok == False, str(extra) + print("CONFIRM: FDB Vlan2:52-54-00-25-06-E9:Ethernet0 is not found in ASIC-DB") + + # check that the FDB entry was not found in STATE DB + print("CHECK: FDB Vlan2:52-54-00-25-06-E9:Ethernet0 is not found in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan2:52:54:00:25:06:e9", + [("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: FDB Vlan2:52-54-00-25-06-E9:Ethernet0 is not found in STATE-DB") + + + print("NEG9 - Add Static MAC M1 to Vlan V1 and Port P1; create V1; assign V1 to P1; remove V1 from P1; remove V1") + mac = "52:54:00:25:06:EF" + #dvs.runcmd("config mac add " + mac.lower() + " 10 Ethernet12") + print("ACTION: Creating static FDB Vlan10|"+mac.lower()+"|Ethernet12 in CONFIG-DB") + create_entry_tbl( + dvs.cdb, + "FDB", "Vlan10|"+mac.lower(), + [ + ("port", "Ethernet12"), + ] + ) + time.sleep(5) + + # check that the FDB entry was added in Config DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan10\|"+mac.lower(), + [("port", "Ethernet12")] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in Config-DB") + + # check that the FDB entry was added in APP DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan10:"+mac.lower(), + [("port", "Ethernet12"), + ("type", "static") + ] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in APP-DB") + + # check that the FDB entry is not inserted into ASIC DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is not created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", mac.lower())], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC")] + ) + assert ok == False, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is not created in ASIC-DB") + + dvs.create_vlan("10") + time.sleep(1) + dvs.create_vlan_member("10", "Ethernet12") + time.sleep(1) + # Find the vlan_oid_10 to be used in DB communications + vlan_oid_10 = dvs.getVlanOid("10") + assert vlan_oid_10 is not None, "Could not find Vlan_oid" + print("VLan-10 vlan_oid="+str(vlan_oid_10)) + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + bp_eth12 = iface_2_bridge_port_id["Ethernet12"] + print("bp_eth12="+str(bp_eth12)) + + print("CHECK: Static FDB Vlan10:"+mac+":Ethernet12 is created in ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", mac), ("bvid", str(vlan_oid_10))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth12)] + ) + assert ok, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac+":Ethernet12 is created in ASIC-DB") + + # check that the FDB entry was added in STATE DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan10:"+mac.lower(), + [("port", "Ethernet12"), + ("type", "static"), + ] + ) + assert mac1_found, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is created in STATE-DB") + + print("ACTION: Remove vlan member Ethernet12") + dvs.remove_vlan_member("10", "Ethernet12") + time.sleep(2) + + print("CHECK: Static FDB Vlan10:"+mac+":Ethernet12 is deleted from ASIC-DB") + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", mac), ("bvid", str(vlan_oid_10))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", bp_eth12)] + ) + assert ok == False, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac+":Ethernet12 is deleted from ASIC-DB") + + # check that the FDB entry was deleted from STATE DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from STATE-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan10:"+mac.lower(), + [("port", "Ethernet12"), + ("type", "static"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from STATE-DB") + + + print("ACTION: Remove vlan Vlan10") + dvs.remove_vlan("10") + time.sleep(2) + + print("ACTION: Remove FDB Vlan10|"+mac.lower()+" from Config DB") + remove_entry_tbl(dvs.cdb, "FDB", "Vlan10|"+mac.lower()) + time.sleep(2) + + #Check the mac is removed from config-db + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from Config-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.cdb, "FDB", + "Vlan10\|"+mac.lower(), + [("port", "Ethernet12")] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from Config-DB") + + # check that the FDB entry is removed from APP DB + print("CHECK: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from APP-DB") + mac1_found, extra = dvs.is_table_entry_exists(dvs.pdb, "FDB_TABLE", + "Vlan10:"+mac.lower(), + [("port", "Ethernet12"), + ("type", "static"), + ] + ) + assert mac1_found == False, str(extra) + print("CONFIRM: Static FDB Vlan10:"+mac.lower()+":Ethernet12 is deleted from APP-DB") + + print("NEG10 - Received move event with invalid bridge-port") + # Move a FDB entry in ASIC DB + print("Action: Creating FDB Vlan2:52-54-00-25-06-EB:Ethernet0 in ASIC-DB") + create_entry_tbl( + dvs.adb, + "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_2+"\",\"mac\":\"52:54:00:25:06:EB\",\"switch_id\":\""+switch_id+"\"}", + [ + ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:EB\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+iface_2_bridge_port_id["Ethernet0"]+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + print("Action: Moving FDB Vlan2:52-54-00-25-06-EB:Ethernet0 to non-existing bridge-port Ethernet12") + ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + fvp = swsscommon.FieldValuePairs() + ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:EB\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_MOVE\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" + ntf.send("fdb_event", ntf_data, fvp) + + time.sleep(2) + + print("CHECK: FDB Vlan2:52-54-00-25-06-EB is not Moved in STATE-DB") + # check that the FDB entry was not moved in STATE DB + mac2_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", + "Vlan2:52:54:00:25:06:eb", + [("port", "Ethernet0"), + ("type", "dynamic"), + ] + ) + assert mac2_found, str(extra) + print("CONFIRM: FDB Vlan2:52-54-00-25-06-EB is not Moved in STATE-DB") + + #raw_input("Check at the end") + + dvs.runcmd("sonic-clear fdb all") + time.sleep(10) + + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan_member("2", "Ethernet4") + dvs.remove_vlan("2") + dvs.remove_vlan("4") + diff --git a/tests/test_fdb_no_flush_static_port_down.py b/tests/test_fdb_no_flush_static_port_down.py new file mode 100644 index 0000000000..520401d7a4 --- /dev/null +++ b/tests/test_fdb_no_flush_static_port_down.py @@ -0,0 +1,92 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def delete_entry_pst(db, table, key): + tbl = swsscommon.ProducerStateTable(db, table) + tbl._del(key) + time.sleep(1) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBNoStaticFlushPortDown(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a FDB entry in Application DB + create_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + [ + ("port", "Ethernet0"), + ("type", "static"), + ] + ) + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.runcmd("config interface shutdown Ethernet0") + time.sleep(2) + # check that the FDB entry was not flushed + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") != 0, "The fdb entry was flushed" + delete_entry_pst( + dvs.pdb, + "FDB_TABLE", "Vlan2:52-54-00-25-06-E9", + ) + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_static_mac_add.py b/tests/test_fdb_static_mac_add.py new file mode 100644 index 0000000000..80caf095e6 --- /dev/null +++ b/tests/test_fdb_static_mac_add.py @@ -0,0 +1,72 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBAddStatic(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a static FDB entry + dvs.runcmd("config mac add 52:54:00:25:06:E9 2 Ethernet0") + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + diff --git a/tests/test_fdb_static_mac_del.py b/tests/test_fdb_static_mac_del.py new file mode 100644 index 0000000000..b1b56bb896 --- /dev/null +++ b/tests/test_fdb_static_mac_del.py @@ -0,0 +1,76 @@ +from swsscommon import swsscommon +import os +import sys +import time +import json +from distutils.version import StrictVersion + +def create_entry(tbl, key, pairs): + fvs = swsscommon.FieldValuePairs(pairs) + tbl.set(key, fvs) + + # FIXME: better to wait until DB create them + time.sleep(1) + +def create_entry_tbl(db, table, key, pairs): + tbl = swsscommon.Table(db, table) + create_entry(tbl, key, pairs) + +def create_entry_pst(db, table, key, pairs): + tbl = swsscommon.ProducerStateTable(db, table) + create_entry(tbl, key, pairs) + +def how_many_entries_exist(db, table): + tbl = swsscommon.Table(db, table) + return len(tbl.getKeys()) + +def test_FDBDelStatic(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + time.sleep(2) + + # create a static FDB entry + dvs.runcmd("config mac add 52:54:00:25:06:E9 2 Ethernet0") + + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + + vlan_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_before = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + # create vlan + dvs.create_vlan("2") + dvs.create_vlan_member("2", "Ethernet0") + + # check that the vlan information was propagated + vlan_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + bp_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") + vm_after = how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") + + assert vlan_after - vlan_before == 1, "The Vlan2 wasn't created" + assert bp_after - bp_before == 1, "The bridge port wasn't created" + assert vm_after - vm_before == 1, "The vlan member wasn't added" + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # check that the FDB entry was inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 1, "The fdb entry wasn't inserted to ASIC" + + ok, extra = dvs.is_fdb_entry_exists(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", + [("mac", "52:54:00:25:06:E9"), ("bvid", str(dvs.getVlanOid("2")))], + [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), + ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] + ) + + assert ok, str(extra) + + dvs.runcmd("config mac del 52:54:00:25:06:E9 2") + time.sleep(2) + # check that the FDB entry wasn't inserted into ASIC DB + assert how_many_entries_exist(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY") == 0, "The fdb entry leaked to ASIC" + dvs.remove_vlan_member("2", "Ethernet0") + dvs.remove_vlan("2") + From a53a4612c8859bb681e6f60768ea42677b63995b Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 13 Sep 2019 17:26:47 -0700 Subject: [PATCH 06/24] Updated to reflect latest code changes Updated to reflect latest code changes. --- orchagent/fdborch.cpp | 32 ++++++++++ orchagent/notifications.cpp | 21 +------ orchagent/portsorch.cpp | 120 ++++++++++++++---------------------- 3 files changed, 79 insertions(+), 94 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 6ed11e02aa..9e0a09fa5e 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -525,6 +525,38 @@ void FdbOrch::doTask(NotificationConsumer& consumer) return; } } + else if (&consumer == m_fdbNotificationConsumer && op == "fdb_event") + { + uint32_t count; + sai_fdb_event_notification_data_t *fdbevent = nullptr; + extern void handle_fdb_event(_In_ const std::string &data); + + /* The sai_redis fdb handling is moved here so that both + * reference count updates (sai_redis and portsOrch) + * happen in same context to avoid any mismatch. + */ + handle_fdb_event(data); + + sai_deserialize_fdb_event_ntf(data, count, &fdbevent); + + for (uint32_t i = 0; i < count; ++i) + { + sai_object_id_t oid = SAI_NULL_OBJECT_ID; + + for (uint32_t j = 0; j < fdbevent[i].attr_count; ++j) + { + if (fdbevent[i].attr[j].id == SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID) + { + oid = fdbevent[i].attr[j].value.oid; + break; + } + } + + this->update(fdbevent[i].event_type, &fdbevent[i].fdb_entry, oid); + } + + sai_deserialize_free_fdb_event_ntf(count, fdbevent); + } } void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) diff --git a/orchagent/notifications.cpp b/orchagent/notifications.cpp index daad09b837..503a012889 100644 --- a/orchagent/notifications.cpp +++ b/orchagent/notifications.cpp @@ -4,29 +4,12 @@ extern "C" { #include "logger.h" #include "notifications.h" -#include "fdborch.h" -extern FdbOrch *gFdbOrch; void on_fdb_event(uint32_t count, sai_fdb_event_notification_data_t *fdbevent) { - //std::lock_guard lock(g_orchmutex); - - for (uint32_t i = 0; i < count; ++i) - { - sai_object_id_t oid = SAI_NULL_OBJECT_ID; - - for (uint32_t j = 0; j < fdbevent[i].attr_count; ++j) - { - if (fdbevent[i].attr[j].id == SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID) - { - oid = fdbevent[i].attr[j].value.oid; - break; - } - } - - gFdbOrch->update(fdbevent[i].event_type, &fdbevent[i].fdb_entry, oid); - } + // don't use this event handler, because it runs by libsairedis in a separate thread + // which causes concurrency access to the DB } void on_port_state_change(uint32_t count, sai_port_oper_status_notification_t *data) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 32ef4ff858..afacac53f7 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -39,7 +39,6 @@ extern NeighOrch *gNeighOrch; extern CrmOrch *gCrmOrch; extern BufferOrch *gBufferOrch; extern FdbOrch *gFdbOrch; -std::recursive_mutex g_orchmutex; #define VLAN_PREFIX "Vlan" @@ -429,16 +428,13 @@ bool PortsOrch::getPort(string alias, Port &p) { SWSS_LOG_ENTER(); - std::unique_lock lock(g_orchmutex); if (m_portList.find(alias) == m_portList.end()) { - std::unique_lock unlock(g_orchmutex); return false; } else { p = m_portList[alias]; - std::unique_lock unlock(g_orchmutex); return true; } } @@ -527,16 +523,7 @@ bool PortsOrch::getAclBindPortId(string alias, sai_object_id_t &port_id) void PortsOrch::setPort(string alias, Port p) { - std::unique_lock lock(g_orchmutex); m_portList[alias] = p; - std::unique_lock unlock(g_orchmutex); -} - -void PortsOrch::erasePort(string alias) -{ - std::unique_lock lock(g_orchmutex); - m_portList.erase(alias); - std::unique_lock unlock(g_orchmutex); } void PortsOrch::getCpuPort(Port &port) @@ -679,7 +666,7 @@ bool PortsOrch::setPortPfc(sai_object_id_t portId, uint8_t pfc_bitmask) if (p.m_pfc_bitmask != pfc_bitmask) { p.m_pfc_bitmask = pfc_bitmask; - setPort(p.m_alias, p); + m_portList[p.m_alias] = p; } return true; @@ -712,7 +699,7 @@ bool PortsOrch::setPortPfcAsym(Port &port, string pfc_asym) } port.m_pfc_asym = new_pfc_asym; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; attr.id = SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_MODE; attr.value.s32 = (int32_t) port.m_pfc_asym; @@ -1384,29 +1371,25 @@ bool PortsOrch::initPort(const string &alias, const set &lane_set) /* Determine if the lane combination exists in switch */ if (m_portListLaneMap.find(lane_set) != m_portListLaneMap.end()) { - Port port; sai_object_id_t id = m_portListLaneMap[lane_set]; /* Determine if the port has already been initialized before */ - auto port_found = getPort(alias, port); - if (port_found && (port.m_port_id == id)) { + if (m_portList.find(alias) != m_portList.end() && m_portList[alias].m_port_id == id) + { SWSS_LOG_INFO("Port has already been initialized before alias:%s", alias.c_str()); } else { Port p(alias, Port::PHY); - { - std::unique_lock lock(g_orchmutex); - p.m_index = static_cast(m_portList.size()); // TODO: Assume no deletion of physical port - std::unique_lock unlock(g_orchmutex); - p.m_port_id = id; - } + p.m_index = static_cast(m_portList.size()); // TODO: Assume no deletion of physical port + p.m_port_id = id; + /* Initialize the port and create corresponding host interface */ if (initializePort(p)) { /* Add port to port list */ - setPort(alias, p); + m_portList[alias] = p; portOidToName[id] = alias; m_port_ref_count[alias] = 0; /* Add port name map to counter table */ @@ -1745,7 +1728,7 @@ void PortsOrch::doPortTask(Consumer &consumer) { SWSS_LOG_NOTICE("Set port %s AutoNeg to %u", alias.c_str(), an); p.m_autoneg = an; - setPort(alias, p); + m_portList[alias] = p; // Once AN is changed // - no speed specified: need to reapply the port speed or port adv speed accordingly @@ -1781,7 +1764,7 @@ void PortsOrch::doPortTask(Consumer &consumer) */ if (speed != 0 && speed != p.m_speed) { - setPort(alias, p); + m_portList[alias] = p; if (p.m_autoneg) { @@ -1815,7 +1798,7 @@ void PortsOrch::doPortTask(Consumer &consumer) } p.m_admin_state_up = false; - setPort(alias, p); + m_portList[alias] = p; if (!setPortSpeed(p.m_port_id, speed)) { @@ -1837,7 +1820,7 @@ void PortsOrch::doPortTask(Consumer &consumer) SWSS_LOG_NOTICE("Set port %s speed to %u", alias.c_str(), speed); } p.m_speed = speed; - setPort(alias, p); + m_portList[alias] = p; } if (mtu != 0 && mtu != p.m_mtu) @@ -1845,7 +1828,7 @@ void PortsOrch::doPortTask(Consumer &consumer) if (setPortMtu(p.m_port_id, mtu)) { p.m_mtu = mtu; - setPort(alias, p); + m_portList[alias] = p; SWSS_LOG_NOTICE("Set port %s MTU to %u", alias.c_str(), mtu); if (p.m_rif_id) { @@ -1870,7 +1853,7 @@ void PortsOrch::doPortTask(Consumer &consumer) p.m_fec_mode = fec_mode_map[fec_mode]; if (setPortFec(p.m_port_id, p.m_fec_mode)) { - setPort(alias, p); + m_portList[alias] = p; SWSS_LOG_NOTICE("Set port %s fec to %s", alias.c_str(), fec_mode.c_str()); } else @@ -1952,7 +1935,7 @@ void PortsOrch::doPortTask(Consumer &consumer) if (setPortAdminStatus(p.m_port_id, admin_status == "up")) { p.m_admin_state_up = (admin_status == "up"); - setPort(alias, p); + m_portList[alias] = p; SWSS_LOG_NOTICE("Set port %s admin status to %s", alias.c_str(), admin_status.c_str()); } else @@ -2001,7 +1984,6 @@ void PortsOrch::doVlanTask(Consumer &consumer) if (op == SET_COMMAND) { - Port vlan; // Retrieve attributes uint32_t mtu = 0; for (auto i : kfvFieldsValues(t)) @@ -2017,7 +1999,7 @@ void PortsOrch::doVlanTask(Consumer &consumer) * We may add support for VLAN mac learning enable/disable, * VLAN flooding control setting and etc. in the future. */ - if (!getPort(vlan_alias, vlan)) + if (m_portList.find(vlan_alias) == m_portList.end()) { if (!addVlan(vlan_alias)) { @@ -2037,7 +2019,7 @@ void PortsOrch::doVlanTask(Consumer &consumer) if (mtu != 0) { vl.m_mtu = mtu; - setPort(vlan_alias, vl); + m_portList[vlan_alias] = vl; if (vl.m_rif_id) { gIntfsOrch->setRouterIntfsMtu(vl); @@ -2224,7 +2206,7 @@ void PortsOrch::doLagTask(Consumer &consumer) if ((mtu != 0) && (mtu != l.m_mtu)) { l.m_mtu = mtu; - setPort(alias, l); + m_portList[alias] = l; if (l.m_rif_id) { gIntfsOrch->setRouterIntfsMtu(l); @@ -2651,7 +2633,7 @@ bool PortsOrch::addBridgePort(Port &port) return false; } port.m_bridge_port_admin_state = true; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_KEEP)) { SWSS_LOG_ERROR("Failed to set %s for hostif of port %s", @@ -2717,7 +2699,7 @@ bool PortsOrch::addBridgePort(Port &port) hostif_vlan_tag[SAI_HOSTIF_VLAN_TAG_KEEP], port.m_alias.c_str()); return false; } - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; portOidToName[port.m_bridge_port_id] = port.m_alias; SWSS_LOG_NOTICE("Add bridge port %s to default 1Q bridge", port.m_alias.c_str()); @@ -2748,7 +2730,7 @@ bool PortsOrch::removeBridgePort(Port &port) return false; } port.m_bridge_port_admin_state = false; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_STRIP)) { @@ -2776,7 +2758,7 @@ bool PortsOrch::removeBridgePort(Port &port) SWSS_LOG_NOTICE("Remove bridge port %s from default 1Q bridge", port.m_alias.c_str()); - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; return true; } @@ -2814,7 +2796,7 @@ bool PortsOrch::addVlan(string vlan_alias) vlan.m_vlan_info.vlan_oid = vlan_oid; vlan.m_vlan_info.vlan_id = vlan_id; vlan.m_members = set(); - setPort(vlan_alias, vlan); + m_portList[vlan_alias] = vlan; portOidToName[vlan_oid] = vlan_alias; m_port_ref_count[vlan_alias] = 0; @@ -2864,7 +2846,7 @@ bool PortsOrch::removeVlan(Port vlan) vlan.m_vlan_info.vlan_id); portOidToName.erase(vlan.m_vlan_info.vlan_oid); - erasePort(vlan.m_alias); + m_portList.erase(vlan.m_alias); m_port_ref_count.erase(vlan.m_alias); return true; @@ -2874,17 +2856,14 @@ bool PortsOrch::getVlanByVlanId(sai_vlan_id_t vlan_id, Port &vlan) { SWSS_LOG_ENTER(); - std::unique_lock lock(g_orchmutex); for (auto &it: m_portList) { if (it.second.m_type == Port::VLAN && it.second.m_vlan_info.vlan_id == vlan_id) { vlan = it.second; - std::unique_lock unlock(g_orchmutex); return true; } } - std::unique_lock unlock(g_orchmutex); return false; } @@ -2939,7 +2918,7 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode) /* a physical port may join multiple vlans */ VlanMemberEntry vme = {vlan.m_alias, vlan_member_id, sai_tagging_mode}; port.m_vlan_members[vlan.m_vlan_info.vlan_id] = vme; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; vlan.m_members.insert(port.m_alias); if (port.m_oper_status == SAI_PORT_OPER_STATUS_UP) { @@ -2950,7 +2929,7 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode) updateDbVlanOperStatus(vlan, "up"); } } - setPort(vlan.m_alias, vlan); + m_portList[vlan.m_alias] = vlan; VlanMemberUpdate update = { vlan, port, true }; notify(SUBJECT_TYPE_VLAN_MEMBER_CHANGE, static_cast(&update)); @@ -2991,7 +2970,7 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port) } } - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; vlan.m_members.erase(port.m_alias); if (port.m_oper_status == SAI_PORT_OPER_STATUS_UP) { @@ -3001,7 +2980,7 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port) updateDbVlanOperStatus(vlan, "down"); } } - setPort(vlan.m_alias, vlan); + m_portList[vlan.m_alias] = vlan; VlanMemberUpdate update = { vlan, port, false }; notify(SUBJECT_TYPE_VLAN_MEMBER_CHANGE, static_cast(&update)); @@ -3013,17 +2992,17 @@ bool PortsOrch::addLag(string lag_alias) { SWSS_LOG_ENTER(); - Port lagport; - if (getPort(lag_alias, lagport)) + auto lagport = m_portList.find(lag_alias); + if (lagport != m_portList.end()) { - if ((lagport.m_bridge_port_id != SAI_NULL_OBJECT_ID) && - (lagport.m_vlan_members.empty())) + if ((m_portList[lag_alias].m_bridge_port_id != SAI_NULL_OBJECT_ID) && + (m_portList[lag_alias].m_vlan_members.empty())) { return false; } return true; } - + sai_object_id_t lag_id; sai_status_t status = sai_lag_api->create_lag(&lag_id, gSwitchId, 0, NULL); @@ -3038,7 +3017,7 @@ bool PortsOrch::addLag(string lag_alias) Port lag(lag_alias, Port::LAG); lag.m_lag_id = lag_id; lag.m_members = set(); - setPort(lag_alias, lag); + m_portList[lag_alias] = lag; portOidToName[lag_id] = lag_alias; m_port_ref_count[lag_alias] = 0; @@ -3097,7 +3076,7 @@ bool PortsOrch::removeLag(Port lag) m_counterTable->hdel("",lag.m_alias.c_str()); portOidToName.erase(lag.m_lag_id); - erasePort(lag.m_alias); + m_portList.erase(lag.m_alias); m_port_ref_count.erase(lag.m_alias); PortUpdate update = { lag, false }; @@ -3157,10 +3136,10 @@ bool PortsOrch::addLagMember(Port &lag, Port &port) port.m_lag_id = lag.m_lag_id; port.m_lag_member_id = lag_member_id; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; lag.m_members.insert(port.m_alias); - setPort(lag.m_alias, lag); + m_portList[lag.m_alias] = lag; if (lag.m_bridge_port_id > 0) { @@ -3194,9 +3173,9 @@ bool PortsOrch::removeLagMember(Port &lag, Port &port) port.m_lag_id = 0; port.m_lag_member_id = 0; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; lag.m_members.erase(port.m_alias); - setPort(lag.m_alias, lag); + m_portList[lag.m_alias] = lag; if (lag.m_bridge_port_id > 0) { @@ -3220,7 +3199,6 @@ void PortsOrch::generateQueueMap() return; } - std::unique_lock lock(g_orchmutex); for (const auto& it: m_portList) { if (it.second.m_type == Port::PHY) @@ -3228,7 +3206,6 @@ void PortsOrch::generateQueueMap() generateQueueMapPerPort(it.second); } } - std::unique_lock unlock(g_orchmutex); m_isQueueMapGenerated = true; } @@ -3308,7 +3285,6 @@ void PortsOrch::generatePriorityGroupMap() return; } - std::unique_lock lock(g_orchmutex); for (const auto& it: m_portList) { if (it.second.m_type == Port::PHY) @@ -3316,7 +3292,6 @@ void PortsOrch::generatePriorityGroupMap() generatePriorityGroupMapPerPort(it.second); } } - std::unique_lock unlock(g_orchmutex); m_isPriorityGroupMapGenerated = true; } @@ -3410,7 +3385,7 @@ void PortsOrch::doTask(NotificationConsumer &consumer) updatePortOperStatus(port, status); /* update m_portList */ - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; } sai_deserialize_free_port_oper_status_ntf(count, portoperstatus); @@ -3434,8 +3409,7 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status) for(auto vlan_member: port.m_vlan_members) { - Port Vlan; - getPort(vlan_member.second.alias, Vlan); + auto Vlan = m_portList[vlan_member.second.alias]; auto old_count = Vlan.m_up_member_count; isUp ? Vlan.m_up_member_count++ : Vlan.m_up_member_count--; if (Vlan.m_up_member_count == 0) @@ -3449,7 +3423,7 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status) SWSS_LOG_NOTICE("Vlan %s Port %s state %s m_up_member_count %d", vlan_member.second.alias.c_str(), port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), Vlan.m_up_member_count); - setPort(Vlan.m_alias, Vlan); + m_portList[Vlan.m_alias] = Vlan; } if (!setHostIntfsOperStatus(port, isUp)) { @@ -3478,14 +3452,13 @@ void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) oper_status_strings.at(status).c_str()); port.m_oper_status = status; - setPort(port.m_alias, port); + m_portList[port.m_alias] = port; bool isUp = status == SAI_PORT_OPER_STATUS_UP; for(auto vlan_member: port.m_vlan_members) { - Port Vlan; - getPort(vlan_member.second.alias, Vlan); + auto Vlan = m_portList[vlan_member.second.alias]; auto old_count = Vlan.m_up_member_count; isUp ? Vlan.m_up_member_count++ : Vlan.m_up_member_count--; if (Vlan.m_up_member_count == 0) @@ -3499,7 +3472,7 @@ void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) SWSS_LOG_NOTICE("Vlan %s Port %s state %s m_up_member_count %d", vlan_member.second.alias.c_str(), port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), Vlan.m_up_member_count); - setPort(Vlan.m_alias, Vlan); + m_portList[Vlan.m_alias] = Vlan; } } @@ -3518,7 +3491,6 @@ void PortsOrch::refreshPortStatus() { SWSS_LOG_ENTER(); - std::unique_lock lock(g_orchmutex); for (auto &it: m_portList) { auto &port = it.second; @@ -3530,14 +3502,12 @@ void PortsOrch::refreshPortStatus() sai_port_oper_status_t status; if (!getPortOperStatus(port, status)) { - std::unique_lock unlock(g_orchmutex); throw runtime_error("PortsOrch get port oper status failure"); } SWSS_LOG_INFO("%s oper status is %s", port.m_alias.c_str(), oper_status_strings.at(status).c_str()); updatePortOperStatus(port, status); } - std::unique_lock unlock(g_orchmutex); } bool PortsOrch::getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const From e02a7e3538ced2eb7768e9c0050109f6ec2a3feb Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 20 Sep 2019 09:03:34 -0700 Subject: [PATCH 07/24] Update fdborch.cpp moved sai redis fdb event processing back to notification thread --- orchagent/fdborch.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9e0a09fa5e..1f83a1eb82 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -529,13 +529,6 @@ void FdbOrch::doTask(NotificationConsumer& consumer) { uint32_t count; sai_fdb_event_notification_data_t *fdbevent = nullptr; - extern void handle_fdb_event(_In_ const std::string &data); - - /* The sai_redis fdb handling is moved here so that both - * reference count updates (sai_redis and portsOrch) - * happen in same context to avoid any mismatch. - */ - handle_fdb_event(data); sai_deserialize_fdb_event_ntf(data, count, &fdbevent); From fb1d01b437dfd9d74af41ca4791d3bcac54aa6c3 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Thu, 26 Sep 2019 15:34:21 -0700 Subject: [PATCH 08/24] add portchannel OID to NAME mapping in LAG_NAME_MAP_TABLE --- orchagent/portsorch.cpp | 5 +++-- orchagent/portsorch.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index afacac53f7..58386f0ce5 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -150,6 +150,7 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) /* Initialize counter table */ m_counter_db = shared_ptr(new DBConnector(COUNTERS_DB, DBConnector::DEFAULT_UNIXSOCKET, 0)); m_counterTable = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_PORT_NAME_MAP)); + m_counterLagTable = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_LAG_NAME_MAP)); /* Initialize port and vlan table */ m_portTable = unique_ptr
(new Table(db, APP_PORT_TABLE_NAME)); @@ -3025,7 +3026,7 @@ bool PortsOrch::addLag(string lag_alias) FieldValueTuple tuple(lag_alias, sai_serialize_object_id(lag_id)); vector fields; fields.push_back(tuple); - m_counterTable->set("",fields); + m_counterLagTable->set("", fields); PortUpdate update = { lag, true }; notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); @@ -3073,7 +3074,7 @@ bool PortsOrch::removeLag(Port lag) SWSS_LOG_NOTICE("Remove LAG %s lid:%lx", lag.m_alias.c_str(), lag.m_lag_id); /* Remove LAG name map from counter table */ - m_counterTable->hdel("",lag.m_alias.c_str()); + m_counterLagTable->hdel("", lag.m_alias.c_str()); portOidToName.erase(lag.m_lag_id); m_portList.erase(lag.m_alias); diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index fc2182bb58..27bb535f9c 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -91,6 +91,7 @@ class PortsOrch : public Orch, public Subject bool removeAclTableGroup(const Port &p); private: unique_ptr
m_counterTable; + unique_ptr
m_counterLagTable; unique_ptr
m_portTable; unique_ptr
m_vlanTable; unique_ptr
m_queueTable; From a61485a44547a165ce63020ee887fcf20eb18e01 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 21 Oct 2019 13:13:47 -0700 Subject: [PATCH 09/24] Update fdborch.cpp When there is an update for an FDB entry, delete and re-add fdb instead of update, as the fdb can be aged out and then the update will fail. Also, handled the case when a delete notification from SAI for a fdb flush due to port removal from vlan may come after the port is readded to vlan. In this case the fdb needs to be re-added. --- orchagent/fdborch.cpp | 51 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 1f83a1eb82..9d1274b049 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -213,9 +213,36 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (existing_entry->second.type == "static") { - update.type = "static"; - saved_fdb_entries[update.port.m_alias].push_back({existing_entry->first.mac, vlan.m_vlan_info.vlan_id, "static"}); + if (vlan.m_members.find(update.port.m_alias) == vlan.m_members.end()) + { + update.type = "static"; + saved_fdb_entries[update.port.m_alias].push_back({existing_entry->first.mac, vlan.m_vlan_info.vlan_id, "static"}); + } + else + { + /*port added back to vlan before we receive delete + notification for flush from SAI. Re-add entry to SAI + */ + sai_attribute_t attr; + vector attrs; + + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + attrs.push_back(attr); + attr.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr.value.oid = bridge_port_id; + attrs.push_back(attr); + auto status = sai_fdb_api->create_fdb_entry(entry, (uint32_t)attrs.size(), attrs.data()); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create FDB %s on %s, rv:%d", + existing_entry->first.mac.to_string().c_str(), update.port.m_alias.c_str(), status); + return; + } + return; + } } + update.add = false; storeFdbEntryState(update); update.port.m_fdb_count--; @@ -669,16 +696,20 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const if(macUpdate) { SWSS_LOG_NOTICE("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); - for(auto itr : attrs) + status = sai_fdb_api->remove_fdb_entry(&fdb_entry); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", + entry.mac.to_string().c_str(), entry.bv_id); + } + status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); + if (status != SAI_STATUS_SUCCESS) { - status = sai_fdb_api->set_fdb_entry_attribute(&fdb_entry, &itr); - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("macUpdate-Failed for attr.id=0x%x for FDB %s in %s on %s, rv:%d", - itr.id, entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str(), status); - return false; - } + 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); + return false; } + if (oldPort.m_bridge_port_id != port.m_bridge_port_id) { oldPort.m_fdb_count--; From 3269a27ab6d8f4b41f9727ffe396481a31010cab Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 22 Oct 2019 11:13:44 -0700 Subject: [PATCH 10/24] Update fdborch.cpp added more code comments for last update --- orchagent/fdborch.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9d1274b049..9c66dd3d34 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -695,6 +695,10 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const if(macUpdate) { + /* delete and re-add fdb entry instead of update, + * as entry may age out in HW/ASIC_DB before + * update, causing the update request to fail. + */ SWSS_LOG_NOTICE("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); status = sai_fdb_api->remove_fdb_entry(&fdb_entry); if (status != SAI_STATUS_SUCCESS) From 30dfa58a94ba0b9151db99f71aa45a2be8ac8b3a Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 28 Oct 2019 17:26:28 -0700 Subject: [PATCH 11/24] Update fdborch.cpp updated as per review comments. --- orchagent/fdborch.cpp | 45 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9c66dd3d34..2be38da486 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -180,7 +180,6 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (!m_portsOrch->getPort(entry->bv_id, vlan)) { SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); - return; } auto existing_entry = m_entries.find(update.entry); @@ -195,7 +194,6 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) { SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to get port by bridge port ID 0x%lx", bridge_port_id); - return; } if (existing_entry->second.bridge_port_id != bridge_port_id) @@ -205,7 +203,6 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, update.port)) { SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to get port by bridge port ID 0x%lx", existing_entry->second.bridge_port_id); - return; } // dont return, let it delete just to bring SONiC and SAI in sync // return; @@ -245,10 +242,16 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj update.add = false; storeFdbEntryState(update); - update.port.m_fdb_count--; - m_portsOrch->setPort(update.port.m_alias, update.port); - vlan.m_fdb_count--; - m_portsOrch->setPort(vlan.m_alias, vlan); + if (!update.port.m_alias.empty()) + { + update.port.m_fdb_count--; + m_portsOrch->setPort(update.port.m_alias, update.port); + } + if (!vlan.m_alias.empty()) + { + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); + } for (auto observer: m_observers) { @@ -281,15 +284,17 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj { SWSS_LOG_INFO("FdbOrch MOVE notification: mac %s is not found in bv_id 0x%lx", update.entry.mac.to_string().c_str(), entry->bv_id); - break; } - if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, port_old)) + else if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, port_old)) { SWSS_LOG_ERROR("FdbOrch MOVE notification: Failed to get port by bridge port ID 0x%lx", existing_entry->second.bridge_port_id); return; } - port_old.m_fdb_count--; - m_portsOrch->setPort(port_old.m_alias, port_old); + if (!port_old.m_alias.empty()) + { + port_old.m_fdb_count--; + m_portsOrch->setPort(port_old.m_alias, port_old); + } update.port.m_fdb_count++; m_portsOrch->setPort(update.port.m_alias, update.port); @@ -319,15 +324,11 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (!m_portsOrch->getPortByBridgePortId(itr->second.bridge_port_id, update.port)) { SWSS_LOG_ERROR("FdbOrch FLUSH notification: Failed to get port by bridge port ID 0x%lx", itr->second.bridge_port_id); - itr++; - continue; } if (!m_portsOrch->getPort(itr->first.bv_id, vlan)) { SWSS_LOG_NOTICE("FdbOrch FLUSH notification: Failed to locate vlan port from bv_id 0x%lx", itr->first.bv_id); - itr++; - continue; } update.entry.mac = itr->first.mac; @@ -339,10 +340,16 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj /* This will invalidate the current iterator hence itr++ is done before */ storeFdbEntryState(update); - update.port.m_fdb_count--; - m_portsOrch->setPort(update.port.m_alias, update.port); - vlan.m_fdb_count--; - m_portsOrch->setPort(vlan.m_alias, vlan); + if (!update.port.m_alias.empty()) + { + update.port.m_fdb_count--; + m_portsOrch->setPort(update.port.m_alias, update.port); + } + if (!vlan.m_alias.empty()) + { + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); + } SWSS_LOG_DEBUG("FdbOrch FLUSH notification: mac %s was removed", update.entry.mac.to_string().c_str()); From 81b5f544f696be91eb14b118a51489fea4192bbe Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 29 Oct 2019 11:29:56 -0700 Subject: [PATCH 12/24] Update conftest.py added definition needed by some pytest --- tests/conftest.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index c510e441cd..c05de79733 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -763,6 +763,24 @@ def setup_db(self): self.cdb = swsscommon.DBConnector(4, self.redis_sock, 0) self.sdb = swsscommon.DBConnector(6, self.redis_sock, 0) + def getSwitchOid(self): + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") + keys = tbl.getKeys() + return str(keys[0]) + + def getVlanOid(self, vlanId): + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") + vlan_oid = None + keys = tbl.getKeys() + for k in keys: + (status, fvs) = tbl.get(k) + assert status == True, "Could not read vlan from DB" + for fv in fvs: + if fv[0] == "SAI_VLAN_ATTR_VLAN_ID" and fv[1] == str(vlanId): + vlan_oid = str(k) + break + return vlan_oid + def getCrmCounterValue(self, key, counter): counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, self.redis_sock, 0) crm_stats_table = swsscommon.Table(counters_db, 'CRM') From 0df7f35566130523f754476e251a7cc2bcf20707 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 1 Nov 2019 11:24:28 -0700 Subject: [PATCH 13/24] Update fdborch.cpp return false if fdb remove from sai fails, so that it is retried from cosumer map. --- orchagent/fdborch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 2be38da486..6a004fbe30 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -814,7 +814,7 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) { SWSS_LOG_ERROR("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); - return true; //FIXME: it should be based on status. Some could be retried. some not + return false; //FIXME: it should be based on status. Some could be retried. some not } port.m_fdb_count--; m_portsOrch->setPort(port.m_alias, port); From 7cb0d374ecb26346e01b01c5afbc976b8abe640d Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 5 Nov 2019 17:23:39 -0800 Subject: [PATCH 14/24] Update fdborch.cpp --- orchagent/fdborch.cpp | 58 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 6a004fbe30..865c700bde 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -702,49 +702,53 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const if(macUpdate) { - /* delete and re-add fdb entry instead of update, + /* delete and re-add fdb entry instead of update, * as entry may age out in HW/ASIC_DB before * update, causing the update request to fail. */ SWSS_LOG_NOTICE("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); status = sai_fdb_api->remove_fdb_entry(&fdb_entry); if (status != SAI_STATUS_SUCCESS) - { + { SWSS_LOG_INFO("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); } - status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); - 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); - return false; - } - - if (oldPort.m_bridge_port_id != port.m_bridge_port_id) + else { oldPort.m_fdb_count--; m_portsOrch->setPort(oldPort.m_alias, oldPort); - port.m_fdb_count++; - m_portsOrch->setPort(port.m_alias, port); + if (oldPort.m_bridge_port_id == port.m_bridge_port_id) + { + port.m_fdb_count--; + m_portsOrch->setPort(port.m_alias, port); + } + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); + (void)m_entries.erase(entry); + // Remove in StateDb + m_fdbStateTable.del(key); + + gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); + FdbUpdate update = {entry, port, type, true}; + for (auto observer: m_observers) + { + observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); + } } } - else - { - SWSS_LOG_INFO("MAC-Create %s FDB %s in %s on %s", type.c_str(), entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str()); + SWSS_LOG_INFO("MAC-Create %s FDB %s in %s on %s", type.c_str(), entry.mac.to_string().c_str(), vlan.m_alias.c_str(), port_name.c_str()); - status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); - 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); - return false; //FIXME: it should be based on status. Some could be retried, some not - } - port.m_fdb_count++; - m_portsOrch->setPort(port.m_alias, port); - vlan.m_fdb_count++; - m_portsOrch->setPort(vlan.m_alias, vlan); + status = sai_fdb_api->create_fdb_entry(&fdb_entry, (uint32_t)attrs.size(), attrs.data()); + 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); + return false; //FIXME: it should be based on status. Some could be retried, some not } + port.m_fdb_count++; + m_portsOrch->setPort(port.m_alias, port); + vlan.m_fdb_count++; + m_portsOrch->setPort(vlan.m_alias, vlan); const FdbData fdbdata = {port.m_bridge_port_id, type}; m_entries[entry] = fdbdata; From 7c294919e95677ec4d0184758206f11f5d95308b Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Thu, 7 Nov 2019 16:28:51 -0800 Subject: [PATCH 15/24] Update fdborch.cpp fix build failure --- orchagent/fdborch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 865c700bde..31ad794690 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -700,6 +700,8 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const attr.value.s32 = SAI_PACKET_ACTION_FORWARD; attrs.push_back(attr); + string key = "Vlan" + to_string(vlan.m_vlan_info.vlan_id) + ":" + entry.mac.to_string(); + if(macUpdate) { /* delete and re-add fdb entry instead of update, @@ -753,8 +755,6 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const const FdbData fdbdata = {port.m_bridge_port_id, type}; m_entries[entry] = fdbdata; - string key = "Vlan" + to_string(vlan.m_vlan_info.vlan_id) + ":" + entry.mac.to_string(); - // Write to StateDb std::vector fvs; fvs.push_back(FieldValueTuple("port", port_name)); From 753acb47b1dc44da80b04e95bd10f22e70ed98ae Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 9 Nov 2019 23:05:29 -0800 Subject: [PATCH 16/24] Update portsorch.cpp --- orchagent/portsorch.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index f0f5017e5e..28a63d29e1 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -1288,7 +1288,6 @@ void PortsOrch::updateDbVlanOperStatus(const Port& vlan, string status) const vector tuples; FieldValueTuple tuple("oper_status", status); tuples.push_back(tuple); - m_vlanTable->set(vlan.m_alias, tuples); std::vector entry; From 0d0cb030a35d2f83422286920ec27c4bea1fffd1 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 9 Nov 2019 23:18:51 -0800 Subject: [PATCH 17/24] Update vlanmgr.cpp --- cfgmgr/vlanmgr.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index c86042b13a..ff72048115 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -452,7 +452,15 @@ void VlanMgr::doVlanTask(Consumer &consumer) /* set up host env .... */ for (auto i : kfvFieldsValues(t)) { - if (fvField(i) == "mtu") + /* Set vlan admin status */ + if (fvField(i) == "admin_status") + { + admin_status = fvValue(i); + setHostVlanAdminState(vlan_id, admin_status); + fvVector.push_back(i); + } + /* Set vlan mtu */ + else if (fvField(i) == "mtu") { mtu = fvValue(i); /* From c852011f6c88806bcb5f3379ebf808376f332044 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 16 Dec 2019 11:28:56 -0800 Subject: [PATCH 18/24] updated as per review comments --- cfgmgr/vlanmgr.cpp | 38 ++++++++++++--------------- orchagent/fdborch.cpp | 58 +++++++++++++++++++++++------------------ orchagent/fdborch.h | 8 +++--- orchagent/portsorch.cpp | 6 ++--- 4 files changed, 56 insertions(+), 54 deletions(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index ff72048115..035730f778 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -18,6 +18,7 @@ using namespace swss; #define DEFAULT_VLAN_ID "1" #define DEFAULT_MTU_STR "9100" #define VLAN_HLEN 4 +#define MAX_VLAN_ID 4095 extern MacAddress gMacAddress; @@ -259,7 +260,7 @@ void VlanMgr::doSwitchTask(Consumer &consumer) /* Ensure the key starts with "switch" otherwise ignore */ if (key != SWITCH_STR) { - SWSS_LOG_INFO("Ignoring SWITCH key %s", key.c_str()); + SWSS_LOG_NOTICE("Ignoring SWITCH key %s", key.c_str()); it = consumer.m_toSync.erase(it); continue; } @@ -270,13 +271,13 @@ void VlanMgr::doSwitchTask(Consumer &consumer) { if (fvField(i) == "fdb_aging_time") { - int agingTime = 0; + long agingTime = 0; SWSS_LOG_DEBUG("attribute:fdb_aging_time"); if (op == SET_COMMAND) { SWSS_LOG_DEBUG("operation:set"); - agingTime = atoi(fvValue(i).c_str()); - if(agingTime < 0) + agingTime = strtol(fvValue(i).c_str(), NULL, 0); + if (agingTime < 0) { SWSS_LOG_ERROR("Invalid fdb_aging_time %s", fvValue(i).c_str()); break; @@ -286,7 +287,7 @@ void VlanMgr::doSwitchTask(Consumer &consumer) else if (op == DEL_COMMAND) { SWSS_LOG_DEBUG("operation:del"); - agingTime=0; + agingTime = 0; } else { @@ -308,13 +309,6 @@ void VlanMgr::doSwitchTask(Consumer &consumer) void VlanMgr::doFdbTask(Consumer &consumer) { - if (!isVlanMacOk()) - { - SWSS_LOG_DEBUG("VLAN mac not ready, delaying FDB task"); - SWSS_LOG_DEBUG("VLAN mac not ready, delaying VLAN task"); - return; - } - auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) @@ -334,10 +328,10 @@ void VlanMgr::doFdbTask(Consumer &consumer) continue; } - int vlan_id; - vlan_id = stoi(keys[0].substr(4)); + unsigned long vlan_id; + vlan_id = strtoul(keys[0].substr(strlen(VLAN_PREFIX)).c_str(), NULL, 0); - if ((vlan_id <= 0) || (vlan_id > 4095)) + if ((vlan_id <= 0) || (vlan_id > MAX_VLAN_ID)) { SWSS_LOG_ERROR("Invalid key format. Vlan is out of range: %s", keys[0].c_str()); it = consumer.m_toSync.erase(it); @@ -453,7 +447,7 @@ void VlanMgr::doVlanTask(Consumer &consumer) for (auto i : kfvFieldsValues(t)) { /* Set vlan admin status */ - if (fvField(i) == "admin_status") + if (fvField(i) == "admin_status") { admin_status = fvValue(i); setHostVlanAdminState(vlan_id, admin_status); @@ -774,18 +768,20 @@ void VlanMgr::doTask(NotificationConsumer &consumer) if (&consumer != m_VlanStateNotificationConsumer) { + SWSS_LOG_WARN("received incorrect notification message); return; } consumer.pop(op, data, values); - int vlan_id = stoi(data.substr(4)); + unsigned long vlan_id = strtoul(data.substr(strlen(VLAN_PREFIX)).c_str(), NULL, 0); - SWSS_LOG_NOTICE("vlanmgr received port status notification state %s vlan %s id %d", - op.c_str(), data.c_str(), vlan_id); + SWSS_LOG_NOTICE("vlanmgr received port status notification state %s vlan %s", + op.c_str(), data.c_str()); - if (isVlanStateOk(data)) { - setHostVlanAdminState(vlan_id, op); + if (isVlanStateOk(data)) + { + setHostVlanAdminState((int)vlan_id, op); } else { diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index d5324d26ec..7f2502c420 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -74,22 +74,23 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) if (update.add) { - bool mac_move=false; + bool mac_move = false; auto it = m_entries.find(entry); - if(it != m_entries.end()) + if (it != m_entries.end()) { - if(port.m_bridge_port_id == it->second.bridge_port_id) + if (port.m_bridge_port_id == it->second.bridge_port_id) { SWSS_LOG_INFO("FdbOrch notification: mac %s is duplicate", entry.mac.to_string().c_str()); return false; } - mac_move=true; + mac_move = true; } m_entries[entry] = fdbdata; - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%lx", + SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%" PRIx64, entry.mac.to_string().c_str(), entry.bv_id); - SWSS_LOG_DEBUG("m_entries size=%lu mac=%s port=%lx", m_entries.size(), entry.mac.to_string().c_str(), m_entries[entry].bridge_port_id); + SWSS_LOG_DEBUG("m_entries size=%lu mac=%s port=0x%" PRIx64, + m_entries.size(), entry.mac.to_string().c_str(), m_entries[entry].bridge_port_id); // Write to StateDb std::vector fvs; @@ -97,7 +98,7 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) fvs.push_back(FieldValueTuple("type", update.type)); m_fdbStateTable.set(key, fvs); - if(!mac_move) + if (!mac_move) { gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); } @@ -106,7 +107,7 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) else { size_t erased = m_entries.erase(entry); - SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed from bv_id 0x%lx", entry.mac.to_string().c_str(), entry.bv_id); + SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed from bv_id 0x%" PRIx64, entry.mac.to_string().c_str(), entry.bv_id); if (erased == 0) { @@ -135,17 +136,17 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj { case SAI_FDB_EVENT_LEARNED: { - SWSS_LOG_INFO("Received LEARN event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + SWSS_LOG_INFO("Received LEARN event for bvid=0x%" PRIx64 "mac=%s port=0x%" PRIx64, entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); if (!m_portsOrch->getPort(entry->bv_id, vlan)) { - SWSS_LOG_NOTICE("FdbOrch LEARN notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); + SWSS_LOG_ERROR("FdbOrch LEARN notification: Failed to locate vlan port from bv_id 0x%" PRIx64, entry->bv_id); return; } if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port)) { - SWSS_LOG_NOTICE("FdbOrch LEARN notification: Failed to get port by bridge port ID 0x%lx", bridge_port_id); + SWSS_LOG_ERROR("FdbOrch LEARN notification: Failed to get port by bridge port ID 0x%" PRIx64, bridge_port_id); return; } @@ -153,8 +154,9 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj auto existing_entry = m_entries.find(update.entry); if (existing_entry != m_entries.end()) { - SWSS_LOG_INFO("FdbOrch LEARN notification: mac %s is already in bv_id 0x%lx existing-bp 0x%lx new-bp:0x%lx", - update.entry.mac.to_string().c_str(), entry->bv_id, existing_entry->second.bridge_port_id, bridge_port_id); + SWSS_LOG_INFO("FdbOrch LEARN notification: mac %s is already in bv_id 0x%" + PRIx64 "existing-bp 0x%" PRIx64 "new-bp:0x%" PRIx64, + update.entry.mac.to_string().c_str(), entry->bv_id, existing_entry->second.bridge_port_id, bridge_port_id); break; } @@ -269,7 +271,7 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj if (!m_portsOrch->getPort(entry->bv_id, vlan)) { - SWSS_LOG_NOTICE("FdbOrch MOVE notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); + SWSS_LOG_ERROR("FdbOrch MOVE notification: Failed to locate vlan port from bv_id 0x%lx", entry->bv_id); return; } @@ -282,7 +284,7 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj // We should already have such entry if (existing_entry == m_entries.end()) { - SWSS_LOG_INFO("FdbOrch MOVE notification: mac %s is not found in bv_id 0x%lx", + SWSS_LOG_WARN("FdbOrch MOVE notification: mac %s is not found in bv_id 0x%lx", update.entry.mac.to_string().c_str(), entry->bv_id); } else if (!m_portsOrch->getPortByBridgePortId(existing_entry->second.bridge_port_id, port_old)) @@ -708,11 +710,11 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const * as entry may age out in HW/ASIC_DB before * update, causing the update request to fail. */ - SWSS_LOG_NOTICE("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); + SWSS_LOG_INFO("MAC-Update FDB %s in %s on from-%s:to-%s from-%s:to-%s", entry.mac.to_string().c_str(), vlan.m_alias.c_str(), oldPort.m_alias.c_str(), port_name.c_str(), oldType.c_str(), type.c_str()); status = sai_fdb_api->remove_fdb_entry(&fdb_entry); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_INFO("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", + SWSS_LOG_WARN("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); } else @@ -818,7 +820,7 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) { SWSS_LOG_ERROR("FdbOrch RemoveFDBEntry: Failed to remove FDB entry. mac=%s, bv_id=0x%lx", entry.mac.to_string().c_str(), entry.bv_id); - return false; //FIXME: it should be based on status. Some could be retried. some not + return true; //FIXME: it should be based on status. Some could be retried. some not } port.m_fdb_count--; m_portsOrch->setPort(port.m_alias, port); @@ -840,7 +842,7 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) return true; } -int FdbOrch::flushFdbAll(bool flush_static) +bool FdbOrch::flushFdbAll(bool flush_static) { sai_status_t status; sai_attribute_t port_attr; @@ -858,11 +860,12 @@ int FdbOrch::flushFdbAll(bool flush_static) if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + return false; } - return 0; + return true; } -int FdbOrch::flushFdbByPort(const string &alias, bool flush_static) +bool FdbOrch::flushFdbByPort(const string &alias, bool flush_static) { sai_status_t status; Port port; @@ -897,11 +900,12 @@ int FdbOrch::flushFdbByPort(const string &alias, bool flush_static) if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + return false; } - return 0; + return true; } -int FdbOrch::flushFdbByVlan(const string &alias, bool flush_static) +bool FdbOrch::flushFdbByVlan(const string &alias, bool flush_static) { sai_status_t status; Port vlan; @@ -929,12 +933,13 @@ int FdbOrch::flushFdbByVlan(const string &alias, bool flush_static) if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + return false; } - return 0; + return true; } -int FdbOrch::flushFdbByPortVlan(const string &port_alias, const string &vlan_alias, bool flush_static) +bool FdbOrch::flushFdbByPortVlan(const string &port_alias, const string &vlan_alias, bool flush_static) { sai_status_t status; @@ -980,9 +985,10 @@ int FdbOrch::flushFdbByPortVlan(const string &port_alias, const string &vlan_ali if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); + return false; } - return 0; + return true; } void FdbOrch::deleteFdbEntryFromSavedFDB(const MacAddress &mac, const unsigned short &vlanId, const string portName) diff --git a/orchagent/fdborch.h b/orchagent/fdborch.h index 6348218a86..d0b74e0d6a 100644 --- a/orchagent/fdborch.h +++ b/orchagent/fdborch.h @@ -62,10 +62,10 @@ class FdbOrch: public Orch, public Subject, public Observer void update(sai_fdb_event_t, const sai_fdb_entry_t *, sai_object_id_t); void update(SubjectType type, void *cntx); bool getPort(const MacAddress&, uint16_t, Port&); - int flushFdbByPortVlan(const string &, const string &, bool flush_static); - int flushFdbByVlan(const string &, bool flush_static); - int flushFdbByPort(const string &, bool flush_static); - int flushFdbAll(bool flush_static); + bool flushFdbByPortVlan(const string &, const string &, bool flush_static); + bool flushFdbByVlan(const string &, bool flush_static); + bool flushFdbByPort(const string &, bool flush_static); + bool flushFdbAll(bool flush_static); bool removeFdbEntry(const FdbEntry&); private: diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index dcea021592..daca2866d3 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -1512,7 +1512,7 @@ bool PortsOrch::initPort(const string &alias, const set &lane_set) p.m_index = static_cast(m_portList.size()); // TODO: Assume no deletion of physical port p.m_port_id = id; - + /* Initialize the port and create corresponding host interface */ if (initializePort(p)) { @@ -2315,11 +2315,11 @@ void PortsOrch::doVlanMemberTask(Consumer &consumer) { ret = removeVlanMember(vlan, port); } - if ((ret == true) && port.m_vlan_members.empty()) + if ((ret) && port.m_vlan_members.empty()) { ret = removeBridgePort(port); } - if (ret == true) + if (ret) { it = consumer.m_toSync.erase(it); } From a9fb507ab76f76ce0efeea1c7d3d522419abbb6f Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 16 Dec 2019 13:13:27 -0800 Subject: [PATCH 19/24] Update vlanmgr.cpp --- cfgmgr/vlanmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index 035730f778..0cf28d4d91 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -768,7 +768,7 @@ void VlanMgr::doTask(NotificationConsumer &consumer) if (&consumer != m_VlanStateNotificationConsumer) { - SWSS_LOG_WARN("received incorrect notification message); + SWSS_LOG_WARN("received incorrect notification message"); return; } From bcaeb98c92ed7883986bd03bf655dafb67d6f185 Mon Sep 17 00:00:00 2001 From: anilkpan <47642449+anilkpan@users.noreply.github.com> Date: Fri, 24 Apr 2020 16:57:05 -0700 Subject: [PATCH 20/24] Update portsorch.cpp --- orchagent/portsorch.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 5684e1e5ae..02322b370a 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -3538,11 +3538,6 @@ bool PortsOrch::addLag(string lag_alias) PortUpdate update = { lag, true }; notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); - FieldValueTuple tuple(lag_alias, sai_serialize_object_id(lag_id)); - vector fields; - fields.push_back(tuple); - m_counterLagTable->set("", fields); - return true; } From 757cf704f41f387cc4f0cb947d76eb8b5900838e Mon Sep 17 00:00:00 2001 From: anilkpan <47642449+anilkpan@users.noreply.github.com> Date: Thu, 3 Dec 2020 20:58:21 -0800 Subject: [PATCH 21/24] Create .DS_Store --- .DS_Store | Bin 0 -> 12292 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..72a51f15c2676a7b48a340975c3c528389245683 GIT binary patch literal 12292 zcmeI2du$xV9mjt^$B*63I$nnab1(a1$JlY4_<>``apIg`#7<1(Vmo#o#JR^NK5@P? zx93MCRVAvn&{n9A-^}b@ zZqE+I0wFi-NxO41znR_r&CTrZ`P~zhm1rr)x|G18l~%tTH2JMU#rtaqtkjfUE0u4KC`C8yP>kCuBo-XYoSOhUVGU( zRXr4q=X8WD>6%1@T`i)WlSKXUQn&jsvvehOI!DX~S5~>zA%k4ff@a0d zwW>OFeKa1?4D(j?4XS%M77XbzEh3BiY-?8CBh#W+wS8vcjyBaj8cs}1kSj(p)|$n; z18(X){-+Q3yCP68ax%U4eb5Nq z&=1FGbj-mW@F{o*9))khx8Nyw2A+qP;1zfk{sw=Cf51O62UlYuuE8R_0xPi!t8o)H zVmt1}0QTYgZ~)(r*WzJ3h9L}N1SinIDV)X`oX6YnBluCg9q+*h@F9E{KaXeear`cR z51+*I_zQdv7x0((GQNU;!q>zD=CIMrKG%rEI^*jX+_d{9r=26;T(A`a&UQNQy za68-yAA|eh3vd>`0Z+h>;XM3=ynGg3gx|p*;4ko3cnw~M|Dc32d8(od%drACVm-Fv z4%~^muoL%TKY6+zhwwT)N}dMs1Ww`&g%~$>0LBO=_+RLNm=pU z>P07Ydcf&{_izue_k*7fmIlmpUZnihK_@05n4L)o{-N*00lds_rU5gZ7b$N_ZFo~k zMN>2p14VNx_p|Dh2F!F`q@p>XXbx!J8BIb#es^l;=hXoNB6ZGA4>&!rxCaWTXldain z^ESwY3EC=QYf_sf0s<{hSXFRyqcu$0EzlR945ItMshcV*JF&NeFA6kB+ilOy$L^L z%KJO;lXx$F8t)_d`$hZ`ei^@lXYf%x$3^ht_=G8febB?sXg+CI~z5)M&e{-Z=k0ms}8Paa08P1Tlo#uE4 zM_Mt%8PbMP$KxDnXYmxD-M8SK_;I|8BkdXdDt?V4?f3DiWg)G7z*@m)NuYHv3AFFZ zfPFz_zZP3ZT3=dG{iZ=Bb0EEG9I=hX1u>izpEZ87$F)7E@Y;TNxfxV=w$fcC(U7J{ z!m>(@o5Bx|B-~o3G?y?tI}ph5^il*0%jx;*Q#{OGOZgeclew)oF2I3dVul2Z8u@1fzoycO3m*8DA~NsL?xTyf5DP#1;LWCR#|s3nV11lq~LCq z#fk-qI?d&Fc`w#VqRq`TFmd)#%3K@R5`|r)G7;=5b5%-Grpgr!s$DfqZ*s{iO13C< zOk;9j;w7#|rHP490ZgK(MQLTq(*h<@xKnB8%O`1K62%>^E+%-hfQd;|_EdW$DFc_5 zEmq$n`+t`hE(t8kh9zs9YXt(e8Pt^deLjs1ABi)~#!AZO&>&D zicibqTk$M=RgK803%mOTQO#3e%XJla<; zAwc({kK@uNf~8uHOWSGpxsCRpdvFiI(q4{B2MCr9a$M30mc}_QrTAVu!=;;PADS)7 z32=YwxMX`-W&zU@3vw$hn!IDnZcF%T#S|3(yU2Vqu0Z~$xSuD~Of}p8@45K@|3oe4 z?DT-s1D9kEU~czdcPF`K?K5P1$@bd)bR46DeOSGDk@6;VGPmQojc>(MnfW&|UKXJ0 gtlhjwc{9q3X7Adc09cfE;=dFB-~P7S|9$-bF9nS>S^xk5 literal 0 HcmV?d00001 From 56e330e288aca0f48dce65ce918ac060f46bf831 Mon Sep 17 00:00:00 2001 From: anilkpan <47642449+anilkpan@users.noreply.github.com> Date: Thu, 3 Dec 2020 21:11:43 -0800 Subject: [PATCH 22/24] update latest changes after synching with master --- cfgmgr/vlanmgr.cpp | 12 ++-- cfgmgr/vlanmgr.h | 1 - orchagent/fdborch.cpp | 138 +++++++++++-------------------------- orchagent/fdborch.h | 14 ++-- orchagent/port.h | 2 +- orchagent/portsorch.cpp | 88 ++++++++++++----------- orchagent/portsorch.h | 1 + tests/conftest.py | 2 +- tests/test_fdb_negative.py | 14 ++-- 9 files changed, 108 insertions(+), 164 deletions(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index d70984ca81..6f017c6af5 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -468,12 +468,12 @@ void VlanMgr::doVlanTask(Consumer &consumer) { /* Set vlan admin status */ if (fvField(i) == "admin_status") - { - admin_status = fvValue(i); - setHostVlanAdminState(vlan_id, admin_status); - fvVector.push_back(i); - } - /* Set vlan mtu */ + { + admin_status = fvValue(i); + setHostVlanAdminState(vlan_id, admin_status); + fvVector.push_back(i); + } + /* Set vlan mtu */ else if (fvField(i) == "mtu") { mtu = fvValue(i); diff --git a/cfgmgr/vlanmgr.h b/cfgmgr/vlanmgr.h index 34ddd00eb4..df0d8974a8 100644 --- a/cfgmgr/vlanmgr.h +++ b/cfgmgr/vlanmgr.h @@ -11,7 +11,6 @@ #include namespace swss { - class VlanMgr : public Orch { public: diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index b5325b1240..8e23ac4698 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -60,6 +60,7 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) const FdbData fdbdata = {update.port.m_bridge_port_id, update.type}; 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)) @@ -233,7 +234,8 @@ void FdbOrch::update(sai_fdb_event_t type, if (vlan.m_members.find(update.port.m_alias) == vlan.m_members.end()) { update.type = "static"; - saved_fdb_entries[update.port.m_alias].push_back({existing_entry->first.mac, vlan.m_vlan_info.vlan_id, "static"}); + saved_fdb_entries[update.port.m_alias].push_back({existing_entry->first.mac, vlan.m_vlan_info.vlan_id, "static"}); + } else { @@ -327,33 +329,12 @@ void FdbOrch::update(sai_fdb_event_t type, } break; } - case SAI_FDB_EVENT_FLUSHED: - - 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) + case SAI_FDB_EVENT_FLUSHED: + SWSS_LOG_INFO("Received FLUSH event for bvid=%lx mac=%s port=%lx", entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id); + for (auto itr = m_entries.begin(); itr != m_entries.end();) { - 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();) + if (itr->second.type == "static") { itr++; continue; @@ -367,69 +348,41 @@ void FdbOrch::update(sai_fdb_event_t type, if (!m_portsOrch->getPortByBridgePortId(itr->second.bridge_port_id, update.port)) { SWSS_LOG_ERROR("FdbOrch FLUSH notification: Failed to get port by bridge port ID 0x%lx", itr->second.bridge_port_id); + itr++; + continue; } if (!m_portsOrch->getPort(itr->first.bv_id, vlan)) { SWSS_LOG_NOTICE("FdbOrch FLUSH notification: Failed to locate vlan port from bv_id 0x%lx", itr->first.bv_id); + itr++; + continue; } update.entry.mac = itr->first.mac; update.entry.bv_id = itr->first.bv_id; update.add = false; + update.vlan_id = vlan.m_vlan_info.vlan_id; itr++; + update.port.m_fdb_count--; + m_portsOrch->setPort(update.port.m_alias, update.port); + vlan.m_fdb_count--; + m_portsOrch->setPort(vlan.m_alias, vlan); + /* This will invalidate the current iterator hence itr++ is done before */ storeFdbEntryState(update); - for (auto observer: m_observers) - { - observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); - } - } - } - else if (entry->bv_id == SAI_NULL_OBJECT_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()); + SWSS_LOG_DEBUG("FdbOrch FLUSH notification: mac %s was removed", update.entry.mac.to_string().c_str()); - for (auto itr = m_entries.begin(); itr != m_entries.end();) + notify(SUBJECT_TYPE_FDB_CHANGE, &update); + } + else { - auto next_item = std::next(itr); - 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); - } - } - itr = next_item; + itr++; } } - else if (bridge_port_id == SAI_NULL_OBJECT_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 - { - /* 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; } @@ -566,7 +519,7 @@ void FdbOrch::doTask(Consumer& consumer) /* FDB type is either dynamic or static */ assert(type == "dynamic" || type == "static"); - if (addFdbEntry(entry, type)) + if (addFdbEntry(entry, port, type)) it = consumer.m_toSync.erase(it); else it++; @@ -719,14 +672,14 @@ void FdbOrch::notifyObserversFDBFlush(Port &port, sai_object_id_t& bvid) for (auto itr = m_entries.begin(); itr != m_entries.end(); ++itr) { - if ((itr->port_name == port.m_alias) && - (itr->bv_id == bvid)) + if ((itr->second.bridge_port_id == port.m_bridge_port_id) && + (itr->first.bv_id == bvid)) { SWSS_LOG_INFO("Adding MAC learnt on [ port:%s , bvid:0x%" PRIx64 "]\ to ARP flush", port.m_alias.c_str(), bvid); FdbEntry entry; - entry.mac = itr->mac; - entry.bv_id = itr->bv_id; + entry.mac = itr->first.mac; + entry.bv_id = itr->first.bv_id; flushUpdate.entries.push_back(entry); } } @@ -768,44 +721,37 @@ void FdbOrch::updatePortOperState(const PortOperStateUpdate& update) void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) { - string port_name = update.member.m_alias; - string vlan_name = update.vlan.m_alias; - SWSS_LOG_ENTER(); if (!update.add) { swss::Port vlan = update.vlan; swss::Port port = update.member; - flushFDBEntries(port.m_bridge_port_id, vlan.m_vlan_info.vlan_oid); + flushFdbByPortVlan(port.m_alias, vlan.m_alias, 1); notifyObserversFDBFlush(port, vlan.m_vlan_info.vlan_oid); return; } + string port_name = update.member.m_alias; auto fdb_list = std::move(saved_fdb_entries[port_name]); saved_fdb_entries[port_name].clear(); for (const auto& fdb: fdb_list) { - for (const auto& fdb: fdb_list) + if(fdb.vlanId == update.vlan.m_vlan_info.vlan_id) { - // 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() - if(fdb.vlanId == update.vlan.m_vlan_info.vlan_id) - { - FdbEntry entry; - entry.mac = fdb.mac; - entry.bv_id = update.vlan.m_vlan_info.vlan_oid; - (void)addFdbEntry(entry, port_name, fdb.type); - } - else - { - saved_fdb_entries[port_name].push_back(fdb); - } + FdbEntry entry; + entry.mac = fdb.mac; + entry.bv_id = update.vlan.m_vlan_info.vlan_oid; + (void)addFdbEntry(entry, port_name, fdb.type); + } + else + { + saved_fdb_entries[port_name].push_back(fdb); } } } -bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& type) +bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const string& type) { Port vlan; Port port; @@ -915,7 +861,7 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& type) m_fdbStateTable.del(key); gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); - FdbUpdate update = {entry, port, type, true}; + FdbUpdate update = {entry, port, vlan.m_vlan_info.vlan_id, type, true}; for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -951,7 +897,7 @@ bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& type) gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); } - FdbUpdate update = {entry, port, type, true}; + FdbUpdate update = {entry, port, vlan.m_vlan_info.vlan_id, type, true}; for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); @@ -1016,7 +962,7 @@ bool FdbOrch::removeFdbEntry(const FdbEntry& entry) gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); - FdbUpdate update = {entry, port, fdbData.type, false}; + FdbUpdate update = {entry, port, vlan.m_vlan_info.vlan_id, fdbData.type, false}; for (auto observer: m_observers) { observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); diff --git a/orchagent/fdborch.h b/orchagent/fdborch.h index 5a3c10b865..3605f550e9 100644 --- a/orchagent/fdborch.h +++ b/orchagent/fdborch.h @@ -25,22 +25,23 @@ struct FdbUpdate { FdbEntry entry; Port port; + uint16_t vlan_id; string type; bool add; }; -struct FdbData -{ - sai_object_id_t bridge_port_id; - string type; -}; - struct FdbFlushUpdate { vector entries; Port port; }; +struct FdbData +{ + sai_object_id_t bridge_port_id; + string type; +}; + struct SavedFdbEntry { MacAddress mac; @@ -95,7 +96,6 @@ class FdbOrch: public Orch, public Subject, public Observer void deleteFdbEntryFromSavedFDB(const MacAddress &mac, const unsigned short &vlanId, const string portName=""); void updatePortOperState(const PortOperStateUpdate&); - bool removeFdbEntry(const FdbEntry&); bool storeFdbEntryState(const FdbUpdate& update); }; diff --git a/orchagent/port.h b/orchagent/port.h index 7f75e5db92..d18681aec6 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -97,8 +97,8 @@ class Port sai_object_id_t m_tunnel_id = 0; sai_object_id_t m_ingress_acl_table_group_id = 0; sai_object_id_t m_egress_acl_table_group_id = 0; - vlan_members_t m_vlan_members; sai_object_id_t m_parent_port_id = 0; + vlan_members_t m_vlan_members; uint32_t m_dependency_bitmap = 0; sai_port_oper_status_t m_oper_status = SAI_PORT_OPER_STATUS_UNKNOWN; std::set m_members; diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index a83f48f76d..db45f927b1 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -28,7 +28,6 @@ #include "countercheckorch.h" #include "notifier.h" #include "fdborch.h" -#include "redisclient.h" extern sai_switch_api_t *sai_switch_api; extern sai_bridge_api_t *sai_bridge_api; @@ -207,6 +206,7 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) /* Initialize counter table */ m_counter_db = shared_ptr(new DBConnector("COUNTERS_DB", 0)); m_counterTable = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_PORT_NAME_MAP)); + m_counterLagTable = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_LAG_NAME_MAP)); FieldValueTuple tuple("", ""); vector defaultLagFv; @@ -1854,7 +1854,7 @@ bool PortsOrch::initPort(const string &alias, const int index, const set &l /* Add port to port list */ m_portList[alias] = p; portOidToName[id] = alias; - m_port_ref_count[alias] = 0; + m_port_ref_count[alias] = 0; m_portOidToIndex[id] = index; /* Add port name map to counter table */ @@ -2804,7 +2804,7 @@ void PortsOrch::doVlanMemberTask(Consumer &consumer) { ret = removeVlanMember(vlan, port); } - if ((ret) && port.m_vlan_members.empty()) + if ((ret) && m_portVlanMember[port.m_alias].empty()) { ret = removeBridgePort(port); } @@ -2844,6 +2844,7 @@ void PortsOrch::doLagTask(Consumer &consumer) string oper_status; string learn_mode; + bool operation_status_changed = false; string operation_status; for (auto i : kfvFieldsValues(t)) @@ -2889,10 +2890,10 @@ void PortsOrch::doLagTask(Consumer &consumer) } else { + if (!operation_status.empty()) { - updatePortOperStatus(l, string_oper_status.at(operation_status)); - + l.m_oper_status = string_oper_status.at(operation_status); m_portList[alias] = l; } if (operation_status_changed) @@ -2914,13 +2915,16 @@ void PortsOrch::doLagTask(Consumer &consumer) updateChildPortsMtu(l, mtu); } - if (!oper_status.empty() && (oper_status != "up")) + if (!oper_status.empty()) { - gFdbOrch->flushFdbByPort(alias, 0); + if (oper_status != "up") + gFdbOrch->flushFdbByPort(alias, 0); + + /* Trigger status updated only if it is set */ + sai_port_oper_status_t status = (oper_status == "up") ? SAI_PORT_OPER_STATUS_UP : SAI_PORT_OPER_STATUS_DOWN; + updateLagOperStatus(l, status); } - sai_port_oper_status_t status = (oper_status == "up") ? SAI_PORT_OPER_STATUS_UP : SAI_PORT_OPER_STATUS_DOWN; - updateLagOperStatus(l, status); - + if (!learn_mode.empty() && (l.m_learn_mode != learn_mode)) { if (l.m_bridge_port_id != SAI_NULL_OBJECT_ID) @@ -3390,12 +3394,8 @@ bool PortsOrch::addBridgePort(Port &port) * This can happen if the port was just removed from * last VLAN and fdb flush is still in progress. */ - if (port.m_vlan_members.empty()) + if (m_portVlanMember[port.m_alias].empty()) { - if (port.m_fdb_count > 0) - { - return false; - } sai_attribute_t attr; attr.id = SAI_BRIDGE_PORT_ATTR_ADMIN_STATE; attr.value.booldata = true; @@ -3488,12 +3488,6 @@ bool PortsOrch::addBridgePort(Port &port) port.m_alias.c_str(), status); return false; } - if (!setPortPvid(port, 0)) - { - SWSS_LOG_ERROR("Failed to set pvid for port %s, rv:%d", - port.m_alias.c_str(), status); - return false; - } port.m_bridge_port_admin_state = true; if (!setHostIntfsStripTag(port, SAI_HOSTIF_VLAN_TAG_KEEP)) @@ -3672,12 +3666,9 @@ bool PortsOrch::removeVlan(Port vlan) vlan.m_alias.c_str(), vlan.m_vnid); return false; } + /* Do not delete default VLAN from driver, but clear internal state */ if (vlan.m_vlan_info.vlan_id != m_defaultVlan_Id) - { - sai_status_t status = sai_vlan_api->remove_vlan(vlan.m_vlan_info.vlan_oid); - } - if (status != SAI_STATUS_SUCCESS) { sai_status_t status = sai_vlan_api->remove_vlan(vlan.m_vlan_info.vlan_oid); if (status != SAI_STATUS_SUCCESS) @@ -3766,6 +3757,7 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode) /* a physical port may join multiple vlans */ VlanMemberEntry vme = {vlan.m_alias, vlan_member_id, sai_tagging_mode}; port.m_vlan_members[vlan.m_vlan_info.vlan_id] = vme; + m_portVlanMember[port.m_alias][vlan.m_vlan_info.vlan_id] = vme; m_portList[port.m_alias] = port; vlan.m_members.insert(port.m_alias); if (port.m_oper_status == SAI_PORT_OPER_STATUS_UP) @@ -3794,7 +3786,7 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port) auto vlan_member = port.m_vlan_members.find(vlan.m_vlan_info.vlan_id); /* Assert the port belongs to this VLAN */ - assert (vlan_member != port.m_vlan_members.end()); + assert (vlan_member != m_portVlanMember[port.m_alias].end()); sai_tagging_mode = vlan_member->second.vlan_mode; vlan_member_id = vlan_member->second.vlan_member_id; @@ -3806,13 +3798,17 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port) return false; } port.m_vlan_members.erase(vlan_member); + auto vlan_member_rev = m_portVlanMember[port.m_alias].find(vlan.m_vlan_info.vlan_id); + m_portVlanMember[port.m_alias].erase(vlan_member_rev); + if (m_portVlanMember[port.m_alias].empty()) + m_portVlanMember.erase(port.m_alias); SWSS_LOG_NOTICE("Remove member %s from VLAN %s lid:%hx vmid:%" PRIx64, port.m_alias.c_str(), vlan.m_alias.c_str(), vlan.m_vlan_info.vlan_id, vlan_member_id); /* Restore to default pvid if this port joined this VLAN in untagged mode previously */ if (sai_tagging_mode == SAI_VLAN_TAGGING_MODE_UNTAGGED) { - if (!setPortPvid(port, 0)) + if (!setPortPvid(port, DEFAULT_PORT_VLAN_ID)) { return false; } @@ -3852,13 +3848,13 @@ bool PortsOrch::addLag(string lag_alias) if (lagport != m_portList.end()) { if ((m_portList[lag_alias].m_bridge_port_id != SAI_NULL_OBJECT_ID) && - (m_portList[lag_alias].m_vlan_members.empty())) + (m_portVlanMember[lag_alias].empty())) { return false; } return true; } - + sai_object_id_t lag_id; sai_status_t status = sai_lag_api->create_lag(&lag_id, gSwitchId, 0, NULL); @@ -3877,15 +3873,14 @@ bool PortsOrch::addLag(string lag_alias) portOidToName[lag_id] = lag_alias; m_port_ref_count[lag_alias] = 0; - /* Add lag name map to counter table */ + PortUpdate update = { lag, true }; + notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); + FieldValueTuple tuple(lag_alias, sai_serialize_object_id(lag_id)); vector fields; fields.push_back(tuple); m_counterLagTable->set("", fields); - PortUpdate update = { lag, true }; - notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); - return true; } @@ -3907,7 +3902,7 @@ bool PortsOrch::removeLag(Port lag) SWSS_LOG_ERROR("Failed to remove non-empty LAG %s", lag.m_alias.c_str()); return false; } - if (lag.m_vlan_members.size() > 0) + if (m_portVlanMember[lag.m_alias].size() > 0) { SWSS_LOG_ERROR("Failed to remove LAG %s, it is still in VLAN", lag.m_alias.c_str()); return false; @@ -4356,7 +4351,7 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status) bool isUp = status == SAI_PORT_OPER_STATUS_UP; - for(auto vlan_member: port.m_vlan_members) + for(auto vlan_member: m_portVlanMember[port.m_alias]) { auto Vlan = m_portList[vlan_member.second.alias]; auto old_count = Vlan.m_up_member_count; @@ -4386,11 +4381,23 @@ 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()); } + for (const auto &child_port : port.m_child_ports) + { + if (!gNeighOrch->ifChangeInformNextHop(child_port, isUp)) + { + SWSS_LOG_WARN("Inform nexthop operation failed for sub interface %s", child_port.c_str()); + } + } + /* flush all dynamic FDB on this port */ if (status == SAI_PORT_OPER_STATUS_DOWN) { gFdbOrch->flushFdbByPort(port.m_alias, 0); } + + PortOperStateUpdate update = {port, status}; + notify(SUBJECT_TYPE_PORT_OPER_STATE_CHANGE, static_cast(&update)); + } void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) @@ -4408,7 +4415,7 @@ void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) bool isUp = status == SAI_PORT_OPER_STATUS_UP; - for(auto vlan_member: port.m_vlan_members) + for(auto vlan_member: m_portVlanMember[port.m_alias]) { auto Vlan = m_portList[vlan_member.second.alias]; auto old_count = Vlan.m_up_member_count; @@ -4425,16 +4432,7 @@ void PortsOrch::updateLagOperStatus(Port &port, sai_port_oper_status_t status) vlan_member.second.alias.c_str(), port.m_alias.c_str(), oper_status_strings.at(port.m_oper_status).c_str(), Vlan.m_up_member_count); m_portList[Vlan.m_alias] = Vlan; - for (const auto &child_port : port.m_child_ports) - { - if (!gNeighOrch->ifChangeInformNextHop(child_port, isUp)) - { - SWSS_LOG_WARN("Inform nexthop operation failed for sub interface %s", child_port.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 eff17d0545..60486df41d 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -204,6 +204,7 @@ class PortsOrch : public Orch, public Subject map, sai_object_id_t> m_portListLaneMap; map, tuple> m_lanesAliasSpeedMap; map m_portList; + map m_portVlanMember; /* mapping from SAI object ID to Name for faster retrieval of Port/VLAN from object ID for events diff --git a/tests/conftest.py b/tests/conftest.py index a04bebaae3..6bc6b0305a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1073,7 +1073,7 @@ def getVlanOid(self, vlanId): vlan_oid = str(k) break return vlan_oid - + # deps: acl_portchannel, fdb def getCrmCounterValue(self, key, counter): counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, self.redis_sock, 0) diff --git a/tests/test_fdb_negative.py b/tests/test_fdb_negative.py index 15a4a5d5b8..4406050a42 100644 --- a/tests/test_fdb_negative.py +++ b/tests/test_fdb_negative.py @@ -277,7 +277,7 @@ def test_negativeFDB(dvs, testlog): ] ) - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_4+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth8+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -320,7 +320,7 @@ def test_negativeFDB(dvs, testlog): ] ) - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_10+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -354,7 +354,7 @@ def test_negativeFDB(dvs, testlog): print("ACTION: Deleting FDB Vlan10:52-54-00-25-06-E9:Ethernet12 from ASIC-DB") remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_10+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_10+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -387,7 +387,7 @@ def test_negativeFDB(dvs, testlog): print("ACTION: Deleting FDB Vlan4:52-54-00-25-06-E9:Ethernet8 from ASIC-DB") remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_4+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_4+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth8+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -422,7 +422,7 @@ def test_negativeFDB(dvs, testlog): print("ACTION: Deleting FDB Vlan2:52-54-00-25-06-E9:Ethernet0 from ASIC-DB") remove_entry_tbl(dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\""+vlan_oid_2+"\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\""+switch_id+"\"}") - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth0+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -589,7 +589,7 @@ def test_negativeFDB(dvs, testlog): ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])] ) - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:EB\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+iface_2_bridge_port_id["Ethernet0"]+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) @@ -597,7 +597,7 @@ def test_negativeFDB(dvs, testlog): time.sleep(2) print("Action: Moving FDB Vlan2:52-54-00-25-06-EB:Ethernet0 to non-existing bridge-port Ethernet12") - ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") + ntf = swsscommon.NotificationProducer(dvs.adb, "FDB_NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\""+vlan_oid_2+"\\\",\\\"mac\\\":\\\"52:54:00:25:06:EB\\\",\\\"switch_id\\\":\\\""+switch_id+"\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_MOVE\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\""+bp_eth12+"\"}]}]" ntf.send("fdb_event", ntf_data, fvp) From 33f513fd342a6f581393318810f68eaa2a86f9eb Mon Sep 17 00:00:00 2001 From: anilkpan <47642449+anilkpan@users.noreply.github.com> Date: Mon, 14 Dec 2020 14:47:52 -0800 Subject: [PATCH 23/24] fix lgtm issue --- orchagent/portsorch.cpp | 2 +- orchagent/portsorch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index db45f927b1..e492a80972 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -235,7 +235,7 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_flexCounterTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_TABLE)); m_flexCounterGroupTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_GROUP_TABLE)); - notifications = new swss::NotificationProducer(db, "VLANSTATE"); + notifications = unique_ptr(new swss::NotificationProducer(db, "VLANSTATE")); initGearbox(); string queueWmSha, pgWmSha; diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 60486df41d..eeb3d3662a 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -156,7 +156,7 @@ class PortsOrch : public Orch, public Subject unique_ptr
m_pgIndexTable; unique_ptr m_flexCounterTable; unique_ptr m_flexCounterGroupTable; - NotificationProducer* notifications; + unique_ptr notifications; std::string getQueueWatermarkFlexCounterTableKey(std::string s); std::string getPriorityGroupWatermarkFlexCounterTableKey(std::string s); From 94bbb5042fa658889cf87858f77235324971afbf Mon Sep 17 00:00:00 2001 From: anilkpan <47642449+anilkpan@users.noreply.github.com> Date: Mon, 14 Dec 2020 19:05:04 -0800 Subject: [PATCH 24/24] Delete .DS_Store --- .DS_Store | Bin 12292 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 72a51f15c2676a7b48a340975c3c528389245683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12292 zcmeI2du$xV9mjt^$B*63I$nnab1(a1$JlY4_<>``apIg`#7<1(Vmo#o#JR^NK5@P? zx93MCRVAvn&{n9A-^}b@ zZqE+I0wFi-NxO41znR_r&CTrZ`P~zhm1rr)x|G18l~%tTH2JMU#rtaqtkjfUE0u4KC`C8yP>kCuBo-XYoSOhUVGU( zRXr4q=X8WD>6%1@T`i)WlSKXUQn&jsvvehOI!DX~S5~>zA%k4ff@a0d zwW>OFeKa1?4D(j?4XS%M77XbzEh3BiY-?8CBh#W+wS8vcjyBaj8cs}1kSj(p)|$n; z18(X){-+Q3yCP68ax%U4eb5Nq z&=1FGbj-mW@F{o*9))khx8Nyw2A+qP;1zfk{sw=Cf51O62UlYuuE8R_0xPi!t8o)H zVmt1}0QTYgZ~)(r*WzJ3h9L}N1SinIDV)X`oX6YnBluCg9q+*h@F9E{KaXeear`cR z51+*I_zQdv7x0((GQNU;!q>zD=CIMrKG%rEI^*jX+_d{9r=26;T(A`a&UQNQy za68-yAA|eh3vd>`0Z+h>;XM3=ynGg3gx|p*;4ko3cnw~M|Dc32d8(od%drACVm-Fv z4%~^muoL%TKY6+zhwwT)N}dMs1Ww`&g%~$>0LBO=_+RLNm=pU z>P07Ydcf&{_izue_k*7fmIlmpUZnihK_@05n4L)o{-N*00lds_rU5gZ7b$N_ZFo~k zMN>2p14VNx_p|Dh2F!F`q@p>XXbx!J8BIb#es^l;=hXoNB6ZGA4>&!rxCaWTXldain z^ESwY3EC=QYf_sf0s<{hSXFRyqcu$0EzlR945ItMshcV*JF&NeFA6kB+ilOy$L^L z%KJO;lXx$F8t)_d`$hZ`ei^@lXYf%x$3^ht_=G8febB?sXg+CI~z5)M&e{-Z=k0ms}8Paa08P1Tlo#uE4 zM_Mt%8PbMP$KxDnXYmxD-M8SK_;I|8BkdXdDt?V4?f3DiWg)G7z*@m)NuYHv3AFFZ zfPFz_zZP3ZT3=dG{iZ=Bb0EEG9I=hX1u>izpEZ87$F)7E@Y;TNxfxV=w$fcC(U7J{ z!m>(@o5Bx|B-~o3G?y?tI}ph5^il*0%jx;*Q#{OGOZgeclew)oF2I3dVul2Z8u@1fzoycO3m*8DA~NsL?xTyf5DP#1;LWCR#|s3nV11lq~LCq z#fk-qI?d&Fc`w#VqRq`TFmd)#%3K@R5`|r)G7;=5b5%-Grpgr!s$DfqZ*s{iO13C< zOk;9j;w7#|rHP490ZgK(MQLTq(*h<@xKnB8%O`1K62%>^E+%-hfQd;|_EdW$DFc_5 zEmq$n`+t`hE(t8kh9zs9YXt(e8Pt^deLjs1ABi)~#!AZO&>&D zicibqTk$M=RgK803%mOTQO#3e%XJla<; zAwc({kK@uNf~8uHOWSGpxsCRpdvFiI(q4{B2MCr9a$M30mc}_QrTAVu!=;;PADS)7 z32=YwxMX`-W&zU@3vw$hn!IDnZcF%T#S|3(yU2Vqu0Z~$xSuD~Of}p8@45K@|3oe4 z?DT-s1D9kEU~czdcPF`K?K5P1$@bd)bR46DeOSGDk@6;VGPmQojc>(MnfW&|UKXJ0 gtlhjwc{9q3X7Adc09cfE;=dFB-~P7S|9$-bF9nS>S^xk5