Skip to content

Commit bbbd5f4

Browse files
authored
[FDB] Fix fbdorch to properly handle syncd FDB FLUSH Notif (sonic-net#2254)
Vlan delete couldn't be handled by OA when there is fdb learnt on the member and when the member is deleted This inability of handling APPL_DB notif is affecting warm-restart. FDB Entry from State DB is not removed. OA doesn't have the logic to handle consolidate flush notif coming from syncd FdbOrch doesn't have logic to clear internal cache and decrement corresponding fdb counters during a flush notification Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com>
1 parent d16f8f1 commit bbbd5f4

7 files changed

Lines changed: 577 additions & 110 deletions

File tree

orchagent/fdborch.cpp

Lines changed: 123 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
extern sai_fdb_api_t *sai_fdb_api;
1919

2020
extern sai_object_id_t gSwitchId;
21-
extern PortsOrch* gPortsOrch;
2221
extern CrmOrch * gCrmOrch;
2322
extern MlagOrch* gMlagOrch;
2423
extern Directory<Orch*> gDirectory;
@@ -175,6 +174,107 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update)
175174
}
176175
}
177176

177+
/*
178+
clears stateDb and decrements corresponding internal fdb counters
179+
*/
180+
void FdbOrch::clearFdbEntry(const MacAddress& mac,
181+
const sai_object_id_t& bv_id,
182+
const string& port_alias)
183+
{
184+
FdbUpdate update;
185+
update.entry.mac = mac;
186+
update.entry.bv_id = bv_id;
187+
update.add = false;
188+
189+
/* Fetch Vlan and decrement the counter */
190+
Port temp_vlan;
191+
if (m_portsOrch->getPort(bv_id, temp_vlan))
192+
{
193+
m_portsOrch->decrFdbCount(temp_vlan.m_alias, 1);
194+
}
195+
196+
/* Decrement port fdb_counter */
197+
m_portsOrch->decrFdbCount(port_alias, 1);
198+
199+
/* Remove the FdbEntry from the internal cache, update state DB and CRM counter */
200+
storeFdbEntryState(update);
201+
notify(SUBJECT_TYPE_FDB_CHANGE, &update);
202+
203+
SWSS_LOG_INFO("FdbEntry removed from internal cache, MAC: %s , port: %s, BVID: 0x%" PRIx64,
204+
mac.to_string().c_str(), port_alias.c_str(), bv_id);
205+
}
206+
207+
/*
208+
Handles the SAI_FDB_EVENT_FLUSHED notification recieved from syncd
209+
*/
210+
void FdbOrch::handleSyncdFlushNotif(const sai_object_id_t& bv_id,
211+
const sai_object_id_t& bridge_port_id,
212+
const MacAddress& mac)
213+
{
214+
// Consolidated flush will have a zero mac
215+
MacAddress flush_mac("00:00:00:00:00:00");
216+
217+
/* TODO: Read the SAI_FDB_FLUSH_ATTR_ENTRY_TYPE attr from the flush notif
218+
and clear the entries accordingly, currently only non-static entries are flushed
219+
*/
220+
if (bridge_port_id == SAI_NULL_OBJECT_ID && bv_id == SAI_NULL_OBJECT_ID)
221+
{
222+
for (auto itr = m_entries.begin(); itr != m_entries.end();)
223+
{
224+
auto curr = itr++;
225+
if (curr->second.type != "static" && (curr->first.mac == mac || mac == flush_mac))
226+
{
227+
clearFdbEntry(curr->first.mac, curr->first.bv_id, curr->first.port_name);
228+
}
229+
}
230+
}
231+
else if (bv_id == SAI_NULL_OBJECT_ID)
232+
{
233+
/* FLUSH based on PORT */
234+
for (auto itr = m_entries.begin(); itr != m_entries.end();)
235+
{
236+
auto curr = itr++;
237+
if (curr->second.bridge_port_id == bridge_port_id)
238+
{
239+
if (curr->second.type != "static" && (curr->first.mac == mac || mac == flush_mac))
240+
{
241+
clearFdbEntry(curr->first.mac, curr->first.bv_id, curr->first.port_name);
242+
}
243+
}
244+
}
245+
}
246+
else if (bridge_port_id == SAI_NULL_OBJECT_ID)
247+
{
248+
/* FLUSH based on BV_ID */
249+
for (auto itr = m_entries.begin(); itr != m_entries.end();)
250+
{
251+
auto curr = itr++;
252+
if (curr->first.bv_id == bv_id)
253+
{
254+
if (curr->second.type != "static" && (curr->first.mac == mac || mac == flush_mac))
255+
{
256+
clearFdbEntry(curr->first.mac, curr->first.bv_id, curr->first.port_name);
257+
}
258+
}
259+
}
260+
}
261+
else
262+
{
263+
/* FLUSH based on port and VLAN */
264+
for (auto itr = m_entries.begin(); itr != m_entries.end();)
265+
{
266+
auto curr = itr++;
267+
if (curr->first.bv_id == bv_id && curr->second.bridge_port_id == bridge_port_id)
268+
{
269+
if (curr->second.type != "static" && (curr->first.mac == mac || mac == flush_mac))
270+
{
271+
clearFdbEntry(curr->first.mac, curr->first.bv_id, curr->first.port_name);
272+
}
273+
}
274+
}
275+
}
276+
}
277+
178278
void FdbOrch::update(sai_fdb_event_t type,
179279
const sai_fdb_entry_t* entry,
180280
sai_object_id_t bridge_port_id)
@@ -192,24 +292,29 @@ void FdbOrch::update(sai_fdb_event_t type,
192292
type, update.entry.mac.to_string().c_str(),
193293
entry->bv_id, bridge_port_id);
194294

