Skip to content

Commit

Permalink
onMsg test added
Browse files Browse the repository at this point in the history
Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com>
  • Loading branch information
vivekrnv committed Apr 28, 2022
1 parent e052e20 commit e267fd9
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 20 deletions.
2 changes: 1 addition & 1 deletion portsyncd/linksync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ LinkSync::LinkSync(DBConnector *appl_db, DBConnector *state_db) :

if (!WarmStart::isWarmStart())
{
/* See the comments for g_portSet in portsyncd.cpp */
/* See the comments for g_portSet */
for (auto port_iter = g_portSet.begin(); port_iter != g_portSet.end();)
{
string port = *port_iter;
Expand Down
162 changes: 143 additions & 19 deletions tests/mock_tests/portsyncd/portsyncd_ut.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "gtest/gtest.h"
#include "producerstatetable.h"
#include <linux/if.h>
#include <netlink/route/link.h>
#include "../mock_table.h"
#define private public
#include "linksync.h"
Expand All @@ -18,6 +19,7 @@ extern "C" {
extern std::string mockCmdStdcout;
extern std::vector<std::string> mockCallArgs;
extern std::set<std::string> g_portSet;

/*
Test Fixture
*/
Expand All @@ -34,30 +36,17 @@ namespace portsyncd_ut
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);
m_portCfgTable = std::make_shared<swss::Table>(m_config_db.get(), CFG_PORT_TABLE_NAME);
m_portAppTable = std::make_shared<swss::Table>(m_app_db.get(), APP_PORT_TABLE_NAME);

/* Construct a mock if_nameindex array */
if_ni_mock = (struct if_nameindex*) calloc(3, sizeof(struct if_nameindex));

if_ni_mock[2].if_index = 0;
if_ni_mock[2].if_name = NULL;

if_ni_mock[1].if_index = 16222;
if_ni_mock[1].if_name = "eth0";

if_ni_mock[0].if_index = 1;
if_ni_mock[0].if_name = "lo";
}

virtual void TearDown() override {
free(if_ni_mock);
if (if_ni_mock != NULL) free(if_ni_mock);
if_ni_mock = NULL;
}
}
};

/* Helper Methods */
Expand All @@ -75,12 +64,97 @@ namespace portsyncd_ut
vec.emplace_back("alias", "etp1");
tbl->set("Ethernet4", vec);
}

/* Create internal ds holding netdev ifaces for eth0 & lo */
inline struct if_nameindex * populateNetDev(){
struct if_nameindex *if_ni_temp;
/* Construct a mock if_nameindex array */
if_ni_temp = (struct if_nameindex*) calloc(3, sizeof(struct if_nameindex));

if_ni_temp[2].if_index = 0;
if_ni_temp[2].if_name = NULL;

if_ni_temp[1].if_index = 16222;
if_ni_temp[1].if_name = "eth0";

if_ni_temp[0].if_index = 1;
if_ni_temp[0].if_name = "lo";

return if_ni_temp;
}

/* Create internal ds holding netdev ifaces for lo & Ethernet0 */
inline struct if_nameindex * populateNetDevAdvanced(){
struct if_nameindex *if_ni_temp;
/* Construct a mock if_nameindex array */
if_ni_temp = (struct if_nameindex*) calloc(3, sizeof(struct if_nameindex));

if_ni_temp[2].if_index = 0;
if_ni_temp[2].if_name = NULL;

if_ni_temp[1].if_index = 142;
if_ni_temp[1].if_name = "Ethernet0";

if_ni_temp[0].if_index = 1;
if_ni_temp[0].if_name = "lo";

return if_ni_temp;
}

