Skip to content

Commit 4742096

Browse files
tomer-israeldprital
authored andcommitted
[orchagent] add & remove port counters dynamically each time port was added or removed (sonic-net#2019)
- What I did Add support for adding & removing port counters dynamically each time port was added or removed the counters that were supported are: 1. pg watermark counters 2. pg drop counters 3. queue stat counters 4. queue watermark counters 5. debug counters 6. buffer drop counters and port stat counters are already supported to be added or removed each time port is added/removed Implemented according to the - 'HLD document on add/remove ports dynamically feature' sonic-net/SONiC#900 - Why I did it In order to support dynamically add or removed ports on sonic - How I verified it tested manually that the flex counters were added or removed correctly whenever we add or remove ports added new test cases to the following vs tests: test_flex_counters.py test_drop_counters.py test_pg_drop_counter.py Co-authored-by: dprital <drorp@nvidia.com>
1 parent 32ed8a0 commit 4742096

11 files changed

+413
-18
lines changed

orchagent/debugcounterorch.cpp

+72-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "schema.h"
66
#include "drop_counter.h"
77
#include <memory>
8+
#include "observer.h"
89

910
using std::string;
1011
using std::unordered_map;
@@ -34,13 +35,61 @@ DebugCounterOrch::DebugCounterOrch(DBConnector *db, const vector<string>& table_
3435
{
3536
SWSS_LOG_ENTER();
3637
publishDropCounterCapabilities();
38+
39+
gPortsOrch->attach(this);
3740
}
3841

3942
DebugCounterOrch::~DebugCounterOrch(void)
4043
{
4144
SWSS_LOG_ENTER();
4245
}
4346

47+
void DebugCounterOrch::update(SubjectType type, void *cntx)
48+
{
49+
SWSS_LOG_ENTER();
50+
51+
if (type == SUBJECT_TYPE_PORT_CHANGE)
52+
{
53+
if (!cntx)
54+
{
55+
SWSS_LOG_ERROR("cntx is NULL");
56+
return;
57+
}
58+
59+
PortUpdate *update = static_cast<PortUpdate *>(cntx);
60+
Port &port = update->port;
61+
62+
if (update->add)
63+
{
64+
for (const auto& debug_counter: debug_counters)
65+
{
66+
DebugCounter *counter = debug_counter.second.get();
67+
auto counter_type = counter->getCounterType();
68+
auto counter_stat = counter->getDebugCounterSAIStat();
69+
auto flex_counter_type = getFlexCounterType(counter_type);
70+
if (flex_counter_type == CounterType::PORT_DEBUG)
71+
{
72+
installDebugFlexCounters(counter_type, counter_stat, port.m_port_id);
73+
}
74+
}
75+
}
76+
else
77+
{
78+
for (const auto& debug_counter: debug_counters)
79+
{
80+
DebugCounter *counter = debug_counter.second.get();
81+
auto counter_type = counter->getCounterType();
82+
auto counter_stat = counter->getDebugCounterSAIStat();
83+
auto flex_counter_type = getFlexCounterType(counter_type);
84+
if (flex_counter_type == CounterType::PORT_DEBUG)
85+
{
86+
uninstallDebugFlexCounters(counter_type, counter_stat, port.m_port_id);
87+
}
88+
}
89+
}
90+
}
91+
}
92+
4493
// doTask processes updates from the consumer and modifies the state of the
4594
// following components:
4695
// 1) The ASIC, by creating, modifying, and deleting debug counters
@@ -476,7 +525,8 @@ CounterType DebugCounterOrch::getFlexCounterType(const string& counter_type)
476525
}
477526

478527
void DebugCounterOrch::installDebugFlexCounters(const string& counter_type,
479-
const string& counter_stat)
528+
const string& counter_stat,
529+
sai_object_id_t port_id)
480530
{
481531
SWSS_LOG_ENTER();
482532
CounterType flex_counter_type = getFlexCounterType(counter_type);
@@ -489,6 +539,14 @@ void DebugCounterOrch::installDebugFlexCounters(const string& counter_type,
489539
{
490540
for (auto const &curr : gPortsOrch->getAllPorts())
491541
{
542+
if (port_id != SAI_NULL_OBJECT_ID)
543+
{
544+
if (curr.second.m_port_id != port_id)
545+
{
546+
continue;
547+
}
548+
}
549+
492550
if (curr.second.m_type != Port::Type::PHY)
493551
{
494552
continue;
@@ -503,7 +561,8 @@ void DebugCounterOrch::installDebugFlexCounters(const string& counter_type,
503561
}
504562

505563
void DebugCounterOrch::uninstallDebugFlexCounters(const string& counter_type,
506-
const string& counter_stat)
564+
const string& counter_stat,
565+
sai_object_id_t port_id)
507566
{
508567
SWSS_LOG_ENTER();
509568
CounterType flex_counter_type = getFlexCounterType(counter_type);
@@ -516,6 +575,14 @@ void DebugCounterOrch::uninstallDebugFlexCounters(const string& counter_type,
516575
{
517576
for (auto const &curr : gPortsOrch->getAllPorts())
518577
{
578+
if (port_id != SAI_NULL_OBJECT_ID)
579+
{
580+
if (curr.second.m_port_id != port_id)
581+
{
582+
continue;
583+
}
584+
}
585+
519586
if (curr.second.m_type != Port::Type::PHY)
520587
{
521588
continue;
@@ -616,3 +683,6 @@ bool DebugCounterOrch::isDropReasonValid(const string& drop_reason) const
616683

617684
return true;
618685
}
686+
687+
688+

orchagent/debugcounterorch.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,27 @@
1010
#include "flex_counter_stat_manager.h"
1111
#include "debug_counter.h"
1212
#include "drop_counter.h"
13+
#include "observer.h"
1314

1415
extern "C" {
1516
#include "sai.h"
1617
}
1718

1819
#define DEBUG_COUNTER_FLEX_COUNTER_GROUP "DEBUG_COUNTER"
1920

21+
using DebugCounterMap = std::unordered_map<std::string, std::unique_ptr<DebugCounter>>;
22+
2023
// DebugCounterOrch is an orchestrator for managing debug counters. It handles
2124
// the creation, deletion, and modification of debug counters.
22-
class DebugCounterOrch: public Orch
25+
class DebugCounterOrch: public Orch, public Observer
2326
{
2427
public:
2528
DebugCounterOrch(swss::DBConnector *db, const std::vector<std::string>& table_names, int poll_interval);
2629
virtual ~DebugCounterOrch(void);
2730

2831
void doTask(Consumer& consumer);
2932

33+
void update(SubjectType, void *cntx);
3034
private:
3135
// Debug Capability Reporting Functions
3236
void publishDropCounterCapabilities();
@@ -48,10 +52,12 @@ class DebugCounterOrch: public Orch
4852
CounterType getFlexCounterType(const std::string& counter_type) noexcept(false);
4953
void installDebugFlexCounters(
5054
const std::string& counter_type,
51-
const std::string& counter_stat);
55+
const std::string& counter_stat,
56+
sai_object_id_t port_id = SAI_NULL_OBJECT_ID);
5257
void uninstallDebugFlexCounters(
5358
const std::string& counter_type,
54-
const std::string& counter_stat);
59+
const std::string& counter_stat,
60+
sai_object_id_t port_id = SAI_NULL_OBJECT_ID);
5561

5662
// Debug Counter Initialization Helper Functions
5763
std::string getDebugCounterType(
@@ -83,7 +89,7 @@ class DebugCounterOrch: public Orch
8389

8490
FlexCounterStatManager flex_counter_manager;
8591

86-
std::unordered_map<std::string, std::unique_ptr<DebugCounter>> debug_counters;
92+
DebugCounterMap debug_counters;
8793

8894
// free_drop_counters are drop counters that have been created by a user
8995
// that do not have any drop reasons associated with them yet. Because

orchagent/orchdaemon.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ CoppOrch *gCoppOrch;
5252
P4Orch *gP4Orch;
5353
BfdOrch *gBfdOrch;
5454
Srv6Orch *gSrv6Orch;
55+
DebugCounterOrch *gDebugCounterOrch;
5556

5657
bool gIsNatSupported = false;
5758

@@ -282,7 +283,7 @@ bool OrchDaemon::init()
282283
CFG_DEBUG_COUNTER_DROP_REASON_TABLE_NAME
283284
};
284285

285-
DebugCounterOrch *debug_counter_orch = new DebugCounterOrch(m_configDb, debug_counter_tables, 1000);
286+
gDebugCounterOrch = new DebugCounterOrch(m_configDb, debug_counter_tables, 1000);
286287

287288
const int natorch_base_pri = 50;
288289

@@ -330,7 +331,7 @@ bool OrchDaemon::init()
330331
* when iterating ConsumerMap. This is ensured implicitly by the order of keys in ordered map.
331332
* For cases when Orch has to process tables in specific order, like PortsOrch during warm start, it has to override Orch::doTask()
332333
*/
333-
m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, mux_orch, mux_cb_orch, gIntfsOrch, gNeighOrch, gNhgMapOrch, gNhgOrch, gCbfNhgOrch, gRouteOrch, gCoppOrch, gQosOrch, wm_orch, policer_orch, tunnel_decap_orch, sflow_orch, debug_counter_orch, gMacsecOrch, gBfdOrch, gSrv6Orch};
334+
m_orchList = { gSwitchOrch, gCrmOrch, gPortsOrch, gBufferOrch, mux_orch, mux_cb_orch, gIntfsOrch, gNeighOrch, gNhgMapOrch, gNhgOrch, gCbfNhgOrch, gRouteOrch, gCoppOrch, gQosOrch, wm_orch, policer_orch, tunnel_decap_orch, sflow_orch, gDebugCounterOrch, gMacsecOrch, gBfdOrch, gSrv6Orch};
334335

335336
bool initialize_dtel = false;
336337
if (platform == BFN_PLATFORM_SUBSTRING || platform == VS_PLATFORM_SUBSTRING)

orchagent/portsorch.cpp

+96-5
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,18 @@ bool PortsOrch::initPort(const string &alias, const string &role, const int inde
23782378
port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats);
23792379
}
23802380

2381+
/* when a port is added and priority group map counter is enabled --> we need to add pg counter for it */
2382+
if (m_isPriorityGroupMapGenerated)
2383+
{
2384+
generatePriorityGroupMapPerPort(p);
2385+
}
2386+
2387+
/* when a port is added and queue map counter is enabled --> we need to add queue map counter for it */
2388+
if (m_isQueueMapGenerated)
2389+
{
2390+
generateQueueMapPerPort(p);
2391+
}
2392+
23812393
PortUpdate update = { p, true };
23822394
notify(SUBJECT_TYPE_PORT_CHANGE, static_cast<void *>(&update));
23832395

@@ -2410,8 +2422,13 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
24102422
{
24112423
SWSS_LOG_ENTER();
24122424

2413-
Port p(alias, Port::PHY);
2414-
p.m_port_id = port_id;
2425+
Port p;
2426+
2427+
if (!getPort(port_id, p))
2428+
{
2429+
SWSS_LOG_ERROR("Failed to get port object for port id 0x%" PRIx64, port_id);
2430+
return;
2431+
}
24152432

24162433
/* remove port from flex_counter_table for updating counters */
24172434
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
@@ -2425,9 +2442,20 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
24252442
port_buffer_drop_stat_manager.clearCounterIdList(p.m_port_id);
24262443
}
24272444

2445+
/* remove pg port counters */
2446+
if (m_isPriorityGroupMapGenerated)
2447+
{
2448+
removePriorityGroupMapPerPort(p);
2449+
}
2450+
2451+
/* remove queue port counters */
2452+
if (m_isQueueMapGenerated)
2453+
{
2454+
removeQueueMapPerPort(p);
2455+
}
24282456

24292457
/* remove port name map from counter table */
2430-
m_counter_db->hdel(COUNTERS_PORT_NAME_MAP, alias);
2458+
m_counterTable->hdel("", alias);
24312459

24322460
/* Remove the associated port serdes attribute */
24332461
removePortSerdesAttribute(p.m_port_id);
@@ -2436,7 +2464,6 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
24362464
SWSS_LOG_NOTICE("De-Initialized port %s", alias.c_str());
24372465
}
24382466

2439-
24402467
bool PortsOrch::bake()
24412468
{
24422469
SWSS_LOG_ENTER();
@@ -5409,6 +5436,44 @@ void PortsOrch::generateQueueMap()
54095436
m_isQueueMapGenerated = true;
54105437
}
54115438

5439+
void PortsOrch::removeQueueMapPerPort(const Port& port)
5440+
{
5441+
/* Remove the Queue map in the Counter DB */
5442+
5443+
for (size_t queueIndex = 0; queueIndex < port.m_queue_ids.size(); ++queueIndex)
5444+
{
5445+
std::ostringstream name;
5446+
name << port.m_alias << ":" << queueIndex;
5447+
std::unordered_set<string> counter_stats;
5448+
5449+
const auto id = sai_serialize_object_id(port.m_queue_ids[queueIndex]);
5450+
5451+
m_queueTable->hdel("",name.str());
5452+
m_queuePortTable->hdel("",id);
5453+
5454+
string queueType;
5455+
uint8_t queueRealIndex = 0;
5456+
if (getQueueTypeAndIndex(port.m_queue_ids[queueIndex], queueType, queueRealIndex))
5457+
{
5458+
m_queueTypeTable->hdel("",id);
5459+
m_queueIndexTable->hdel("",id);
5460+
}
5461+
5462+
for (const auto& it: queue_stat_ids)
5463+
{
5464+
counter_stats.emplace(sai_serialize_queue_stat(it));
5465+
}
5466+
queue_stat_manager.clearCounterIdList(port.m_queue_ids[queueIndex]);
5467+
5468+
/* remove watermark queue counters */
5469+
string key = getQueueWatermarkFlexCounterTableKey(id);
5470+
5471+
m_flexCounterTable->del(key);
5472+
}
5473+
5474+
CounterCheckOrch::getInstance().removePort(port);
5475+
}
5476+
54125477
void PortsOrch::generateQueueMapPerPort(const Port& port)
54135478
{
54145479
/* Create the Queue map in the Counter DB */
@@ -5487,6 +5552,32 @@ void PortsOrch::generatePriorityGroupMap()
54875552
m_isPriorityGroupMapGenerated = true;
54885553
}
54895554

5555+
void PortsOrch::removePriorityGroupMapPerPort(const Port& port)
5556+
{
5557+
/* Remove the PG map in the Counter DB */
5558+
5559+
for (size_t pgIndex = 0; pgIndex < port.m_priority_group_ids.size(); ++pgIndex)
5560+
{
5561+
std::ostringstream name;
5562+
name << port.m_alias << ":" << pgIndex;
5563+
5564+
const auto id = sai_serialize_object_id(port.m_priority_group_ids[pgIndex]);
5565+
string key = getPriorityGroupWatermarkFlexCounterTableKey(id);
5566+
5567+
m_pgTable->hdel("",name.str());
5568+
m_pgPortTable->hdel("",id);
5569+
m_pgIndexTable->hdel("",id);
5570+
5571+
m_flexCounterTable->del(key);
5572+
5573+
key = getPriorityGroupDropPacketsFlexCounterTableKey(id);
5574+
/* remove dropped packets counters to flex_counter */
5575+
m_flexCounterTable->del(key);
5576+
}
5577+
5578+
CounterCheckOrch::getInstance().removePort(port);
5579+
}
5580+
54905581
void PortsOrch::generatePriorityGroupMapPerPort(const Port& port)
54915582
{
54925583
/* Create the PG map in the Counter DB */
@@ -5644,7 +5735,7 @@ void PortsOrch::doTask(NotificationConsumer &consumer)
56445735
updateDbPortOperSpeed(port, 0);
56455736
}
56465737
}
5647-
5738+
56485739
/* update m_portList */
56495740
m_portList[port.m_alias] = port;
56505741
}

orchagent/portsorch.h

+2
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,11 @@ class PortsOrch : public Orch, public Subject
312312

313313
bool m_isQueueMapGenerated = false;
314314
void generateQueueMapPerPort(const Port& port);
315+
void removeQueueMapPerPort(const Port& port);
315316

316317
bool m_isPriorityGroupMapGenerated = false;
317318
void generatePriorityGroupMapPerPort(const Port& port);
319+
void removePriorityGroupMapPerPort(const Port& port);
318320

319321
bool m_isPortCounterMapGenerated = false;
320322
bool m_isPortBufferDropCounterMapGenerated = false;

tests/conftest.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from dvslib.dvs_pbh import DVSPbh
2323
from dvslib.dvs_route import DVSRoute
2424
from dvslib import dvs_vlan
25+
from dvslib import dvs_port
2526
from dvslib import dvs_lag
2627
from dvslib import dvs_mirror
2728
from dvslib import dvs_policer
@@ -1765,7 +1766,11 @@ def dvs_vlan_manager(request, dvs):
17651766
dvs.get_counters_db(),
17661767
dvs.get_app_db())
17671768

1768-
1769+
@pytest.yield_fixture(scope="class")
1770+
def dvs_port_manager(request, dvs):
1771+
request.cls.dvs_port = dvs_port.DVSPort(dvs.get_asic_db(),
1772+
dvs.get_config_db())
1773+
17691774
@pytest.yield_fixture(scope="class")
17701775
def dvs_mirror_manager(request, dvs):
17711776
request.cls.dvs_mirror = dvs_mirror.DVSMirror(dvs.get_asic_db(),

0 commit comments

Comments
 (0)