Skip to content

Commit ab4f804

Browse files
[portsorch] remove port OID from saiOidToAlias map on port deletion (sonic-net#2483)
- What I did I fixed an issue that on port deletion (port breakout scenario), the port OID is not removed from saiOidToAlias map, resulting in getPort returns true when querying non-existing port OID but the Port structure is not filled with correct values. Also lowered the log level on receiving non-existing port operational status update - Why I did it To fix errors in the log during breakout: Oct 4 13:15:45.654396 r-bulldog-04 NOTICE swss#orchagent: :- updatePortOperStatus: Port oper state set from unknown to down Oct 4 13:15:45.654773 r-bulldog-04 ERR swss#orchagent: :- set: switch id oid:0x0 doesn't exist Oct 4 13:15:45.654773 r-bulldog-04 WARNING swss#orchagent: :- setHostIntfsOperStatus: Failed to set operation status DOWN to host interface Oct 4 13:15:45.654773 r-bulldog-04 ERR swss#orchagent: :- updatePortOperStatus: Failed to set host interface operational status down Oct 4 13:15:45.654773 r-bulldog-04 WARNING swss#orchagent: :- flushFDBEntries: Couldn't flush FDB. Bridge port OID: 0x0 bvid:0, - How I verified it Run UT, run manual port breakout tests. Signed-off-by: Stepan Blyschak <[email protected]>
1 parent ab29920 commit ab4f804

File tree

2 files changed

+68
-24
lines changed

2 files changed

+68
-24
lines changed

orchagent/portsorch.cpp

+20-16
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,10 @@ bool PortsOrch::getPort(sai_object_id_t id, Port &port)
828828
}
829829
else
830830
{
831-
getPort(itr->second, port);
831+
if (!getPort(itr->second, port))
832+
{
833+
SWSS_LOG_THROW("Inconsistent saiOidToAlias map and m_portList map: oid=%" PRIx64, id);
834+
}
832835
return true;
833836
}
834837

@@ -1069,9 +1072,9 @@ void PortsOrch::getCpuPort(Port &port)
10691072
port = m_cpuPort;
10701073
}
10711074

1072-
/*
1073-
* Create host_tx_ready field in PORT_TABLE of STATE-DB
1074-
* and set the field to false by default for the
1075+
/*
1076+
* Create host_tx_ready field in PORT_TABLE of STATE-DB
1077+
* and set the field to false by default for the
10751078
* front<Ethernet> port.
10761079
*/
10771080
void PortsOrch::initHostTxReadyState(Port &port)
@@ -1096,7 +1099,7 @@ void PortsOrch::initHostTxReadyState(Port &port)
10961099
if (hostTxReady.empty())
10971100
{
10981101
m_portStateTable.hset(port.m_alias, "host_tx_ready", "false");
1099-
SWSS_LOG_INFO("initalize hostTxReady %s with status %s",
1102+
SWSS_LOG_INFO("initalize hostTxReady %s with status %s",
11001103
port.m_alias.c_str(), hostTxReady.c_str());
11011104
}
11021105
}
@@ -1110,13 +1113,13 @@ bool PortsOrch::setPortAdminStatus(Port &port, bool state)
11101113
attr.value.booldata = state;
11111114

11121115
/* Update the host_tx_ready to false before setting admin_state, when admin state is false */
1113-
if (!state)
1116+
if (!state)
11141117
{
11151118
m_portStateTable.hset(port.m_alias, "host_tx_ready", "false");
11161119
SWSS_LOG_INFO("Set admin status DOWN host_tx_ready to false to port pid:%" PRIx64,
11171120
port.m_port_id);
11181121
}
1119-
1122+
11201123
sai_status_t status = sai_port_api->set_port_attribute(port.m_port_id, &attr);
11211124
if (status != SAI_STATUS_SUCCESS)
11221125
{
@@ -1135,14 +1138,14 @@ bool PortsOrch::setPortAdminStatus(Port &port, bool state)
11351138
{
11361139
m_portStateTable.hset(port.m_alias, "host_tx_ready", "false");
11371140
}
1138-
1141+
11391142
/* Update the state table for host_tx_ready*/
11401143
if (state && (gbstatus == true) && (status == SAI_STATUS_SUCCESS) )
11411144
{
11421145
m_portStateTable.hset(port.m_alias, "host_tx_ready", "true");
11431146
SWSS_LOG_INFO("Set admin status UP host_tx_ready to true to port pid:%" PRIx64,
11441147
port.m_port_id);
1145-
}
1148+
}
11461149

11471150
return true;
11481151
}
@@ -1376,9 +1379,9 @@ bool PortsOrch::setPortPfcWatchdogStatus(sai_object_id_t portId, uint8_t pfcwd_b
13761379
SWSS_LOG_ERROR("Failed to get port object for port id 0x%" PRIx64, portId);
13771380
return false;
13781381
}
1379-
1382+
13801383
p.m_pfcwd_sw_bitmask = pfcwd_bitmask;
1381-
1384+
13821385
m_portList[p.m_alias] = p;
13831386

13841387
SWSS_LOG_INFO("Set PFC watchdog port id=0x%" PRIx64 ", bitmast=0x%x", portId, pfcwd_bitmask);
@@ -1396,9 +1399,9 @@ bool PortsOrch::getPortPfcWatchdogStatus(sai_object_id_t portId, uint8_t *pfcwd_
13961399
SWSS_LOG_ERROR("Failed to get port object for port id 0x%" PRIx64, portId);
13971400
return false;
13981401
}
1399-
1402+
14001403
*pfcwd_bitmask = p.m_pfcwd_sw_bitmask;
1401-
1404+
14021405
return true;
14031406
}
14041407

