Skip to content

Commit a2decc5

Browse files
Support SAI_PORT_SERDES_ATTR_CUSTOM_COLLECTION (#3764)
sonic-platform-daemon side change: sonic-net/sonic-platform-daemons#643 What I did Support SAI_PORT_SERDES_ATTR_CUSTOM_COLLECTION (i.e. custom serdes attributes represented in JSON based string format) Use boost::variant for the serdes_attr map value to support both std::vector<uint32_t> and std::string in a type-safe way, with easy extensibility to add more types later.
1 parent c5caf50 commit a2decc5

File tree

8 files changed

+144
-57
lines changed

8 files changed

+144
-57
lines changed

orchagent/port.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern "C" {
1414
#include <unordered_set>
1515
#include <iomanip>
1616
#include <sstream>
17+
#include <boost/variant.hpp>
1718
#include <macaddress.h>
1819
#include <sairedis.h>
1920

@@ -33,6 +34,28 @@ extern "C" {
3334

3435
#define VNID_NONE 0xFFFFFFFF
3536

37+
// SerdesValue using boost::variant to support both vector<uint32_t> and string values
38+
using SerdesValue = boost::variant<std::vector<uint32_t>, std::string>;
39+
40+
// Visitor class for processing SerdesValue in SAI attribute setting
41+
class SerdesValueVisitor : public boost::static_visitor<void> {
42+
public:
43+
explicit SerdesValueVisitor(sai_attribute_t& attr) : attr_(attr) {}
44+
45+
void operator()(const std::vector<uint32_t>& values) const {
46+
attr_.value.u32list.count = static_cast<uint32_t>(values.size());
47+
attr_.value.u32list.list = const_cast<uint32_t*>(values.data());
48+
}
49+
50+
void operator()(const std::string& str_value) const {
51+
attr_.value.json.json.count = static_cast<uint32_t>(str_value.size());
52+
attr_.value.json.json.list = reinterpret_cast<int8_t*>(const_cast<char*>(str_value.data()));
53+
}
54+
55+
private:
56+
sai_attribute_t& attr_;
57+
};
58+
3659
namespace swss {
3760

3861
struct VlanMemberEntry
@@ -240,8 +263,8 @@ class Port
240263
/* Port oper error status to event map*/
241264
std::unordered_map<sai_port_error_status_t, PortOperErrorEvent> m_portOperErrorToEvent;
242265

243-
/* pre-emphasis */
244-
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> m_preemphasis;
266+
/* serdes attributes */
267+
std::map<sai_port_serdes_attr_t, SerdesValue> m_serdes_attrs;
245268

246269
/* Force initial parameter configuration flags */
247270
bool m_an_cfg = false; // Auto-negotiation (AN)

orchagent/port/portcnt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ class PortConfig final
190190
bool is_set = false;
191191
} unreliable_los; // Port unreliable_los
192192

193+
struct {
194+
std::string value;
195+
bool is_set = false;
196+
} custom_collection; // Port serdes custom_collection
197+
193198
} serdes; // Port serdes
194199

195200
struct {

orchagent/port/porthlpr.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,25 @@ bool PortHelper::parsePortSerdes(T &serdes, const std::string &field, const std:
708708
return false;
709709
}
710710

711+
// Use SFINAE with enable_if for extensible type handling for serdes.value
712+
return parseSerdesValueImpl(serdes, field, value);
713+
}
714+
715+
// Helper function for JSON string-based serdes (custom_collection)
716+
template<typename T>
717+
typename std::enable_if<std::is_same<decltype(T::value), std::string>::value, bool>::type
718+
PortHelper::parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const
719+
{
720+
serdes.value = value;
721+
serdes.is_set = true;
722+
return true;
723+
}
724+
725+
// Helper function for vector<uint32_t>-based serdes (most serdes attributes)
726+
template<typename T>
727+
typename std::enable_if<std::is_same<decltype(T::value), std::vector<std::uint32_t>>::value, bool>::type
728+
PortHelper::parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const
729+
{
711730
const auto &serdesList = tokenize(value, ',');
712731

713732
try
@@ -745,6 +764,7 @@ template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::obplev) &serdes
745764
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::obnlev) &serdes, const std::string &field, const std::string &value) const;
746765
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::regn_bfm1p) &serdes, const std::string &field, const std::string &value) const;
747766
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::regn_bfm1n) &serdes, const std::string &field, const std::string &value) const;
767+
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::custom_collection) &serdes, const std::string &field, const std::string &value) const;
748768

749769

750770

