Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern "C" {
#include <unordered_set>
#include <iomanip>
#include <sstream>
#include <boost/variant.hpp>
#include <macaddress.h>
#include <sairedis.h>

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

#define VNID_NONE 0xFFFFFFFF

// SerdesValue using boost::variant to support both vector<uint32_t> and string values
using SerdesValue = boost::variant<std::vector<uint32_t>, std::string>;

// Visitor class for processing SerdesValue in SAI attribute setting
class SerdesValueVisitor : public boost::static_visitor<void> {
public:
explicit SerdesValueVisitor(sai_attribute_t& attr) : attr_(attr) {}

void operator()(const std::vector<uint32_t>& values) const {
attr_.value.u32list.count = static_cast<uint32_t>(values.size());
attr_.value.u32list.list = const_cast<uint32_t*>(values.data());
}

void operator()(const std::string& str_value) const {
attr_.value.json.json.count = static_cast<uint32_t>(str_value.size());
attr_.value.json.json.list = reinterpret_cast<int8_t*>(const_cast<char*>(str_value.data()));
}

private:
sai_attribute_t& attr_;
};

namespace swss {

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

/* pre-emphasis */
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> m_preemphasis;
/* serdes attributes */
std::map<sai_port_serdes_attr_t, SerdesValue> m_serdes_attrs;

/* Force initial parameter configuration flags */
bool m_an_cfg = false; // Auto-negotiation (AN)
Expand Down
5 changes: 5 additions & 0 deletions orchagent/port/portcnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ class PortConfig final
bool is_set = false;
} unreliable_los; // Port unreliable_los

struct {
std::string value;
bool is_set = false;
} custom_collection; // Port serdes custom_collection

} serdes; // Port serdes

struct {
Expand Down
27 changes: 27 additions & 0 deletions orchagent/port/porthlpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,25 @@ bool PortHelper::parsePortSerdes(T &serdes, const std::string &field, const std:
return false;
}

// Use SFINAE with enable_if for extensible type handling for serdes.value
return parseSerdesValueImpl(serdes, field, value);
}

// Helper function for JSON string-based serdes (custom_collection)
template<typename T>
typename std::enable_if<std::is_same<decltype(T::value), std::string>::value, bool>::type
PortHelper::parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const
{
serdes.value = value;
serdes.is_set = true;
return true;
}

// Helper function for vector<uint32_t>-based serdes (most serdes attributes)
template<typename T>
typename std::enable_if<std::is_same<decltype(T::value), std::vector<std::uint32_t>>::value, bool>::type
PortHelper::parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const
{
const auto &serdesList = tokenize(value, ',');

try
Expand Down Expand Up @@ -745,6 +764,7 @@ template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::obplev) &serdes
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::obnlev) &serdes, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::regn_bfm1p) &serdes, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::regn_bfm1n) &serdes, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortSerdes(decltype(PortSerdes_t::custom_collection) &serdes, const std::string &field, const std::string &value) const;



Expand Down Expand Up @@ -1182,6 +1202,13 @@ bool PortHelper::parsePortConfig(PortConfig &port) const
return false;
}
}
else if (field == PORT_CUSTOM_SERDES_ATTRS)
{
if (!this->parsePortSerdes(port.serdes.custom_collection, field, value))
{
return false;
}
}
else if (field == PORT_ROLE)
{
if (!this->parsePortRole(port, field, value))
Expand Down
8 changes: 8 additions & 0 deletions orchagent/port/porthlpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class PortHelper final
template<typename T>
bool parsePortSerdes(T &serdes, const std::string &field, const std::string &value) const;

template<typename T>
typename std::enable_if<std::is_same<decltype(T::value), std::string>::value, bool>::type
parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const;

template<typename T>
typename std::enable_if<std::is_same<decltype(T::value), std::vector<std::uint32_t>>::value, bool>::type
parseSerdesValueImpl(T &serdes, const std::string &field, const std::string &value) const;

bool parsePortLinkEventDampingAlgorithm(PortConfig &port, const std::string &field, const std::string &value) const;
template<typename T>
bool parsePortLinkEventDampingConfig(T &damping_config_attr, const std::string &field, const std::string &value) const;
Expand Down
1 change: 1 addition & 0 deletions orchagent/port/portschema.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#define PORT_OBNLEV "obnlev"
#define PORT_REGN_BFM1P "regn_bfm1p"
#define PORT_REGN_BFM1N "regn_bfm1n"
#define PORT_CUSTOM_SERDES_ATTRS "custom_serdes_attrs"
#define PORT_ROLE "role"
#define PORT_ADMIN_STATUS "admin_status"
#define PORT_DESCRIPTION "description"
Expand Down
74 changes: 40 additions & 34 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ struct PortAttrValue
};

