From 756dd9c8123cd06dc581d9b2eb236334deee1850 Mon Sep 17 00:00:00 2001 From: madhanmellanox <62459540+madhanmellanox@users.noreply.github.com> Date: Fri, 20 Nov 2020 19:34:13 -0800 Subject: [PATCH] [201911 sonic-swss] Flushing FDB entries before removing BridgePort (#1516) **What I did** I added coded in sonic-swss orchagent to flush the FDB entries corresponding to the bridge port before removing the bridgeport. **Why I did it** I did it because if we don't flush the FDB entries before removing the bridge port and try to remove the bridge port, the bridge port removal results in a failure and the port operational status is set to down. **How I verified it** I created a VLAN interface, assigned IP address to it and added 2 Ethernet ports as tagged members to it. I waited for the switch to add its neighbors through these bridge ports. Then I removed VLAN membership of one of the bridge ports and see it is successful and the operational state of the port does not go down on removing the VLAN membership. **Details if related** flushFDBEntries() function is introduce in orchagent/fdborch.cpp and called from orchagent/portsorch.cpp Co-authored-by: Madhan Babu --- orchagent/fdborch.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ orchagent/fdborch.h | 2 ++ orchagent/portsorch.cpp | 4 ++++ 3 files changed, 46 insertions(+) diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9a54ba98f1bd..bb0b4b2c226a 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -416,6 +416,46 @@ void FdbOrch::doTask(NotificationConsumer& consumer) } } +void FdbOrch::flushFDBEntries(sai_object_id_t bridge_port_oid, + sai_object_id_t vlan_oid) +{ + vector attrs; + sai_attribute_t attr; + sai_status_t rv = SAI_STATUS_SUCCESS; + + SWSS_LOG_ENTER(); + + if (SAI_NULL_OBJECT_ID == bridge_port_oid && + SAI_NULL_OBJECT_ID == vlan_oid) + { + SWSS_LOG_WARN("Couldn't flush FDB. Bridge port OID: 0x%" PRIx64 " bvid:%" PRIx64 ",", + bridge_port_oid, vlan_oid); + return; + } + + if (SAI_NULL_OBJECT_ID != bridge_port_oid) + { + attr.id = SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID; + attr.value.oid = bridge_port_oid; + attrs.push_back(attr); + } + + if (SAI_NULL_OBJECT_ID != vlan_oid) + { + attr.id = SAI_FDB_FLUSH_ATTR_BV_ID; + attr.value.oid = vlan_oid; + attrs.push_back(attr); + } + + SWSS_LOG_INFO("Flushing FDB bridge_port_oid: 0x%" PRIx64 ", and bvid_oid:0x%" PRIx64 ".", bridge_port_oid, vlan_oid); + + rv = sai_fdb_api->flush_fdb_entries(gSwitchId, (uint32_t)attrs.size(), attrs.data()); + if (SAI_STATUS_SUCCESS != rv) + { + SWSS_LOG_ERROR("Flushing FDB failed. rv:%d", rv); + } +} + void FdbOrch::updateVlanMember(const VlanMemberUpdate& update) { SWSS_LOG_ENTER(); diff --git a/orchagent/fdborch.h b/orchagent/fdborch.h index 3125b3112d9d..df6368e33a16 100644 --- a/orchagent/fdborch.h +++ b/orchagent/fdborch.h @@ -46,6 +46,8 @@ 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&); + void flushFDBEntries(sai_object_id_t bridge_port_oid, + sai_object_id_t vlan_oid); private: PortsOrch *m_portsOrch; diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 1026001e3f7b..f0de66d198b1 100755 --- 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,7 @@ extern IntfsOrch *gIntfsOrch; extern NeighOrch *gNeighOrch; extern CrmOrch *gCrmOrch; extern BufferOrch *gBufferOrch; +extern FdbOrch *gFdbOrch; #define VLAN_PREFIX "Vlan" #define DEFAULT_VLAN_ID 1 @@ -3019,6 +3021,8 @@ bool PortsOrch::removeBridgePort(Port &port) /* Flush FDB entries pointing to this bridge port */ // TODO: Remove all FDB entries associated with this bridge port before // removing the bridge port itself + gFdbOrch->flushFDBEntries(port.m_bridge_port_id, SAI_NULL_OBJECT_ID); + SWSS_LOG_INFO("Flush FDB entries for port %s", port.m_alias.c_str()); /* Remove bridge port */ status = sai_bridge_api->remove_bridge_port(port.m_bridge_port_id);