From e267fd9513a7ad700e557852fdadbc6fe9f43ce8 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri Date: Thu, 28 Apr 2022 21:54:36 +0000 Subject: [PATCH] onMsg test added Signed-off-by: Vivek Reddy Karri --- portsyncd/linksync.cpp | 2 +- tests/mock_tests/portsyncd/portsyncd_ut.cpp | 162 +++++++++++++++++--- 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index 0b65fd26e9..e058355969 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -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; diff --git a/tests/mock_tests/portsyncd/portsyncd_ut.cpp b/tests/mock_tests/portsyncd/portsyncd_ut.cpp index 909eb5bbd8..b7c9c02dbc 100644 --- a/tests/mock_tests/portsyncd/portsyncd_ut.cpp +++ b/tests/mock_tests/portsyncd/portsyncd_ut.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" -#include "producerstatetable.h" +#include +#include #include "../mock_table.h" #define private public #include "linksync.h" @@ -18,6 +19,7 @@ extern "C" { extern std::string mockCmdStdcout; extern std::vector mockCallArgs; extern std::set g_portSet; + /* Test Fixture */ @@ -34,30 +36,17 @@ namespace portsyncd_ut virtual void SetUp() override { testing_db::reset(); - m_config_db = std::make_shared("CONFIG_DB", 0); m_app_db = std::make_shared("APPL_DB", 0); m_state_db = std::make_shared("STATE_DB", 0); m_portCfgTable = std::make_shared(m_config_db.get(), CFG_PORT_TABLE_NAME); m_portAppTable = std::make_shared(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 */ @@ -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 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 keys; @@ -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); @@ -124,4 +198,54 @@ namespace portsyncd_ut m_portAppTable->getKeys(keys_to_app_db); ASSERT_EQ(keys_to_app_db.size(), 0); } -} \ No newline at end of file + + 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 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 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); + } +}