-
Notifications
You must be signed in to change notification settings - Fork 691
Warm reboot: store FDB entries and warm start #615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
961de03
6918f8d
8129570
a3b436e
5c52b6c
05e8e24
5ff6401
e92fd5f
c3f8a93
162aef9
b358021
25632a4
a98a474
41de268
9ffca45
9b42775
9627c54
4ba2adf
e6f9235
97eb09c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,13 +19,14 @@ extern CrmOrch * gCrmOrch; | |
|
|
||
| const int fdborch_pri = 20; | ||
|
|
||
| FdbOrch::FdbOrch(DBConnector *db, string tableName, PortsOrch *port) : | ||
| Orch(db, tableName, fdborch_pri), | ||
| FdbOrch::FdbOrch(TableConnector applDbConnector, TableConnector stateDbConnector, PortsOrch *port) : | ||
| Orch(applDbConnector.first, applDbConnector.second, fdborch_pri), | ||
| m_portsOrch(port), | ||
| m_table(Table(db, tableName)) | ||
| m_table(applDbConnector.first, applDbConnector.second), | ||
| m_fdbStateTable(stateDbConnector.first, stateDbConnector.second) | ||
| { | ||
| m_portsOrch->attach(this); | ||
| m_flushNotificationsConsumer = new NotificationConsumer(db, "FLUSHFDBREQUEST"); | ||
| m_flushNotificationsConsumer = new NotificationConsumer(applDbConnector.first, "FLUSHFDBREQUEST"); | ||
| auto flushNotifier = new Notifier(m_flushNotificationsConsumer, this, "FLUSHFDBREQUEST"); | ||
| Orch::addExecutor(flushNotifier); | ||
|
|
||
|
|
@@ -36,6 +37,73 @@ FdbOrch::FdbOrch(DBConnector *db, string tableName, PortsOrch *port) : | |
| Orch::addExecutor(fdbNotifier); | ||
| } | ||
|
|
||
| bool FdbOrch::bake() | ||
| { | ||
| Orch::bake(); | ||
|
|
||
| auto consumer = dynamic_cast<Consumer *>(getExecutor(APP_FDB_TABLE_NAME)); | ||
| if (consumer == NULL) | ||
| { | ||
| SWSS_LOG_ERROR("No consumer %s in Orch", APP_FDB_TABLE_NAME); | ||
| return false; | ||
| } | ||
|
|
||
| size_t refilled = consumer->refillToSync(&m_fdbStateTable); | ||
| SWSS_LOG_NOTICE("Add warm input FDB State: %s, %zd", APP_FDB_TABLE_NAME, refilled); | ||
| return true; | ||
| } | ||
|
|
||
| bool FdbOrch::storeFdbEntryState(const FdbUpdate& update) | ||
| { | ||
| const FdbEntry& entry = update.entry; | ||
| const Port& port = update.port; | ||
| sai_vlan_id_t vlan_id = port.m_port_vlan_id; | ||
| const MacAddress& mac = entry.mac; | ||
| string portName = port.m_alias; | ||
|
|
||
| // ref: https://github.com/Azure/sonic-swss/blob/master/doc/swss-schema.md#fdb_table | ||
| string key = "Vlan" + to_string(vlan_id) + ":" + mac.to_string(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
should this be '|' #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently there is a trick. All entries stored in StateDB FDB_TABLE will be fed into ApplDB during warm starting. So I keep them the same pattern. In reply to: 219357862 [](ancestors = 219357862)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still feel it is more convenient to save the data in appDB using a new table like ASIC_FDB_TABLE, so to eliminate all the exception handling (stateDB save/restore during system warm reboot, and the special ":" separator in stateDB). |
||
|
|
||
| if (update.add) | ||
| { | ||
| auto inserted = m_entries.insert(entry); | ||
|
|
||
| SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%lx", | ||
| entry.mac.to_string().c_str(), entry.bv_id); | ||
|
|
||
| if (!inserted.second) | ||
| { | ||
| SWSS_LOG_INFO("FdbOrch notification: mac %s is duplicate", entry.mac.to_string().c_str()); | ||
| return false; | ||
| } | ||
|
|
||
| // Write to StateDb | ||
| std::vector<FieldValueTuple> fvs; | ||
| fvs.push_back(FieldValueTuple("port", portName)); | ||
| fvs.push_back(FieldValueTuple("type", "dynamic")); | ||
| m_fdbStateTable.set(key, fvs); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If FDB entries are saved to stateDB. During system warm reboot, will stateDB be restored? #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean will stateDB in redis persistent during warm reboot? Yes, it should be. Or do you mean if fdborch will restore from stateDB? Yes, restored in bake(). In reply to: 218964895 [](ancestors = 218964895)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stateDB will be cleared during state warm reboot. it is a problem. #Resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will save the fdb entries in state db in the warm-reboot script and recover it in the going up path. @jipanyang , thanks for the catch. #Pending
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be easier if the data is put in a separate table in appDB so no special handling is needed for stateDB? #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree easier because of the implementation detail. The design of stateDB is for SWSS state, and applDB is very old which is originally designed for inter-process communication between SWSS applications. So I made the decision to store in stateDB. BTW, there is already a FDB_TABLE (ProviderStateTable) in applDB for user custom FDB. In reply to: 218993140 [](ancestors = 218993140) |
||
|
|
||
| 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%lx", entry.mac.to_string().c_str(), entry.bv_id); | ||
|
|
||
| if (erased == 0) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| // Remove in StateDb | ||
| m_fdbStateTable.del(key); | ||
|
|
||
| gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_object_id_t bridge_port_id) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
@@ -62,22 +130,7 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj | |
| } | ||
|
|
||
| update.add = true; | ||
|
|
||
| { | ||
| auto ret = m_entries.insert(update.entry); | ||
|
|
||
| SWSS_LOG_DEBUG("FdbOrch notification: mac %s was inserted into bv_id 0x%lx", | ||
| update.entry.mac.to_string().c_str(), entry->bv_id); | ||
|
|
||
| if (ret.second) | ||
| { | ||
| gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); | ||
| } | ||
| else | ||
| { | ||
| SWSS_LOG_INFO("FdbOrch notification: mac %s is duplicate", update.entry.mac.to_string().c_str()); | ||
| } | ||
| } | ||
| storeFdbEntryState(update); | ||
|
|
||
| for (auto observer: m_observers) | ||
| { | ||
|
|
@@ -89,16 +142,7 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj | |
| case SAI_FDB_EVENT_AGED: | ||
| case SAI_FDB_EVENT_MOVE: | ||
| update.add = false; | ||
|
|
||
| { | ||
| auto ret = m_entries.erase(update.entry); | ||
| SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed from bv_id 0x%lx", update.entry.mac.to_string().c_str(), entry->bv_id); | ||
|
|
||
| if (ret) | ||
| { | ||
| gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); | ||
| } | ||
| } | ||
| storeFdbEntryState(update); | ||
|
|
||
| for (auto observer: m_observers) | ||
| { | ||
|
|
@@ -121,13 +165,12 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj | |
| update.entry.mac = itr->mac; | ||
| update.entry.bv_id = itr->bv_id; | ||
| update.add = false; | ||
| itr++; | ||
|
|
||
| itr = m_entries.erase(itr); | ||
| storeFdbEntryState(update); | ||
|
|
||
| SWSS_LOG_DEBUG("FdbOrch notification: mac %s was removed", update.entry.mac.to_string().c_str()); | ||
|
|
||
| gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_FDB_ENTRY); | ||
|
|
||
| for (auto observer: m_observers) | ||
| { | ||
| observer->update(SUBJECT_TYPE_FDB_CHANGE, &update); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,7 +69,11 @@ bool OrchDaemon::init() | |
|
|
||
| gCrmOrch = new CrmOrch(m_configDb, CFG_CRM_TABLE_NAME); | ||
| gPortsOrch = new PortsOrch(m_applDb, ports_tables); | ||
| gFdbOrch = new FdbOrch(m_applDb, APP_FDB_TABLE_NAME, gPortsOrch); | ||
|
|
||
| TableConnector applDbFdb(m_applDb, APP_FDB_TABLE_NAME); | ||
| TableConnector stateDbFdb(m_stateDb, STATE_FDB_TABLE_NAME); | ||
| gFdbOrch = new FdbOrch(applDbFdb, stateDbFdb, gPortsOrch); | ||
|
|
||
| gIntfsOrch = new IntfsOrch(m_applDb, APP_INTF_TABLE_NAME); | ||
| gNeighOrch = new NeighOrch(m_applDb, APP_NEIGH_TABLE_NAME, gIntfsOrch); | ||
| gRouteOrch = new RouteOrch(m_applDb, APP_ROUTE_TABLE_NAME, gNeighOrch); | ||
|
|
@@ -454,7 +458,7 @@ bool OrchDaemon::warmRestoreValidation() | |
| } | ||
| } | ||
| WarmStart::setWarmStartState("orchagent", WarmStart::RESTORED); | ||
| return true; | ||
| return ts.empty(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true is 1. "return !ts.empty();" or do further update? #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it, thanks #Resolved |
||
| } | ||
|
|
||
| /* | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this call fdb notification? here the consumer is the app db? how can the fdb entries in state db got translated into fdb notificastions? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In reply to: 219421390 [](ancestors = 219421390)