@@ -1182,6 +1202,13 @@ bool PortHelper::parsePortConfig(PortConfig &port) const
11821202
return false;
11831203
}
11841204
}
1205+
else if (field == PORT_CUSTOM_SERDES_ATTRS)
1206+
{
1207+
if (!this->parsePortSerdes(port.serdes.custom_collection, field, value))
1208+
{
1209+
return false;
1210+
}
1211+
}
11851212
else if (field == PORT_ROLE)
11861213
{
11871214
if (!this->parsePortRole(port, field, value))

orchagent/port/porthlpr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ class PortHelper final
3939
template<typename T>
4040
bool parsePortSerdes(T &serdes, const std::string &field, const std::string &value) const;
4141

42+
template<typename T>
43+
typename std::enable_if<std::is_same<decltype(T::value), std::string>::value, bool>::type
44+
parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const;
45+
46+
template<typename T>
47+
typename std::enable_if<std::is_same<decltype(T::value), std::vector<std::uint32_t>>::value, bool>::type
48+
parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const;
49+
4250
bool parsePortLinkEventDampingAlgorithm(PortConfig &port, const std::string &field, const std::string &value) const;
4351
template<typename T>
4452
bool parsePortLinkEventDampingConfig(T &damping_config_attr, const std::string &field, const std::string &value) const;

orchagent/port/portschema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#define PORT_OBNLEV "obnlev"
9090
#define PORT_REGN_BFM1P "regn_bfm1p"
9191
#define PORT_REGN_BFM1N "regn_bfm1n"
92+
#define PORT_CUSTOM_SERDES_ATTRS "custom_serdes_attrs"
9293
#define PORT_ROLE "role"
9394
#define PORT_ADMIN_STATUS "admin_status"
9495
#define PORT_DESCRIPTION "description"

orchagent/portsorch.cpp

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ struct PortAttrValue
9797
};
9898

9999
typedef PortAttrValue PortAttrValue_t;
100-
typedef std::map<sai_port_serdes_attr_t, std::vector<std::uint32_t>> PortSerdesAttrMap_t;
100+
typedef std::map<sai_port_serdes_attr_t, SerdesValue> PortSerdesAttrMap_t;
101101

102102
struct PortBulker
103103
{
@@ -436,90 +436,93 @@ static void getPortSerdesAttr(PortSerdesAttrMap_t &map, const PortConfig &port)
436436
{
437437
if (port.serdes.preemphasis.is_set)
438438
{
439-
map[SAI_PORT_SERDES_ATTR_PREEMPHASIS] = port.serdes.preemphasis.value;
439+
map[SAI_PORT_SERDES_ATTR_PREEMPHASIS] = SerdesValue(port.serdes.preemphasis.value);
440440
}
441441

442442
if (port.serdes.idriver.is_set)
443443
{
444-
map[SAI_PORT_SERDES_ATTR_IDRIVER] = port.serdes.idriver.value;
444+
map[SAI_PORT_SERDES_ATTR_IDRIVER] = SerdesValue(port.serdes.idriver.value);
445445
}
446446

447447
if (port.serdes.ipredriver.is_set)
448448
{
449-
map[SAI_PORT_SERDES_ATTR_IPREDRIVER] = port.serdes.ipredriver.value;
449+
map[SAI_PORT_SERDES_ATTR_IPREDRIVER] = SerdesValue(port.serdes.ipredriver.value);
450450
}
451451

452452
if (port.serdes.pre1.is_set)
453453
{
454-
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE1] = port.serdes.pre1.value;
454+
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE1] = SerdesValue(port.serdes.pre1.value);
455455
}
456456

457457
if (port.serdes.pre2.is_set)
458458
{
459-
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE2] = port.serdes.pre2.value;
459+
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE2] = SerdesValue(port.serdes.pre2.value);
460460
}
461461

462462
if (port.serdes.pre3.is_set)
463463
{
464-
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE3] = port.serdes.pre3.value;
464+
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE3] = SerdesValue(port.serdes.pre3.value);
465465
}
466466

467467
if (port.serdes.main.is_set)
468468
{
469-
map[SAI_PORT_SERDES_ATTR_TX_FIR_MAIN] = port.serdes.main.value;
469+
map[SAI_PORT_SERDES_ATTR_TX_FIR_MAIN] = SerdesValue(port.serdes.main.value);
470470
}
471471

472472
if (port.serdes.post1.is_set)
473473
{
474-
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST1] = port.serdes.post1.value;
474+
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST1] = SerdesValue(port.serdes.post1.value);
475475
}
476476

