From 16fc11a4e593f656167b02ba3146fc496c3115c8 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Fri, 14 Apr 2023 21:47:40 +0000 Subject: [PATCH 1/9] Added def sflow sampling rates for 800g Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 1 + cfgmgr/sflowmgr.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index bb732e83d5..aa89003e23 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -12,6 +12,7 @@ using namespace swss; map<string,string> sflowSpeedRateInitMap = { + {SFLOW_SAMPLE_RATE_KEY_800G, SFLOW_SAMPLE_RATE_VALUE_800G}, {SFLOW_SAMPLE_RATE_KEY_400G, SFLOW_SAMPLE_RATE_VALUE_400G}, {SFLOW_SAMPLE_RATE_KEY_200G, SFLOW_SAMPLE_RATE_VALUE_200G}, {SFLOW_SAMPLE_RATE_KEY_100G, SFLOW_SAMPLE_RATE_VALUE_100G}, diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index eb35ec2125..7ed8e9fc11 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -10,6 +10,7 @@ namespace swss { +#define SFLOW_SAMPLE_RATE_KEY_800G "800000" #define SFLOW_SAMPLE_RATE_KEY_400G "400000" #define SFLOW_SAMPLE_RATE_KEY_200G "200000" #define SFLOW_SAMPLE_RATE_KEY_100G "100000" @@ -19,6 +20,7 @@ namespace swss { #define SFLOW_SAMPLE_RATE_KEY_10G "10000" #define SFLOW_SAMPLE_RATE_KEY_1G "1000" +#define SFLOW_SAMPLE_RATE_VALUE_800G "800000" #define SFLOW_SAMPLE_RATE_VALUE_400G "400000" #define SFLOW_SAMPLE_RATE_VALUE_200G "200000" #define SFLOW_SAMPLE_RATE_VALUE_100G "100000" From 3430ba99486e81c8a4e425cf16268273f54e2f50 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Tue, 23 May 2023 23:03:55 +0000 Subject: [PATCH 2/9] Infer sampling rate for any speed Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 53 +++++++++++++++------------------------------ cfgmgr/sflowmgr.h | 25 +++------------------ 2 files changed, 20 insertions(+), 58 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index aa89003e23..d97aee1835 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -10,19 +10,6 @@ using namespace std; using namespace swss; -map<string,string> sflowSpeedRateInitMap = -{ - {SFLOW_SAMPLE_RATE_KEY_800G, SFLOW_SAMPLE_RATE_VALUE_800G}, - {SFLOW_SAMPLE_RATE_KEY_400G, SFLOW_SAMPLE_RATE_VALUE_400G}, - {SFLOW_SAMPLE_RATE_KEY_200G, SFLOW_SAMPLE_RATE_VALUE_200G}, - {SFLOW_SAMPLE_RATE_KEY_100G, SFLOW_SAMPLE_RATE_VALUE_100G}, - {SFLOW_SAMPLE_RATE_KEY_50G, SFLOW_SAMPLE_RATE_VALUE_50G}, - {SFLOW_SAMPLE_RATE_KEY_40G, SFLOW_SAMPLE_RATE_VALUE_40G}, - {SFLOW_SAMPLE_RATE_KEY_25G, SFLOW_SAMPLE_RATE_VALUE_25G}, - {SFLOW_SAMPLE_RATE_KEY_10G, SFLOW_SAMPLE_RATE_VALUE_10G}, - {SFLOW_SAMPLE_RATE_KEY_1G, SFLOW_SAMPLE_RATE_VALUE_1G} -}; - SflowMgr::SflowMgr(DBConnector *cfgDb, DBConnector *appDb, const vector<string> &tableNames) : Orch(cfgDb, tableNames), m_cfgSflowTable(cfgDb, CFG_SFLOW_TABLE_NAME), @@ -113,7 +100,7 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) if (new_port || (speed_change && !m_sflowPortConfMap[key].local_rate_cfg)) { vector<FieldValueTuple> fvs; - sflowGetGlobalInfo(fvs, m_sflowPortConfMap[key].speed); + sflowGetGlobalInfo(fvs, key); m_appSflowSessionTable.set(key, fvs); } } @@ -155,7 +142,7 @@ void SflowMgr::sflowHandleSessionAll(bool enable) } else { - sflowGetGlobalInfo(fvs, it.second.speed); + sflowGetGlobalInfo(fvs, it.first); } m_appSflowSessionTable.set(it.first, fvs); } @@ -186,21 +173,13 @@ void SflowMgr::sflowHandleSessionLocal(bool enable) } } -void SflowMgr::sflowGetGlobalInfo(vector<FieldValueTuple> &fvs, string speed) +void SflowMgr::sflowGetGlobalInfo(vector<FieldValueTuple> &fvs, const string& alias) { string rate; FieldValueTuple fv1("admin_state", "up"); fvs.push_back(fv1); - if (speed != SFLOW_ERROR_SPEED_STR && sflowSpeedRateInitMap.find(speed) != sflowSpeedRateInitMap.end()) - { - rate = sflowSpeedRateInitMap[speed]; - } - else - { - rate = SFLOW_ERROR_SPEED_STR; - } - FieldValueTuple fv2("sample_rate",rate); + FieldValueTuple fv2("sample_rate", findSamplingRate(alias)); fvs.push_back(fv2); } @@ -256,16 +235,7 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va m_sflowPortConfMap[alias].local_rate_cfg) { string speed = m_sflowPortConfMap[alias].speed; - - if (speed != SFLOW_ERROR_SPEED_STR && sflowSpeedRateInitMap.find(speed) != sflowSpeedRateInitMap.end()) - { - rate = sflowSpeedRateInitMap[speed]; - } - else - { - rate = SFLOW_ERROR_SPEED_STR; - } - m_sflowPortConfMap[alias].rate = rate; + m_sflowPortConfMap[alias].rate = findSamplingRate(alias); } m_sflowPortConfMap[alias].local_rate_cfg = false; FieldValueTuple fv("sample_rate", m_sflowPortConfMap[alias].rate); @@ -285,6 +255,17 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va } } +string SflowMgr::findSamplingRate(const string& alias) +{ + /* Default sampling rate is equal to the speed in Gbps or error */ + if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) + { + SWSS_LOG_ERROR("%s not found in port configuration map", alias.c_str()); + return SFLOW_ERROR_SPEED_STR; + } + return m_sflowPortConfMap[alias].speed; +} + void SflowMgr::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -412,7 +393,7 @@ void SflowMgr::doTask(Consumer &consumer) if (m_intfAllConf) { vector<FieldValueTuple> fvs; - sflowGetGlobalInfo(fvs, m_sflowPortConfMap[key].speed); + sflowGetGlobalInfo(fvs, key); m_appSflowSessionTable.set(key,fvs); } } diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index 7ed8e9fc11..a1377ccbc7 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -10,26 +10,6 @@ namespace swss { -#define SFLOW_SAMPLE_RATE_KEY_800G "800000" -#define SFLOW_SAMPLE_RATE_KEY_400G "400000" -#define SFLOW_SAMPLE_RATE_KEY_200G "200000" -#define SFLOW_SAMPLE_RATE_KEY_100G "100000" -#define SFLOW_SAMPLE_RATE_KEY_50G "50000" -#define SFLOW_SAMPLE_RATE_KEY_40G "40000" -#define SFLOW_SAMPLE_RATE_KEY_25G "25000" -#define SFLOW_SAMPLE_RATE_KEY_10G "10000" -#define SFLOW_SAMPLE_RATE_KEY_1G "1000" - -#define SFLOW_SAMPLE_RATE_VALUE_800G "800000" -#define SFLOW_SAMPLE_RATE_VALUE_400G "400000" -#define SFLOW_SAMPLE_RATE_VALUE_200G "200000" -#define SFLOW_SAMPLE_RATE_VALUE_100G "100000" -#define SFLOW_SAMPLE_RATE_VALUE_50G "50000" -#define SFLOW_SAMPLE_RATE_VALUE_40G "40000" -#define SFLOW_SAMPLE_RATE_VALUE_25G "25000" -#define SFLOW_SAMPLE_RATE_VALUE_10G "10000" -#define SFLOW_SAMPLE_RATE_VALUE_1G "1000" - #define SFLOW_ERROR_SPEED_STR "error" struct SflowPortInfo @@ -55,7 +35,7 @@ class SflowMgr : public Orch Table m_cfgSflowSessionTable; ProducerStateTable m_appSflowTable; ProducerStateTable m_appSflowSessionTable; - SflowPortConfMap m_sflowPortConfMap; + SflowPortConfMap m_sflowPortConfMap; bool m_intfAllConf; bool m_gEnable; @@ -66,7 +46,8 @@ class SflowMgr : public Orch void sflowHandleSessionLocal(bool enable); void sflowCheckAndFillValues(std::string alias, std::vector<FieldValueTuple> &values, std::vector<FieldValueTuple> &fvs); void sflowGetPortInfo(std::vector<FieldValueTuple> &fvs, SflowPortInfo &local_info); - void sflowGetGlobalInfo(std::vector<FieldValueTuple> &fvs, std::string speed); + void sflowGetGlobalInfo(std::vector<FieldValueTuple> &fvs, const std::string& alias); + std::string findSamplingRate(const std::string& speed); }; } From 57f76699c862cc77537de1e6907f9c8a9b433ead Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Thu, 25 May 2023 03:17:36 +0000 Subject: [PATCH 3/9] listen to oper speed Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 83 +++++++++++-- cfgmgr/sflowmgr.h | 8 +- cfgmgr/sflowmgrd.cpp | 25 ++-- tests/mock_tests/Makefile.am | 2 + tests/mock_tests/sflowmgrd_ut.cpp | 199 ++++++++++++++++++++++++++++++ 5 files changed, 297 insertions(+), 20 deletions(-) create mode 100644 tests/mock_tests/sflowmgrd_ut.cpp diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index d97aee1835..b372135abf 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -10,10 +10,8 @@ using namespace std; using namespace swss; -SflowMgr::SflowMgr(DBConnector *cfgDb, DBConnector *appDb, const vector<string> &tableNames) : - Orch(cfgDb, tableNames), - m_cfgSflowTable(cfgDb, CFG_SFLOW_TABLE_NAME), - m_cfgSflowSessionTable(cfgDb, CFG_SFLOW_SESSION_TABLE_NAME), +SflowMgr::SflowMgr(DBConnector *appDb, const std::vector<TableConnector>& tableNames) : + Orch(tableNames), m_appSflowTable(appDb, APP_SFLOW_TABLE_NAME), m_appSflowSessionTable(appDb, APP_SFLOW_SESSION_TABLE_NAME) { @@ -57,7 +55,6 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) while (it != consumer.m_toSync.end()) { KeyOpFieldsValuesTuple t = it->second; - string key = kfvKey(t); string op = kfvOp(t); auto values = kfvFieldsValues(t); @@ -73,7 +70,9 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) new_port = true; port_info.local_rate_cfg = false; port_info.local_admin_cfg = false; + port_info.autoneg_enabled = false; port_info.speed = SFLOW_ERROR_SPEED_STR; + port_info.oper_speed = SFLOW_NA_SPEED_STR; port_info.rate = ""; port_info.admin = ""; m_sflowPortConfMap[key] = port_info; @@ -87,6 +86,15 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) { new_speed = fvValue(i); } + else if (fvField(i) == "autoneg") + { + m_sflowPortConfMap[key].autoneg_enabled = fvValue(i) == "on" ? true : false; + if (fvValue(i) != "on") + { + /* If auto-neg is disabled, update sample_rate based on configured speed */ + speed_change = true; + } + } } if (m_sflowPortConfMap[key].speed != new_speed) { @@ -124,6 +132,53 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) } } +void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) +{ + auto it = consumer.m_toSync.begin(); + + while (it != consumer.m_toSync.end()) + { + KeyOpFieldsValuesTuple t = it->second; + string alias = kfvKey(t); + string op = kfvOp(t); + auto values = kfvFieldsValues(t); + string oper_speed = ""; + bool iface_found = true; + + for (auto i : values) + { + if (fvField(i) == "speed") + { + oper_speed = fvValue(i); + } + } + + if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) + { + SWSS_LOG_NOTICE("Port %s not found in port conf map", alias.c_str()); + iface_found = false; + } + + if (oper_speed != m_sflowPortConfMap[alias].oper_speed && + iface_found && op == SET_COMMAND) + { + m_sflowPortConfMap[alias].oper_speed = oper_speed; + if (!m_sflowPortConfMap[alias].local_rate_cfg && m_gEnable && + m_intfAllConf && m_sflowPortConfMap[alias].autoneg_enabled) + { + auto rate = findSamplingRate(alias); + FieldValueTuple fv("sample_rate", rate); + vector<FieldValueTuple> fvs = {fv}; + m_appSflowSessionTable.set(alias, fvs); + SWSS_LOG_INFO("Default sampling rate for %s updated to %s", alias.c_str(), rate.c_str()); + } + } + /* Do nothing for DEL as the SflowPortConfMap will already be cleared by the DEL from CONFIG_DB + Also don't act on the notifications from the STATE_DB if the speed is not set, happens during init by portsyncd */ + it = consumer.m_toSync.erase(it); + } +} + void SflowMgr::sflowHandleSessionAll(bool enable) { for (auto it: m_sflowPortConfMap) @@ -234,7 +289,6 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va if (m_sflowPortConfMap[alias].rate == "" || m_sflowPortConfMap[alias].local_rate_cfg) { - string speed = m_sflowPortConfMap[alias].speed; m_sflowPortConfMap[alias].rate = findSamplingRate(alias); } m_sflowPortConfMap[alias].local_rate_cfg = false; @@ -257,13 +311,21 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va string SflowMgr::findSamplingRate(const string& alias) { - /* Default sampling rate is equal to the speed in Gbps or error */ + /* Default sampling rate is equal to the oper_speed in Gbps or error + if auto_neg is not configured, use the configured speed */ if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) { SWSS_LOG_ERROR("%s not found in port configuration map", alias.c_str()); return SFLOW_ERROR_SPEED_STR; } - return m_sflowPortConfMap[alias].speed; + string oper_speed = m_sflowPortConfMap[alias].oper_speed; + string cfg_speed = m_sflowPortConfMap[alias].speed; + bool autoneg = m_sflowPortConfMap[alias].autoneg_enabled; + if (autoneg && !oper_speed.empty() && oper_speed != SFLOW_NA_SPEED_STR) + { + return oper_speed; + } + return cfg_speed; } void SflowMgr::doTask(Consumer &consumer) @@ -277,6 +339,11 @@ void SflowMgr::doTask(Consumer &consumer) sflowUpdatePortInfo(consumer); return; } + else if (table == STATE_PORT_TABLE_NAME) + { + sflowProcessOperSpeed(consumer); + return; + } auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index a1377ccbc7..d36d29533d 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -11,12 +11,15 @@ namespace swss { #define SFLOW_ERROR_SPEED_STR "error" +#define SFLOW_NA_SPEED_STR "N/A" struct SflowPortInfo { bool local_rate_cfg; bool local_admin_cfg; + bool autoneg_enabled; std::string speed; + std::string oper_speed; std::string rate; std::string admin; }; @@ -27,12 +30,10 @@ typedef std::map<std::string, SflowPortInfo> SflowPortConfMap; class SflowMgr : public Orch { public: - SflowMgr(DBConnector *cfgDb, DBConnector *appDb, const std::vector<std::string> &tableNames); + SflowMgr(DBConnector *appDb, const std::vector<TableConnector>& tableNames); using Orch::doTask; private: - Table m_cfgSflowTable; - Table m_cfgSflowSessionTable; ProducerStateTable m_appSflowTable; ProducerStateTable m_appSflowSessionTable; SflowPortConfMap m_sflowPortConfMap; @@ -42,6 +43,7 @@ class SflowMgr : public Orch void doTask(Consumer &consumer); void sflowHandleService(bool enable); void sflowUpdatePortInfo(Consumer &consumer); + void sflowProcessOperSpeed(Consumer &consumer); void sflowHandleSessionAll(bool enable); void sflowHandleSessionLocal(bool enable); void sflowCheckAndFillValues(std::string alias, std::vector<FieldValueTuple> &values, std::vector<FieldValueTuple> &fvs); diff --git a/cfgmgr/sflowmgrd.cpp b/cfgmgr/sflowmgrd.cpp index 7de5f15a2d..39def61811 100644 --- a/cfgmgr/sflowmgrd.cpp +++ b/cfgmgr/sflowmgrd.cpp @@ -44,21 +44,28 @@ int main(int argc, char **argv) try { - vector<string> cfg_sflow_tables = { - CFG_SFLOW_TABLE_NAME, - CFG_SFLOW_SESSION_TABLE_NAME, - CFG_PORT_TABLE_NAME - }; - DBConnector cfgDb("CONFIG_DB", 0); DBConnector appDb("APPL_DB", 0); + DBConnector stateDb("STATE_DB", 0); + + TableConnector conf_port_table(&cfgDb, CFG_PORT_TABLE_NAME); + TableConnector state_port_table(&stateDb, STATE_PORT_TABLE_NAME); + TableConnector conf_sflow_table(&cfgDb, CFG_SFLOW_TABLE_NAME); + TableConnector conf_sflow_session_table(&cfgDb, CFG_SFLOW_SESSION_TABLE_NAME); + + vector<TableConnector> sflow_tables = { + conf_port_table, + state_port_table, + conf_sflow_table, + conf_sflow_session_table + }; - SflowMgr sflowmgr(&cfgDb, &appDb, cfg_sflow_tables); + SflowMgr sflowmgr(&appDb, sflow_tables); - vector<Orch *> cfgOrchList = {&sflowmgr}; + vector<Orch *> orchList = {&sflowmgr}; swss::Select s; - for (Orch *o : cfgOrchList) + for (Orch *o : orchList) { s.addSelectables(o->getSelectables()); } diff --git a/tests/mock_tests/Makefile.am b/tests/mock_tests/Makefile.am index 3741e7da27..fd8982eae8 100644 --- a/tests/mock_tests/Makefile.am +++ b/tests/mock_tests/Makefile.am @@ -45,6 +45,7 @@ tests_SOURCES = aclorch_ut.cpp \ mock_redisreply.cpp \ bulker_ut.cpp \ portmgr_ut.cpp \ + sflowmgrd_ut.cpp \ fake_response_publisher.cpp \ swssnet_ut.cpp \ flowcounterrouteorch_ut.cpp \ @@ -109,6 +110,7 @@ tests_SOURCES = aclorch_ut.cpp \ $(top_srcdir)/orchagent/srv6orch.cpp \ $(top_srcdir)/orchagent/nvgreorch.cpp \ $(top_srcdir)/cfgmgr/portmgr.cpp \ + $(top_srcdir)/cfgmgr/sflowmgr.cpp \ $(top_srcdir)/cfgmgr/buffermgrdyn.cpp \ $(top_srcdir)/warmrestart/warmRestartAssist.cpp diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp new file mode 100644 index 0000000000..71c6a31a4f --- /dev/null +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -0,0 +1,199 @@ +#include "gtest/gtest.h" +#include "mock_table.h" +#include "redisutility.h" +#define private public +#include "sflowmgr.h" +#undef private + +namespace sflowmgr_ut +{ + using namespace swss; + using namespace std; + + struct SflowMgrTest : public ::testing::Test + { + shared_ptr<swss::DBConnector> m_app_db; + shared_ptr<swss::DBConnector> m_config_db; + shared_ptr<swss::DBConnector> m_state_db; + shared_ptr<SflowMgr> m_sflowMgr; + SflowMgrTest() + { + m_app_db = make_shared<swss::DBConnector>( + "APPL_DB", 0); + m_config_db = make_shared<swss::DBConnector>( + "CONFIG_DB", 0); + m_state_db = make_shared<swss::DBConnector>( + "STATE_DB", 0); + } + + virtual void SetUp() override + { + ::testing_db::reset(); + TableConnector conf_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + TableConnector state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); + TableConnector conf_sflow_table(m_config_db.get(), CFG_SFLOW_TABLE_NAME); + TableConnector conf_sflow_session_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + + vector<TableConnector> sflow_tables = { + conf_port_table, + state_port_table, + conf_sflow_table, + conf_sflow_session_table + }; + m_sflowMgr.reset(new SflowMgr(m_app_db.get(), sflow_tables)); + m_sflowMgr->m_gEnable = true; + } + }; + + TEST_F(SflowMgrTest, test_RateConfiguration) + { + Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + + cfg_port_table.set("Ethernet0", { + {"speed", "100000"}, + {"autoneg", "on"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "100000"); + + /* Scenario: Operational Speed Changes to 25000 */ + state_port_table.set("Ethernet0", { + {"speed", "25000"} + }); + + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + values.clear(); + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "25000"); + } + + TEST_F(SflowMgrTest, test_OnlyStateDbNotif) + { + Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + + state_port_table.set("Ethernet0", { + {"speed", "100000"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_FALSE(value_rate); + } + + TEST_F(SflowMgrTest, tets_LocalRateConfiguration) + { + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + + cfg_port_table.set("Ethernet0", { + {"speed", "100000"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "100000"); + + cfg_sflow_table.set("Ethernet0", { + {"sample_rate", "12345"} + }); + + m_sflowMgr->addExistingData(&cfg_sflow_table); + m_sflowMgr->doTask(); + + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "12345"); + } + + TEST_F(SflowMgrTest, tets_LocalRateConfigurationWithOperSpeed) + { + Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + + cfg_port_table.set("Ethernet0", { + {"speed", "100000"}, + {"autoneg", "on"} + }); + + /* Scenario: Operational Speed Changes to 25000 */ + state_port_table.set("Ethernet0", { + {"speed", "25000"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "25000"); + + cfg_sflow_table.set("Ethernet0", { + {"sample_rate", "12345"} + }); + + m_sflowMgr->addExistingData(&cfg_sflow_table); + m_sflowMgr->doTask(); + + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "12345"); + + /* Operational Speed Changes again to 50000 */ + state_port_table.set("Ethernet0", { + {"speed", "50000"} + }); + + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + /* Local config wouldn't change */ + ASSERT_TRUE(value_rate.get() == "12345"); + } + + TEST_F(SflowMgrTest, tets_800g) + { + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + + cfg_port_table.set("Ethernet0", { + {"speed", "800000"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "800000"); + } +} From 431d3f8f4779bc66697728134219099dfd35cefa Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Thu, 25 May 2023 21:21:27 +0000 Subject: [PATCH 4/9] handle auto-neg disabled flow Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 14 +++++--------- tests/mock_tests/sflowmgrd_ut.cpp | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index b372135abf..1fee8bcc12 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -78,7 +78,7 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) m_sflowPortConfMap[key] = port_info; } - bool speed_change = false; + bool rate_update = false; string new_speed = SFLOW_ERROR_SPEED_STR; for (auto i : values) { @@ -89,23 +89,20 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) else if (fvField(i) == "autoneg") { m_sflowPortConfMap[key].autoneg_enabled = fvValue(i) == "on" ? true : false; - if (fvValue(i) != "on") - { - /* If auto-neg is disabled, update sample_rate based on configured speed */ - speed_change = true; - } + /* If autoneg is diabled, should set the rate back to configured speed */ + rate_update = !m_sflowPortConfMap[key].autoneg_enabled; } } if (m_sflowPortConfMap[key].speed != new_speed) { m_sflowPortConfMap[key].speed = new_speed; - speed_change = true; + rate_update = true; } if (m_gEnable && m_intfAllConf) { // If the Local rate Conf is already present, dont't override it even though the speed is changed - if (new_port || (speed_change && !m_sflowPortConfMap[key].local_rate_cfg)) + if (new_port || (rate_update && !m_sflowPortConfMap[key].local_rate_cfg)) { vector<FieldValueTuple> fvs; sflowGetGlobalInfo(fvs, key); @@ -230,7 +227,6 @@ void SflowMgr::sflowHandleSessionLocal(bool enable) void SflowMgr::sflowGetGlobalInfo(vector<FieldValueTuple> &fvs, const string& alias) { - string rate; FieldValueTuple fv1("admin_state", "up"); fvs.push_back(fv1); diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index 71c6a31a4f..f38aa6b69d 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -76,6 +76,20 @@ namespace sflowmgr_ut appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate.get() == "25000"); + + cfg_port_table.set("Ethernet0", { + {"speed", "100000"}, + {"autoneg", "off"} + }); + + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + + /* Sample rate should be back to configured speed if auto-neg is disabled */ + values.clear(); + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate.get() == "100000"); } TEST_F(SflowMgrTest, test_OnlyStateDbNotif) From 8f439d7f19f33770320d856616394ee9eab5d792 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Thu, 25 May 2023 21:42:19 +0000 Subject: [PATCH 5/9] cleanup tests Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- tests/mock_tests/sflowmgrd_ut.cpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index f38aa6b69d..25dbf972cf 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -1,9 +1,7 @@ #include "gtest/gtest.h" #include "mock_table.h" #include "redisutility.h" -#define private public #include "sflowmgr.h" -#undef private namespace sflowmgr_ut { @@ -41,7 +39,17 @@ namespace sflowmgr_ut conf_sflow_session_table }; m_sflowMgr.reset(new SflowMgr(m_app_db.get(), sflow_tables)); - m_sflowMgr->m_gEnable = true; + enableSflow(); + } + + void enableSflow() + { + Table cfg_sflow(m_config_db.get(), CFG_SFLOW_TABLE_NAME); + cfg_sflow.set("global", { + {"admin_state", "up"} + }); + m_sflowMgr->addExistingData(&cfg_sflow); + m_sflowMgr->doTask(); } }; @@ -62,6 +70,7 @@ namespace sflowmgr_ut std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "100000"); /* Scenario: Operational Speed Changes to 25000 */ @@ -75,6 +84,7 @@ namespace sflowmgr_ut values.clear(); appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "25000"); cfg_port_table.set("Ethernet0", { @@ -89,6 +99,7 @@ namespace sflowmgr_ut values.clear(); appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "100000"); } @@ -111,7 +122,7 @@ namespace sflowmgr_ut ASSERT_FALSE(value_rate); } - TEST_F(SflowMgrTest, tets_LocalRateConfiguration) + TEST_F(SflowMgrTest, test_LocalRateConfiguration) { Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); @@ -127,6 +138,7 @@ namespace sflowmgr_ut std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "100000"); cfg_sflow_table.set("Ethernet0", { @@ -138,10 +150,11 @@ namespace sflowmgr_ut appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "12345"); } - TEST_F(SflowMgrTest, tets_LocalRateConfigurationWithOperSpeed) + TEST_F(SflowMgrTest, test_LocalRateConfigurationWithOperSpeed) { Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); @@ -165,6 +178,7 @@ namespace sflowmgr_ut std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "25000"); cfg_sflow_table.set("Ethernet0", { @@ -176,6 +190,7 @@ namespace sflowmgr_ut appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "12345"); /* Operational Speed Changes again to 50000 */ @@ -189,10 +204,11 @@ namespace sflowmgr_ut appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); /* Local config wouldn't change */ + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "12345"); } - TEST_F(SflowMgrTest, tets_800g) + TEST_F(SflowMgrTest, test_800g) { Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); @@ -208,6 +224,7 @@ namespace sflowmgr_ut std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "800000"); } } From 020747af4f10913d257bbdf468d83073140ba6bd Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Fri, 26 May 2023 18:48:39 +0000 Subject: [PATCH 6/9] Remove autoneg parameter Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 60 +++++++++------- cfgmgr/sflowmgr.h | 2 +- cfgmgr/sflowmgrd.cpp | 2 + tests/mock_tests/sflowmgrd_ut.cpp | 111 +++++++++++++++++++++--------- 4 files changed, 120 insertions(+), 55 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index 1fee8bcc12..fecff136ed 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -19,6 +19,20 @@ SflowMgr::SflowMgr(DBConnector *appDb, const std::vector<TableConnector>& tableN m_gEnable = false; } +void SflowMgr::readPortConfig() +{ + auto consumer_it = m_consumerMap.find(CFG_PORT_TABLE_NAME); + if (consumer_it != m_consumerMap.end()) + { + consumer_it->second->drain(); + SWSS_LOG_INFO("Port Configuration Read.."); + } + else + { + throw std::runtime_error("Consumer for config db PORT_TABLE not found"); + } +} + void SflowMgr::sflowHandleService(bool enable) { stringstream cmd; @@ -70,7 +84,6 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) new_port = true; port_info.local_rate_cfg = false; port_info.local_admin_cfg = false; - port_info.autoneg_enabled = false; port_info.speed = SFLOW_ERROR_SPEED_STR; port_info.oper_speed = SFLOW_NA_SPEED_STR; port_info.rate = ""; @@ -86,12 +99,6 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) { new_speed = fvValue(i); } - else if (fvField(i) == "autoneg") - { - m_sflowPortConfMap[key].autoneg_enabled = fvValue(i) == "on" ? true : false; - /* If autoneg is diabled, should set the rate back to configured speed */ - rate_update = !m_sflowPortConfMap[key].autoneg_enabled; - } } if (m_sflowPortConfMap[key].speed != new_speed) { @@ -139,29 +146,38 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) string alias = kfvKey(t); string op = kfvOp(t); auto values = kfvFieldsValues(t); - string oper_speed = ""; - bool iface_found = true; - + string oper_speed = SFLOW_NA_SPEED_STR; + bool oper_status = false; + for (auto i : values) { if (fvField(i) == "speed") { oper_speed = fvValue(i); } + else if (fvField(i) == "netdev_oper_status") + { + oper_status = fvValue(i) == "up" ? true : false; + } } + /* When the oper_status is down, the speed (if present) is just a stale entry and hence discard */ + oper_speed = oper_status ? oper_speed : SFLOW_NA_SPEED_STR; + if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) { - SWSS_LOG_NOTICE("Port %s not found in port conf map", alias.c_str()); - iface_found = false; + SWSS_LOG_ERROR("Port %s not found in port conf map", alias.c_str()); } - - if (oper_speed != m_sflowPortConfMap[alias].oper_speed && - iface_found && op == SET_COMMAND) + else { - m_sflowPortConfMap[alias].oper_speed = oper_speed; - if (!m_sflowPortConfMap[alias].local_rate_cfg && m_gEnable && - m_intfAllConf && m_sflowPortConfMap[alias].autoneg_enabled) + bool speed_change = false; + if (m_sflowPortConfMap[alias].oper_speed != oper_speed) + { + speed_change = true; + m_sflowPortConfMap[alias].oper_speed = oper_speed; + } + if (speed_change && m_gEnable && m_intfAllConf && + !m_sflowPortConfMap[alias].local_rate_cfg) { auto rate = findSamplingRate(alias); FieldValueTuple fv("sample_rate", rate); @@ -170,8 +186,7 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) SWSS_LOG_INFO("Default sampling rate for %s updated to %s", alias.c_str(), rate.c_str()); } } - /* Do nothing for DEL as the SflowPortConfMap will already be cleared by the DEL from CONFIG_DB - Also don't act on the notifications from the STATE_DB if the speed is not set, happens during init by portsyncd */ + /* Do nothing for DEL as the SflowPortConfMap will already be cleared by the DEL from CONFIG_DB */ it = consumer.m_toSync.erase(it); } } @@ -308,7 +323,7 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va string SflowMgr::findSamplingRate(const string& alias) { /* Default sampling rate is equal to the oper_speed in Gbps or error - if auto_neg is not configured, use the configured speed */ + if oper_speed is not found, use the configured speed */ if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) { SWSS_LOG_ERROR("%s not found in port configuration map", alias.c_str()); @@ -316,8 +331,7 @@ string SflowMgr::findSamplingRate(const string& alias) } string oper_speed = m_sflowPortConfMap[alias].oper_speed; string cfg_speed = m_sflowPortConfMap[alias].speed; - bool autoneg = m_sflowPortConfMap[alias].autoneg_enabled; - if (autoneg && !oper_speed.empty() && oper_speed != SFLOW_NA_SPEED_STR) + if (!oper_speed.empty() && oper_speed != SFLOW_NA_SPEED_STR) { return oper_speed; } diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index d36d29533d..51dae92d7b 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -17,7 +17,6 @@ struct SflowPortInfo { bool local_rate_cfg; bool local_admin_cfg; - bool autoneg_enabled; std::string speed; std::string oper_speed; std::string rate; @@ -31,6 +30,7 @@ class SflowMgr : public Orch { public: SflowMgr(DBConnector *appDb, const std::vector<TableConnector>& tableNames); + void readPortConfig(); using Orch::doTask; private: diff --git a/cfgmgr/sflowmgrd.cpp b/cfgmgr/sflowmgrd.cpp index 39def61811..83fb134c82 100644 --- a/cfgmgr/sflowmgrd.cpp +++ b/cfgmgr/sflowmgrd.cpp @@ -62,6 +62,8 @@ int main(int argc, char **argv) SflowMgr sflowmgr(&appDb, sflow_tables); + sflowmgr.readPortConfig(); + vector<Orch *> orchList = {&sflowmgr}; swss::Select s; diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index 25dbf972cf..5c3e291e4a 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -61,7 +61,6 @@ namespace sflowmgr_ut cfg_port_table.set("Ethernet0", { {"speed", "100000"}, - {"autoneg", "on"} }); m_sflowMgr->addExistingData(&cfg_port_table); @@ -75,7 +74,8 @@ namespace sflowmgr_ut /* Scenario: Operational Speed Changes to 25000 */ state_port_table.set("Ethernet0", { - {"speed", "25000"} + {"speed", "25000"}, + {"netdev_oper_status", "up"} }); m_sflowMgr->addExistingData(&state_port_table); @@ -87,20 +87,82 @@ namespace sflowmgr_ut ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "25000"); + /* oper status is down since rate_neg is disabled */ + state_port_table.set("Ethernet0", { + {"speed", "25000"}, + {"netdev_oper_status", "down"} + }); + + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + values.clear(); + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); + /* Sample rate is restored to original value */ + ASSERT_TRUE(value_rate.get() == "100000"); + } + + TEST_F(SflowMgrTest, test_RateConfigurationOperUpDown) + { + /* Simulates a realistic scenario of oper up down events mixed with auto neg */ + Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + std::vector<FieldValueTuple> values; + + /* Configure the Speed to 100G */ cfg_port_table.set("Ethernet0", { {"speed", "100000"}, - {"autoneg", "off"} + }); + + /* Scenario: Operational Speed Changes to 100G, no autoneg */ + state_port_table.set("Ethernet0", { + {"speed", "100000"}, + {"netdev_oper_status", "up"} }); + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + /* Scenario: Operational Speed Changes to 25G, with autoneg */ + state_port_table.set("Ethernet0", { + {"speed", "25000"}, + {"netdev_oper_status", "up"} + }); + + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + values.clear(); + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); + /* Rate is supposed to be updated */ + ASSERT_TRUE(value_rate.get() == "25000"); + + /* rate_neg is disabled and oper status happen to get disabled */ + state_port_table.set("Ethernet0", { + {"speed", "25000"}, + {"netdev_oper_status", "down"} + }); + + /* Configured speed is updated by user */ + cfg_port_table.set("Ethernet0", { + {"speed", "200000"}, + }); + + m_sflowMgr->addExistingData(&state_port_table); m_sflowMgr->addExistingData(&cfg_port_table); m_sflowMgr->doTask(); - /* Sample rate should be back to configured speed if auto-neg is disabled */ values.clear(); appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "100000"); + ASSERT_TRUE(value_rate.get() == "200000"); } TEST_F(SflowMgrTest, test_OnlyStateDbNotif) @@ -132,29 +194,22 @@ namespace sflowmgr_ut {"speed", "100000"} }); - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "100000"); - cfg_sflow_table.set("Ethernet0", { {"sample_rate", "12345"} }); + m_sflowMgr->addExistingData(&cfg_port_table); m_sflowMgr->addExistingData(&cfg_sflow_table); m_sflowMgr->doTask(); + std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "12345"); } - TEST_F(SflowMgrTest, test_LocalRateConfigurationWithOperSpeed) + TEST_F(SflowMgrTest, test_LocalRateConfWithOperSpeed) { Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); @@ -163,39 +218,33 @@ namespace sflowmgr_ut cfg_port_table.set("Ethernet0", { {"speed", "100000"}, - {"autoneg", "on"} }); /* Scenario: Operational Speed Changes to 25000 */ state_port_table.set("Ethernet0", { - {"speed", "25000"} + {"speed", "25000"}, + {"netdev_oper_status", "up"} }); - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "25000"); - cfg_sflow_table.set("Ethernet0", { {"sample_rate", "12345"} }); + m_sflowMgr->addExistingData(&cfg_port_table); m_sflowMgr->addExistingData(&cfg_sflow_table); + m_sflowMgr->addExistingData(&state_port_table); m_sflowMgr->doTask(); + std::vector<FieldValueTuple> values; appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "12345"); /* Operational Speed Changes again to 50000 */ state_port_table.set("Ethernet0", { - {"speed", "50000"} + {"speed", "50000"}, + {"netdev_oper_status", "up"} }); m_sflowMgr->addExistingData(&state_port_table); @@ -208,7 +257,7 @@ namespace sflowmgr_ut ASSERT_TRUE(value_rate.get() == "12345"); } - TEST_F(SflowMgrTest, test_800g) + TEST_F(SflowMgrTest, test_new_speed) { Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); From 2fe2160b1342ce4c61f1b5683a29fbe0826dc60b Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Sat, 27 May 2023 00:42:40 +0000 Subject: [PATCH 7/9] Handle comments Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 53 ++++++++++++++-------------- cfgmgr/sflowmgr.h | 4 +-- cfgmgr/sflowmgrd.cpp | 3 +- tests/mock_tests/sflowmgrd_ut.cpp | 58 +++++++++++++------------------ 4 files changed, 54 insertions(+), 64 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index fecff136ed..88a37f53e5 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -25,11 +25,11 @@ void SflowMgr::readPortConfig() if (consumer_it != m_consumerMap.end()) { consumer_it->second->drain(); - SWSS_LOG_INFO("Port Configuration Read.."); + SWSS_LOG_NOTICE("Port Configuration Read.."); } else { - throw std::runtime_error("Consumer for config db PORT_TABLE not found"); + SWSS_LOG_ERROR("Consumer object for PORT_TABLE not found"); } } @@ -84,15 +84,15 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) new_port = true; port_info.local_rate_cfg = false; port_info.local_admin_cfg = false; - port_info.speed = SFLOW_ERROR_SPEED_STR; - port_info.oper_speed = SFLOW_NA_SPEED_STR; + port_info.speed = ERROR_SPEED; + port_info.oper_speed = NA_SPEED; port_info.rate = ""; port_info.admin = ""; m_sflowPortConfMap[key] = port_info; } bool rate_update = false; - string new_speed = SFLOW_ERROR_SPEED_STR; + string new_speed = ERROR_SPEED; for (auto i : values) { if (fvField(i) == "speed") @@ -146,8 +146,8 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) string alias = kfvKey(t); string op = kfvOp(t); auto values = kfvFieldsValues(t); - string oper_speed = SFLOW_NA_SPEED_STR; - bool oper_status = false; + string oper_speed = ""; + bool rate_update = false; for (auto i : values) { @@ -155,35 +155,34 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) { oper_speed = fvValue(i); } - else if (fvField(i) == "netdev_oper_status") - { - oper_status = fvValue(i) == "up" ? true : false; - } } - /* When the oper_status is down, the speed (if present) is just a stale entry and hence discard */ - oper_speed = oper_status ? oper_speed : SFLOW_NA_SPEED_STR; - - if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) - { - SWSS_LOG_ERROR("Port %s not found in port conf map", alias.c_str()); - } - else + if (m_sflowPortConfMap.find(alias) != m_sflowPortConfMap.end() && op == SET_COMMAND) { - bool speed_change = false; - if (m_sflowPortConfMap[alias].oper_speed != oper_speed) + SWSS_LOG_DEBUG("STATE_DB update: iface: %s, oper_speed: %s, cfg_speed: %s, new_speed: %s", + alias.c_str(), m_sflowPortConfMap[alias].oper_speed.c_str(), + m_sflowPortConfMap[alias].speed.c_str(), + oper_speed.c_str()); + /* oper_speed is updated by orchagent if the vendor supports and oper status is up */ + if (m_sflowPortConfMap[alias].oper_speed != oper_speed && !oper_speed.empty()) { - speed_change = true; + rate_update = true; + if (oper_speed == m_sflowPortConfMap[alias].speed && m_sflowPortConfMap[alias].oper_speed == NA_SPEED) + { + /* if oper_speed is equal to cfg_speed, avoid the write to APP_DB + Can happen if auto-neg is not set */ + rate_update = false; + } m_sflowPortConfMap[alias].oper_speed = oper_speed; } - if (speed_change && m_gEnable && m_intfAllConf && - !m_sflowPortConfMap[alias].local_rate_cfg) + + if (rate_update && m_gEnable && m_intfAllConf && !m_sflowPortConfMap[alias].local_rate_cfg ) { auto rate = findSamplingRate(alias); FieldValueTuple fv("sample_rate", rate); vector<FieldValueTuple> fvs = {fv}; m_appSflowSessionTable.set(alias, fvs); - SWSS_LOG_INFO("Default sampling rate for %s updated to %s", alias.c_str(), rate.c_str()); + SWSS_LOG_NOTICE("Default sampling rate for %s updated to %s", alias.c_str(), rate.c_str()); } } /* Do nothing for DEL as the SflowPortConfMap will already be cleared by the DEL from CONFIG_DB */ @@ -327,11 +326,11 @@ string SflowMgr::findSamplingRate(const string& alias) if (m_sflowPortConfMap.find(alias) == m_sflowPortConfMap.end()) { SWSS_LOG_ERROR("%s not found in port configuration map", alias.c_str()); - return SFLOW_ERROR_SPEED_STR; + return ERROR_SPEED; } string oper_speed = m_sflowPortConfMap[alias].oper_speed; string cfg_speed = m_sflowPortConfMap[alias].speed; - if (!oper_speed.empty() && oper_speed != SFLOW_NA_SPEED_STR) + if (!oper_speed.empty() && oper_speed != NA_SPEED) { return oper_speed; } diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index 51dae92d7b..c1c1f92b60 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -10,8 +10,8 @@ namespace swss { -#define SFLOW_ERROR_SPEED_STR "error" -#define SFLOW_NA_SPEED_STR "N/A" +#define ERROR_SPEED "error" +#define NA_SPEED "N/A" struct SflowPortInfo { diff --git a/cfgmgr/sflowmgrd.cpp b/cfgmgr/sflowmgrd.cpp index 83fb134c82..ebe489dfdc 100644 --- a/cfgmgr/sflowmgrd.cpp +++ b/cfgmgr/sflowmgrd.cpp @@ -61,7 +61,8 @@ int main(int argc, char **argv) }; SflowMgr sflowmgr(&appDb, sflow_tables); - + /* During process startup, the ordering of cfg_db followed by state_db notifications cannot be guaranteed + and so handle the cfg notifs manually */ sflowmgr.readPortConfig(); vector<Orch *> orchList = {&sflowmgr}; diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index 5c3e291e4a..e07cf04359 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -74,8 +74,7 @@ namespace sflowmgr_ut /* Scenario: Operational Speed Changes to 25000 */ state_port_table.set("Ethernet0", { - {"speed", "25000"}, - {"netdev_oper_status", "up"} + {"speed", "25000"} }); m_sflowMgr->addExistingData(&state_port_table); @@ -86,22 +85,6 @@ namespace sflowmgr_ut value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); ASSERT_TRUE(value_rate.get() == "25000"); - - /* oper status is down since rate_neg is disabled */ - state_port_table.set("Ethernet0", { - {"speed", "25000"}, - {"netdev_oper_status", "down"} - }); - - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - values.clear(); - appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - /* Sample rate is restored to original value */ - ASSERT_TRUE(value_rate.get() == "100000"); } TEST_F(SflowMgrTest, test_RateConfigurationOperUpDown) @@ -117,38 +100,45 @@ namespace sflowmgr_ut {"speed", "100000"}, }); - /* Scenario: Operational Speed Changes to 100G, no autoneg */ + /* Scenario: Operational Speed Changes to 100G with autoneg */ state_port_table.set("Ethernet0", { - {"speed", "100000"}, - {"netdev_oper_status", "up"} + {"speed", "100000"} }); m_sflowMgr->addExistingData(&cfg_port_table); m_sflowMgr->addExistingData(&state_port_table); m_sflowMgr->doTask(); - /* Scenario: Operational Speed Changes to 25G, with autoneg */ - state_port_table.set("Ethernet0", { - {"speed", "25000"}, - {"netdev_oper_status", "up"} + /* User changes the config speed to 10G */ + cfg_port_table.set("Ethernet0", { + {"speed", "10000"}, }); - m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->addExistingData(&cfg_port_table); m_sflowMgr->doTask(); values.clear(); appl_sflow_table.get("Ethernet0", values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); - /* Rate is supposed to be updated */ - ASSERT_TRUE(value_rate.get() == "25000"); + /* Rate Should still adhere to oper_speed */ + ASSERT_TRUE(value_rate.get() == "100000"); - /* rate_neg is disabled and oper status happen to get disabled */ + /* Scenario: Operational Speed Changes to 10G, with autoneg */ state_port_table.set("Ethernet0", { - {"speed", "25000"}, - {"netdev_oper_status", "down"} + {"speed", "10000"} }); + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + + values.clear(); + appl_sflow_table.get("Ethernet0", values); + value_rate = swss::fvsGetValue(values, "sample_rate", true); + ASSERT_TRUE(value_rate); + /* Rate is supposed to be updated */ + ASSERT_TRUE(value_rate.get() == "10000"); + /* Configured speed is updated by user */ cfg_port_table.set("Ethernet0", { {"speed", "200000"}, @@ -162,7 +152,8 @@ namespace sflowmgr_ut appl_sflow_table.get("Ethernet0", values); value_rate = swss::fvsGetValue(values, "sample_rate", true); ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "200000"); + /* Sampling Rate will not be updated */ + ASSERT_TRUE(value_rate.get() == "10000"); } TEST_F(SflowMgrTest, test_OnlyStateDbNotif) @@ -243,8 +234,7 @@ namespace sflowmgr_ut /* Operational Speed Changes again to 50000 */ state_port_table.set("Ethernet0", { - {"speed", "50000"}, - {"netdev_oper_status", "up"} + {"speed", "50000"} }); m_sflowMgr->addExistingData(&state_port_table); From 0bf48266480c1e80b17c2b0dedad9cf1db2274fc Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Sat, 27 May 2023 08:24:59 +0000 Subject: [PATCH 8/9] Handled comments, Refactored and added new tests Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 25 ++- cfgmgr/sflowmgr.h | 1 + tests/mock_tests/sflowmgrd_ut.cpp | 321 ++++++++++++++---------------- 3 files changed, 168 insertions(+), 179 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index 88a37f53e5..d9d46f59b2 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -33,6 +33,19 @@ void SflowMgr::readPortConfig() } } +bool SflowMgr::isPortEnabled(const std::string& alias) +{ + /* Checks if the sflow is enabled on the port */ + auto it = m_sflowPortConfMap.find(alias); + if (it == m_sflowPortConfMap.end()) + { + return false; + } + bool local_admin = it->second.local_admin_cfg; + bool status = it->second.admin == "up" ? true : false; + return m_gEnable && (m_intfAllConf || (local_admin && status)); +} + void SflowMgr::sflowHandleService(bool enable) { stringstream cmd; @@ -103,12 +116,16 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer) if (m_sflowPortConfMap[key].speed != new_speed) { m_sflowPortConfMap[key].speed = new_speed; - rate_update = true; + /* if oper_speed is set, no need to write to APP_DB */ + if (m_sflowPortConfMap[key].oper_speed == NA_SPEED) + { + rate_update = true; + } } - if (m_gEnable && m_intfAllConf) + if (isPortEnabled(key)) { - // If the Local rate Conf is already present, dont't override it even though the speed is changed + // If the Local rate conf is already present, dont't override it even though the speed is changed if (new_port || (rate_update && !m_sflowPortConfMap[key].local_rate_cfg)) { vector<FieldValueTuple> fvs; @@ -176,7 +193,7 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) m_sflowPortConfMap[alias].oper_speed = oper_speed; } - if (rate_update && m_gEnable && m_intfAllConf && !m_sflowPortConfMap[alias].local_rate_cfg ) + if (isPortEnabled(alias) && rate_update && !m_sflowPortConfMap[alias].local_rate_cfg) { auto rate = findSamplingRate(alias); FieldValueTuple fv("sample_rate", rate); diff --git a/cfgmgr/sflowmgr.h b/cfgmgr/sflowmgr.h index c1c1f92b60..0a3df13652 100644 --- a/cfgmgr/sflowmgr.h +++ b/cfgmgr/sflowmgr.h @@ -49,6 +49,7 @@ class SflowMgr : public Orch void sflowCheckAndFillValues(std::string alias, std::vector<FieldValueTuple> &values, std::vector<FieldValueTuple> &fvs); void sflowGetPortInfo(std::vector<FieldValueTuple> &fvs, SflowPortInfo &local_info); void sflowGetGlobalInfo(std::vector<FieldValueTuple> &fvs, const std::string& alias); + bool isPortEnabled(const std::string& alias); std::string findSamplingRate(const std::string& speed); }; diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index e07cf04359..96f79daa41 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -51,219 +51,190 @@ namespace sflowmgr_ut m_sflowMgr->addExistingData(&cfg_sflow); m_sflowMgr->doTask(); } + + void cfgSflowSession(string alias, bool status, string sample_rate) + { + Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + vector<FieldValueTuple> values; + values.emplace_back("admin_state", status ? "up" : "down"); + if (!sample_rate.empty()) + { + values.emplace_back("sample_rate", sample_rate); + } + cfg_sflow_table.set(alias, values); + m_sflowMgr->addExistingData(&cfg_sflow_table); + m_sflowMgr->doTask(); + } + + void cfgSflowSessionAll(bool status) + { + Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); + cfg_sflow_table.set("all", { + {"admin_state", status ? "up" : "down"}, + }); + m_sflowMgr->addExistingData(&cfg_sflow_table); + m_sflowMgr->doTask(); + } + + void cfgPortSpeed(string alias, string speed) + { + Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); + cfg_port_table.set(alias, { + {"speed", speed} + }); + m_sflowMgr->addExistingData(&cfg_port_table); + m_sflowMgr->doTask(); + } + + void statePortSpeed(string alias, string speed) + { + Table state_port_table(m_config_db.get(), STATE_PORT_TABLE_NAME); + state_port_table.set(alias, { + {"speed", speed} + }); + m_sflowMgr->addExistingData(&state_port_table); + m_sflowMgr->doTask(); + } + + string getSflowSampleRate(string alias) + { + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "sample_rate", true); + if (value_rate) + { + string ret = value_rate.get(); + return ret; + } + return ""; + } + + string getSflowAdminStatus(string alias) + { + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + std::vector<FieldValueTuple> values; + appl_sflow_table.get("Ethernet0", values); + auto value_rate = swss::fvsGetValue(values, "admin_state", true); + if (value_rate) + { + string ret = value_rate.get(); + return ret; + } + return "down"; + } }; TEST_F(SflowMgrTest, test_RateConfiguration) { - Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - - cfg_port_table.set("Ethernet0", { - {"speed", "100000"}, - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "100000"); + cfgPortSpeed("Ethernet0", "100000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); /* Scenario: Operational Speed Changes to 25000 */ - state_port_table.set("Ethernet0", { - {"speed", "25000"} - }); - - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - values.clear(); - appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "25000"); + statePortSpeed("Ethernet0", "25000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "25000"); } - TEST_F(SflowMgrTest, test_RateConfigurationOperUpDown) + TEST_F(SflowMgrTest, test_RateConfigurationCfgSpeed) { - /* Simulates a realistic scenario of oper up down events mixed with auto neg */ - Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - std::vector<FieldValueTuple> values; - /* Configure the Speed to 100G */ - cfg_port_table.set("Ethernet0", { - {"speed", "100000"}, - }); + cfgPortSpeed("Ethernet0", "100000"); /* Scenario: Operational Speed Changes to 100G with autoneg */ - state_port_table.set("Ethernet0", { - {"speed", "100000"} - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); + statePortSpeed("Ethernet0", "100000"); /* User changes the config speed to 10G */ - cfg_port_table.set("Ethernet0", { - {"speed", "10000"}, - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); + cfgPortSpeed("Ethernet0", "10000"); - values.clear(); - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - /* Rate Should still adhere to oper_speed */ - ASSERT_TRUE(value_rate.get() == "100000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); /* Scenario: Operational Speed Changes to 10G, with autoneg */ - state_port_table.set("Ethernet0", { - {"speed", "10000"} - }); - - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - values.clear(); - appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - /* Rate is supposed to be updated */ - ASSERT_TRUE(value_rate.get() == "10000"); + statePortSpeed("Ethernet0", "10000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "10000"); /* Configured speed is updated by user */ - cfg_port_table.set("Ethernet0", { - {"speed", "200000"}, - }); - - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); - - values.clear(); - appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); + cfgPortSpeed("Ethernet0", "200000"); + /* Sampling Rate will not be updated */ - ASSERT_TRUE(value_rate.get() == "10000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "10000"); } TEST_F(SflowMgrTest, test_OnlyStateDbNotif) { - Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - - state_port_table.set("Ethernet0", { - {"speed", "100000"} - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_FALSE(value_rate); + statePortSpeed("Ethernet0", "100000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); } TEST_F(SflowMgrTest, test_LocalRateConfiguration) { - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); - - cfg_port_table.set("Ethernet0", { - {"speed", "100000"} - }); - - cfg_sflow_table.set("Ethernet0", { - {"sample_rate", "12345"} - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->addExistingData(&cfg_sflow_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "12345"); + cfgPortSpeed("Ethernet0", "100000"); + cfgSflowSession("Ethernet0", true, "12345"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); } TEST_F(SflowMgrTest, test_LocalRateConfWithOperSpeed) { - Table state_port_table(m_state_db.get(), STATE_PORT_TABLE_NAME); - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); - - cfg_port_table.set("Ethernet0", { - {"speed", "100000"}, - }); + cfgPortSpeed("Ethernet0", "100000"); /* Scenario: Operational Speed Changes to 25000 */ - state_port_table.set("Ethernet0", { - {"speed", "25000"}, - {"netdev_oper_status", "up"} - }); - - cfg_sflow_table.set("Ethernet0", { - {"sample_rate", "12345"} - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->addExistingData(&cfg_sflow_table); - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "12345"); + statePortSpeed("Ethernet0", "25000"); + + /* Set per interface sampling rate*/ + cfgSflowSession("Ethernet0", true, "12345"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); /* Operational Speed Changes again to 50000 */ - state_port_table.set("Ethernet0", { - {"speed", "50000"} - }); - - m_sflowMgr->addExistingData(&state_port_table); - m_sflowMgr->doTask(); - - appl_sflow_table.get("Ethernet0", values); - value_rate = swss::fvsGetValue(values, "sample_rate", true); - /* Local config wouldn't change */ - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "12345"); + statePortSpeed("Ethernet0", "50000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); + } + + TEST_F(SflowMgrTest, test_newSpeed) + { + cfgPortSpeed("Ethernet0", "800000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "800000"); + } + + TEST_F(SflowMgrTest, test_CfgSpeedAdminCfg) + { + cfgPortSpeed("Ethernet0", "100000"); + cfgSflowSessionAll(false); /* Disable sflow on all interfaces*/ + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); + cfgSflowSession("Ethernet0", true, ""); /* Set local admin up with no rate */ + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + + /* Sampling rate should adhere to config speed*/ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); + + cfgPortSpeed("Ethernet0", "25000"); /* Change cfg speed */ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "25000"); } - TEST_F(SflowMgrTest, test_new_speed) + TEST_F(SflowMgrTest, test_OperSpeedAdminCfg) { - Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); - Table cfg_port_table(m_config_db.get(), CFG_PORT_TABLE_NAME); - Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); - - cfg_port_table.set("Ethernet0", { - {"speed", "800000"} - }); - - m_sflowMgr->addExistingData(&cfg_port_table); - m_sflowMgr->doTask(); - - std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); - auto value_rate = swss::fvsGetValue(values, "sample_rate", true); - ASSERT_TRUE(value_rate); - ASSERT_TRUE(value_rate.get() == "800000"); + cfgPortSpeed("Ethernet0", "100000"); + cfgSflowSessionAll(false); /* Disable sflow on all interfaces*/ + cfgSflowSession("Ethernet0", true, ""); /* Set local admin up with no rate */ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + + statePortSpeed("Ethernet0", "50000"); + /* Sampling rate should adhere to oper speed*/ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "50000"); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + + /* Change cfg speed */ + cfgPortSpeed("Ethernet0", "25000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "50000"); + + statePortSpeed("Ethernet0", "1000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "1000"); + + cfgSflowSession("Ethernet0", true, "12345"); /* Set local sampling rate */ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + + /* Change oper speed now */ + statePortSpeed("Ethernet0", "12345"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); } } From 0009f3d3b0cc703ae88683be89072a39d6d5238f Mon Sep 17 00:00:00 2001 From: Vivek Reddy Karri <vkarri@nvidia.com> Date: Thu, 1 Jun 2023 22:29:38 +0000 Subject: [PATCH 9/9] Handle merge problem and ut's to cover direction case Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com> --- cfgmgr/sflowmgr.cpp | 11 ++-- tests/mock_tests/sflowmgrd_ut.cpp | 88 +++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/cfgmgr/sflowmgr.cpp b/cfgmgr/sflowmgr.cpp index 72043a3f6c..122ffc0780 100644 --- a/cfgmgr/sflowmgr.cpp +++ b/cfgmgr/sflowmgr.cpp @@ -206,11 +206,10 @@ void SflowMgr::sflowProcessOperSpeed(Consumer &consumer) if (isPortEnabled(alias) && rate_update && !m_sflowPortConfMap[alias].local_rate_cfg) { - auto rate = findSamplingRate(alias); - FieldValueTuple fv("sample_rate", rate); - vector<FieldValueTuple> fvs = {fv}; + vector<FieldValueTuple> fvs; + sflowGetGlobalInfo(fvs, alias, m_sflowPortConfMap[alias].dir); m_appSflowSessionTable.set(alias, fvs); - SWSS_LOG_NOTICE("Default sampling rate for %s updated to %s", alias.c_str(), rate.c_str()); + SWSS_LOG_NOTICE("Default sampling rate for %s updated to %s", alias.c_str(), findSamplingRate(alias).c_str()); } } /* Do nothing for DEL as the SflowPortConfMap will already be cleared by the DEL from CONFIG_DB */ @@ -242,7 +241,7 @@ void SflowMgr::sflowHandleSessionAll(bool enable, string direction) } else { - sflowGetGlobalInfo(fvs, it.second.speed, direction); + sflowGetGlobalInfo(fvs, it.first, direction); } m_appSflowSessionTable.set(it.first, fvs); } @@ -577,7 +576,7 @@ void SflowMgr::doTask(Consumer &consumer) if (m_intfAllConf) { vector<FieldValueTuple> fvs; - sflowGetGlobalInfo(fvs, m_sflowPortConfMap[key].speed, m_intfAllDir); + sflowGetGlobalInfo(fvs, key, m_intfAllDir); m_appSflowSessionTable.set(key,fvs); } } diff --git a/tests/mock_tests/sflowmgrd_ut.cpp b/tests/mock_tests/sflowmgrd_ut.cpp index 96f79daa41..7e47b162f2 100644 --- a/tests/mock_tests/sflowmgrd_ut.cpp +++ b/tests/mock_tests/sflowmgrd_ut.cpp @@ -39,7 +39,6 @@ namespace sflowmgr_ut conf_sflow_session_table }; m_sflowMgr.reset(new SflowMgr(m_app_db.get(), sflow_tables)); - enableSflow(); } void enableSflow() @@ -52,7 +51,7 @@ namespace sflowmgr_ut m_sflowMgr->doTask(); } - void cfgSflowSession(string alias, bool status, string sample_rate) + void cfgSflowSession(string alias, bool status, string sample_rate, string direction = "") { Table cfg_sflow_table(m_config_db.get(), CFG_SFLOW_SESSION_TABLE_NAME); vector<FieldValueTuple> values; @@ -61,6 +60,10 @@ namespace sflowmgr_ut { values.emplace_back("sample_rate", sample_rate); } + if (!direction.empty()) + { + values.emplace_back("sample_direction", direction); + } cfg_sflow_table.set(alias, values); m_sflowMgr->addExistingData(&cfg_sflow_table); m_sflowMgr->doTask(); @@ -100,7 +103,7 @@ namespace sflowmgr_ut { Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); + appl_sflow_table.get(alias, values); auto value_rate = swss::fvsGetValue(values, "sample_rate", true); if (value_rate) { @@ -110,11 +113,25 @@ namespace sflowmgr_ut return ""; } + string getSflowSampleDir(string alias) + { + Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); + std::vector<FieldValueTuple> values; + appl_sflow_table.get(alias, values); + auto value_rate = swss::fvsGetValue(values, "sample_direction", true); + if (value_rate) + { + string ret = value_rate.get(); + return ret; + } + return ""; + } + string getSflowAdminStatus(string alias) { Table appl_sflow_table(m_app_db.get(), APP_SFLOW_SESSION_TABLE_NAME); std::vector<FieldValueTuple> values; - appl_sflow_table.get("Ethernet0", values); + appl_sflow_table.get(alias, values); auto value_rate = swss::fvsGetValue(values, "admin_state", true); if (value_rate) { @@ -127,16 +144,19 @@ namespace sflowmgr_ut TEST_F(SflowMgrTest, test_RateConfiguration) { + enableSflow(); cfgPortSpeed("Ethernet0", "100000"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); /* Scenario: Operational Speed Changes to 25000 */ statePortSpeed("Ethernet0", "25000"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "25000"); + ASSERT_TRUE(getSflowSampleDir("Ethernet0") == "rx"); } TEST_F(SflowMgrTest, test_RateConfigurationCfgSpeed) { + enableSflow(); /* Configure the Speed to 100G */ cfgPortSpeed("Ethernet0", "100000"); @@ -161,12 +181,14 @@ namespace sflowmgr_ut TEST_F(SflowMgrTest, test_OnlyStateDbNotif) { + enableSflow(); statePortSpeed("Ethernet0", "100000"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); } TEST_F(SflowMgrTest, test_LocalRateConfiguration) { + enableSflow(); cfgPortSpeed("Ethernet0", "100000"); cfgSflowSession("Ethernet0", true, "12345"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); @@ -174,6 +196,7 @@ namespace sflowmgr_ut TEST_F(SflowMgrTest, test_LocalRateConfWithOperSpeed) { + enableSflow(); cfgPortSpeed("Ethernet0", "100000"); /* Scenario: Operational Speed Changes to 25000 */ @@ -190,12 +213,14 @@ namespace sflowmgr_ut TEST_F(SflowMgrTest, test_newSpeed) { + enableSflow(); cfgPortSpeed("Ethernet0", "800000"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "800000"); } TEST_F(SflowMgrTest, test_CfgSpeedAdminCfg) { + enableSflow(); cfgPortSpeed("Ethernet0", "100000"); cfgSflowSessionAll(false); /* Disable sflow on all interfaces*/ ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); @@ -211,6 +236,7 @@ namespace sflowmgr_ut TEST_F(SflowMgrTest, test_OperSpeedAdminCfg) { + enableSflow(); cfgPortSpeed("Ethernet0", "100000"); cfgSflowSessionAll(false); /* Disable sflow on all interfaces*/ cfgSflowSession("Ethernet0", true, ""); /* Set local admin up with no rate */ @@ -237,4 +263,58 @@ namespace sflowmgr_ut statePortSpeed("Ethernet0", "12345"); ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "12345"); } + + TEST_F(SflowMgrTest, test_SflowCfgAfterPortCfg) + { + cfgPortSpeed("Ethernet0", "100000"); + /* Nothing is written yet since cfg is not enabled */ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); + + /* State DB is updated with oper speed */ + statePortSpeed("Ethernet0", "100000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); + + /* enable sflow */ + enableSflow(); + cfgSflowSessionAll(true); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + ASSERT_TRUE(getSflowSampleDir("Ethernet0") == "rx"); + } + + TEST_F(SflowMgrTest, test_SflowCfgAfterOperSpeed) + { + cfgPortSpeed("Ethernet0", "100000"); + /* Nothing is written yet since cfg is not enabled */ + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); + + /* State DB is updated with oper speed */ + statePortSpeed("Ethernet0", "50000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == ""); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "down"); + + /* enable sflow */ + cfgSflowSessionAll(true); + enableSflow(); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "50000"); + ASSERT_TRUE(getSflowAdminStatus("Ethernet0") == "up"); + ASSERT_TRUE(getSflowSampleDir("Ethernet0") == "rx"); + } + + TEST_F(SflowMgrTest, test_RateConfigEgressDir) + { + enableSflow(); + cfgPortSpeed("Ethernet0", "100000"); + /* Set local admin up with no rate and no egress direction */ + cfgSflowSession("Ethernet0", true, "", "tx"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "100000"); + + /* Scenario: Operational Speed Changes to 25000 */ + statePortSpeed("Ethernet0", "25000"); + ASSERT_TRUE(getSflowSampleRate("Ethernet0") == "25000"); + ASSERT_TRUE(getSflowSampleDir("Ethernet0") == "tx"); + } }