Skip to content

Commit 43cc486

Browse files
authored
[portmgr] Fixed the orchagent crash due to late arrival of notif (#2431)
Signed-off-by: Vivek Reddy Karri <[email protected]> Bulk write to APP_DB i.e. alias, lanes, speed must be read through one notification by orchagent during create_port Handled a race condition in portmgrd which tries to immediately apply a mtu/admin_status SET notif after a DEL causing it to crash
1 parent b62c716 commit 43cc486

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

cfgmgr/portmgr.cpp

+47-13
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,55 @@ PortMgr::PortMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c
2323
bool PortMgr::setPortMtu(const string &alias, const string &mtu)
2424
{
2525
stringstream cmd;
26-
string res;
26+
string res, cmd_str;
2727

2828
// ip link set dev <port_name> mtu <mtu>
2929
cmd << IP_CMD << " link set dev " << shellquote(alias) << " mtu " << shellquote(mtu);
30-
EXEC_WITH_ERROR_THROW(cmd.str(), res);
31-
32-
// Set the port MTU in application database to update both
33-
// the port MTU and possibly the port based router interface MTU
34-
return writeConfigToAppDb(alias, "mtu", mtu);
30+
cmd_str = cmd.str();
31+
int ret = swss::exec(cmd_str, res);
32+
if (!ret)
33+
{
34+
// Set the port MTU in application database to update both
35+
// the port MTU and possibly the port based router interface MTU
36+
return writeConfigToAppDb(alias, "mtu", mtu);
37+
}
38+
else if (!isPortStateOk(alias))
39+
{
40+
// Can happen when a DEL notification is sent by portmgrd immediately followed by a new SET notif
41+
SWSS_LOG_WARN("Setting mtu to alias:%s netdev failed with cmd:%s, rc:%d, error:%s", alias.c_str(), cmd_str.c_str(), ret, res.c_str());
42+
return false;
43+
}
44+
else
45+
{
46+
throw runtime_error(cmd_str + " : " + res);
47+
}
48+
return true;
3549
}
3650

3751
bool PortMgr::setPortAdminStatus(const string &alias, const bool up)
3852
{
3953
stringstream cmd;
40-
string res;
54+
string res, cmd_str;
4155

4256
// ip link set dev <port_name> [up|down]
4357
cmd << IP_CMD << " link set dev " << shellquote(alias) << (up ? " up" : " down");
44-
EXEC_WITH_ERROR_THROW(cmd.str(), res);
45-
46-
return writeConfigToAppDb(alias, "admin_status", (up ? "up" : "down"));
58+
cmd_str = cmd.str();
59+
int ret = swss::exec(cmd_str, res);
60+
if (!ret)
61+
{
62+
return writeConfigToAppDb(alias, "admin_status", (up ? "up" : "down"));
63+
}
64+
else if (!isPortStateOk(alias))
65+
{
66+
// Can happen when a DEL notification is sent by portmgrd immediately followed by a new SET notification
67+
SWSS_LOG_WARN("Setting admin_status to alias:%s netdev failed with cmd%s, rc:%d, error:%s", alias.c_str(), cmd_str.c_str(), ret, res.c_str());
68+
return false;
69+
}
70+
else
71+
{
72+
throw runtime_error(cmd_str + " : " + res);
73+
}
74+
return true;
4775
}
4876

4977
bool PortMgr::isPortStateOk(const string &alias)
@@ -124,10 +152,9 @@ void PortMgr::doTask(Consumer &consumer)
124152
}
125153
}
126154

127-
for (auto &entry : field_values)
155+
if (field_values.size())
128156
{
129-
writeConfigToAppDb(alias, fvField(entry), fvValue(entry));
130-
SWSS_LOG_NOTICE("Configure %s %s to %s", alias.c_str(), fvField(entry).c_str(), fvValue(entry).c_str());
157+
writeConfigToAppDb(alias, field_values);
131158
}
132159

133160
if (!portOk)
@@ -136,6 +163,7 @@ void PortMgr::doTask(Consumer &consumer)
136163

137164
writeConfigToAppDb(alias, "mtu", mtu);
138165
writeConfigToAppDb(alias, "admin_status", admin_status);
166+
/* Retry setting these params after the netdev is created */
139167
field_values.clear();
140168
field_values.emplace_back("mtu", mtu);
141169
field_values.emplace_back("admin_status", admin_status);
@@ -176,3 +204,9 @@ bool PortMgr::writeConfigToAppDb(const std::string &alias, const std::string &fi
176204

177205
return true;
178206
}
207+
208+
bool PortMgr::writeConfigToAppDb(const std::string &alias, std::vector<FieldValueTuple> &field_values)
209+
{
210+
m_appPortTable.set(alias, field_values);
211+
return true;
212+
}

cfgmgr/portmgr.h

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class PortMgr : public Orch
3030

3131
void doTask(Consumer &consumer);
3232
bool writeConfigToAppDb(const std::string &alias, const std::string &field, const std::string &value);
33+
bool writeConfigToAppDb(const std::string &alias, std::vector<FieldValueTuple> &field_values);
3334
bool setPortMtu(const std::string &alias, const std::string &mtu);
3435
bool setPortAdminStatus(const std::string &alias, const bool up);
3536
bool isPortStateOk(const std::string &alias);

orchagent/portsorch.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -2615,6 +2615,15 @@ bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed, int an, string
26152615
{
26162616
SWSS_LOG_ENTER();
26172617

2618+
if (!speed || lane_set.empty())
2619+
{
2620+
/*
2621+
speed and lane list are mandatory attributes for the initial create_port call
2622+
This check is required because the incoming notifs may not be atomic
2623+
*/
2624+
return true;
2625+
}
2626+
26182627
vector<uint32_t> lanes(lane_set.begin(), lane_set.end());
26192628

26202629
sai_attribute_t attr;

0 commit comments

Comments
 (0)