477477
if (port.serdes.post2.is_set)
478478
{
479-
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST2] = port.serdes.post2.value;
479+
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST2] = SerdesValue(port.serdes.post2.value);
480480
}
481481

482482
if (port.serdes.post3.is_set)
483483
{
484-
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST3] = port.serdes.post3.value;
484+
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST3] = SerdesValue(port.serdes.post3.value);
485485
}
486486

487487
if (port.serdes.attn.is_set)
488488
{
489-
map[SAI_PORT_SERDES_ATTR_TX_FIR_ATTN] = port.serdes.attn.value;
489+
map[SAI_PORT_SERDES_ATTR_TX_FIR_ATTN] = SerdesValue(port.serdes.attn.value);
490490
}
491491

492492
if (port.serdes.ob_m2lp.is_set)
493493
{
494-
495-
map[SAI_PORT_SERDES_ATTR_TX_PAM4_RATIO] = port.serdes.ob_m2lp.value;
494+
map[SAI_PORT_SERDES_ATTR_TX_PAM4_RATIO] = SerdesValue(port.serdes.ob_m2lp.value);
496495
}
497496

498497
if (port.serdes.ob_alev_out.is_set)
499498
{
500-
map[SAI_PORT_SERDES_ATTR_TX_OUT_COMMON_MODE] = port.serdes.ob_alev_out.value;
499+
map[SAI_PORT_SERDES_ATTR_TX_OUT_COMMON_MODE] = SerdesValue(port.serdes.ob_alev_out.value);
501500
}
502501

503502
if (port.serdes.obplev.is_set)
504503
{
505-
map[SAI_PORT_SERDES_ATTR_TX_PMOS_COMMON_MODE] = port.serdes.obplev.value;
504+
map[SAI_PORT_SERDES_ATTR_TX_PMOS_COMMON_MODE] = SerdesValue(port.serdes.obplev.value);
506505
}
507506

508507
if (port.serdes.obnlev.is_set)
509508
{
510-
map[SAI_PORT_SERDES_ATTR_TX_NMOS_COMMON_MODE] = port.serdes.obnlev.value;
509+
map[SAI_PORT_SERDES_ATTR_TX_NMOS_COMMON_MODE] = SerdesValue(port.serdes.obnlev.value);
511510
}
512511

513512
if (port.serdes.regn_bfm1p.is_set)
514513
{
515-
map[SAI_PORT_SERDES_ATTR_TX_PMOS_VLTG_REG] = port.serdes.regn_bfm1p.value;
514+
map[SAI_PORT_SERDES_ATTR_TX_PMOS_VLTG_REG] = SerdesValue(port.serdes.regn_bfm1p.value);
516515
}
517516

518517
if (port.serdes.regn_bfm1n.is_set)
519518
{
520-
map[SAI_PORT_SERDES_ATTR_TX_NMOS_VLTG_REG] = port.serdes.regn_bfm1n.value;
519+
map[SAI_PORT_SERDES_ATTR_TX_NMOS_VLTG_REG] = SerdesValue(port.serdes.regn_bfm1n.value);
521520
}
522521

522+
if (port.serdes.custom_collection.is_set)
523+
{
524+
map[SAI_PORT_SERDES_ATTR_CUSTOM_COLLECTION] = SerdesValue(port.serdes.custom_collection.value);
525+
}
523526

524527
}
525528

@@ -4600,10 +4603,10 @@ void PortsOrch::doPortTask(Consumer &consumer)
46004603
m_portList[p.m_alias] = p;
46014604
updatePortStatePoll(p, PORT_STATE_POLL_LT, pCfg.link_training.value);
46024605

4603-
// Restore pre-emphasis when LT is transitioned from ON to OFF
4606+
// Restore serdes attributes when LT is transitioned from ON to OFF
46044607
if (!p.m_link_training && serdes_attr.empty())
46054608
{
4606-
serdes_attr = p.m_preemphasis;
4609+
serdes_attr = p.m_serdes_attrs;
46074610
}
46084611

