Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class Port

/* pre-emphasis */
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> m_preemphasis;
std::string m_custom_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
29 changes: 28 additions & 1 deletion orchagent/port/porthlpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ using namespace swss;

// types --------------------------------------------------------------------------------------------------------------

typedef decltype(PortConfig::serdes) PortSerdes_t;
typedef decltype(PortConfig::link_event_damping_config) PortDampingConfig_t;

// constants ----------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -697,6 +696,27 @@ bool PortHelper::parsePortLinkTraining(PortConfig &port, const std::string &fiel
return true;
}

// custom_collection specialization
bool PortHelper::parsePortSerdes(
decltype(PortSerdes_t::custom_collection)& serdes,
const std::string& field,
const std::string& value) const
{
SWSS_LOG_ENTER();

if (value.empty())
{
SWSS_LOG_ERROR("Failed to parse field(%s): empty string is prohibited",
field.c_str());
return false;
}

// directly assign the raw string
serdes.value = value;
serdes.is_set = true;
return true;
}

template<typename T>
bool PortHelper::parsePortSerdes(T &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
4 changes: 4 additions & 0 deletions orchagent/port/porthlpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#include "portcnt.h"

typedef decltype(PortConfig::serdes) PortSerdes_t;
typedef decltype(PortSerdes_t::custom_collection) CustomSerdes_t;

class PortHelper final
{
public:
Expand Down Expand Up @@ -36,6 +39,7 @@ class PortHelper final
private:
std::string getFieldValueStr(const PortConfig &port, const std::string &field) const;

bool parsePortSerdes(CustomSerdes_t& serdes, const std::string& field, const std::string& value) const;
template<typename T>
bool parsePortSerdes(T &serdes, 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
45 changes: 37 additions & 8 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4284,7 +4284,11 @@ void PortsOrch::doPortTask(Consumer &consumer)
else
{
PortSerdesAttrMap_t serdes_attr;
string custom_serdes_attrs_str;
getPortSerdesAttr(serdes_attr, pCfg);
if (pCfg.serdes.custom_collection.is_set) {
custom_serdes_attrs_str = pCfg.serdes.custom_collection.value;
}

// Saved configured admin status
bool admin_status = p.m_admin_state_up;
Expand Down Expand Up @@ -4395,9 +4399,14 @@ void PortsOrch::doPortTask(Consumer &consumer)
updatePortStatePoll(p, PORT_STATE_POLL_LT, pCfg.link_training.value);

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

SWSS_LOG_NOTICE(
Expand Down Expand Up @@ -4908,12 +4917,17 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
}

if (!serdes_attr.empty())
if (!serdes_attr.empty() or !custom_serdes_attrs_str.empty())
{
if (p.m_link_training)
{
SWSS_LOG_NOTICE("Save port %s preemphasis for LT", p.m_alias.c_str());
p.m_preemphasis = serdes_attr;
if (!serdes_attr.empty()) {
p.m_preemphasis = serdes_attr;
}
if (!custom_serdes_attrs_str.empty()) {
p.m_custom_serdes_attrs = custom_serdes_attrs_str;
}
m_portList[p.m_alias] = p;
}
else
Expand All @@ -4932,10 +4946,15 @@ void PortsOrch::doPortTask(Consumer &consumer)
m_portList[p.m_alias] = p;
}

if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr))
if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr, custom_serdes_attrs_str))
{
SWSS_LOG_NOTICE("Set port %s SI settings is successful", p.m_alias.c_str());
p.m_preemphasis = serdes_attr;
if (!serdes_attr.empty()) {
p.m_preemphasis = serdes_attr;
}
if (!custom_serdes_attrs_str.empty()) {
p.m_custom_serdes_attrs = custom_serdes_attrs_str;
}
m_portList[p.m_alias] = p;
}
else
Expand Down Expand Up @@ -9013,7 +9032,8 @@ 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, vector<uint32_t>> &serdes_attr,
const std::string& custom_serdes_attrs_str)
{
SWSS_LOG_ENTER();

Expand Down Expand Up @@ -9064,8 +9084,17 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t
port_serdes_attr.value.u32list.list = it->second.data();
attr_list.emplace_back(port_serdes_attr);
}

if (!custom_serdes_attrs_str.empty())
{
port_serdes_attr.id = SAI_PORT_SERDES_ATTR_CUSTOM_COLLECTION;
port_serdes_attr.value.json.json.count = static_cast<uint32_t>(custom_serdes_attrs_str.size());
port_serdes_attr.value.json.json.list = reinterpret_cast<int8_t*>(const_cast<char*>(custom_serdes_attrs_str.data()));
attr_list.emplace_back(port_serdes_attr);
}

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
3 changes: 2 additions & 1 deletion orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,8 @@ 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, std::vector<uint32_t>> &serdes_attr,
const std::string &custom_serdes_attrs_str = "");


void removePortSerdesAttribute(sai_object_id_t port_id);
Expand Down
7 changes: 6 additions & 1 deletion tests/mock_tests/portsorch_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,8 @@ namespace portsorch_test
{ "obplev", "0x69,0x6b,0x6a,0x6c" },
{ "obnlev", "0x5f,0x61,0x60,0x62" },
{ "regn_bfm1p", "0x1e,0x20,0x1f,0x21" },
{ "regn_bfm1n", "0xaa,0xac,0xab,0xad" }
{ "regn_bfm1n", "0xaa,0xac,0xab,0xad" },
{ "custom_serdes_attrs", "{'attributes':[]}" }
}
}};

Expand Down Expand Up @@ -1174,6 +1175,10 @@ namespace portsorch_test
// Verify unreliablelos
ASSERT_EQ(p.m_unreliable_los, false);

// Verify custom_serdes_attrs
std::string custom_serdes_attrs = "{'attributes':[]}";
ASSERT_EQ(p.m_custom_serdes_attrs, custom_serdes_attrs);

// Dump pending tasks
std::vector<std::string> taskList;
gPortsOrch->dumpPendingTasks(taskList);
Expand Down
Loading