diff --git a/doc/swss-schema.md b/doc/swss-schema.md index 7b3d31f904..c0b5b2581e 100644 --- a/doc/swss-schema.md +++ b/doc/swss-schema.md @@ -24,6 +24,9 @@ Stores information for physical switch ports managed by the switch chip. Ports t mtu = 1*4DIGIT ; port MTU fec = 1*64VCHAR ; port fec mode autoneg = BIT ; auto-negotiation mode + preemphasis = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane + idriver = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane + ipredriver = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane ;QOS Mappings map_dscp_to_tc = ref_hash_key_reference diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index d423b48a7b..48c04b956d 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -1519,6 +1519,9 @@ void PortsOrch::doPortTask(Consumer &consumer) if (op == SET_COMMAND) { set lane_set; + vector pre_emphasis; + vector idriver; + vector ipredriver; string admin_status; string fec_mode; string pfc_asym; @@ -1575,6 +1578,24 @@ void PortsOrch::doPortTask(Consumer &consumer) { an = (int)stoul(fvValue(i)); } + + /* Set port serdes Pre-emphasis */ + if (fvField(i) == "preemphasis") + { + getPortSerdesVal(fvValue(i), pre_emphasis); + } + + /* Set port serdes idriver */ + if (fvField(i) == "idriver") + { + getPortSerdesVal(fvValue(i), idriver); + } + + /* Set port serdes ipredriver */ + if (fvField(i) == "ipredriver") + { + getPortSerdesVal(fvValue(i), ipredriver); + } } /* Collect information about all received ports */ @@ -1855,6 +1876,51 @@ void PortsOrch::doPortTask(Consumer &consumer) } } + if (pre_emphasis.size() != 0) + { + if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_PREEMPHASIS, pre_emphasis)) + { + SWSS_LOG_NOTICE("Set port %s preemphasis is success", alias.c_str()); + } + else + { + SWSS_LOG_ERROR("Failed to set port %s pre-emphasis", alias.c_str()); + it++; + continue; + } + + } + + if (idriver.size() != 0) + { + if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_IDRIVER, idriver)) + { + SWSS_LOG_NOTICE("Set port %s idriver is success", alias.c_str()); + } + else + { + SWSS_LOG_ERROR("Failed to set port %s idriver", alias.c_str()); + it++; + continue; + } + + } + + if (ipredriver.size() != 0) + { + if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_IPREDRIVER, ipredriver)) + { + SWSS_LOG_NOTICE("Set port %s ipredriver is success", alias.c_str()); + } + else + { + SWSS_LOG_ERROR("Failed to set port %s ipredriver", alias.c_str()); + it++; + continue; + } + + } + /* Last step set port admin status */ if (!admin_status.empty() && (p.m_admin_state_up != (admin_status == "up"))) { @@ -3297,3 +3363,41 @@ bool PortsOrch::removeAclTableGroup(const Port &p) return true; } +bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_attr_id_t attr_id, + vector &serdes_val) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + attr.id = attr_id; + + attr.value.u32list.count = (uint32_t)serdes_val.size(); + attr.value.u32list.list = serdes_val.data(); + + sai_status_t status = sai_port_api->set_port_attribute(port_id, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set serdes attribute %d to port pid:%lx", + attr_id, port_id); + return false; + } + return true; +} + +void PortsOrch::getPortSerdesVal(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, 16); + lane_values.push_back(lane_val); + } +} diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index cfd33b7614..5eb8558e28 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -189,6 +189,11 @@ class PortsOrch : public Orch, public Subject bool getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const; void updatePortOperStatus(Port &port, sai_port_oper_status_t status); + + void getPortSerdesVal(const std::string& s, std::vector &lane_values); + + bool setPortSerdesAttribute(sai_object_id_t port_id, sai_attr_id_t attr_id, + vector &serdes_val); }; #endif /* SWSS_PORTSORCH_H */ diff --git a/tests/test_port.py b/tests/test_port.py index 54de1d0b52..cf429ca985 100644 --- a/tests/test_port.py +++ b/tests/test_port.py @@ -125,3 +125,93 @@ def test_PortFec(dvs, testlog): for fv in fvs: if fv[0] == "SAI_PORT_ATTR_FEC_MODE": assert fv[1] == "SAI_PORT_FEC_MODE_RS" + +def test_PortPreemp(dvs, testlog): + + pre_name = 'preemphasis' + pre_val = [0x1234,0x2345,0x3456,0x4567] + pre_val_str = str(hex(pre_val[0])) + "," + str(hex(pre_val[1]))+ "," + \ + str(hex(pre_val[2]))+ "," + str(hex(pre_val[3])) + + pre_val_asic = '4:' + str(pre_val[0]) + "," + str(pre_val[1]) + "," + \ + str(pre_val[2]) + "," + str(pre_val[3]) + fvs = swsscommon.FieldValuePairs([(pre_name, pre_val_str)]) + db = swsscommon.DBConnector(0, dvs.redis_sock, 0) + adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + + tbl = swsscommon.Table(db, "PORT_TABLE") + ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") + atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") + + ptbl.set("Ethernet0", fvs) + + + time.sleep(1) + + # get fec + (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) + assert status == True + + for fv in fvs: + if fv[0] == "SAI_PORT_ATTR_SERDES_PREEMPHASIS": + assert fv[1] == pre_val_asic + +def test_PortIdriver(dvs, testlog): + + idrv_name = 'idriver' + idrv_val = [0x1,0x1,0x2,0x2] + idrv_val_str = str(hex(idrv_val[0])) + "," + str(hex(idrv_val[1]))+ "," + \ + str(hex(idrv_val[2]))+ "," + str(hex(idrv_val[3])) + + idrv_val_asic = '4:' + str(idrv_val[0]) + "," + str(idrv_val[1]) + "," + \ + str(idrv_val[2]) + "," + str(idrv_val[3]) + fvs = swsscommon.FieldValuePairs([(idrv_name, idrv_val_str)]) + db = swsscommon.DBConnector(0, dvs.redis_sock, 0) + adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + + tbl = swsscommon.Table(db, "PORT_TABLE") + ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") + atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") + + ptbl.set("Ethernet0", fvs) + + + time.sleep(1) + + # get fec + (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) + assert status == True + + for fv in fvs: + if fv[0] == "SAI_PORT_ATTR_SERDES_IDRIVER": + assert fv[1] == idrv_val_asic + +def test_PortIpredriver(dvs, testlog): + + ipre_name = 'ipredriver' + ipre_val = [0x2,0x3,0x4,0x5] + ipre_val_str = str(hex(ipre_val[0])) + "," + str(hex(ipre_val[1]))+ "," + \ + str(hex(ipre_val[2]))+ "," + str(hex(ipre_val[3])) + + ipre_val_asic = '4:' + str(ipre_val[0]) + "," + str(ipre_val[1]) + "," + \ + str(ipre_val[2]) + "," + str(ipre_val[3]) + fvs = swsscommon.FieldValuePairs([(ipre_name, ipre_val_str)]) + db = swsscommon.DBConnector(0, dvs.redis_sock, 0) + adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + + tbl = swsscommon.Table(db, "PORT_TABLE") + ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") + atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") + + ptbl.set("Ethernet0", fvs) + + + time.sleep(1) + + # get fec + (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) + assert status == True + + for fv in fvs: + if fv[0] == "SAI_PORT_ATTR_SERDES_IPREDRIVER": + assert fv[1] == ipre_val_asic