46094612
SWSS_LOG_NOTICE(
@@ -5120,8 +5123,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
51205123
{
51215124
if (p.m_link_training)
51225125
{
5123-
SWSS_LOG_NOTICE("Save port %s preemphasis for LT", p.m_alias.c_str());
5124-
p.m_preemphasis = serdes_attr;
5126+
SWSS_LOG_NOTICE("Save port %s serdes attributes for LT", p.m_alias.c_str());
5127+
p.m_serdes_attrs = serdes_attr;
51255128
m_portList[p.m_alias] = p;
51265129
}
51275130
else
@@ -5143,7 +5146,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
51435146
if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr))
51445147
{
51455148
SWSS_LOG_NOTICE("Set port %s SI settings is successful", p.m_alias.c_str());
5146-
p.m_preemphasis = serdes_attr;
5149+
p.m_serdes_attrs = serdes_attr;
51475150
m_portList[p.m_alias] = p;
51485151
}
51495152
else
@@ -9424,7 +9427,7 @@ bool PortsOrch::removeAclTableGroup(const Port &p)
94249427
}
94259428

94269429
bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
9427-
map<sai_port_serdes_attr_t, vector<uint32_t>> &serdes_attr)
9430+
map<sai_port_serdes_attr_t, SerdesValue> &serdes_attr)
94289431
{
94299432
SWSS_LOG_ENTER();
94309433

@@ -9471,12 +9474,15 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t
94719474
for (auto it = serdes_attr.begin(); it != serdes_attr.end(); it++)
94729475
{
94739476
port_serdes_attr.id = it->first;
9474-
port_serdes_attr.value.u32list.count = (uint32_t)it->second.size();
9475-
port_serdes_attr.value.u32list.list = it->second.data();
9477+
9478+
// Use boost::variant visitor to handle both vector and string types
9479+
boost::apply_visitor(SerdesValueVisitor(port_serdes_attr), it->second);
9480+
94769481
attr_list.emplace_back(port_serdes_attr);
94779482
}
9483+
assert(serdes_attr.size() + 1 == attr_list.size());
94789484
status = sai_port_api->create_port_serdes(&port_serdes_id, switch_id,
9479-
static_cast<uint32_t>(serdes_attr.size()+1),
9485+
static_cast<uint32_t>(attr_list.size()),
94809486
attr_list.data());
94819487

94829488
if (status != SAI_STATUS_SUCCESS)
@@ -9876,8 +9882,8 @@ bool PortsOrch::initGearboxPort(Port &port)
98769882
m_gbcounterTable->set("", fields);
98779883

98789884
/* Set serdes tx taps on system and line side */
9879-
map<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr;
9880-
typedef pair<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr_pair;
9885+
map<sai_port_serdes_attr_t, SerdesValue> serdes_attr;
9886+
typedef pair<sai_port_serdes_attr_t, SerdesValue> serdes_attr_pair;
98819887
vector<uint32_t> attr_val;
98829888
for (auto pair: tx_fir_strings_system_side) {
98839889
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
@@ -9890,11 +9896,11 @@ bool PortsOrch::initGearboxPort(Port &port)
98909896
{
98919897
if (setPortSerdesAttribute(systemPort, phyOid, serdes_attr))
98929898
{
9893-
SWSS_LOG_NOTICE("Set port %s system side preemphasis is success", port.m_alias.c_str());
9899+
SWSS_LOG_NOTICE("Set port %s system side serdes attributes is success", port.m_alias.c_str());
98949900
}
98959901
else
98969902
{
9897-
SWSS_LOG_ERROR("Failed to set port %s system side pre-emphasis", port.m_alias.c_str());
9903+
SWSS_LOG_ERROR("Failed to set port %s system side serdes attributes", port.m_alias.c_str());
98989904
return false;
98999905
}
99009906
}
@@ -9910,11 +9916,11 @@ bool PortsOrch::initGearboxPort(Port &port)
99109916
{
99119917
if (setPortSerdesAttribute(linePort, phyOid, serdes_attr))
99129918
{
9913-
SWSS_LOG_NOTICE("Set port %s line side preemphasis is success", port.m_alias.c_str());
9919+
SWSS_LOG_NOTICE("Set port %s line side serdes attributes is success", port.m_alias.c_str());
99149920
}
99159921
else
99169922
{
9917-
SWSS_LOG_ERROR("Failed to set port %s line side pre-emphasis", port.m_alias.c_str());
9923+
SWSS_LOG_ERROR("Failed to set port %s line side serdes attributes", port.m_alias.c_str());
99189924
return false;
99199925
}
99209926
}

orchagent/portsorch.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,7 @@ class PortsOrch : public Orch, public Subject
525525

526526
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values, int base = 16);
527527
bool setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
528-
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> &serdes_attr);
529-
528+
std::map<sai_port_serdes_attr_t, SerdesValue> &serdes_attr);
530529

531530
void removePortSerdesAttribute(sai_object_id_t port_id);
532531

0 commit comments

Comments
 (0)