Skip to content

Commit

Permalink
[202205] Fixed set admin_status for deleted subintf due to late notif…
Browse files Browse the repository at this point in the history
…ication (#2704)

What I did
Handled a race condition in intfmgrd which tries to immediately apply an admin_status SET notif after a DEL causing it to crash

Why I did it
Ignores errors on the set admin_status command for subinterface when the subinterface state is not OK.

How I verified it
Unit tests

Details if related
This PR reference to older PR that fix the same issue in portmgr: #2431
  • Loading branch information
EdenGri committed Mar 20, 2023
1 parent 142abdf commit bf496d1
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
15 changes: 13 additions & 2 deletions cfgmgr/intfmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,13 +491,24 @@ void IntfMgr::updateSubIntfAdminStatus(const string &alias, const string &admin)
std::string IntfMgr::setHostSubIntfAdminStatus(const string &alias, const string &admin_status, const string &parent_admin_status)
{
stringstream cmd;
string res;
string res, cmd_str;

if (parent_admin_status == "up" || admin_status == "down")
{
SWSS_LOG_INFO("subintf %s admin_status: %s", alias.c_str(), admin_status.c_str());
cmd << IP_CMD " link set " << shellquote(alias) << " " << shellquote(admin_status);
EXEC_WITH_ERROR_THROW(cmd.str(), res);
cmd_str = cmd.str();
int ret = swss::exec(cmd_str, res);
if (ret && !isIntfStateOk(alias))
{
// Can happen when a DEL notification is sent by portmgrd immediately followed by a new SET notification
SWSS_LOG_WARN("Setting admin_status to %s netdev failed with cmd:%s, rc:%d, error:%s",
alias.c_str(), cmd_str.c_str(), ret, res.c_str());
}
else if (ret)
{
throw runtime_error(cmd_str + " : " + res);
}
return admin_status;
}
else
Expand Down
2 changes: 1 addition & 1 deletion tests/mock_tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ tests_LDADD = $(LDADD_GTEST) $(LDADD_SAI) -lnl-genl-3 -lhiredis -lhiredis -lpthr

## intfmgrd unit tests

tests_intfmgrd_SOURCES = intfmgrd/add_ipv6_prefix_ut.cpp \
tests_intfmgrd_SOURCES = intfmgrd/intfmgr_ut.cpp \
$(top_srcdir)/cfgmgr/intfmgr.cpp \
$(top_srcdir)/orchagent/orch.cpp \
$(top_srcdir)/orchagent/request_parser.cpp \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "gtest/gtest.h"
#include <iostream>
#include <fstream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>
#include "../mock_table.h"
Expand Down Expand Up @@ -28,29 +28,32 @@ int cb(const std::string &cmd, std::string &stdout){
else if (cmd.find("/sbin/ip -6 address \"add\"") == 0) {
return Ethernet0IPv6Set ? 0 : 2;
}
else if (cmd == "/sbin/ip link set \"Ethernet64.10\" \"up\""){
return 1;
}
else {
return 0;
}
return 0;
}

// Test Fixture
namespace add_ipv6_prefix_ut
namespace intfmgr_ut
{
struct IntfMgrTest : public ::testing::Test
{
std::shared_ptr<swss::DBConnector> m_config_db;
std::shared_ptr<swss::DBConnector> m_app_db;
std::shared_ptr<swss::DBConnector> m_state_db;
std::vector<std::string> cfg_intf_tables;

virtual void SetUp() override
{
{
testing_db::reset();
m_config_db = std::make_shared<swss::DBConnector>("CONFIG_DB", 0);
m_app_db = std::make_shared<swss::DBConnector>("APPL_DB", 0);
m_state_db = std::make_shared<swss::DBConnector>("STATE_DB", 0);

swss::WarmStart::initialize("intfmgrd", "swss");

std::vector<std::string> tables = {
Expand Down Expand Up @@ -114,4 +117,22 @@ namespace add_ipv6_prefix_ut
}
ASSERT_EQ(ip_cmd_called, 1);
}

//This test except no runtime error when the set admin status command failed
//and the subinterface has not ok status (for example not existing subinterface)
TEST_F(IntfMgrTest, testSetAdminStatusFailToNotOkSubInt){
swss::IntfMgr intfmgr(m_config_db.get(), m_app_db.get(), m_state_db.get(), cfg_intf_tables);
intfmgr.setHostSubIntfAdminStatus("Ethernet64.10", "up", "up");
}

//This test except runtime error when the set admin status command failed
//and the subinterface has ok status
TEST_F(IntfMgrTest, testSetAdminStatusFailToOkSubInt){
swss::IntfMgr intfmgr(m_config_db.get(), m_app_db.get(), m_state_db.get(), cfg_intf_tables);
/* Set portStateTable */
std::vector<swss::FieldValueTuple> values;
values.emplace_back("state", "ok");
intfmgr.m_statePortTable.set("Ethernet64.10", values, "SET", "");
EXPECT_THROW(intfmgr.setHostSubIntfAdminStatus("Ethernet64.10", "up", "up"), std::runtime_error);
}
}

0 comments on commit bf496d1

Please sign in to comment.