typedef PortAttrValue PortAttrValue_t;
typedef std::map<sai_port_serdes_attr_t, std::vector<std::uint32_t>> PortSerdesAttrMap_t;
typedef std::map<sai_port_serdes_attr_t, SerdesValue> PortSerdesAttrMap_t;

struct PortBulker
{
Expand Down Expand Up @@ -421,90 +421,93 @@ static void getPortSerdesAttr(PortSerdesAttrMap_t &map, const PortConfig &port)
{
if (port.serdes.preemphasis.is_set)
{
map[SAI_PORT_SERDES_ATTR_PREEMPHASIS] = port.serdes.preemphasis.value;
map[SAI_PORT_SERDES_ATTR_PREEMPHASIS] = SerdesValue(port.serdes.preemphasis.value);
}

if (port.serdes.idriver.is_set)
{
map[SAI_PORT_SERDES_ATTR_IDRIVER] = port.serdes.idriver.value;
map[SAI_PORT_SERDES_ATTR_IDRIVER] = SerdesValue(port.serdes.idriver.value);
}

if (port.serdes.ipredriver.is_set)
{
map[SAI_PORT_SERDES_ATTR_IPREDRIVER] = port.serdes.ipredriver.value;
map[SAI_PORT_SERDES_ATTR_IPREDRIVER] = SerdesValue(port.serdes.ipredriver.value);
}

if (port.serdes.pre1.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE1] = port.serdes.pre1.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE1] = SerdesValue(port.serdes.pre1.value);
}

if (port.serdes.pre2.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE2] = port.serdes.pre2.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE2] = SerdesValue(port.serdes.pre2.value);
}

if (port.serdes.pre3.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE3] = port.serdes.pre3.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_PRE3] = SerdesValue(port.serdes.pre3.value);
}

if (port.serdes.main.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_MAIN] = port.serdes.main.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_MAIN] = SerdesValue(port.serdes.main.value);
}

if (port.serdes.post1.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST1] = port.serdes.post1.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST1] = SerdesValue(port.serdes.post1.value);
}

if (port.serdes.post2.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST2] = port.serdes.post2.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST2] = SerdesValue(port.serdes.post2.value);
}

if (port.serdes.post3.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST3] = port.serdes.post3.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_POST3] = SerdesValue(port.serdes.post3.value);
}

if (port.serdes.attn.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_FIR_ATTN] = port.serdes.attn.value;
map[SAI_PORT_SERDES_ATTR_TX_FIR_ATTN] = SerdesValue(port.serdes.attn.value);
}

if (port.serdes.ob_m2lp.is_set)
{

map[SAI_PORT_SERDES_ATTR_TX_PAM4_RATIO] = port.serdes.ob_m2lp.value;
map[SAI_PORT_SERDES_ATTR_TX_PAM4_RATIO] = SerdesValue(port.serdes.ob_m2lp.value);
}

if (port.serdes.ob_alev_out.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_OUT_COMMON_MODE] = port.serdes.ob_alev_out.value;
map[SAI_PORT_SERDES_ATTR_TX_OUT_COMMON_MODE] = SerdesValue(port.serdes.ob_alev_out.value);
}

if (port.serdes.obplev.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_PMOS_COMMON_MODE] = port.serdes.obplev.value;
map[SAI_PORT_SERDES_ATTR_TX_PMOS_COMMON_MODE] = SerdesValue(port.serdes.obplev.value);
}

if (port.serdes.obnlev.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_NMOS_COMMON_MODE] = port.serdes.obnlev.value;
map[SAI_PORT_SERDES_ATTR_TX_NMOS_COMMON_MODE] = SerdesValue(port.serdes.obnlev.value);
}

if (port.serdes.regn_bfm1p.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_PMOS_VLTG_REG] = port.serdes.regn_bfm1p.value;
map[SAI_PORT_SERDES_ATTR_TX_PMOS_VLTG_REG] = SerdesValue(port.serdes.regn_bfm1p.value);
}

if (port.serdes.regn_bfm1n.is_set)
{
map[SAI_PORT_SERDES_ATTR_TX_NMOS_VLTG_REG] = port.serdes.regn_bfm1n.value;
map[SAI_PORT_SERDES_ATTR_TX_NMOS_VLTG_REG] = SerdesValue(port.serdes.regn_bfm1n.value);
}

