From ee5aa420b8488efe9b13d5fa11772f3d696683d4 Mon Sep 17 00:00:00 2001 From: Boyang Yu Date: Thu, 24 Feb 2022 15:05:59 -0800 Subject: [PATCH] Support setting tx taps on gearbox ports --- gearsyncd/gearboxparser.cpp | 24 +++++++++++++- lib/gearboxutils.cpp | 5 +++ lib/gearboxutils.h | 19 +++++++++++ orchagent/portsorch.cpp | 66 +++++++++++++++++++++++++++++++++++-- orchagent/portsorch.h | 25 +++++++++++++- 5 files changed, 134 insertions(+), 5 deletions(-) diff --git a/gearsyncd/gearboxparser.cpp b/gearsyncd/gearboxparser.cpp index dfd68be2ec3..879624fd252 100644 --- a/gearsyncd/gearboxparser.cpp +++ b/gearsyncd/gearboxparser.cpp @@ -15,6 +15,7 @@ */ #include "gearboxparser.h" +#include "gearboxutils.h" #include "phyparser.h" #include @@ -42,7 +43,7 @@ bool GearboxParser::parse() return false; } - json phys, phy, interfaces, interface, val, lanes; + json phys, phy, interfaces, interface, val, lanes, txFir; std::vector attrs; @@ -285,6 +286,27 @@ bool GearboxParser::parse() SWSS_LOG_ERROR("missing 'line_lanes' field in 'interfaces' item %d in gearbox configuration", iter); return false; } + + for (std::string txFirKey: swss::tx_fir_strings) + { + if (interface.find(txFirKey) != interface.end()) + { + txFir = interface[txFirKey]; // vec + std::string txFirValuesStr(""); + for (uint32_t iter2 = 0; iter2 < txFir.size(); iter2++) + { + val = txFir[iter2]; + if (txFirValuesStr.length() > 0) + { + txFirValuesStr += ","; + } + txFirValuesStr += std::to_string(val.get()); + } + attr = std::make_pair(txFirKey, txFirValuesStr); + attrs.push_back(attr); + } + } + std::string key; key = "interface:" + std::to_string(index); if (getWriteToDb() == true) diff --git a/lib/gearboxutils.cpp b/lib/gearboxutils.cpp index f9b32286213..bc35ed34568 100644 --- a/lib/gearboxutils.cpp +++ b/lib/gearboxutils.cpp @@ -266,6 +266,11 @@ std::map GearboxUtils::loadInterfaceMap(Table *gearbox } } } + else if (tx_fir_strings.find(val.first) != tx_fir_strings.end()) + { + SWSS_LOG_DEBUG("Parsed key:%s, val:%s", val.first.c_str(), val.second.c_str()); + interface.tx_firs[val.first] = val.second; + } } gearboxInterfaceMap[interface.index] = interface; } diff --git a/lib/gearboxutils.h b/lib/gearboxutils.h index 28ab48761e6..a239aa3a10f 100644 --- a/lib/gearboxutils.h +++ b/lib/gearboxutils.h @@ -30,6 +30,24 @@ namespace swss { +static const std::set tx_fir_strings = +{ + "system_tx_fir_pre1", + "system_tx_fir_pre2", + "system_tx_fir_pre3", + "system_tx_fir_post1", + "system_tx_fir_post2", + "system_tx_fir_post3", + "system_tx_fir_main", + "line_tx_fir_pre1", + "line_tx_fir_pre2", + "line_tx_fir_pre3", + "line_tx_fir_post1", + "line_tx_fir_post2", + "line_tx_fir_post3", + "line_tx_fir_main" +}; + typedef struct { int phy_id; @@ -54,6 +72,7 @@ typedef struct int phy_id; std::set line_lanes; std::set system_lanes; + std::map tx_firs; } gearbox_interface_t; typedef struct diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index dc1be1b3b67..00b1909a114 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -3322,7 +3322,7 @@ void PortsOrch::doPortTask(Consumer &consumer) if (serdes_attr.size() != 0) { - if (setPortSerdesAttribute(p.m_port_id, serdes_attr)) + if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr)) { SWSS_LOG_NOTICE("Set port %s preemphasis is success", alias.c_str()); } @@ -6203,7 +6203,7 @@ bool PortsOrch::removeAclTableGroup(const Port &p) return true; } -bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, +bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id, map> &serdes_attr) { SWSS_LOG_ENTER(); @@ -6255,7 +6255,7 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, port_serdes_attr.value.u32list.list = it->second.data(); attr_list.emplace_back(port_serdes_attr); } - status = sai_port_api->create_port_serdes(&port_serdes_id, gSwitchId, + status = sai_port_api->create_port_serdes(&port_serdes_id, switch_id, static_cast(serdes_attr.size()+1), attr_list.data()); @@ -6321,6 +6321,22 @@ void PortsOrch::getPortSerdesVal(const std::string& val_str, } } +void PortsOrch::getPortSerdesValBase10(const std::string& val_str, + std::vector &lane_values) +{ + SWSS_LOG_ENTER(); + + uint32_t lane_val; + std::string lane_str; + std::istringstream iss(val_str); + + while (std::getline(iss, lane_str, ',')) + { + lane_val = (uint32_t)std::stoul(lane_str, NULL, 10); + lane_values.push_back(lane_val); + } +} + bool PortsOrch::getPortAdvSpeedsVal(const std::string &val_str, std::vector &speed_values) { @@ -6690,6 +6706,50 @@ bool PortsOrch::initGearboxPort(Port &port) fields[0] = FieldValueTuple(port.m_alias + "_line", sai_serialize_object_id(linePort)); m_gbcounterTable->set("", fields); + + /* Set serdes tx taps on system and line side */ + map> serdes_attr; + typedef pair> serdes_attr_pair; + vector 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() ) { + attr_val.clear(); + getPortSerdesValBase10(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val); + serdes_attr.insert(serdes_attr_pair(pair.second, attr_val)); + } + } + if (serdes_attr.size() != 0) + { + if (setPortSerdesAttribute(systemPort, phyOid, serdes_attr)) + { + SWSS_LOG_NOTICE("Set port %s system side preemphasis 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()); + return false; + } + } + serdes_attr.clear(); + for (auto pair: tx_fir_strings_line_side) { + if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) { + attr_val.clear(); + getPortSerdesValBase10(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val); + serdes_attr.insert(serdes_attr_pair(pair.second, attr_val)); + } + } + if (serdes_attr.size() != 0) + { + if (setPortSerdesAttribute(linePort, phyOid, serdes_attr)) + { + SWSS_LOG_NOTICE("Set port %s line side preemphasis 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()); + return false; + } + } } } diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 6291231ae70..1077bd07e7e 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -47,6 +47,28 @@ static const unordered_map string_oper_status = { "not present", SAI_PORT_OPER_STATUS_NOT_PRESENT } }; +static const std::map tx_fir_strings_system_side = +{ + {"system_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1}, + {"system_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2}, + {"system_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3}, + {"system_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1}, + {"system_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2}, + {"system_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3}, + {"system_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN} +}; + +static const std::map tx_fir_strings_line_side = +{ + {"line_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1}, + {"line_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2}, + {"line_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3}, + {"line_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1}, + {"line_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2}, + {"line_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3}, + {"line_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN} +}; + struct PortUpdate { Port port; @@ -350,11 +372,12 @@ class PortsOrch : public Orch, public Subject void updateDbPortOperSpeed(Port &port, sai_uint32_t speed); void getPortSerdesVal(const std::string& s, std::vector &lane_values); + void getPortSerdesValBase10(const std::string& s, std::vector &lane_values); bool getPortAdvSpeedsVal(const std::string &s, std::vector &speed_values); bool getPortInterfaceTypeVal(const std::string &s, sai_port_interface_type_t &interface_type); bool getPortAdvInterfaceTypesVal(const std::string &s, std::vector &type_values); - bool setPortSerdesAttribute(sai_object_id_t port_id, + bool setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id, std::map> &serdes_attr);