195-
196295
if (bridge_port_id &&
197296
!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port))
198297
{
199298
if (type == SAI_FDB_EVENT_FLUSHED)
200299
{
201-
/* In case of flush - can be ignored due to a race.
202-
There are notifications about FDB FLUSH (syncd/sai_redis) on port,
203-
which was already removed by orchagent as a result of
204-
removeVlanMember action (removeBridgePort) */
300+
/* There are notifications about FDB FLUSH (syncd/sai_redis) on port,
301+
which was already removed by orchagent as a result of removeVlanMember
302+
action (removeBridgePort). But the internal cleanup of statedb and
303+
internal counters is yet to be performed, thus continue
304+
*/
205305
SWSS_LOG_INFO("Flush event: Failed to get port by bridge port ID 0x%" PRIx64 ".",
206306
bridge_port_id);
207-
208307
} else {
209308
SWSS_LOG_ERROR("Failed to get port by bridge port ID 0x%" PRIx64 ".",
210309
bridge_port_id);
211-
310+
return;
212311
}
312+
}
313+
314+
if (entry->bv_id &&
315+
!m_portsOrch->getPort(entry->bv_id, vlan))
316+
{
317+
SWSS_LOG_NOTICE("FdbOrch notification type %d: Failed to locate vlan port from bv_id 0x%" PRIx64, type, entry->bv_id);
213318
return;
214319
}
215320