/* Draft a rtnl_link msg */
struct nl_object* draft_nlmsg(const std::string& name,
std::vector<unsigned int> flags,
const std::string& type,
const std::string& ll_add,
int ifindex,
unsigned int mtu,
int master_ifindex = 0){

struct rtnl_link* nl_obj = rtnl_link_alloc();
if (!nl_obj){
throw std::runtime_error("netlink: rtnl_link object allocation failed");
}
/* Set name for rtnl link object */
rtnl_link_set_name(nl_obj, name.c_str());

/* Set flags */
for (auto nlflag : flags){
rtnl_link_set_flags(nl_obj, nlflag);
}

/* Set type */
if (!type.empty()){
rtnl_link_set_type(nl_obj, type.c_str());
}

/* Set Link layer Address */
struct nl_addr * ll_addr;
int result = nl_addr_parse(ll_add.c_str(), AF_LLC, &ll_addr);
if (result < 0){
throw std::runtime_error("netlink: Link layer address allocation failed");
}
rtnl_link_set_addr(nl_obj, ll_addr);

/* Set ifindex */
rtnl_link_set_ifindex(nl_obj, ifindex);

/* Set mtu */
rtnl_link_set_mtu(nl_obj, mtu);

/* Set master_ifindex if any */
if (master_ifindex){
rtnl_link_set_master(nl_obj, master_ifindex);
}

return (struct nl_object*)nl_obj;
}
}

namespace portsyncd_ut
{
TEST_F(PortSyncdTest, test_linkSyncInit)
{
{
if_ni_mock = populateNetDev();
mockCmdStdcout = "up\n";
swss::LinkSync sync(m_app_db.get(), m_state_db.get());
std::vector<std::string> keys;
Expand All @@ -91,7 +165,7 @@ namespace portsyncd_ut
}

TEST_F(PortSyncdTest, test_handlePortConfigFromConfigDB)
{
{
swss::ProducerStateTable p(m_app_db.get(), APP_PORT_TABLE_NAME);
populateCfgDb(m_portCfgTable.get());
swss::DBConnector cfg_db_conn("CONFIG_DB", 0);
Expand Down Expand Up @@ -124,4 +198,54 @@ namespace portsyncd_ut
m_portAppTable->getKeys(keys_to_app_db);
ASSERT_EQ(keys_to_app_db.size(), 0);
}
}

TEST_F(PortSyncdTest, test_cacheOldIfaces)
{
if_ni_mock = populateNetDevAdvanced();
swss::LinkSync sync(m_app_db.get(), m_state_db.get());
ASSERT_EQ(mockCallArgs.back(), "ip link set \"Ethernet0\" down");
ASSERT_NE(sync.m_ifindexOldNameMap.find(142), sync.m_ifindexOldNameMap.end());
ASSERT_EQ(sync.m_ifindexOldNameMap[142], "Ethernet0");
}

TEST_F(PortSyncdTest, test_onMsg)
{
swss::LinkSync sync(m_app_db.get(), m_state_db.get());
/* Write config to Config DB */
populateCfgDb(m_portCfgTable.get());
swss::DBConnector cfg_db_conn("CONFIG_DB", 0);

/* Handle CFG DB notifs and Write them to APPL_DB */
swss::ProducerStateTable p(m_app_db.get(), APP_PORT_TABLE_NAME);
handlePortConfigFromConfigDB(p, cfg_db_conn, false);

/* Generate a netlink notification about the netdev iface */
std::vector<unsigned int> flags = {IFF_UP, IFF_RUNNING};
struct nl_object* msg = draft_nlmsg("Ethernet0",
flags,
"sx_netdev",
"1c:34:da:1c:9f:00",
142,
9100,
0);
sync.onMsg(RTM_NEWLINK, msg);

/* Verify if the update has been written to State DB */
std::vector<swss::FieldValueTuple> ovalues;
ASSERT_EQ(sync.m_statePortTable.get("Ethernet0", ovalues), true);
for (auto value : ovalues){
if (fvField(value) == "state") {ASSERT_EQ(fvValue(value), "ok");}
if (fvField(value) == "mtu") {ASSERT_EQ(fvValue(value), "9100");}
if (fvField(value) == "netdev_oper_status") {ASSERT_EQ(fvValue(value), "up");}
if (fvField(value) == "admin_status") {ASSERT_EQ(fvValue(value), "up");}
if (fvField(value) == "speed") {ASSERT_EQ(fvValue(value), "10000");}
}

/* Verify if the internal strctures are updated as expected */
ASSERT_NE(sync.m_ifindexNameMap.find(142), sync.m_ifindexNameMap.end());
ASSERT_EQ(sync.m_ifindexNameMap[142], "Ethernet0");

/* Free Nl_object */
nl_object_free(msg);
}
}

0 comments on commit e267fd9

Please sign in to comment.