diff --git a/orchagent/flexcounterorch.cpp b/orchagent/flexcounterorch.cpp index a48bd9ceb78..828b793c65a 100644 --- a/orchagent/flexcounterorch.cpp +++ b/orchagent/flexcounterorch.cpp @@ -37,6 +37,8 @@ extern FlowCounterRouteOrch *gFlowCounterRouteOrch; #define TUNNEL_KEY "TUNNEL" #define FLOW_CNT_TRAP_KEY "FLOW_CNT_TRAP" #define FLOW_CNT_ROUTE_KEY "FLOW_CNT_ROUTE" +#define WRED_QUEUE_KEY "WRED_ECN_QUEUE" +#define WRED_PORT_KEY "WRED_ECN_PORT" unordered_map flexCounterGroupMap = { @@ -59,6 +61,8 @@ unordered_map flexCounterGroupMap = {"MACSEC_SA", COUNTERS_MACSEC_SA_GROUP}, {"MACSEC_SA_ATTR", COUNTERS_MACSEC_SA_ATTR_GROUP}, {"MACSEC_FLOW", COUNTERS_MACSEC_FLOW_GROUP}, + {"WRED_ECN_PORT", WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP}, + {"WRED_ECN_QUEUE", WRED_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP}, }; @@ -184,6 +188,17 @@ void FlexCounterOrch::doTask(Consumer &consumer) m_pg_watermark_enabled = true; gPortsOrch->addPriorityGroupWatermarkFlexCounters(getPgConfigurations()); } + else if(key == WRED_PORT_KEY) + { + gPortsOrch->generateWredPortCounterMap(); + m_wred_port_counter_enabled = true; + } + else if(key == WRED_QUEUE_KEY) + { + gPortsOrch->generateQueueMap(getQueueConfigurations()); + m_wred_queue_counter_enabled = true; + gPortsOrch->addWredQueueFlexCounters(getQueueConfigurations()); + } } if(gIntfsOrch && (key == RIF_KEY) && (value == "enable")) { @@ -286,6 +301,16 @@ bool FlexCounterOrch::getPgWatermarkCountersState() const return m_pg_watermark_enabled; } +bool FlexCounterOrch::getWredQueueCountersState() const +{ + return m_wred_queue_counter_enabled; +} + +bool FlexCounterOrch::getWredPortCountersState() const +{ + return m_wred_port_counter_enabled; +} + bool FlexCounterOrch::bake() { /* diff --git a/orchagent/flexcounterorch.h b/orchagent/flexcounterorch.h index 6126588261e..4b072e83606 100644 --- a/orchagent/flexcounterorch.h +++ b/orchagent/flexcounterorch.h @@ -50,6 +50,8 @@ class FlexCounterOrch: public Orch std::map getPgConfigurations(); bool getHostIfTrapCounterState() const {return m_hostif_trap_counter_enabled;} bool getRouteFlowCountersState() const {return m_route_flow_counter_enabled;} + bool getWredQueueCountersState() const; + bool getWredPortCountersState() const; bool bake() override; private: @@ -65,6 +67,8 @@ class FlexCounterOrch: public Orch bool m_pg_watermark_enabled = false; bool m_hostif_trap_counter_enabled = false; bool m_route_flow_counter_enabled = false; + bool m_wred_queue_counter_enabled = false; + bool m_wred_port_counter_enabled = false; Table m_flexCounterConfigTable; Table m_bufferQueueConfigTable; Table m_bufferPgConfigTable; diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 03bc0d74f38..da0aefd864e 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -330,6 +330,22 @@ static const vector ingressPriorityGroupDropS SAI_INGRESS_PRIORITY_GROUP_STAT_DROPPED_PACKETS }; +const vector wred_port_stat_ids = +{ + SAI_PORT_STAT_GREEN_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS, + SAI_PORT_STAT_WRED_DROPPED_PACKETS +}; + +static const vector wred_queue_stat_ids = +{ + SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS, + SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES, + SAI_QUEUE_STAT_WRED_DROPPED_PACKETS, + SAI_QUEUE_STAT_WRED_DROPPED_BYTES +}; + static char* hostif_vlan_tag[] = { [SAI_HOSTIF_VLAN_TAG_STRIP] = "SAI_HOSTIF_VLAN_TAG_STRIP", [SAI_HOSTIF_VLAN_TAG_KEEP] = "SAI_HOSTIF_VLAN_TAG_KEEP", @@ -365,6 +381,8 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector(new DBConnector("STATE_DB", 0)); m_stateBufferMaximumValueTable = unique_ptr(new Table(m_state_db.get(), STATE_BUFFER_MAXIMUM_VALUE_TABLE)); + /* Initialize counter capability table*/ + m_queueCounterCapabilitiesTable = unique_ptr
(new Table(m_state_db.get(), STATE_QUEUE_COUNTER_CAPABILITIES_NAME)); + m_portCounterCapabilitiesTable = unique_ptr
(new Table(m_state_db.get(), STATE_PORT_COUNTER_CAPABILITIES_NAME)); + initGearbox(); string queueWmSha, pgWmSha; @@ -634,6 +656,9 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector (new LagIdAllocator(chassisAppDb)); } + /* Initialize the stats capability in STATE_DB */ + initCounterCapabilities(gSwitchId); + auto executor = new ExecutableTimer(m_port_state_poller, this, "PORT_STATE_POLLER"); Orch::addExecutor(executor); } @@ -871,6 +896,146 @@ bool PortsOrch::getBridgePortReferenceCount(Port &port) return m_bridge_port_ref_count[port.m_alias]; } + +/**** +* Func Name : initCounterCapabilities +* Parameters : switch oid +* Returns : void +* Description: It updates the STATE_DB with platform stat capability +* As of now, it only handles WRED counters +* 1. Initialize the WRED stats capabilities with false for all counters +* 2. Get queue stats capability from the platform +* 3. Based on the fetched queue stats capability, update the STATE_DB +* 4. Get port stats capability from the platform +* 5. Based on the fetched port stats capability, update the STATE_DB +**/ +void PortsOrch::initCounterCapabilities(sai_object_id_t switchId) +{ + sai_stat_capability_list_t queue_stats_capability, port_stats_capability; + + uint32_t queue_stat_count = (uint32_t) queue_stat_ids.size() + + (uint32_t) queueWatermarkStatIds.size() + + (uint32_t) wred_queue_stat_ids.size(); + uint32_t port_stat_count = (uint32_t) port_stat_ids.size() + + (uint32_t) wred_port_stat_ids.size() + + (uint32_t) port_buffer_drop_stat_ids.size(); + uint32_t it = 0; + bool pt_grn_pkt = false, pt_red_pkt = false, pt_ylw_pkt = false, pt_tot_pkt = false; + bool q_ecn_byte = false, q_ecn_pkt = false, q_wred_byte = false, q_wred_pkt = false; + + sai_stat_capability_t stat_initializer; + stat_initializer.stat_enum = 0; + stat_initializer.stat_modes = 0; + vector qstat_cap_list(queue_stat_count, stat_initializer); + queue_stats_capability.count = queue_stat_count; + queue_stats_capability.list = qstat_cap_list.data(); + + vector fieldValuesTrue; + fieldValuesTrue.push_back(FieldValueTuple("isSupported", "true")); + + vector fieldValuesFalse; + fieldValuesFalse.push_back(FieldValueTuple("isSupported", "false")); + + /* 1. Initialize the WRED stats capabilities with false for all counters */ + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_ECN_MARKED_PKT_COUNTER",fieldValuesFalse); + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_ECN_MARKED_BYTE_COUNTER",fieldValuesFalse); + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_WRED_DROPPED_PKT_COUNTER",fieldValuesFalse); + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_WRED_DROPPED_BYTE_COUNTER",fieldValuesFalse); + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_GREEN_DROP_COUNTER",fieldValuesFalse); + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_YELLOW_DROP_COUNTER",fieldValuesFalse); + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_RED_DROP_COUNTER",fieldValuesFalse); + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_TOTAL_DROP_COUNTER",fieldValuesFalse); + + /* 2. Get queue stats capability from the platform */ + sai_status_t status = sai_query_stats_capability(switchId, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability); + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + qstat_cap_list.resize(queue_stats_capability.count); + queue_stats_capability.list = qstat_cap_list.data(); + status = sai_query_stats_capability(switchId, SAI_OBJECT_TYPE_QUEUE, &queue_stats_capability); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_NOTICE("Queue stat capability get failed: WRED queue stats can not be enabled, rv:%d", status); + } + else + { + /* 3. Based on the fetched queue stats capability, update the STATE_DB */ + for(it=0; itset("WRED_ECN_QUEUE_ECN_MARKED_PKT_COUNTER",fieldValuesTrue); + q_ecn_pkt = true; + } + else if (SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES == queue_stats_capability.list[it].stat_enum) + { + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_ECN_MARKED_BYTE_COUNTER",fieldValuesTrue); + q_ecn_byte = true; + } + else if (SAI_QUEUE_STAT_WRED_DROPPED_PACKETS == queue_stats_capability.list[it].stat_enum) + { + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_WRED_DROPPED_PKT_COUNTER",fieldValuesTrue); + q_wred_pkt = true; + } + else if (SAI_QUEUE_STAT_WRED_DROPPED_BYTES == queue_stats_capability.list[it].stat_enum) + { + m_queueCounterCapabilitiesTable->set("WRED_ECN_QUEUE_WRED_DROPPED_BYTE_COUNTER",fieldValuesTrue); + q_wred_byte = true; + } + + } + SWSS_LOG_INFO("WRED queue stats is_capable: [ecn-marked-pkts:%d,ecn-marked-bytes:%d,wred-drop-pkts:%d,wred-drop-bytes:%d]", + q_ecn_pkt, q_ecn_byte, q_wred_pkt, q_wred_byte); + } + + vector pstat_cap_list(port_stat_count, stat_initializer); + port_stats_capability.count = port_stat_count; + port_stats_capability.list = pstat_cap_list.data(); + + /* 4. Get port stats capability from the platform*/ + status = sai_query_stats_capability(switchId, SAI_OBJECT_TYPE_PORT, &port_stats_capability); + if (status == SAI_STATUS_BUFFER_OVERFLOW) + { + pstat_cap_list.resize(port_stats_capability.count); + port_stats_capability.list = pstat_cap_list.data(); + status = sai_query_stats_capability(switchId, SAI_OBJECT_TYPE_PORT, &port_stats_capability); + } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_NOTICE("Port stat capability get failed: WRED port stats can not be enabled, rv:%d", status); + } + else + { + /* 5. Based on the fetched port stats capability, update the STATE_DB*/ + for(it=0; itset("WRED_ECN_PORT_WRED_GREEN_DROP_COUNTER",fieldValuesTrue); + pt_grn_pkt = true; + } + else if (SAI_PORT_STAT_YELLOW_WRED_DROPPED_PACKETS == port_stats_capability.list[it].stat_enum) + { + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_YELLOW_DROP_COUNTER",fieldValuesTrue); + pt_ylw_pkt = true; + } + else if (SAI_PORT_STAT_RED_WRED_DROPPED_PACKETS == port_stats_capability.list[it].stat_enum) + { + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_RED_DROP_COUNTER",fieldValuesTrue); + pt_red_pkt = true; + } + else if (SAI_PORT_STAT_WRED_DROPPED_PACKETS == port_stats_capability.list[it].stat_enum) + { + m_portCounterCapabilitiesTable->set("WRED_ECN_PORT_WRED_TOTAL_DROP_COUNTER",fieldValuesTrue); + pt_tot_pkt = true; + } + } + SWSS_LOG_INFO("WRED port drop stats is_capable: [wred-grn-pkts:%d,wred-ylw-pkts:%d,wred-red-pkts:%d,wred-total-pkts:%d]", + pt_grn_pkt, pt_ylw_pkt, pt_red_pkt, pt_tot_pkt); + } +} + bool PortsOrch::getPortByBridgePortId(sai_object_id_t bridge_port_id, Port &port) { SWSS_LOG_ENTER(); @@ -2809,6 +2974,16 @@ string PortsOrch::getPriorityGroupDropPacketsFlexCounterTableKey(string key) { return string(PG_DROP_STAT_COUNTER_FLEX_COUNTER_GROUP) + ":" + key; } +/**** +* Func Name : getWredQueueFlexCounterTableKey +* Parameters : Key as string +* Returns : Returns the Wred queue stat flexcounter table Key +* Description: Form the key and return +**/ +string PortsOrch::getWredQueueFlexCounterTableKey(string key) +{ + return string(WRED_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP) + ":" + key; +} bool PortsOrch::initPort(const string &alias, const string &role, const int index, const set &lane_set) { @@ -2872,6 +3047,12 @@ bool PortsOrch::initPort(const string &alias, const string &role, const int inde port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats); } + if (flex_counters_orch->getWredPortCountersState()) + { + auto wred_port_stats = generateCounterStats(WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP); + wred_port_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, wred_port_stats); + } + PortUpdate update = { p, true }; notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); @@ -2923,6 +3104,10 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id) { port_buffer_drop_stat_manager.clearCounterIdList(p.m_port_id); } + if (flex_counters_orch->getWredPortCountersState()) + { + wred_port_stat_manager.clearCounterIdList(p.m_port_id); + } /* remove port name map from counter table */ m_counterTable->hdel("", alias); @@ -6441,6 +6626,12 @@ void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues) /* add watermark queue counters */ addQueueWatermarkFlexCountersPerPortPerQueueIndex(port, queueIndex); } + + if (flexCounterOrch->getWredQueueCountersState()) + { + /* add wred queue counters */ + addWredQueueFlexCountersPerPortPerQueueIndex(port, queueIndex, false); + } } m_queueTable->set("", queueVector); @@ -6496,6 +6687,11 @@ void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues) string key = getQueueWatermarkFlexCounterTableKey(id); m_flexCounterTable->del(key); } + if (flexCounterOrch->getWredQueueCountersState()) + { + /* Remove wred queue counters */ + wred_queue_stat_manager.clearCounterIdList(port.m_queue_ids[queueIndex]); + } } CounterCheckOrch::getInstance().removePort(port); @@ -6814,6 +7010,115 @@ void PortsOrch::generatePortBufferDropCounterMap() m_isPortBufferDropCounterMapGenerated = true; } +/**** +* Func Name : generateWredPortCounterMap +* Parameters : None +* Returns : void +* Description: Set the list of counters to be used for syncd counter polling +**/ +void PortsOrch::generateWredPortCounterMap() +{ + if (m_isWredPortCounterMapGenerated) + { + return; + } + + auto wred_port_stats = generateCounterStats(WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP); + for (const auto& it: m_portList) + { + // Set counter stats only for PHY ports to ensure syncd will not try to query the counter statistics from the HW for non-PHY ports. + if (it.second.m_type != Port::Type::PHY) + { + continue; + } + wred_port_stat_manager.setCounterIdList(it.second.m_port_id, CounterType::PORT, wred_port_stats); + } + + m_isWredPortCounterMapGenerated = true; +} + +/**** +* Func Name : addWredQueueFlexCounters +* Parameters : queueStateVector +* Returns : void +* Description: Top level API to Set WRED flex counters for Queues +**/ +void PortsOrch::addWredQueueFlexCounters(map queuesStateVector) +{ + if (m_isWredQueueCounterMapGenerated) + { + return; + } + + for (const auto& it: m_portList) + { + if (it.second.m_type == Port::PHY) + { + if (!queuesStateVector.count(it.second.m_alias)) + { + auto maxQueueNumber = getNumberOfPortSupportedQueueCounters(it.second.m_alias); + FlexCounterQueueStates flexCounterQueueState(maxQueueNumber); + queuesStateVector.insert(make_pair(it.second.m_alias, flexCounterQueueState)); + } + addWredQueueFlexCountersPerPort(it.second, queuesStateVector.at(it.second.m_alias)); + } + } + + m_isWredQueueCounterMapGenerated = true; +} + +/**** +* Func Name : addWredQueueFlexCountersPerPort +* Parameters : port and Queuestate +* Returns : void +* Description: Port level API to program flexcounter for queues +**/ +void PortsOrch::addWredQueueFlexCountersPerPort(const Port& port, FlexCounterQueueStates& queuesState) +{ + /* Add stat counters to flex_counter */ + + for (size_t queueIndex = 0; queueIndex < port.m_queue_ids.size(); ++queueIndex) + { + string queueType; + uint8_t queueRealIndex = 0; + if (getQueueTypeAndIndex(port.m_queue_ids[queueIndex], queueType, queueRealIndex)) + { + if (!queuesState.isQueueCounterEnabled(queueRealIndex)) + { + continue; + } + addWredQueueFlexCountersPerPortPerQueueIndex(port, queueIndex, false); + } + } +} +/**** +* Func Name : addWredQueueFlexCountersPerPortPerQueueIndex +* Parameters : port, queueIndex, is_voq +* Returns : void +* Description: Sets the Stats list to be polled by the flexcounter +**/ + +void PortsOrch::addWredQueueFlexCountersPerPortPerQueueIndex(const Port& port, size_t queueIndex, bool voq) +{ + std::unordered_set counter_stats; + std::vector queue_ids; + + for (const auto& it: wred_queue_stat_ids) + { + counter_stats.emplace(sai_serialize_queue_stat(it)); + } + if (voq) + { + queue_ids = m_port_voq_ids[port.m_alias]; + } + else + { + queue_ids = port.m_queue_ids; + } + + wred_queue_stat_manager.setCounterIdList(queue_ids[queueIndex], CounterType::QUEUE, counter_stats); +} + uint32_t PortsOrch::getNumberOfPortSupportedPgCounters(string port) { return static_cast(m_portList[port].m_priority_group_ids.size()); @@ -8152,6 +8457,13 @@ std::unordered_set PortsOrch::generateCounterStats(const string& ty counter_stats.emplace(sai_serialize_port_stat(it)); } } + else if (type == WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP) + { + for (const auto& it: wred_port_stat_ids) + { + counter_stats.emplace(sai_serialize_port_stat(it)); + } + } return counter_stats; } diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 843dcc8956d..b6967863e8d 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -27,6 +27,8 @@ #define QUEUE_WATERMARK_STAT_COUNTER_FLEX_COUNTER_GROUP "QUEUE_WATERMARK_STAT_COUNTER" #define PG_WATERMARK_STAT_COUNTER_FLEX_COUNTER_GROUP "PG_WATERMARK_STAT_COUNTER" #define PG_DROP_STAT_COUNTER_FLEX_COUNTER_GROUP "PG_DROP_STAT_COUNTER" +#define WRED_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP "WRED_ECN_QUEUE_STAT_COUNTER" +#define WRED_PORT_STAT_COUNTER_FLEX_COUNTER_GROUP "WRED_ECN_PORT_STAT_COUNTER" typedef std::vector PortSupportedSpeeds; typedef std::set PortSupportedFecModes; @@ -168,6 +170,7 @@ class PortsOrch : public Orch, public Subject void removePortBufferQueueCounters(const Port &port, string queues); void addQueueFlexCounters(map queuesStateVector); void addQueueWatermarkFlexCounters(map queuesStateVector); + void addWredQueueFlexCounters(map queuesStateVector); void generatePriorityGroupMap(map pgsStateVector); uint32_t getNumberOfPortSupportedPgCounters(string port); @@ -179,6 +182,9 @@ class PortsOrch : public Orch, public Subject void generatePortCounterMap(); void generatePortBufferDropCounterMap(); + void generateWredPortCounterMap(); + void generateWredQueueCounterMap(); + void refreshPortStatus(); bool removeAclTableGroup(const Port &p); @@ -246,6 +252,7 @@ class PortsOrch : public Orch, public Subject std::string getPriorityGroupWatermarkFlexCounterTableKey(std::string s); std::string getPriorityGroupDropPacketsFlexCounterTableKey(std::string s); std::string getPortRateFlexCounterTableKey(std::string s); + std::string getWredQueueFlexCounterTableKey(std::string s); shared_ptr m_counter_db; shared_ptr m_flex_db; @@ -254,6 +261,8 @@ class PortsOrch : public Orch, public Subject FlexCounterManager port_stat_manager; FlexCounterManager port_buffer_drop_stat_manager; FlexCounterManager queue_stat_manager; + FlexCounterManager wred_port_stat_manager; + FlexCounterManager wred_queue_stat_manager; FlexCounterManager gb_port_stat_manager; shared_ptr m_gb_counter_db; @@ -401,6 +410,10 @@ class PortsOrch : public Orch, public Subject void addQueueWatermarkFlexCountersPerPort(const Port& port, FlexCounterQueueStates& queuesState); void addQueueWatermarkFlexCountersPerPortPerQueueIndex(const Port& port, size_t queueIndex); + bool m_isWredQueueCounterMapGenerated = false; + void addWredQueueFlexCountersPerPort(const Port& port, FlexCounterQueueStates& queuesState); + void addWredQueueFlexCountersPerPortPerQueueIndex(const Port& port, size_t queueIndex, bool voq); + bool m_isPriorityGroupMapGenerated = false; void generatePriorityGroupMapPerPort(const Port& port, FlexCounterPgStates& pgsState); bool m_isPriorityGroupFlexCountersAdded = false; @@ -474,5 +487,10 @@ class PortsOrch : public Orch, public Subject std::unordered_set generateCounterStats(const string& type, bool gearbox = false); map m_queueInfo; + + void initCounterCapabilities(sai_object_id_t switchId); + bool m_isWredPortCounterMapGenerated = false; + std::unique_ptr m_queueCounterCapabilitiesTable = nullptr; + std::unique_ptr m_portCounterCapabilitiesTable = nullptr; }; #endif /* SWSS_PORTSORCH_H */ diff --git a/tests/test_flex_counters.py b/tests/test_flex_counters.py index eefef8bab4c..72f0068db18 100644 --- a/tests/test_flex_counters.py +++ b/tests/test_flex_counters.py @@ -78,6 +78,16 @@ 'name_map': 'COUNTERS_ROUTE_NAME_MAP', 'pre_test': 'pre_route_flow_counter_test', 'post_test': 'post_route_flow_counter_test', + }, + 'wred_queue_counter': { + 'key': 'WRED_ECN_QUEUE', + 'group_name': 'WRED_ECN_QUEUE_STAT_COUNTER', + 'name_map': 'COUNTERS_QUEUE_NAME_MAP', + }, + 'wred_port_counter': { + 'key': 'WRED_ECN_PORT', + 'group_name': 'WRED_ECN_PORT_STAT_COUNTER', + 'name_map': 'COUNTERS_PORT_NAME_MAP', } } @@ -795,3 +805,29 @@ def test_create_remove_buffer_watermark_queue_pg_counter(self, dvs): if 'queue' in counterpoll_type or 'pg' in counterpoll_type: self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', False) self.wait_for_id_list_remove(meta_data['group_name'], "Ethernet0", counter_oid) + + def test_create_remove_buffer_wred_queue_counter(self, dvs): + """ + Test steps: + 1. Enable WRED Queue flex counters. + 2. Configure new buffer queue for a port + 3. Verify counter is automatically created + 4. Remove the new buffer queue for the port + 5. Verify counter is automatically removed + + Args: + dvs (object): virtual switch object + """ + self.setup_dbs(dvs) + meta_data = counter_group_meta['wred_queue_counter'] + + self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) + + self.config_db.update_entry('BUFFER_QUEUE', 'Ethernet0|7', {'profile': 'egress_lossless_profile'}) + counter_oid = self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', True) + self.wait_for_id_list(meta_data['group_name'], "Ethernet0", counter_oid) + + self.config_db.delete_entry('BUFFER_QUEUE', 'Ethernet0|7') + self.wait_for_buffer_pg_queue_counter(meta_data['name_map'], 'Ethernet0', '7', False) + self.wait_for_id_list_remove(meta_data['group_name'], "Ethernet0", counter_oid) +