@@ -3778,10 +3781,10 @@ void PortsOrch::doPortTask(Consumer &consumer)
37783781
continue;
37793782
}
37803783
}
3781-
3784+
37823785
/* create host_tx_ready field in state-db */
37833786
initHostTxReadyState(p);
3784-
3787+
37853788
/* Last step set port admin status */
37863789
if (!admin_status.empty() && (p.m_admin_state_up != (admin_status == "up")))
37873790
{
@@ -3859,6 +3862,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
38593862

38603863
/* Delete port from port list */
38613864
m_portList.erase(alias);
3865+
saiOidToAlias.erase(port_id);
38623866
}
38633867
else
38643868
{
@@ -6371,7 +6375,7 @@ void PortsOrch::doTask(NotificationConsumer &consumer)
63716375

63726376
if (!getPort(id, port))
63736377
{
6374-
SWSS_LOG_ERROR("Failed to get port object for port id 0x%" PRIx64, id);
6378+
SWSS_LOG_NOTICE("Got port state change for port id 0x%" PRIx64 " which does not exist, possibly outdated event", id);
63756379
continue;
63766380
}
63776381

tests/mock_tests/portsorch_ut.cpp

+48-8
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,16 @@ namespace portsorch_test
8282
{
8383
sai_port_api = pold_sai_port_api;
8484
}
85-
85+
8686
sai_queue_api_t ut_sai_queue_api;
8787
sai_queue_api_t *pold_sai_queue_api;
8888
int _sai_set_queue_attr_count = 0;
89-
89+
9090
sai_status_t _ut_stub_sai_set_queue_attribute(sai_object_id_t queue_id, const sai_attribute_t *attr)
9191
{
9292
if(attr->id == SAI_QUEUE_ATTR_PFC_DLR_INIT)
9393
{
94-
if(attr->value.booldata == true)
94+
if(attr->value.booldata == true)
9595
{
9696
_sai_set_queue_attr_count++;
9797
}
@@ -269,6 +269,46 @@ namespace portsorch_test
269269

270270
};
271271

272+
/**
273+
* Test that verifies PortsOrch::getPort() on a port that has been deleted
274+
*/
275+
TEST_F(PortsOrchTest, GetPortTest)
276+
{
277+
Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME);
278+
std::deque<KeyOpFieldsValuesTuple> entries;
279+
280+
// Get SAI default ports to populate DB
281+
auto ports = ut_helper::getInitialSaiPorts();
282+
283+
for (const auto &it : ports)
284+
{
285+
portTable.set(it.first, it.second);
286+
}
287+
288+
// Set PortConfigDone
289+
portTable.set("PortConfigDone", { { "count", to_string(ports.size()) } });
290+
291+
// refill consumer
292+
gPortsOrch->addExistingData(&portTable);
293+
294+
// Apply configuration :
295+
// create ports
296+
static_cast<Orch *>(gPortsOrch)->doTask();
297+
298+
Port port;
299+
ASSERT_TRUE(gPortsOrch->getPort("Ethernet0", port));
300+
ASSERT_NE(port.m_port_id, SAI_NULL_OBJECT_ID);
301+
302+
// Delete port
303+
entries.push_back({"Ethernet0", "DEL", {}});
304+
auto consumer = dynamic_cast<Consumer *>(gPortsOrch->getExecutor(APP_PORT_TABLE_NAME));
305+
consumer->addToSync(entries);
306+
static_cast<Orch *>(gPortsOrch)->doTask();
307+
entries.clear();
308+
309+
ASSERT_FALSE(gPortsOrch->getPort(port.m_port_id, port));
310+
}
311+
272312
TEST_F(PortsOrchTest, PortSupportedFecModes)
273313
{
274314
_hook_sai_port_api();
@@ -892,7 +932,7 @@ namespace portsorch_test
892932
* updated to DB.
893933
*/
894934
TEST_F(PortsOrchTest, PortOperStatusIsUpAndOperSpeedIsZero)
895-
{
935+
{
896936
Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME);
897937

898938
// Get SAI default ports to populate DB
@@ -917,7 +957,7 @@ namespace portsorch_test
917957
Port port;
918958
gPortsOrch->getPort("Ethernet0", port);
919959
ASSERT_TRUE(port.m_oper_status != SAI_PORT_OPER_STATUS_UP);
920-
960+
921961
// save original api since we will spy
922962
auto orig_port_api = sai_port_api;
923963
sai_port_api = new sai_port_api_t();
@@ -935,14 +975,14 @@ namespace portsorch_test
935975
// Return 0 for port operational speed
936976
attrs[0].value.u32 = 0;
937977
}
938-
978+
939979
return (sai_status_t)SAI_STATUS_SUCCESS;
940980
}
941981
);
942982

943983
auto exec = static_cast<Notifier *>(gPortsOrch->getExecutor("PORT_STATUS_NOTIFICATIONS"));
944984
auto consumer = exec->getNotificationConsumer();
945-
985+
946986
// mock a redis reply for notification, it notifies that Ehernet0 is going to up
947987
mockReply = (redisReply *)calloc(sizeof(redisReply), 1);
948988
mockReply->type = REDIS_REPLY_ARRAY;
@@ -964,7 +1004,7 @@ namespace portsorch_test
9641004
// trigger the notification
9651005
consumer->readData();
9661006
gPortsOrch->doTask(*consumer);
967-
mockReply = nullptr;
1007+
mockReply = nullptr;
9681008

9691009
gPortsOrch->getPort("Ethernet0", port);
9701010
ASSERT_TRUE(port.m_oper_status == SAI_PORT_OPER_STATUS_UP);

0 commit comments

Comments
 (0)