if (port.serdes.custom_collection.is_set)
{
map[SAI_PORT_SERDES_ATTR_CUSTOM_COLLECTION] = SerdesValue(port.serdes.custom_collection.value);
}

}

Expand Down Expand Up @@ -4585,10 +4588,10 @@ void PortsOrch::doPortTask(Consumer &consumer)
m_portList[p.m_alias] = p;
updatePortStatePoll(p, PORT_STATE_POLL_LT, pCfg.link_training.value);

// Restore pre-emphasis when LT is transitioned from ON to OFF
// Restore serdes attributes when LT is transitioned from ON to OFF
if (!p.m_link_training && serdes_attr.empty())
{
serdes_attr = p.m_preemphasis;
serdes_attr = p.m_serdes_attrs;
}

SWSS_LOG_NOTICE(
Expand Down Expand Up @@ -5105,8 +5108,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
{
if (p.m_link_training)
{
SWSS_LOG_NOTICE("Save port %s preemphasis for LT", p.m_alias.c_str());
p.m_preemphasis = serdes_attr;
SWSS_LOG_NOTICE("Save port %s serdes attributes for LT", p.m_alias.c_str());
p.m_serdes_attrs = serdes_attr;
m_portList[p.m_alias] = p;
}
else
Expand All @@ -5128,7 +5131,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s SI settings is successful", p.m_alias.c_str());
p.m_preemphasis = serdes_attr;
p.m_serdes_attrs = serdes_attr;
m_portList[p.m_alias] = p;
}
else
Expand Down Expand Up @@ -9387,7 +9390,7 @@ bool PortsOrch::removeAclTableGroup(const Port &p)
}

bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
map<sai_port_serdes_attr_t, vector<uint32_t>> &serdes_attr)
map<sai_port_serdes_attr_t, SerdesValue> &serdes_attr)
{
SWSS_LOG_ENTER();

Expand Down Expand Up @@ -9434,12 +9437,15 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t
for (auto it = serdes_attr.begin(); it != serdes_attr.end(); it++)
{
port_serdes_attr.id = it->first;
port_serdes_attr.value.u32list.count = (uint32_t)it->second.size();
port_serdes_attr.value.u32list.list = it->second.data();

// Use boost::variant visitor to handle both vector and string types
boost::apply_visitor(SerdesValueVisitor(port_serdes_attr), it->second);

attr_list.emplace_back(port_serdes_attr);
}
assert(serdes_attr.size() + 1 == attr_list.size());
status = sai_port_api->create_port_serdes(&port_serdes_id, switch_id,
static_cast<uint32_t>(serdes_attr.size()+1),
static_cast<uint32_t>(attr_list.size()),
attr_list.data());

if (status != SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -9839,8 +9845,8 @@ bool PortsOrch::initGearboxPort(Port &port)
m_gbcounterTable->set("", fields);

/* Set serdes tx taps on system and line side */
map<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr;
typedef pair<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr_pair;
map<sai_port_serdes_attr_t, SerdesValue> serdes_attr;
typedef pair<sai_port_serdes_attr_t, SerdesValue> serdes_attr_pair;
vector<uint32_t> attr_val;
for (auto pair: tx_fir_strings_system_side) {
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
Expand All @@ -9853,11 +9859,11 @@ bool PortsOrch::initGearboxPort(Port &port)
{
if (setPortSerdesAttribute(systemPort, phyOid, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s system side preemphasis is success", port.m_alias.c_str());
SWSS_LOG_NOTICE("Set port %s system side serdes attributes is success", port.m_alias.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s system side pre-emphasis", port.m_alias.c_str());
SWSS_LOG_ERROR("Failed to set port %s system side serdes attributes", port.m_alias.c_str());
return false;
}
}
Expand All @@ -9873,11 +9879,11 @@ bool PortsOrch::initGearboxPort(Port &port)
{
if (setPortSerdesAttribute(linePort, phyOid, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s line side preemphasis is success", port.m_alias.c_str());
SWSS_LOG_NOTICE("Set port %s line side serdes attributes is success", port.m_alias.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s line side pre-emphasis", port.m_alias.c_str());
SWSS_LOG_ERROR("Failed to set port %s line side serdes attributes", port.m_alias.c_str());
return false;
}
}
Expand Down
3 changes: 1 addition & 2 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,7 @@ class PortsOrch : public Orch, public Subject

void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values, int base = 16);
bool setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> &serdes_attr);

std::map<sai_port_serdes_attr_t, SerdesValue> &serdes_attr);

void removePortSerdesAttribute(sai_object_id_t port_id);

Expand Down
Loading
Loading