@@ -219,12 +324,6 @@ void FdbOrch::update(sai_fdb_event_t type,
219324
{
220325
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);
221326

222-
if (!m_portsOrch->getPort(entry->bv_id, vlan))
223-
{
224-
SWSS_LOG_ERROR("FdbOrch LEARN notification: Failed to locate vlan port from bv_id 0x%" PRIx64, entry->bv_id);
225-
return;
226-
}
227-
228327
// we already have such entries
229328
auto existing_entry = m_entries.find(update.entry);
230329
if (existing_entry != m_entries.end())
@@ -319,11 +418,6 @@ void FdbOrch::update(sai_fdb_event_t type,
319418
SWSS_LOG_INFO("Received AGE event for bvid=0x%" PRIx64 " mac=%s port=0x%" PRIx64,
320419
entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id);
321420

322-
if (!m_portsOrch->getPort(entry->bv_id, vlan))
323-
{
324-
SWSS_LOG_NOTICE("FdbOrch AGE notification: Failed to locate vlan port from bv_id 0x%" PRIx64, entry->bv_id);
325-
}
326-
327421
auto existing_entry = m_entries.find(update.entry);
328422
// we don't have such entries
329423
if (existing_entry == m_entries.end())
@@ -457,12 +551,6 @@ void FdbOrch::update(sai_fdb_event_t type,
457551
SWSS_LOG_INFO("Received MOVE event for bvid=0x%" PRIx64 " mac=%s port=0x%" PRIx64,
458552
entry->bv_id, update.entry.mac.to_string().c_str(), bridge_port_id);
459553

460-
if (!m_portsOrch->getPort(entry->bv_id, vlan))
461-
{
462-
SWSS_LOG_ERROR("FdbOrch MOVE notification: Failed to locate vlan port from bv_id 0x%" PRIx64, entry->bv_id);
463-
return;
464-
}
465-
466554
// We should already have such entry
467555
if (existing_entry == m_entries.end())
468556
{
@@ -500,80 +588,15 @@ void FdbOrch::update(sai_fdb_event_t type,
500588
bridge_port_id);
501589

502590
string vlanName = "-";
503-
if (entry->bv_id) {
504-
Port vlan;
505-
506-
if (!m_portsOrch->getPort(entry->bv_id, vlan))
507-
{
508-
SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate vlan\
509-
port from bv_id 0x%" PRIx64, entry->bv_id);
510-
return;
511-
}
591+
if (!vlan.m_alias.empty()) {
512592
vlanName = "Vlan" + to_string(vlan.m_vlan_info.vlan_id);
513593
}
514594

595+
SWSS_LOG_INFO("FDB Flush: [ %s , %s ] = { port: %s }", update.entry.mac.to_string().c_str(),
596+
vlanName.c_str(), update.port.m_alias.c_str());
515597

516-
if (bridge_port_id == SAI_NULL_OBJECT_ID &&
517-
entry->bv_id == SAI_NULL_OBJECT_ID)
518-
{
519-
SWSS_LOG_INFO("FDB Flush: [ %s , %s ] = { port: - }",
520-
update.entry.mac.to_string().c_str(), vlanName.c_str());
521-
for (auto itr = m_entries.begin(); itr != m_entries.end();)
522-
{
523-
/*
524-
TODO: here should only delete the dynamic fdb entries,
525-
but unfortunately in structure FdbEntry currently have
526-
no member to indicate the fdb entry type,
527-
if there is static mac added, here will have issue.
528-
*/
529-
update.entry.mac = itr->first.mac;
530-
update.entry.bv_id = itr->first.bv_id;
531-
update.add = false;
532-
itr++;
533-
534-
storeFdbEntryState(update);
535-
536-
notify(SUBJECT_TYPE_FDB_CHANGE, &update);
537-
538-
}
539-
}
540-
else if (entry->bv_id == SAI_NULL_OBJECT_ID)
541-
{
542-
/* FLUSH based on port */
543-
SWSS_LOG_INFO("FDB Flush: [ %s , %s ] = { port: %s }",
544-
update.entry.mac.to_string().c_str(),
545-
vlanName.c_str(), update.port.m_alias.c_str());
546-
547-
for (auto itr = m_entries.begin(); itr != m_entries.end();)
548-
{
549-
auto next_item = std::next(itr);
550-
if (itr->first.port_name == update.port.m_alias)
551-
{
552-
update.entry.mac = itr->first.mac;
553-
update.entry.bv_id = itr->first.bv_id;
554-
update.add = false;
598+
handleSyncdFlushNotif(entry->bv_id, bridge_port_id, update.entry.mac);
555599

556-
storeFdbEntryState(update);
557-
notify(SUBJECT_TYPE_FDB_CHANGE, &update);
558-
}
559-
itr = next_item;
560-
}
561-
}
562-
else if (bridge_port_id == SAI_NULL_OBJECT_ID)
563-
{
564-
/* FLUSH based on VLAN - unsupported */
565-
SWSS_LOG_ERROR("Unsupported FDB Flush: [ %s , %s ] = { port: - }",
566-
update.entry.mac.to_string().c_str(),
567-
vlanName.c_str());
568-
569-
}
570-
else
571-
{
572-
/* FLUSH based on port and VLAN - unsupported */
573-
SWSS_LOG_ERROR("Unsupported FDB Flush: [ %s , %s ] = { port: %s }",
574-
update.entry.mac.to_string().c_str(),
575-
vlanName.c_str(), update.port.m_alias.c_str());
576-
}
577600
break;
578601
}
579602

@@ -649,7 +672,7 @@ void FdbOrch::doTask(Consumer& consumer)
649672
{
650673
SWSS_LOG_ENTER();
651674

652-
if (!gPortsOrch->allPortsReady())
675+
if (!m_portsOrch->allPortsReady())
653676
{
654677
return;
655678
}
@@ -856,7 +879,7 @@ void FdbOrch::doTask(NotificationConsumer& consumer)
856879
{
857880
SWSS_LOG_ENTER();
858881

859-
if (!gPortsOrch->allPortsReady())
882+
if (!m_portsOrch->allPortsReady())
860883
{
861884
return;
862885
}
@@ -892,7 +915,7 @@ void FdbOrch::doTask(NotificationConsumer& consumer)
892915
SWSS_LOG_ERROR("Receive wrong port to flush fdb!");
893916
return;
894917
}
895-
if (!gPortsOrch->getPort(alias, port))
918+
if (!m_portsOrch->getPort(alias, port))
896919
{
897920
SWSS_LOG_ERROR("Get Port from port(%s) failed!", alias.c_str());
898921
return;
@@ -913,7 +936,7 @@ void FdbOrch::doTask(NotificationConsumer& consumer)
913936
SWSS_LOG_ERROR("Receive wrong vlan to flush fdb!");
914937
return;
915938
}
916-
if (!gPortsOrch->getPort(vlan, vlanPort))
939+
if (!m_portsOrch->getPort(vlan, vlanPort))
917940
{
918941
SWSS_LOG_ERROR("Get Port from vlan(%s) failed!", vlan.c_str());
919942
return;
@@ -939,12 +962,12 @@ void FdbOrch::doTask(NotificationConsumer& consumer)
939962
SWSS_LOG_ERROR("Receive wrong port or vlan to flush fdb!");
940963
return;
941964
}
942-
if (!gPortsOrch->getPort(alias, port))
965+
if (!m_portsOrch->getPort(alias, port))
943966
{
944967
SWSS_LOG_ERROR("Get Port from port(%s) failed!", alias.c_str());
945968
return;
946969
}
947-
if (!gPortsOrch->getPort(vlan, vlanPort))
970+
if (!m_portsOrch->getPort(vlan, vlanPort))
948971
{
949972
SWSS_LOG_ERROR("Get Port from vlan(%s) failed!", vlan.c_str());
950973
return;

orchagent/fdborch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ class FdbOrch: public Orch, public Subject, public Observer
122122

123123
bool storeFdbEntryState(const FdbUpdate& update);
124124
void notifyTunnelOrch(Port& port);
125+
126+
void clearFdbEntry(const MacAddress&, const sai_object_id_t&, const string&);
127+
void handleSyncdFlushNotif(const sai_object_id_t&, const sai_object_id_t&, const MacAddress& );
125128
};
126129

127130
#endif /* SWSS_FDBORCH_H */

orchagent/portsorch.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4573,9 +4573,10 @@ bool PortsOrch::removeVlan(Port vlan)
45734573
return false for retry */
45744574
if (vlan.m_fdb_count > 0)
45754575
{
4576-
SWSS_LOG_NOTICE("VLAN %s still has assiciated FDB entries", vlan.m_alias.c_str());
4576+
SWSS_LOG_NOTICE("VLAN %s still has %d FDB entries", vlan.m_alias.c_str(), vlan.m_fdb_count);
45774577
return false;
45784578
}
4579+
45794580
if (m_port_ref_count[vlan.m_alias] > 0)
45804581
{
45814582
SWSS_LOG_ERROR("Failed to remove ref count %d VLAN %s",
@@ -6928,3 +6929,17 @@ std::unordered_set<std::string> PortsOrch::generateCounterStats(const string& ty
69286929
}
69296930
return counter_stats;
69306931
}
6932+
6933+
bool PortsOrch::decrFdbCount(const std::string& alias, int count)
6934+
{
6935+
auto itr = m_portList.find(alias);
6936+
if (itr == m_portList.end())
6937+
{
6938+
return false;
6939+
}
6940+
else
6941+
{
6942+
itr->second.m_fdb_count -= count;
6943+
}
6944+
return true;
6945+
}

orchagent/portsorch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class PortsOrch : public Orch, public Subject
168168

169169
bool getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const;
170170

171+
bool decrFdbCount(const string& alias, int count);
171172
private:
172173
unique_ptr<Table> m_counterTable;
173174
unique_ptr<Table> m_counterLagTable;

tests/mock_tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ tests_SOURCES = aclorch_ut.cpp \
2626
routeorch_ut.cpp \
2727
qosorch_ut.cpp \
2828
bufferorch_ut.cpp \
29+
fdborch/flush_syncd_notif_ut.cpp \
2930
copporch_ut.cpp \
3031
saispy_ut.cpp \
3132
consumer_ut.cpp \

0 commit comments

Comments
 (0)