From eb162b8ad32794037e7d347ab806d25468113537 Mon Sep 17 00:00:00 2001 From: Prince Sunny Date: Fri, 4 Jun 2021 10:00:40 -0700 Subject: [PATCH] [Mux] Add support for mux metrics to State DB (#1757) * Update Mux metric table for orchagent switchover * Add VS test to check metric fields --- orchagent/muxorch.cpp | 35 ++++++++++++++++++++++--- orchagent/muxorch.h | 4 ++- orchagent/orchdaemon.cpp | 2 +- tests/test_mux.py | 55 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/orchagent/muxorch.cpp b/orchagent/muxorch.cpp index 7d629705ab7..503ff3cd166 100644 --- a/orchagent/muxorch.cpp +++ b/orchagent/muxorch.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include "sai.h" #include "ipaddress.h" @@ -405,6 +408,8 @@ void MuxCable::setState(string new_state) return; } + mux_cb_orch_->updateMuxMetricState(mux_name_, new_state, true); + MuxState state = state_; state_ = ns; @@ -419,6 +424,8 @@ void MuxCable::setState(string new_state) throw std::runtime_error("Failed to handle state transition"); } + mux_cb_orch_->updateMuxMetricState(mux_name_, new_state, false); + st_chg_in_progress_ = false; st_chg_failed_ = false; SWSS_LOG_INFO("Changed state to %s", new_state.c_str()); @@ -1261,9 +1268,10 @@ bool MuxOrch::delOperation(const Request& request) return true; } -MuxCableOrch::MuxCableOrch(DBConnector *db, const std::string& tableName): +MuxCableOrch::MuxCableOrch(DBConnector *db, DBConnector *sdb, const std::string& tableName): Orch2(db, tableName, request_), - app_tunnel_route_table_(db, APP_TUNNEL_ROUTE_TABLE_NAME) + app_tunnel_route_table_(db, APP_TUNNEL_ROUTE_TABLE_NAME), + mux_metric_table_(sdb, STATE_MUX_METRICS_TABLE_NAME) { mux_table_ = unique_ptr(new Table(db, APP_HW_MUX_CABLE_TABLE_NAME)); } @@ -1276,6 +1284,27 @@ void MuxCableOrch::updateMuxState(string portName, string muxState) mux_table_->set(portName, tuples); } +void MuxCableOrch::updateMuxMetricState(string portName, string muxState, bool start) +{ + string msg = "orch_switch_" + muxState; + msg += start? "_start": "_end"; + + auto now = std::chrono::system_clock::now(); + auto now_t = std::chrono::system_clock::to_time_t(now); + auto dur = now - std::chrono::system_clock::from_time_t(now_t); + auto micros = std::chrono::duration_cast(dur).count(); + + std::tm now_tm; + gmtime_r(&now_t, &now_tm); + + char buf[256]; + std::strftime(buf, 256, "%Y-%b-%d %H:%M:%S.", &now_tm); + + string time = string(buf) + to_string(micros); + + mux_metric_table_.hset(portName, msg, time); +} + void MuxCableOrch::addTunnelRoute(const NextHopKey &nhKey) { vector data; @@ -1349,7 +1378,7 @@ MuxStateOrch::MuxStateOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_), mux_state_table_(db, STATE_MUX_CABLE_TABLE_NAME) { - SWSS_LOG_ENTER(); + SWSS_LOG_ENTER(); } void MuxStateOrch::updateMuxState(string portName, string muxState) diff --git a/orchagent/muxorch.h b/orchagent/muxorch.h index 0c34936f75f..ed1f5bd4b1a 100644 --- a/orchagent/muxorch.h +++ b/orchagent/muxorch.h @@ -228,9 +228,10 @@ class MuxCableRequest : public Request class MuxCableOrch : public Orch2 { public: - MuxCableOrch(DBConnector *db, const std::string& tableName); + MuxCableOrch(DBConnector *db, DBConnector *sdb, const std::string& tableName); void updateMuxState(string portName, string muxState); + void updateMuxMetricState(string portName, string muxState, bool start); void addTunnelRoute(const NextHopKey &nhKey); void removeTunnelRoute(const NextHopKey &nhKey); @@ -240,6 +241,7 @@ class MuxCableOrch : public Orch2 unique_ptr
mux_table_; MuxCableRequest request_; + swss::Table mux_metric_table_; ProducerStateTable app_tunnel_route_table_; }; diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index f28908418a5..4c9fc3a4e7b 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -262,7 +262,7 @@ bool OrchDaemon::init() MuxOrch *mux_orch = new MuxOrch(m_configDb, mux_tables, tunnel_decap_orch, gNeighOrch, gFdbOrch); gDirectory.set(mux_orch); - MuxCableOrch *mux_cb_orch = new MuxCableOrch(m_applDb, APP_MUX_CABLE_TABLE_NAME); + MuxCableOrch *mux_cb_orch = new MuxCableOrch(m_applDb, m_stateDb, APP_MUX_CABLE_TABLE_NAME); gDirectory.set(mux_cb_orch); MuxStateOrch *mux_st_orch = new MuxStateOrch(m_stateDb, STATE_HW_MUX_CABLE_TABLE_NAME); diff --git a/tests/test_mux.py b/tests/test_mux.py index f4fefae651d..84458a841d7 100644 --- a/tests/test_mux.py +++ b/tests/test_mux.py @@ -410,6 +410,51 @@ def create_and_test_acl(self, appdb, asicdb, dvs, dvs_acl): self.set_mux_state(appdb, "Ethernet4", "active") dvs_acl.verify_no_acl_rules() + def create_and_test_metrics(self, appdb, statedb, dvs): + + # Set to active and test attributes for start and end time + self.set_mux_state(appdb, "Ethernet0", "active") + keys = statedb.get_keys("MUX_METRICS_TABLE") + assert len(keys) != 0 + + for key in keys: + if key != "Ethernet0": + continue + fvs = statedb.get_entry("MUX_METRICS_TABLE", key) + assert fvs != {} + + start = end = False + for f,v in fvs.items(): + if f == "orch_switch_active_start": + start = True + elif f == "orch_switch_active_end": + end = True + + assert start + assert end + + # Set to standby and test attributes for start and end time + self.set_mux_state(appdb, "Ethernet0", "standby") + + keys = statedb.get_keys("MUX_METRICS_TABLE") + assert len(keys) != 0 + + for key in keys: + if key != "Ethernet0": + continue + fvs = statedb.get_entry("MUX_METRICS_TABLE", key) + assert fvs != {} + + start = end = False + for f,v in fvs.items(): + if f == "orch_switch_standby_start": + start = True + elif f == "orch_switch_standby_end": + end = True + + assert start + assert end + def check_interface_exists_in_asicdb(self, asicdb, sai_oid): asicdb.wait_for_entry(self.ASIC_RIF_TABLE, sai_oid) @@ -643,13 +688,21 @@ def test_Route(self, dvs, dvs_route, testlog): def test_acl(self, dvs, dvs_acl, testlog): - """ test Route entries and mux state change """ + """ test acl and mux state change """ appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) asicdb = dvs.get_asic_db() self.create_and_test_acl(appdb, asicdb, dvs, dvs_acl) + def test_mux_metrics(self, dvs, testlog): + """ test metrics for mux state change """ + + appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + statedb = dvs.get_state_db() + + self.create_and_test_metrics(appdb, statedb, dvs) + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying