diff --git a/orchagent/dash/dashorch.cpp b/orchagent/dash/dashorch.cpp index d7c7818e5a..c02871fefa 100644 --- a/orchagent/dash/dashorch.cpp +++ b/orchagent/dash/dashorch.cpp @@ -17,6 +17,7 @@ #include "tokenize.h" #include "crmorch.h" #include "saihelper.h" +#include "flex_counter_manager.h" #include "taskworker.h" #include "pbutils.h" @@ -31,10 +32,38 @@ extern sai_dash_eni_api_t* sai_dash_eni_api; extern sai_object_id_t gSwitchId; extern size_t gMaxBulkSize; extern CrmOrch *gCrmOrch; +extern bool gTraditionalFlexCounter; -DashOrch::DashOrch(DBConnector *db, vector &tableName, ZmqServer *zmqServer) : ZmqOrch(db, tableName, zmqServer) +#define FLEX_COUNTER_UPD_INTERVAL 1 + +DashOrch::DashOrch(DBConnector *db, vector &tableName, ZmqServer *zmqServer) : + ZmqOrch(db, tableName, zmqServer), + m_eni_stat_manager(ENI_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, ENI_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false) { SWSS_LOG_ENTER(); + + m_asic_db = std::shared_ptr(new DBConnector("ASIC_DB", 0)); + m_counter_db = std::shared_ptr(new DBConnector("COUNTERS_DB", 0)); + m_eni_name_table = std::unique_ptr(new Table(m_counter_db.get(), COUNTERS_ENI_NAME_MAP)); + + if (gTraditionalFlexCounter) + { + m_vid_to_rid_table = std::make_unique
(m_asic_db.get(), "VIDTORID"); + } + + auto intervT = timespec { .tv_sec = FLEX_COUNTER_UPD_INTERVAL , .tv_nsec = 0 }; + m_fc_update_timer = new SelectableTimer(intervT); + auto executorT = new ExecutableTimer(m_fc_update_timer, this, "FLEX_COUNTER_UPD_TIMER"); + Orch::addExecutor(executorT); + + /* Fetch the available counter Ids */ + m_counter_stats.clear(); + auto stat_enum_list = queryAvailableCounterStats((sai_object_type_t)SAI_OBJECT_TYPE_ENI); + for (auto &stat_enum: stat_enum_list) + { + auto counter_id = static_cast(stat_enum); + m_counter_stats.insert(sai_serialize_eni_stat(counter_id)); + } } bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::appliance::Appliance &entry) @@ -370,6 +399,8 @@ bool DashOrch::addEniObject(const string& eni, EniEntry& entry) } } + addEniToFC(eni_id, eni); + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_DASH_ENI); SWSS_LOG_NOTICE("Created ENI object for %s", eni.c_str()); @@ -468,6 +499,8 @@ bool DashOrch::removeEniObject(const string& eni) } } + removeEniFromFC(entry.eni_id, eni); + gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_DASH_ENI); SWSS_LOG_NOTICE("Removed ENI object for %s", eni.c_str()); @@ -682,3 +715,93 @@ void DashOrch::doTask(ConsumerBase& consumer) SWSS_LOG_ERROR("Unknown table: %s", tn.c_str()); } } + +void DashOrch::removeEniFromFC(sai_object_id_t oid, const string &name) +{ + SWSS_LOG_ENTER(); + + if (oid == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_WARN("Cannot remove counter on NULL OID for eni %s", name.c_str()); + return; + } + + if (m_eni_stat_work_queue.find(oid) != m_eni_stat_work_queue.end()) + { + m_eni_stat_work_queue.erase(oid); + return; + } + + m_eni_name_table->hdel("", name); + m_eni_stat_manager.clearCounterIdList(oid); + SWSS_LOG_DEBUG("Unregistered eni %s to Flex counter", name.c_str()); +} + +void DashOrch::clearEniFCStats() +{ + for (auto it = eni_entries_.begin(); it != eni_entries_.end(); it++) + { + removeEniFromFC(it->second.eni_id, it->first); + } +} + +void DashOrch::handleFCStatusUpdate(bool enabled) +{ + if (!enabled && m_eni_fc_status) + { + m_fc_update_timer->stop(); + clearEniFCStats(); + } + else if (enabled && !m_eni_fc_status) + { + m_fc_update_timer->start(); + } + m_eni_fc_status = enabled; +} + +void DashOrch::addEniToFC(sai_object_id_t oid, const string &name) +{ + auto was_empty = m_eni_stat_work_queue.empty(); + m_eni_stat_work_queue[oid] = name; + if (was_empty) + { + m_fc_update_timer->start(); + } +} + +void DashOrch::doTask(SelectableTimer &timer) +{ + SWSS_LOG_ENTER(); + + if (!m_eni_fc_status) + { + m_fc_update_timer->stop(); + return ; + } + + for (auto it = m_eni_stat_work_queue.begin(); it != m_eni_stat_work_queue.end(); ) + { + string value; + const auto id = sai_serialize_object_id(it->first); + + if (!gTraditionalFlexCounter || m_vid_to_rid_table->hget("", id, value)) + { + SWSS_LOG_INFO("Registering %s, id %s", it->second.c_str(), id.c_str()); + std::vector eniNameFvs; + eniNameFvs.emplace_back(it->second, id); + m_eni_name_table->set("", eniNameFvs); + + m_eni_stat_manager.setCounterIdList(it->first, CounterType::ENI, m_counter_stats); + it = m_eni_stat_work_queue.erase(it); + } + else + { + ++it; + } + } + + if (m_eni_stat_work_queue.empty()) + { + m_fc_update_timer->stop(); + } +} diff --git a/orchagent/dash/dashorch.h b/orchagent/dash/dashorch.h index eca365225c..2bf359be04 100644 --- a/orchagent/dash/dashorch.h +++ b/orchagent/dash/dashorch.h @@ -17,12 +17,16 @@ #include "timer.h" #include "zmqorch.h" #include "zmqserver.h" +#include "flex_counter_manager.h" #include "dash_api/appliance.pb.h" #include "dash_api/route_type.pb.h" #include "dash_api/eni.pb.h" #include "dash_api/qos.pb.h" +#define ENI_STAT_COUNTER_FLEX_COUNTER_GROUP "ENI_STAT_COUNTER" +#define ENI_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 10000 + struct EniEntry { sai_object_id_t eni_id; @@ -39,12 +43,14 @@ class DashOrch : public ZmqOrch public: DashOrch(swss::DBConnector *db, std::vector &tables, swss::ZmqServer *zmqServer); const EniEntry *getEni(const std::string &eni) const; + void handleFCStatusUpdate(bool is_enabled); private: ApplianceTable appliance_entries_; RoutingTypeTable routing_type_entries_; EniTable eni_entries_; QosTable qos_entries_; + void doTask(ConsumerBase &consumer); void doTaskApplianceTable(ConsumerBase &consumer); void doTaskRoutingTypeTable(ConsumerBase &consumer); @@ -63,4 +69,20 @@ class DashOrch : public ZmqOrch bool setEniAdminState(const std::string& eni, const EniEntry& entry); bool addQosEntry(const std::string& qos_name, const dash::qos::Qos &entry); bool removeQosEntry(const std::string& qos_name); + +private: + std::map m_eni_stat_work_queue; + FlexCounterManager m_eni_stat_manager; + bool m_eni_fc_status = false; + std::unordered_set m_counter_stats; + std::unique_ptr m_eni_name_table; + std::unique_ptr m_vid_to_rid_table; + std::shared_ptr m_counter_db; + std::shared_ptr m_asic_db; + swss::SelectableTimer* m_fc_update_timer = nullptr; + + void doTask(swss::SelectableTimer&); + void addEniToFC(sai_object_id_t oid, const std::string& name); + void removeEniFromFC(sai_object_id_t oid, const std::string& name); + void clearEniFCStats(); }; diff --git a/orchagent/flex_counter/flex_counter_manager.cpp b/orchagent/flex_counter/flex_counter_manager.cpp index c29c4b9d6e..635c757601 100644 --- a/orchagent/flex_counter/flex_counter_manager.cpp +++ b/orchagent/flex_counter/flex_counter_manager.cpp @@ -49,6 +49,7 @@ const unordered_map FlexCounterManager::counter_id_field_lo { CounterType::TUNNEL, TUNNEL_COUNTER_ID_LIST }, { CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST }, { CounterType::ROUTE, FLOW_COUNTER_ID_LIST }, + { CounterType::ENI, ENI_COUNTER_ID_LIST }, }; FlexManagerDirectory g_FlexManagerDirectory; diff --git a/orchagent/flex_counter/flex_counter_manager.h b/orchagent/flex_counter/flex_counter_manager.h index 80a9e606e6..b9e6e4c487 100644 --- a/orchagent/flex_counter/flex_counter_manager.h +++ b/orchagent/flex_counter/flex_counter_manager.h @@ -32,6 +32,7 @@ enum class CounterType TUNNEL, HOSTIF_TRAP, ROUTE, + ENI }; // FlexCounterManager allows users to manage a group of flex counters. diff --git a/orchagent/flexcounterorch.cpp b/orchagent/flexcounterorch.cpp index 19302face9..705622bfa0 100644 --- a/orchagent/flexcounterorch.cpp +++ b/orchagent/flexcounterorch.cpp @@ -13,6 +13,7 @@ #include #include "routeorch.h" #include "macsecorch.h" +#include "dash/dashorch.h" #include "flowcounterrouteorch.h" extern sai_port_api_t *sai_port_api; @@ -39,6 +40,7 @@ extern sai_object_id_t gSwitchId; #define TUNNEL_KEY "TUNNEL" #define FLOW_CNT_TRAP_KEY "FLOW_CNT_TRAP" #define FLOW_CNT_ROUTE_KEY "FLOW_CNT_ROUTE" +#define ENI_KEY "ENI" unordered_map flexCounterGroupMap = { @@ -61,6 +63,7 @@ unordered_map flexCounterGroupMap = {"MACSEC_SA", COUNTERS_MACSEC_SA_GROUP}, {"MACSEC_SA_ATTR", COUNTERS_MACSEC_SA_ATTR_GROUP}, {"MACSEC_FLOW", COUNTERS_MACSEC_FLOW_GROUP}, + {"ENI", ENI_STAT_COUNTER_FLEX_COUNTER_GROUP} }; @@ -84,6 +87,7 @@ void FlexCounterOrch::doTask(Consumer &consumer) SWSS_LOG_ENTER(); VxlanTunnelOrch* vxlan_tunnel_orch = gDirectory.get(); + DashOrch* dash_orch = gDirectory.get(); if (gPortsOrch && !gPortsOrch->allPortsReady()) { return; @@ -200,6 +204,10 @@ void FlexCounterOrch::doTask(Consumer &consumer) { vxlan_tunnel_orch->generateTunnelCounterMap(); } + if (dash_orch && (key == ENI_KEY)) + { + dash_orch->handleFCStatusUpdate((value == "enable")); + } if (gCoppOrch && (key == FLOW_CNT_TRAP_KEY)) { if (value == "enable") diff --git a/orchagent/saihelper.cpp b/orchagent/saihelper.cpp index 1265364d97..02c7901455 100644 --- a/orchagent/saihelper.cpp +++ b/orchagent/saihelper.cpp @@ -1100,3 +1100,26 @@ void stopFlexCounterPolling(sai_object_id_t switch_oid, sai_switch_api->set_switch_attribute(switch_oid, &attr); } + +/* + Use metadata info of the SAI object to infer all the available stats + Syncd already has logic to filter out the supported stats +*/ +std::vector queryAvailableCounterStats(const sai_object_type_t object_type) +{ + std::vector stat_list; + auto info = sai_metadata_get_object_type_info(object_type); + + SWSS_LOG_NOTICE("SAI object %s supports stat type %s", + sai_serialize_object_type(object_type).c_str(), + info->statenum->name); + + auto statenumlist = info->statenum->values; + auto statnumcount = (uint32_t)info->statenum->valuescount; + + for (uint32_t i = 0; i < statnumcount; i++) + { + stat_list.push_back(static_cast(statenumlist[i])); + } + return stat_list; +} diff --git a/orchagent/saihelper.h b/orchagent/saihelper.h index 693fffd742..7334adff35 100644 --- a/orchagent/saihelper.h +++ b/orchagent/saihelper.h @@ -49,3 +49,5 @@ void startFlexCounterPolling(sai_object_id_t switch_oid, const std::string &stats_mode=""); void stopFlexCounterPolling(sai_object_id_t switch_oid, const std::string &key); + +std::vector queryAvailableCounterStats(const sai_object_type_t); diff --git a/tests/dvslib/dvs_flex_counter.py b/tests/dvslib/dvs_flex_counter.py new file mode 100644 index 0000000000..a2f4e52280 --- /dev/null +++ b/tests/dvslib/dvs_flex_counter.py @@ -0,0 +1,120 @@ +import time + +NUMBER_OF_RETRIES = 10 + +class TestFlexCountersBase(object): + + def setup_dbs(self, dvs): + self.config_db = dvs.get_config_db() + self.flex_db = dvs.get_flex_db() + self.counters_db = dvs.get_counters_db() + self.app_db = dvs.get_app_db() + + def wait_for_table(self, table): + for retry in range(NUMBER_OF_RETRIES): + counters_keys = self.counters_db.db_connection.hgetall(table) + if len(counters_keys) > 0: + return + else: + time.sleep(1) + + assert False, str(table) + " not created in Counters DB" + + def wait_for_table_empty(self, table): + for retry in range(NUMBER_OF_RETRIES): + counters_keys = self.counters_db.db_connection.hgetall(table) + if len(counters_keys) == 0: + return + else: + time.sleep(1) + + assert False, str(table) + " is still in Counters DB" + + def wait_for_id_list(self, stat, name, oid): + for retry in range(NUMBER_OF_RETRIES): + id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() + if len(id_list) > 0: + return + else: + time.sleep(1) + + assert False, "No ID list for counter " + str(name) + + def wait_for_id_list_remove(self, stat, name, oid): + for retry in range(NUMBER_OF_RETRIES): + id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() + if len(id_list) == 0: + return + else: + time.sleep(1) + + assert False, "ID list for counter " + str(name) + " is still there" + + def wait_for_interval_set(self, group, interval): + interval_value = None + for retry in range(NUMBER_OF_RETRIES): + interval_value = self.flex_db.db_connection.hget("FLEX_COUNTER_GROUP_TABLE:" + group, 'POLL_INTERVAL') + if interval_value == interval: + return + else: + time.sleep(1) + + assert False, "Polling interval is not applied to FLEX_COUNTER_GROUP_TABLE for group {}, expect={}, actual={}".format(group, interval, interval_value) + + def set_flex_counter_group_status(self, group, map, status='enable', check_name_map=True): + group_stats_entry = {"FLEX_COUNTER_STATUS": status} + self.config_db.create_entry("FLEX_COUNTER_TABLE", group, group_stats_entry) + if check_name_map: + if status == 'enable': + self.wait_for_table(map) + else: + self.wait_for_table_empty(map) + + def verify_flex_counters_populated(self, map, stat): + counters_keys = self.counters_db.db_connection.hgetall(map) + for counter_entry in counters_keys.items(): + name = counter_entry[0] + oid = counter_entry[1] + self.wait_for_id_list(stat, name, oid) + + def set_flex_counter_group_interval(self, key, group, interval): + group_stats_entry = {"POLL_INTERVAL": interval} + self.config_db.create_entry("FLEX_COUNTER_TABLE", key, group_stats_entry) + self.wait_for_interval_set(group, interval) + + def verify_no_flex_counters_tables(self, counter_stat): + counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + counter_stat) + assert len(counters_stat_keys) == 0, "FLEX_COUNTER_TABLE:" + str(counter_stat) + " tables exist before enabling the flex counter group" + + def verify_flex_counter_flow(self, dvs, meta_data): + """ + The test will check there are no flex counters tables on FlexCounter DB when the counters are disabled. + After enabling each counter group, the test will check the flow of creating flex counters tables on FlexCounter DB. + For some counter types the MAPS on COUNTERS DB will be created as well after enabling the counter group, this will be also verified on this test. + """ + self.setup_dbs(dvs) + counter_key = meta_data['key'] + counter_stat = meta_data['group_name'] + counter_map = meta_data['name_map'] + pre_test = meta_data.get('pre_test') + post_test = meta_data.get('post_test') + meta_data['dvs'] = dvs + + self.verify_no_flex_counters_tables(counter_stat) + + if pre_test: + if not hasattr(self, pre_test): + assert False, "Test object does not have the method {}".format(pre_test) + cb = getattr(self, pre_test) + cb(meta_data) + + self.set_flex_counter_group_status(counter_key, counter_map) + self.verify_flex_counters_populated(counter_map, counter_stat) + self.set_flex_counter_group_interval(counter_key, counter_stat, '2500') + + if post_test: + if not hasattr(self, post_test): + assert False, "Test object does not have the method {}".format(post_test) + cb = getattr(self, post_test) + cb(meta_data) + diff --git a/tests/test_dash_vnet.py b/tests/test_dash_vnet.py index ec9c56b2a0..1d24dcd5db 100644 --- a/tests/test_dash_vnet.py +++ b/tests/test_dash_vnet.py @@ -8,7 +8,9 @@ from dash_api.vnet_mapping_pb2 import * from dash_api.route_type_pb2 import * from dash_api.types_pb2 import * +from dvslib.dvs_flex_counter import TestFlexCountersBase +from typing import Union import typing import time import binascii @@ -17,6 +19,12 @@ import sys import socket +eni_counter_group_meta = { + 'key': 'ENI', + 'group_name': 'ENI_STAT_COUNTER', + 'name_map': 'COUNTERS_ENI_NAME_MAP', + 'post_test': 'post_eni_counter_test' +} DVS_ENV = ["HWSKU=DPU-2P"] NUM_PORTS = 2 @@ -35,7 +43,7 @@ def __init__(self, database, table_name: str): database.db_connection, table_name) - def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]): + def __setitem__(self, key: str, pairs: Union[dict, list, tuple]): pairs_str = [] if isinstance(pairs, dict): pairs = pairs.items() @@ -138,7 +146,7 @@ def create_inbound_routing(self, mac_string, vni, ip, attr_maps: dict): def remove_inbound_routing(self, mac_string, vni, ip): del self.app_dash_route_rule_table[str(mac_string) + ":" + str(vni) + ":" + str(ip)] -class TestDash(object): +class TestDash(TestFlexCountersBase): def test_appliance(self, dvs): dashobj = Dash(dvs) self.appliance_id = "100" @@ -181,6 +189,14 @@ def test_vnet(self, dvs): assert vnet_attr["SAI_VNET_ATTR_VNI"] == "45654" return dashobj + def post_eni_counter_test(self, meta_data): + counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) + self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable') + + for counter_entry in counters_keys.items(): + self.wait_for_id_list_remove(meta_data['group_name'], counter_entry[0], counter_entry[1]) + self.wait_for_table_empty(meta_data['name_map']) + def test_eni(self, dvs): dashobj = Dash(dvs) self.vnet = "Vnet1" @@ -202,7 +218,7 @@ def test_eni(self, dvs): self.vnet_oid = vnets[0] enis = dashobj.asic_eni_table.get_keys() assert enis - self.eni_oid = enis[0]; + self.eni_oid = enis[0] fvs = dashobj.asic_eni_table[enis[0]] for fv in fvs.items(): if fv[0] == "SAI_ENI_ATTR_VNET_ID": @@ -216,7 +232,10 @@ def test_eni(self, dvs): if fv[0] == "SAI_ENI_ATTR_ADMIN_STATE": assert fv[1] == "true" - time.sleep(3) + time.sleep(1) + self.verify_flex_counter_flow(dvs, eni_counter_group_meta) + + time.sleep(2) eni_addr_maps = dashobj.asic_eni_ether_addr_map_table.get_keys() assert eni_addr_maps fvs = dashobj.asic_eni_ether_addr_map_table[eni_addr_maps[0]] diff --git a/tests/test_flex_counters.py b/tests/test_flex_counters.py index f590b7748c..c664f0390e 100644 --- a/tests/test_flex_counters.py +++ b/tests/test_flex_counters.py @@ -1,11 +1,11 @@ import time import pytest +from dvslib.dvs_flex_counter import TestFlexCountersBase, NUMBER_OF_RETRIES from swsscommon import swsscommon TUNNEL_TYPE_MAP = "COUNTERS_TUNNEL_TYPE_MAP" ROUTE_TO_PATTERN_MAP = "COUNTERS_ROUTE_TO_PATTERN_MAP" -NUMBER_OF_RETRIES = 10 CPU_PORT_OID = "0x0" counter_group_meta = { @@ -81,64 +81,8 @@ } } -class TestFlexCounters(object): - def setup_dbs(self, dvs): - self.config_db = dvs.get_config_db() - self.flex_db = dvs.get_flex_db() - self.counters_db = dvs.get_counters_db() - self.app_db = dvs.get_app_db() - - def wait_for_table(self, table): - for retry in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(table) - if len(counters_keys) > 0: - return - else: - time.sleep(1) - - assert False, str(table) + " not created in Counters DB" - - def wait_for_table_empty(self, table): - for retry in range(NUMBER_OF_RETRIES): - counters_keys = self.counters_db.db_connection.hgetall(table) - if len(counters_keys) == 0: - return - else: - time.sleep(1) - - assert False, str(table) + " is still in Counters DB" - - def wait_for_id_list(self, stat, name, oid): - for retry in range(NUMBER_OF_RETRIES): - id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() - if len(id_list) > 0: - return - else: - time.sleep(1) - - assert False, "No ID list for counter " + str(name) - - def wait_for_id_list_remove(self, stat, name, oid): - for retry in range(NUMBER_OF_RETRIES): - id_list = self.flex_db.db_connection.hgetall("FLEX_COUNTER_TABLE:" + stat + ":" + oid).items() - if len(id_list) == 0: - return - else: - time.sleep(1) - - assert False, "ID list for counter " + str(name) + " is still there" - - def wait_for_interval_set(self, group, interval): - interval_value = None - for retry in range(NUMBER_OF_RETRIES): - interval_value = self.flex_db.db_connection.hget("FLEX_COUNTER_GROUP_TABLE:" + group, 'POLL_INTERVAL') - if interval_value == interval: - return - else: - time.sleep(1) - - assert False, "Polling interval is not applied to FLEX_COUNTER_GROUP_TABLE for group {}, expect={}, actual={}".format(group, interval, interval_value) +class TestFlexCounters(TestFlexCountersBase): def wait_for_buffer_pg_queue_counter(self, map, port, index, isSet): for retry in range(NUMBER_OF_RETRIES): @@ -152,10 +96,6 @@ def wait_for_buffer_pg_queue_counter(self, map, port, index, isSet): assert False, "Counter not {} for port: {}, type: {}, index: {}".format("created" if isSet else "removed", port, map, index) - def verify_no_flex_counters_tables(self, counter_stat): - counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + counter_stat) - assert len(counters_stat_keys) == 0, "FLEX_COUNTER_TABLE:" + str(counter_stat) + " tables exist before enabling the flex counter group" - def verify_no_flex_counters_tables_after_delete(self, counter_stat): for retry in range(NUMBER_OF_RETRIES): counters_stat_keys = self.flex_db.get_keys("FLEX_COUNTER_TABLE:" + counter_stat + ":") @@ -165,13 +105,6 @@ def verify_no_flex_counters_tables_after_delete(self, counter_stat): time.sleep(1) assert False, "FLEX_COUNTER_TABLE:" + str(counter_stat) + " tables exist after removing the entries" - def verify_flex_counters_populated(self, map, stat): - counters_keys = self.counters_db.db_connection.hgetall(map) - for counter_entry in counters_keys.items(): - name = counter_entry[0] - oid = counter_entry[1] - self.wait_for_id_list(stat, name, oid) - def verify_tunnel_type_vxlan(self, meta_data, type_map): counters_keys = self.counters_db.db_connection.hgetall(meta_data['name_map']) for counter_entry in counters_keys.items(): @@ -186,53 +119,13 @@ def verify_only_phy_ports_created(self, meta_data): for port_stat in port_counters_stat_keys: assert port_stat in dict(port_counters_keys.items()).values(), "Non PHY port created on PORT_STAT_COUNTER group: {}".format(port_stat) - def set_flex_counter_group_status(self, group, map, status='enable', check_name_map=True): - group_stats_entry = {"FLEX_COUNTER_STATUS": status} - self.config_db.create_entry("FLEX_COUNTER_TABLE", group, group_stats_entry) - if check_name_map: - if status == 'enable': - self.wait_for_table(map) - else: - self.wait_for_table_empty(map) - - def set_flex_counter_group_interval(self, key, group, interval): - group_stats_entry = {"POLL_INTERVAL": interval} - self.config_db.create_entry("FLEX_COUNTER_TABLE", key, group_stats_entry) - self.wait_for_interval_set(group, interval) - def set_only_config_db_buffers_field(self, value): fvs = {'create_only_config_db_buffers' : value} self.config_db.update_entry("DEVICE_METADATA", "localhost", fvs) @pytest.mark.parametrize("counter_type", counter_group_meta.keys()) def test_flex_counters(self, dvs, counter_type): - """ - The test will check there are no flex counters tables on FlexCounter DB when the counters are disabled. - After enabling each counter group, the test will check the flow of creating flex counters tables on FlexCounter DB. - For some counter types the MAPS on COUNTERS DB will be created as well after enabling the counter group, this will be also verified on this test. - """ - self.setup_dbs(dvs) - meta_data = counter_group_meta[counter_type] - counter_key = meta_data['key'] - counter_stat = meta_data['group_name'] - counter_map = meta_data['name_map'] - pre_test = meta_data.get('pre_test') - post_test = meta_data.get('post_test') - meta_data['dvs'] = dvs - - self.verify_no_flex_counters_tables(counter_stat) - - if pre_test: - cb = getattr(self, pre_test) - cb(meta_data) - - self.set_flex_counter_group_status(counter_key, counter_map) - self.verify_flex_counters_populated(counter_map, counter_stat) - self.set_flex_counter_group_interval(counter_key, counter_stat, '2500') - - if post_test: - cb = getattr(self, post_test) - cb(meta_data) + self.verify_flex_counter_flow(dvs, counter_group_meta[counter_type]) def pre_rif_counter_test(self, meta_data): self.config_db.db_connection.hset('INTERFACE|Ethernet0', "NULL", "NULL")