diff --git a/orchagent/fabricportsorch.cpp b/orchagent/fabricportsorch.cpp index e9e7ae972d..8252cdd53c 100644 --- a/orchagent/fabricportsorch.cpp +++ b/orchagent/fabricportsorch.cpp @@ -26,6 +26,10 @@ #define FABRIC_DEBUG_POLLING_INTERVAL_DEFAULT (60) #define FABRIC_MONITOR_DATA "FABRIC_MONITOR_DATA" #define APPL_FABRIC_PORT_PREFIX "Fabric" +#define SWITCH_DEBUG_COUNTER_FLEX_COUNTER_GROUP "SWITCH_DEBUG_COUNTER" +#define SWITCH_DEBUG_COUNTER_POLLING_INTERVAL_MS 500 +#define FABRIC_SWITCH_DEBUG_COUNTER_POLLING_INTERVAL_MS 60000 +#define SWITCH_STANDARD_DROP_COUNTERS "SWITCH_STD_DROP_COUNTER-" // constants for link monitoring #define MAX_SKIP_CRCERR_ON_LNKUP_POLLS 20 @@ -43,6 +47,7 @@ extern sai_object_id_t gSwitchId; extern sai_switch_api_t *sai_switch_api; extern sai_port_api_t *sai_port_api; extern sai_queue_api_t *sai_queue_api; +extern string gMySwitchType; const vector port_stat_ids = { @@ -63,6 +68,11 @@ static const vector queue_stat_ids = SAI_QUEUE_STAT_CURR_OCCUPANCY_LEVEL, }; +const vector switch_drop_counter_ids = +{ + SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP +}; + FabricPortsOrch::FabricPortsOrch(DBConnector *appl_db, vector &tableNames, bool fabricPortStatEnabled, bool fabricQueueStatEnabled) : Orch(appl_db, tableNames), @@ -86,6 +96,15 @@ FabricPortsOrch::FabricPortsOrch(DBConnector *appl_db, vector(new Table(m_counter_db.get(), COUNTERS_FABRIC_PORT_NAME_MAP)); m_fabricCounterTable = unique_ptr(new Table(m_counter_db.get(), COUNTERS_TABLE)); + // Create Switch level drop counters for voq & fabric switch. + if ((gMySwitchType == "voq") || (gMySwitchType == "fabric")) + { + auto timer = ((gMySwitchType == "voq") ? SWITCH_DEBUG_COUNTER_POLLING_INTERVAL_MS : FABRIC_SWITCH_DEBUG_COUNTER_POLLING_INTERVAL_MS); + switch_drop_counter_manager = new FlexCounterManager(SWITCH_DEBUG_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, + timer, true); + m_counterNameToSwitchStatMap = unique_ptr
(new Table(m_counter_db.get(), COUNTERS_DEBUG_NAME_SWITCH_STAT_MAP)); + } + m_appl_db = shared_ptr(new DBConnector("APPL_DB", 0)); m_applTable = unique_ptr
(new Table(m_appl_db.get(), APP_FABRIC_MONITOR_PORT_TABLE_NAME)); m_applMonitorConstTable = unique_ptr
(new Table(m_appl_db.get(), APP_FABRIC_MONITOR_DATA_TABLE_NAME)); @@ -1461,7 +1480,11 @@ void FabricPortsOrch::doTask(swss::SelectableTimer &timer) { updateFabricPortState(); } - + if (((gMySwitchType == "voq") || (gMySwitchType == "fabric")) && (!m_isSwitchStatsGenerated)) + { + createSwitchDropCounters(); + m_isSwitchStatsGenerated = true; + } if (checkFabricPortMonState() && !m_debugTimerEnabled) { m_debugTimer->start(); @@ -1496,3 +1519,17 @@ void FabricPortsOrch::doTask(swss::SelectableTimer &timer) } } } + +void FabricPortsOrch::createSwitchDropCounters(void) +{ + std::unordered_set counter_stats; + for (const auto& it: switch_drop_counter_ids) + { + std::string drop_stats = sai_serialize_switch_stat(it); + counter_stats.emplace(drop_stats); + vector switchNameSwitchCounterMap; + switchNameSwitchCounterMap.emplace_back((SWITCH_STANDARD_DROP_COUNTERS + drop_stats), drop_stats); + m_counterNameToSwitchStatMap->set("", switchNameSwitchCounterMap); + } + switch_drop_counter_manager->setCounterIdList(gSwitchId, CounterType::SWITCH_DEBUG, counter_stats); +} diff --git a/orchagent/fabricportsorch.h b/orchagent/fabricportsorch.h index e9c8b9fe67..66172e9227 100644 --- a/orchagent/fabricportsorch.h +++ b/orchagent/fabricportsorch.h @@ -36,12 +36,14 @@ class FabricPortsOrch : public Orch, public Subject unique_ptr
m_fabricCapacityTable; unique_ptr
m_applMonitorConstTable; unique_ptr m_flexCounterTable; + shared_ptr
m_counterNameToSwitchStatMap; swss::SelectableTimer *m_timer = nullptr; swss::SelectableTimer *m_debugTimer = nullptr; FlexCounterManager port_stat_manager; FlexCounterManager queue_stat_manager; + FlexCounterManager *switch_drop_counter_manager = nullptr; sai_uint32_t m_fabricPortCount; map m_fabricLanePortMap; @@ -52,6 +54,7 @@ class FabricPortsOrch : public Orch, public Subject bool m_getFabricPortListDone = false; bool m_isQueueStatsGenerated = false; bool m_debugTimerEnabled = false; + bool m_isSwitchStatsGenerated = false; string m_defaultPollWithErrors = "0"; string m_defaultPollWithNoErrors = "8"; @@ -68,6 +71,7 @@ class FabricPortsOrch : public Orch, public Subject void updateFabricCapacity(); bool checkFabricPortMonState(); void updateFabricRate(); + void createSwitchDropCounters(); void doTask() override; void doTask(Consumer &consumer); diff --git a/orchagent/port/port_capabilities.h b/orchagent/port/port_capabilities.h index e937e7b943..3941615cfc 100644 --- a/orchagent/port/port_capabilities.h +++ b/orchagent/port/port_capabilities.h @@ -4,6 +4,7 @@ extern "C" { #include #include #include +#include } class PortCapabilities final diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index ebce79093c..40f79eb1b6 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -279,6 +279,11 @@ static const vector queue_stat_ids = SAI_QUEUE_STAT_DROPPED_PACKETS, SAI_QUEUE_STAT_DROPPED_BYTES, }; +static const vector voq_stat_ids = +{ + SAI_QUEUE_STAT_CREDIT_WD_DELETED_PACKETS +}; + static const vector queueWatermarkStatIds = { @@ -7415,6 +7420,10 @@ void PortsOrch::addQueueFlexCountersPerPortPerQueueIndex(const Port& port, size_ } if (voq) { + for (const auto& voq_it: voq_stat_ids) + { + counter_stats.emplace(sai_serialize_queue_stat(voq_it)); + } queue_ids = m_port_voq_ids[port.m_alias]; } else diff --git a/tests/test_virtual_chassis.py b/tests/test_virtual_chassis.py index cd1e66a2b8..aee3e09a70 100644 --- a/tests/test_virtual_chassis.py +++ b/tests/test_virtual_chassis.py @@ -1121,7 +1121,51 @@ def test_remote_port_down(self, vct): # Cleanup inband if configuration self.del_inbandif_port(vct, inband_port) - + def test_voq_drop_counters(self, vct): + """Test VOQ switch drop counters. + + This test validates VOQ Switch counters for Voq/fabric switches - packet integrity counters + """ + + if vct is None: + return + + dvss = vct.dvss + for name in dvss.keys(): + dvs = dvss[name] + # Get the config info + config_db = dvs.get_config_db() + metatbl = config_db.get_entry("DEVICE_METADATA", "localhost") + + cfg_switch_type = metatbl.get("switch_type") + + # Test only for voq or fabric + if cfg_switch_type == "voq" or cfg_switch_type == "fabric": + print("VOQ drop counters test for {}".format(name)) + + # Verify that a counter has been created FLEX_COUNTER_DB and COUNTERS_DB. We will verify the state of + # the counter in the next step. + flex_db = dvs.get_flex_db() + keys = flex_db.get_keys("FLEX_COUNTER_TABLE") + assert len(keys), "No FLEX_COUNTER_TABLE in FLEX_COUNTER_DB" + for key in keys: + if "SWITCH_DEBUG_COUNTER" in key: + drop_entry = flex_db.get_entry("FLEX_COUNTER_TABLE", key) + value = drop_entry.get("SWITCH_DEBUG_COUNTER_ID_LIST") + assert value == "SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP", "Got error in getting Voq Switch Drop counter from FLEX_COUNTER_DB" + + cntr_db = dvs.get_counters_db() + stat_name_entry = cntr_db.get_entry("COUNTERS_DEBUG_NAME_SWITCH_STAT_MAP", "") + value = stat_name_entry.get("SWITCH_STD_DROP_COUNTER-SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP") + assert value == "SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP", "Got error in getting Voq Switch Drop counter name map from COUNTERS_DB" + + asic_db = dvs.get_asic_db() + keys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_SWITCH") + switch_oid_key = keys[0] + stat_entry = cntr_db.get_entry("COUNTERS", switch_oid_key) + value = stat_entry.get("SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP") + assert value == "0", "SAI_SWITCH_STAT_PACKET_INTEGRITY_DROP is non zero in COUNTERS_DB" + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying def test_nonflaky_dummy():