Skip to content

Commit c79d2ec

Browse files
Add PORT_PHY_ATTR flex counter support (#3957)
What I did Added support for polling PORT PHY attributes using the flex counter infrastructure. Following changes are added in swss to support this feature define a new counter type PORT_PHY_ATTR support added for polling following attributes, SAI_PORT_ATTR_RX_SIGNAL_DETECT, SAI_PORT_ATTR_FEC_ALIGNMENT_LOCK, SAI_PORT_ATTR_RX_SNR Add port_phy_attr_manager to set counter id list in FLEX_COUNTERS_DB Added unit tests to validate the enable/disable code flow, generatePortAttrCounterMap and QueryPortAttrCapabilitiesWithMockedSAI.
1 parent ee45787 commit c79d2ec

File tree

10 files changed

+492
-19
lines changed

10 files changed

+492
-19
lines changed

orchagent/flex_counter/flex_counter_manager.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,24 @@ const unordered_map<bool, string> FlexCounterManager::status_lookup =
3636

3737
const unordered_map<CounterType, string> FlexCounterManager::counter_id_field_lookup =
3838
{
39-
{ CounterType::PORT_DEBUG, PORT_DEBUG_COUNTER_ID_LIST },
40-
{ CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST },
41-
{ CounterType::PORT, PORT_COUNTER_ID_LIST },
42-
{ CounterType::QUEUE, QUEUE_COUNTER_ID_LIST },
43-
{ CounterType::QUEUE_ATTR, QUEUE_ATTR_ID_LIST },
44-
{ CounterType::PRIORITY_GROUP, PG_COUNTER_ID_LIST },
45-
{ CounterType::MACSEC_SA_ATTR, MACSEC_SA_ATTR_ID_LIST },
46-
{ CounterType::MACSEC_SA, MACSEC_SA_COUNTER_ID_LIST },
47-
{ CounterType::MACSEC_FLOW, MACSEC_FLOW_COUNTER_ID_LIST },
48-
{ CounterType::ACL_COUNTER, ACL_COUNTER_ATTR_ID_LIST },
49-
{ CounterType::TUNNEL, TUNNEL_COUNTER_ID_LIST },
50-
{ CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST },
51-
{ CounterType::ROUTE, FLOW_COUNTER_ID_LIST },
52-
{ CounterType::ENI, ENI_COUNTER_ID_LIST },
53-
{ CounterType::DASH_METER, DASH_METER_COUNTER_ID_LIST },
54-
{ CounterType::SRV6, SRV6_COUNTER_ID_LIST },
55-
{ CounterType::SWITCH, SWITCH_COUNTER_ID_LIST },
39+
{ CounterType::PORT_DEBUG, PORT_DEBUG_COUNTER_ID_LIST },
40+
{ CounterType::PORT_PHY_ATTR, PORT_PHY_ATTR_ID_LIST },
41+
{ CounterType::SWITCH_DEBUG, SWITCH_DEBUG_COUNTER_ID_LIST },
42+
{ CounterType::PORT, PORT_COUNTER_ID_LIST },
43+
{ CounterType::QUEUE, QUEUE_COUNTER_ID_LIST },
44+
{ CounterType::QUEUE_ATTR, QUEUE_ATTR_ID_LIST },
45+
{ CounterType::PRIORITY_GROUP, PG_COUNTER_ID_LIST },
46+
{ CounterType::MACSEC_SA_ATTR, MACSEC_SA_ATTR_ID_LIST },
47+
{ CounterType::MACSEC_SA, MACSEC_SA_COUNTER_ID_LIST },
48+
{ CounterType::MACSEC_FLOW, MACSEC_FLOW_COUNTER_ID_LIST },
49+
{ CounterType::ACL_COUNTER, ACL_COUNTER_ATTR_ID_LIST },
50+
{ CounterType::TUNNEL, TUNNEL_COUNTER_ID_LIST },
51+
{ CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST },
52+
{ CounterType::ROUTE, FLOW_COUNTER_ID_LIST },
53+
{ CounterType::ENI, ENI_COUNTER_ID_LIST },
54+
{ CounterType::DASH_METER, DASH_METER_COUNTER_ID_LIST },
55+
{ CounterType::SRV6, SRV6_COUNTER_ID_LIST },
56+
{ CounterType::SWITCH, SWITCH_COUNTER_ID_LIST },
5657
};
5758

5859
FlexManagerDirectory g_FlexManagerDirectory;

orchagent/flex_counter/flex_counter_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ enum class StatsMode
2727
enum class CounterType
2828
{
2929
PORT,
30+
PORT_PHY_ATTR,
3031
QUEUE,
3132
QUEUE_ATTR,
3233
PRIORITY_GROUP,

orchagent/flexcounterorch.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ int gFlexCounterDelaySec;
4343

4444
#define BUFFER_POOL_WATERMARK_KEY "BUFFER_POOL_WATERMARK"
4545
#define PORT_KEY "PORT"
46+
#define PORT_PHY_ATTR_KEY "PORT_PHY_ATTR"
4647
#define PORT_BUFFER_DROP_KEY "PORT_BUFFER_DROP"
4748
#define QUEUE_KEY "QUEUE"
4849
#define QUEUE_WATERMARK "QUEUE_WATERMARK"
@@ -63,6 +64,7 @@ int gFlexCounterDelaySec;
6364
unordered_map<string, string> flexCounterGroupMap =
6465
{
6566
{"PORT", PORT_STAT_COUNTER_FLEX_COUNTER_GROUP},
67+
{"PORT_PHY_ATTR", PORT_PHY_ATTR_FLEX_COUNTER_GROUP},
6668
{"PORT_RATES", PORT_RATE_COUNTER_FLEX_COUNTER_GROUP},
6769
{"DEBUG_MONITOR_COUNTER", DEBUG_DROP_MONITOR_FLEX_COUNTER_GROUP},
6870
{"PORT_BUFFER_DROP", PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP},
@@ -321,6 +323,19 @@ void FlexCounterOrch::doTask(Consumer &consumer)
321323
{
322324
gSrv6Orch->setCountersState((value == "enable"));
323325
}
326+
if (gPortsOrch && (key == PORT_PHY_ATTR_KEY))
327+
{
328+
if(value == "enable" && !m_port_phy_attr_enabled)
329+
{
330+
m_port_phy_attr_enabled = true;
331+
gPortsOrch->generatePortPhyAttrCounterMap();
332+
}
333+
if (value == "disable" && m_port_phy_attr_enabled)
334+
{
335+
gPortsOrch->clearPortPhyAttrCounterMap();
336+
m_port_phy_attr_enabled = false;
337+
}
338+
}
324339
if (gSwitchOrch && (key == SWITCH_KEY) && (value == "enable"))
325340
{
326341
gSwitchOrch->generateSwitchCounterIdList();
@@ -384,6 +399,11 @@ bool FlexCounterOrch::getPortCountersState() const
384399
return m_port_counter_enabled;
385400
}
386401

402+
bool FlexCounterOrch::getPortPhyAttrCounterState() const
403+
{
404+
return m_port_phy_attr_enabled;
405+
}
406+
387407
bool FlexCounterOrch::getPortBufferDropCountersState() const
388408
{
389409
return m_port_buffer_drop_counter_enabled;

orchagent/flexcounterorch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class FlexCounterOrch: public Orch
5757
FlexCounterOrch(swss::DBConnector *db, std::vector<std::string> &tableNames);
5858
virtual ~FlexCounterOrch(void);
5959
bool getPortCountersState() const;
60+
bool getPortPhyAttrCounterState() const;
6061
bool getPortBufferDropCountersState() const;
6162
bool getQueueCountersState() const;
6263
bool getQueueWatermarkCountersState() const;
@@ -74,6 +75,7 @@ class FlexCounterOrch: public Orch
7475
private:
7576
void handleDeviceMetadataTable(Consumer &consumer);
7677
bool m_port_counter_enabled = false;
78+
bool m_port_phy_attr_enabled = false;
7779
bool m_port_buffer_drop_counter_enabled = false;
7880
bool m_queue_enabled = false;
7981
bool m_queue_watermark_enabled = false;

orchagent/p4orch/tests/fake_portorch.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern "C"
1212
#define PORT_STATE_POLLING_SEC 5
1313
#define PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000
1414
#define PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS 60000
15+
#define PORT_PHY_ATTR_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
1516
#define QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
1617
#define QUEUE_WATERMARK_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 60000
1718
#define PG_WATERMARK_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 60000
@@ -24,6 +25,7 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
2425
m_portOpErrTable(stateDb, STATE_PORT_OPER_ERR_TABLE_NAME),
2526
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ,
2627
PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, true),
28+
port_phy_attr_manager(PORT_PHY_ATTR_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_PHY_ATTR_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
2729
port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ,
2830
PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, true),
2931
queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
@@ -693,6 +695,12 @@ std::unordered_set<std::string> PortsOrch::generateCounterStats(const vector<T>
693695
return {};
694696
}
695697

698+
const std::vector<sai_port_attr_t>& PortsOrch::getPortPhyAttrIds() const
699+
{
700+
static const std::vector<sai_port_attr_t> empty_vector = {};
701+
return empty_vector;
702+
}
703+
696704
void PortsOrch::doTask(swss::SelectableTimer &timer)
697705
{
698706
}

orchagent/portsorch.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern bool gMultiAsicVoq;
8484
#define PORT_STATE_POLLING_SEC 5
8585
#define PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000
8686
#define PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS 60000
87+
#define PORT_PHY_ATTR_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
8788
#define QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
8889
#define QUEUE_WATERMARK_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 60000
8990
#define PG_WATERMARK_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 60000
@@ -223,6 +224,13 @@ static map<sai_queue_type_t, string> sai_queue_type_string_map =
223224
{SAI_QUEUE_TYPE_UNICAST_VOQ, "SAI_QUEUE_TYPE_UNICAST_VOQ"},
224225
};
225226

227+
const vector<sai_port_attr_t> port_phy_attr_ids =
228+
{
229+
SAI_PORT_ATTR_RX_SIGNAL_DETECT, // RX signal detection per lane
230+
SAI_PORT_ATTR_FEC_ALIGNMENT_LOCK, // FEC alignment lock status per lane
231+
SAI_PORT_ATTR_RX_SNR // Receive Signal-to-Noise Ratio per lane
232+
};
233+
226234
const vector<sai_port_stat_t> port_stat_ids =
227235
{
228236
SAI_PORT_STAT_IF_IN_OCTETS,
@@ -708,6 +716,7 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
708716
m_portStateTable(stateDb, STATE_PORT_TABLE_NAME),
709717
m_portOpErrTable(stateDb, STATE_PORT_OPER_ERR_TABLE_NAME),
710718
port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
719+
port_phy_attr_manager(PORT_PHY_ATTR_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_PHY_ATTR_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
711720
gb_port_stat_manager(true,
712721
PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ,
713722
PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
@@ -720,6 +729,7 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
720729
wred_queue_stat_manager(WRED_QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false),
721730
counter_managers({
722731
ref(port_stat_manager),
732+
ref(port_phy_attr_manager),
723733
ref(port_buffer_drop_stat_manager),
724734
ref(queue_stat_manager),
725735
ref(queue_watermark_manager),
@@ -1069,6 +1079,9 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
10691079
/* Query Path Tracing capability */
10701080
checkPathTracingCapability();
10711081

1082+
/* Query PORT_PHY_ATTR capabilities */
1083+
queryPortPhyAttrCapabilities();
1084+
10721085
/* Initialize the stats capability in STATE_DB */
10731086
initCounterCapabilities(gSwitchId);
10741087

@@ -4065,6 +4078,18 @@ void PortsOrch::registerPort(Port &p)
40654078
gb_port_stat_manager.setCounterIdList(p.m_line_side_id,
40664079
CounterType::PORT, gbport_counter_stats, p.m_switch_id);
40674080
}
4081+
if (flex_counters_orch->getPortPhyAttrCounterState())
4082+
{
4083+
if (!m_supported_phy_attrs.empty())
4084+
{
4085+
if (p.m_type == Port::Type::PHY && verifyPortSupportsAllPhyAttr(p.m_port_id, p.m_alias.c_str()))
4086+
{
4087+
auto port_phy_attr_stats = generateCounterStats(m_supported_phy_attrs, sai_serialize_port_attr);
4088+
port_phy_attr_manager.setCounterIdList(p.m_port_id,
4089+
CounterType::PORT_PHY_ATTR, port_phy_attr_stats);
4090+
}
4091+
}
4092+
}
40684093
if (flex_counters_orch->getPortBufferDropCountersState())
40694094
{
40704095
auto port_buffer_drop_stats = generateCounterStats(port_buffer_drop_stat_ids, sai_serialize_port_stat);
@@ -4170,6 +4195,13 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
41704195
{
41714196
wred_port_stat_manager.clearCounterIdList(p.m_port_id);
41724197
}
4198+
if (!m_supported_phy_attrs.empty())
4199+
{
4200+
if (p.m_type == Port::Type::PHY && verifyPortSupportsAllPhyAttr(p.m_port_id, p.m_alias.c_str()))
4201+
{
4202+
port_phy_attr_manager.clearCounterIdList(p.m_port_id);
4203+
}
4204+
}
41734205

41744206
/* remove port name map from counter table */
41754207
m_counterNameMapUpdater->delCounterNameMap(alias);
@@ -8916,6 +8948,134 @@ void PortsOrch::generatePortBufferDropCounterMap()
89168948
m_isPortBufferDropCounterMapGenerated = true;
89178949
}
89188950

8951+
void PortsOrch::queryPortPhyAttrCapabilities()
8952+
{
8953+
for (const auto& attr_id : port_phy_attr_ids)
8954+
{
8955+
sai_attr_capability_t capability;
8956+
8957+
sai_status_t status = sai_query_attribute_capability(
8958+
gSwitchId,
8959+
SAI_OBJECT_TYPE_PORT,
8960+
attr_id,
8961+
&capability
8962+
);
8963+
8964+
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr_id);
8965+
std::string attr_id_str = std::to_string(attr_id);
8966+
const char* attr_name = meta ? meta->attridname : attr_id_str.c_str();
8967+
8968+
if (status == SAI_STATUS_SUCCESS && capability.get_implemented)
8969+
{
8970+
m_supported_phy_attrs.push_back(attr_id);
8971+
SWSS_LOG_NOTICE("PORT_PHY_ATTR: Attribute %s is SUPPORTED for GET",
8972+
attr_name);
8973+
}
8974+
else
8975+
{
8976+
SWSS_LOG_NOTICE("PORT_PHY_ATTR: Attribute %s is NOT supported (status=%d, get_implemented=%d)",
8977+
attr_name, status, capability.get_implemented);
8978+
}
8979+
}
8980+
}
8981+
8982+
bool PortsOrch::verifyPortSupportsAllPhyAttr(sai_object_id_t port_id, const char* port_name)
8983+
{
8984+
// Verify port supports ALL SERDES attributes
8985+
// Query with count=0 to check if attribute is supported (expect BUFFER_OVERFLOW)
8986+
8987+
// Check RX_SIGNAL_DETECT
8988+
sai_attribute_t port_attr;
8989+
port_attr.id = SAI_PORT_ATTR_RX_SIGNAL_DETECT;
8990+
port_attr.value.portlanelatchstatuslist.count = 0;
8991+
port_attr.value.portlanelatchstatuslist.list = nullptr;
8992+
8993+
sai_status_t status = sai_port_api->get_port_attribute(port_id, 1, &port_attr);
8994+
if (status != SAI_STATUS_BUFFER_OVERFLOW)
8995+
{
8996+
SWSS_LOG_ERROR("PORT_PHY_ATTR: Port %s does not support RX_SIGNAL_DETECT attribute (status=%d)",
8997+
port_name, status);
8998+
return false;
8999+
}
9000+
SWSS_LOG_DEBUG("PORT_PHY_ATTR: Port %s supports RX_SIGNAL_DETECT attribute (count=%d)",
9001+
port_name, port_attr.value.portlanelatchstatuslist.count);
9002+
9003+
// Check FEC_ALIGNMENT_LOCK
9004+
port_attr.id = SAI_PORT_ATTR_FEC_ALIGNMENT_LOCK;
9005+
port_attr.value.portlanelatchstatuslist.count = 0;
9006+
port_attr.value.portlanelatchstatuslist.list = nullptr;
9007+
9008+
status = sai_port_api->get_port_attribute(port_id, 1, &port_attr);
9009+
if (status != SAI_STATUS_BUFFER_OVERFLOW)
9010+
{
9011+
SWSS_LOG_ERROR("PORT_PHY_ATTR: Port %s does not support FEC_ALIGNMENT_LOCK attribute (status=%d)",
9012+
port_name, status);
9013+
return false;
9014+
}
9015+
SWSS_LOG_DEBUG("PORT_PHY_ATTR: Port %s supports FEC_ALIGNMENT_LOCK attribute (count=%d)",
9016+
port_name, port_attr.value.portlanelatchstatuslist.count);
9017+
9018+
// Check RX_SNR
9019+
port_attr.id = SAI_PORT_ATTR_RX_SNR;
9020+
port_attr.value.portsnrlist.count = 0;
9021+
port_attr.value.portsnrlist.list = nullptr;
9022+
9023+
status = sai_port_api->get_port_attribute(port_id, 1, &port_attr);
9024+
if (status != SAI_STATUS_BUFFER_OVERFLOW)
9025+
{
9026+
SWSS_LOG_ERROR("PORT_PHY_ATTR: Port %s does not support RX_SNR attribute (status=%d)",
9027+
port_name, status);
9028+
return false;
9029+
}
9030+
SWSS_LOG_DEBUG("PORT_PHY_ATTR: Port %s supports RX_SNR attribute (count=%d)",
9031+
port_name, port_attr.value.portsnrlist.count);
9032+
return true;
9033+
}
9034+
9035+
void PortsOrch::generatePortPhyAttrCounterMap()
9036+
{
9037+
if (m_supported_phy_attrs.empty())
9038+
{
9039+
SWSS_LOG_WARN("PORT_PHY_ATTR: No PHY attributes supported on this platform");
9040+
return;
9041+
}
9042+
9043+
auto port_phy_attr_stats = generateCounterStats(m_supported_phy_attrs, sai_serialize_port_attr);
9044+
9045+
for (const auto& it: m_portList)
9046+
{
9047+
if (it.second.m_type == Port::Type::PHY && verifyPortSupportsAllPhyAttr(it.second.m_port_id, it.second.m_alias.c_str()))
9048+
{
9049+
SWSS_LOG_DEBUG("PORT_PHY_ATTR: Setting counter ID list for port %s",
9050+
it.second.m_alias.c_str());
9051+
9052+
port_phy_attr_manager.setCounterIdList(it.second.m_port_id,
9053+
CounterType::PORT_PHY_ATTR, port_phy_attr_stats);
9054+
}
9055+
}
9056+
}
9057+
9058+
void PortsOrch::clearPortPhyAttrCounterMap()
9059+
{
9060+
for (const auto& it: m_portList)
9061+
{
9062+
// Clear counter stats only for PHY ports that were previously configured
9063+
if (it.second.m_type != Port::Type::PHY)
9064+
{
9065+
continue;
9066+
}
9067+
9068+
SWSS_LOG_DEBUG("PORT_PHY_ATTR: Clearing counter ID list for port %s", it.second.m_alias.c_str());
9069+
9070+
port_phy_attr_manager.clearCounterIdList(it.second.m_port_id);
9071+
}
9072+
}
9073+
9074+
const std::vector<sai_port_attr_t>& PortsOrch::getPortPhyAttrIds() const
9075+
{
9076+
return port_phy_attr_ids;
9077+
}
9078+
89199079
/****
89209080
* Func Name : generateWredPortCounterMap
89219081
* Parameters : None

0 commit comments

Comments
 (0)