-
Notifications
You must be signed in to change notification settings - Fork 517
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
[orchagent]: Remove global lock caused by notifications running in another thread #478
Changes from 5 commits
b0cac37
f61cacb
94fcb19
e90839d
a8408c3
e337326
b6f857b
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 |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
#include "fdborch.h" | ||
#include "crmorch.h" | ||
#include "notifier.h" | ||
#include "sai_serialize.h" | ||
|
||
extern sai_fdb_api_t *sai_fdb_api; | ||
|
||
|
@@ -25,8 +26,14 @@ FdbOrch::FdbOrch(DBConnector *db, string tableName, PortsOrch *port) : | |
{ | ||
m_portsOrch->attach(this); | ||
auto consumer = new NotificationConsumer(db, "FLUSHFDBREQUEST"); | ||
auto fdbNotification = new Notifier(consumer, this); | ||
auto fdbNotification = new Notifier(consumer, this, "FLUSHFDBREQUEST"); | ||
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.
Confused about fdbNotification vs fdb_notification. What is the diff? #Closed 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. Renamed all the variable names for notification related stuff |
||
Orch::addExecutor("", fdbNotification); | ||
|
||
/* Add FDB notification support from ASIC */ | ||
DBConnector *notification_db = new DBConnector(ASIC_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
auto notification_consumer = new swss::NotificationConsumer(notification_db, "NOTIFICATIONS"); | ||
auto fdb_notification = new Notifier(notification_consumer, this, "NOTIFICATIONS"); | ||
Orch::addExecutor("FDB_NOTIFICATIONS", fdb_notification); | ||
} | ||
|
||
void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_object_id_t bridge_port_id) | ||
|
@@ -274,7 +281,7 @@ void FdbOrch::doTask(Consumer& consumer) | |
} | ||
} | ||
|
||
void FdbOrch::doTask(NotificationConsumer& consumer) | ||
void FdbOrch::doTask(NotificationConsumer& consumer, const std::string &name) | ||
{ | ||
SWSS_LOG_ENTER(); | ||
|
||
|
@@ -290,36 +297,64 @@ void FdbOrch::doTask(NotificationConsumer& consumer) | |
|
||
consumer.pop(op, data, values); | ||
|
||
if (op == "ALL") | ||
if (name == "FLUSHFDBREQUEST") | ||
{ | ||
/* | ||
* 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) | ||
if (op == "ALL") | ||
{ | ||
SWSS_LOG_ERROR("Flush fdb failed, return code %x", status); | ||
} | ||
/* | ||
* 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); | ||
} | ||
|
||
return; | ||
} | ||
else if (op == "PORT") | ||
{ | ||
/*place holder for flush port fdb*/ | ||
SWSS_LOG_ERROR("Received unsupported flush port fdb request"); | ||
return; | ||
} | ||
else if (op == "VLAN") | ||
{ | ||
/*place holder for flush vlan fdb*/ | ||
SWSS_LOG_ERROR("Received unsupported flush vlan fdb request"); | ||
return; | ||
return; | ||
} | ||
else if (op == "PORT") | ||
{ | ||
/*place holder for flush port fdb*/ | ||
SWSS_LOG_ERROR("Received unsupported flush port fdb request"); | ||
return; | ||
} | ||
else if (op == "VLAN") | ||
{ | ||
/*place holder for flush vlan fdb*/ | ||
SWSS_LOG_ERROR("Received unsupported flush vlan fdb request"); | ||
return; | ||
} | ||
else | ||
{ | ||
SWSS_LOG_ERROR("Received unknown flush fdb request"); | ||
return; | ||
} | ||
} | ||
else | ||
else if (name == "NOTIFICATIONS" && op == "fdb_event") | ||
{ | ||
SWSS_LOG_ERROR("Received unknown flush fdb request"); | ||
return; | ||
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); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,8 @@ | |
|
||
class Notifier : public Executor { | ||
public: | ||
Notifier(NotificationConsumer *select, Orch *orch) | ||
: Executor(select, orch) | ||
Notifier(NotificationConsumer *select, Orch *orch, const std::string& notifier_name) | ||
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 notice there is a similar name at NotificationConsumer.m_channel. I prefer using that one instread of a new parameter. #Closed 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. Renamed to m_channel #Closed 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. Let me clarify. I mean you could use getNotificationConsumer()->m_channel internally, instead ask user provide a new argument. In reply to: 182863130 [](ancestors = 182863130) |
||
: Executor(select, orch), m_name(notifier_name) | ||
{ | ||
} | ||
|
||
|
@@ -14,6 +14,9 @@ class Notifier : public Executor { | |
|
||
void execute() | ||
{ | ||
m_orch->doTask(*getNotificationConsumer()); | ||
m_orch->doTask(*getNotificationConsumer(), m_name); | ||
} | ||
|
||
private: | ||
std::string m_name; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -152,7 +152,7 @@ class Orch | |
|
||
/* Run doTask against a specific executor */ | ||
virtual void doTask(Consumer &consumer) = 0; | ||
virtual void doTask(NotificationConsumer &consumer) { } | ||
virtual void doTask(NotificationConsumer &consumer, const std::string &name) { } | ||
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.
can you add a comment on the name, what does this name use for? 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. Comments added 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've also renamed this parameter to more clear name |
||
virtual void doTask(SelectableTimer &timer) { } | ||
|
||
/* TODO: refactor recording */ | ||
|
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.
Can we define the notification events as enumerations and derive the names from them? This way, we can put them in a common place so no hardcode of strings from different places.
Also, it would make the addition of future events implementation easier in case we want to implement the existing notification events or new added events.
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.
With enumerations we will have hardcoded enumerations.
I think in this case it's better to develop better abstraction than NotificationConsumer(). Currently it's connected too deep into Orch class (doTask methods for NotificationConsumer). We should decouple them from each other and implement doTask methods as a base class for Orch classes.
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.
I agree more changes is needed for a better abstraction than what we have today. but I am not sure if you are going to do it in this PR.
My point was, at least we should put the message types in a common place and reuse then on different places so you don't end up with mistype something and get run-time problem. enumerations will detect the errors during the build time not run time if you mistyped, also by putting things in the same place improves manageability and extendability.
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.
I agree with you that enumerations will work better here. But what I don't like with this approach is to have one common enum for all cases. I better prefer to have a separateenumeration for every class. Otherwise it's not clear what notifications could come to a target doTask.
Anyway, after Qi's comment I removed the string parameter. You can check new version of the code.
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.
Thank you for your comments, anyway