-
Notifications
You must be signed in to change notification settings - Fork 689
[AclOrch] aclOrch enhancement to handle LAG port not configured case #494
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 6 commits
3bf6269
bf93016
f2d3035
032e862
c6dcd31
de11d51
d32c1c1
c670c3b
3e56f49
de198bd
be203be
0499f41
879d7fe
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 |
|---|---|---|
|
|
@@ -936,7 +936,7 @@ bool AclTable::validate() | |
| { | ||
| // Control plane ACLs are handled by a separate process | ||
| if (type == ACL_TABLE_UNKNOWN || type == ACL_TABLE_CTRLPLANE) return false; | ||
| if (ports.empty()) return false; | ||
| if (portSet.empty()) return false; | ||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -1365,8 +1365,8 @@ bool AclRange::remove() | |
| return true; | ||
| } | ||
|
|
||
| AclOrch::AclOrch(DBConnector *db, vector<string> tableNames, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch) : | ||
| Orch(db, tableNames), | ||
| AclOrch::AclOrch(vector<TableConnector>& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch) : | ||
| Orch(connectors), | ||
| m_mirrorOrch(mirrorOrch), | ||
| m_neighOrch(neighOrch), | ||
| m_routeOrch(routeOrch) | ||
|
|
@@ -1449,6 +1449,11 @@ void AclOrch::doTask(Consumer &consumer) | |
| unique_lock<mutex> lock(m_countersMutex); | ||
| doAclRuleTask(consumer); | ||
| } | ||
| else if (table_name == STATE_LAG_TABLE_NAME) | ||
| { | ||
| unique_lock<mutex> lock(m_countersMutex); | ||
| doAclTablePortUpdateTask(consumer); | ||
| } | ||
| else | ||
| { | ||
| SWSS_LOG_ERROR("Invalid table %s", table_name.c_str()); | ||
|
|
@@ -1584,7 +1589,7 @@ void AclOrch::doAclTableTask(Consumer &consumer) | |
| } | ||
| else if (attr_name == TABLE_PORTS) | ||
| { | ||
| bool suc = processPorts(attr_value, [&](sai_object_id_t portOid) { | ||
| bool suc = processPorts(newTable, attr_value, [&](sai_object_id_t portOid) { | ||
| newTable.link(portOid); | ||
| }); | ||
|
|
||
|
|
@@ -1729,17 +1734,114 @@ void AclOrch::doAclRuleTask(Consumer &consumer) | |
| } | ||
| } | ||
|
|
||
| bool AclOrch::processPorts(string portsList, std::function<void (sai_object_id_t)> inserter) | ||
| void AclOrch::doAclTablePortUpdateTask(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); | ||
| size_t found = key.find('|'); | ||
| string port_alias = key.substr(0, found); | ||
| string op = kfvOp(t); | ||
|
|
||
| SWSS_LOG_INFO("doAclTablePortUpdateTask: OP: %s, port_alias: %s", op.c_str(), port_alias.c_str()); | ||
|
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.
this is debug level message. |
||
|
|
||
| if (op == SET_COMMAND) | ||
| { | ||
| for (auto itmap : m_AclTables) | ||
| { | ||
| auto table = itmap.second; | ||
| if (table.pendingPortSet.find(port_alias) != table.pendingPortSet.end()) | ||
| { | ||
| SWSS_LOG_INFO("found the port: %s in ACL table: %s pending port list, bind it to ACL table.", port_alias.c_str(), table.description.c_str()); | ||
|
|
||
| bool suc = processPendingPort(table, port_alias, [&](sai_object_id_t portOid) { | ||
| table.link(portOid); | ||
| }); | ||
|
|
||
| if (!suc) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to bind the ACL table: %s to port: %s", table.description.c_str(), port_alias.c_str()); | ||
| } | ||
| else | ||
| { | ||
| table.pendingPortSet.erase(port_alias); | ||
| SWSS_LOG_NOTICE("port: %s bound to ACL table table: %s, remove it from pending list", port_alias.c_str(), table.description.c_str()); | ||
|
||
| } | ||
| } | ||
| } | ||
| } | ||
| else if (op == DEL_COMMAND) | ||
| { | ||
| for (auto itmap : m_AclTables) | ||
| { | ||
| auto table = itmap.second; | ||
| if (table.portSet.find(port_alias) != table.portSet.end()) | ||
| { | ||
| table.pendingPortSet.emplace(port_alias); | ||
| SWSS_LOG_WARN("Add deleted port: %s to the pending list of ACL table: %s", port_alias.c_str(), table.description.c_str()); | ||
|
||
| } | ||
| } | ||
|
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. what is the scenario here? when a port is removed, then to update the acl table? In this case, you need to unbind the port from acl table, and then put the port to pending list. You cannot simply put the port into the pending list.
Collaborator
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. for this one maybe need to marked as TODO here. if one port or LAG deleted, do will still have the chance to unbind it? I mean maybe some DB entries already destroyed and for SDK level all the configuration should already be cleared? |
||
| } | ||
| else | ||
| { | ||
| SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); | ||
| } | ||
| it = consumer.m_toSync.erase(it); | ||
| } | ||
| } | ||
|
|
||
| sai_object_id_t AclOrch::getValidPortId(string alias, Port port) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| sai_object_id_t port_id; | ||
|
||
|
|
||
| switch (port.m_type) | ||
| { | ||
| case Port::PHY: | ||
| if (port.m_lag_member_id != SAI_NULL_OBJECT_ID) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to process port. Bind table to LAG member %s is not allowed", alias.c_str()); | ||
|
||
| port_id = SAI_NULL_OBJECT_ID; | ||
|
||
| } | ||
| else | ||
| { | ||
| port_id = port.m_port_id; | ||
| } | ||
| break; | ||
| case Port::LAG: | ||
| port_id = port.m_lag_id; | ||
| break; | ||
| case Port::VLAN: | ||
| port_id = port.m_vlan_info.vlan_oid; | ||
| break; | ||
| default: | ||
| SWSS_LOG_ERROR("Failed to process port. Incorrect port %s type %d", alias.c_str(), port.m_type); | ||
| port_id = SAI_NULL_OBJECT_ID; | ||
|
||
| break; | ||
| } | ||
|
|
||
| return port_id; | ||
| } | ||
|
|
||
| bool AclOrch::processPorts(AclTable &aclTable, string portsList, std::function<void (sai_object_id_t)> inserter) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| sai_object_id_t port_id; | ||
|
||
|
|
||
| vector<string> strList; | ||
|
|
||
| SWSS_LOG_INFO("Processing ACL table port list %s", portsList.c_str()); | ||
|
||
|
|
||
| split(portsList, strList, ','); | ||
|
|
||
| set<string> strSet(strList.begin(), strList.end()); | ||
| aclTable.portSet = strSet; | ||
|
|
||
| if (strList.size() != strSet.size()) | ||
| { | ||
|
|
@@ -1758,30 +1860,50 @@ bool AclOrch::processPorts(string portsList, std::function<void (sai_object_id_t | |
| Port port; | ||
| if (!gPortsOrch->getPort(alias, port)) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to process port. Port %s doesn't exist", alias.c_str()); | ||
| return false; | ||
| SWSS_LOG_WARN("Port %s not configured yet, add it to ACL table %s pending list", alias.c_str(), aclTable.description.c_str()); | ||
|
||
| aclTable.pendingPortSet.emplace(alias); | ||
| continue; | ||
| } | ||
|
|
||
| switch (port.m_type) | ||
| port_id = getValidPortId(alias, port); | ||
| if (port_id != SAI_NULL_OBJECT_ID) | ||
| { | ||
| case Port::PHY: | ||
| if (port.m_lag_member_id != SAI_NULL_OBJECT_ID) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to process port. Bind table to LAG member %s is not allowed", alias.c_str()); | ||
| return false; | ||
| } | ||
| inserter(port.m_port_id); | ||
| break; | ||
| case Port::LAG: | ||
| inserter(port.m_lag_id); | ||
| break; | ||
| case Port::VLAN: | ||
| inserter(port.m_vlan_info.vlan_oid); | ||
| break; | ||
| default: | ||
| SWSS_LOG_ERROR("Failed to process port. Incorrect port %s type %d", alias.c_str(), port.m_type); | ||
| return false; | ||
| } | ||
| inserter(port_id); | ||
| } | ||
| else | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool AclOrch::processPendingPort(AclTable &aclTable, string portAlias, std::function<void (sai_object_id_t)> inserter) | ||
| { | ||
| SWSS_LOG_ENTER(); | ||
|
|
||
| SWSS_LOG_INFO("Processing ACL table port %s", portAlias.c_str()); | ||
|
||
|
|
||
| sai_object_id_t port_id; | ||
|
|
||
| Port port; | ||
| if (!gPortsOrch->getPort(portAlias, port)) | ||
| { | ||
| SWSS_LOG_WARN("Port %s not configured yet, add it to ACL table %s pending list", portAlias.c_str(), aclTable.description.c_str()); | ||
|
||
| aclTable.pendingPortSet.insert(portAlias); | ||
| return true; | ||
| } | ||
|
|
||
| port_id = getValidPortId(portAlias, port); | ||
| if (port_id != SAI_NULL_OBJECT_ID) | ||
| { | ||
| inserter(port_id); | ||
| aclTable.bind(port_id); | ||
|
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.
move this out of processPendingPort() so that you can reuse this function.
Collaborator
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 have clarified with Qi before, my view is that these two functions do share some same code, but since processPorts is for "normal" flow and for processPendingPort is dedicated to receiving the notification and handle the pending port, to keep the code more straightforward, I feel like to have these two functions separated though will have some slight redundant code. |
||
| } | ||
| else | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
|
|
@@ -1898,18 +2020,14 @@ sai_status_t AclOrch::bindAclTable(sai_object_id_t table_oid, AclTable &aclTable | |
| sai_status_t status = SAI_STATUS_SUCCESS; | ||
|
|
||
| SWSS_LOG_INFO("%s table %s to ports", bind ? "Bind" : "Unbind", aclTable.id.c_str()); | ||
|
|
||
| if (aclTable.ports.empty()) | ||
| { | ||
| if (bind) | ||
| { | ||
| SWSS_LOG_ERROR("Port list is not configured for %s table", aclTable.id.c_str()); | ||
| return SAI_STATUS_FAILURE; | ||
| } | ||
| else | ||
| { | ||
| return SAI_STATUS_SUCCESS; | ||
| SWSS_LOG_WARN("Binding port list is empty for %s table", aclTable.id.c_str()); | ||
| } | ||
| return SAI_STATUS_SUCCESS; | ||
| } | ||
|
|
||
| if (bind) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -248,6 +248,10 @@ class AclTable { | |
| std::map<sai_object_id_t, sai_object_id_t> ports; | ||
| // Map rule name to rule data | ||
| map<string, shared_ptr<AclRule>> rules; | ||
| // Set to store the ACL table port alias | ||
| set<string> portSet; | ||
| // Set to store the not cofigured ACL table port alias | ||
| set<string> pendingPortSet; | ||
|
|
||
| AclTable() | ||
| : type(ACL_TABLE_UNKNOWN) | ||
|
|
@@ -294,7 +298,7 @@ inline void split(string str, Iterable& out, char delim = ' ') | |
| class AclOrch : public Orch, public Observer | ||
| { | ||
| public: | ||
| AclOrch(DBConnector *db, vector<string> tableNames, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch); | ||
| AclOrch(vector<TableConnector>& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch); | ||
| ~AclOrch(); | ||
| void update(SubjectType, void *); | ||
|
|
||
|
|
@@ -319,6 +323,7 @@ class AclOrch : public Orch, public Observer | |
| void doTask(Consumer &consumer); | ||
| void doAclTableTask(Consumer &consumer); | ||
| void doAclRuleTask(Consumer &consumer); | ||
| void doAclTablePortUpdateTask(Consumer &consumer); | ||
| void doTask(SelectableTimer &timer); | ||
|
|
||
| static void collectCountersThread(AclOrch *pAclOrch); | ||
|
|
@@ -329,8 +334,10 @@ class AclOrch : public Orch, public Observer | |
|
|
||
| bool processAclTableType(string type, acl_table_type_t &table_type); | ||
| bool processAclTableStage(string stage, acl_stage_type_t &acl_stage); | ||
| bool processPorts(string portsList, std::function<void (sai_object_id_t)> inserter); | ||
| bool processPorts(AclTable &aclTable, string portsList, std::function<void (sai_object_id_t)> inserter); | ||
| bool processPendingPort(AclTable &aclTable, string portAlias, std::function<void (sai_object_id_t)> inserter); | ||
| bool validateAclTable(AclTable &aclTable); | ||
| sai_object_id_t getValidPortId(string alias, Port port); | ||
|
||
|
|
||
| //vector <AclTable> m_AclTables; | ||
| map <sai_object_id_t, AclTable> m_AclTables; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -247,13 +247,15 @@ int main(int argc, char **argv) | |
| SWSS_LOG_NOTICE("Created underlay router interface ID %lx", gUnderlayIfId); | ||
|
|
||
| /* Initialize orchestration components */ | ||
| DBConnector *appl_db = new DBConnector(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
| DBConnector *config_db = new DBConnector(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
| DBConnector appl_db(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
| DBConnector config_db(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
| DBConnector state_db(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); | ||
|
|
||
| OrchDaemon *orchDaemon = new OrchDaemon(appl_db, config_db); | ||
|
Collaborator
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 don't think we would need to have orchDaemon allocate from stack. This could still be retained as it is (allocate via
Collaborator
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. revised. |
||
| OrchDaemon *orchDaemon = new OrchDaemon(&appl_db, &config_db, &state_db); | ||
| if (!orchDaemon->init()) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to initialize orchstration daemon"); | ||
| delete orchDaemon; | ||
| exit(EXIT_FAILURE); | ||
| } | ||
|
|
||
|
|
@@ -268,6 +270,7 @@ int main(int argc, char **argv) | |
| if (status != SAI_STATUS_SUCCESS) | ||
| { | ||
| SWSS_LOG_ERROR("Failed to notify syncd APPLY_VIEW %d", status); | ||
| delete orchDaemon; | ||
| exit(EXIT_FAILURE); | ||
| } | ||
|
|
||
|
|
@@ -282,5 +285,6 @@ int main(int argc, char **argv) | |
| SWSS_LOG_ERROR("Failed due to exception: %s", e.what()); | ||
| } | ||
|
|
||
| delete orchDaemon; | ||
| return 0; | ||
| } | ||
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.
are we still hardcoding this separator? We need to get rid of such hardcoded symbol.