From 35996350fb88833b55956521b0e708a1bc4c5099 Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Thu, 5 Oct 2023 08:58:53 -0700 Subject: [PATCH] [FEC]Auto FEC initial changes (#2893) * [FEC]Auto FEC initial changes Initial Changes to support Auto FEC feature. Added support for mode "auto" in FEC Why I did it To implement auto FEC feature HLD: sonic-net/SONiC#1416 --- orchagent/p4orch/tests/fake_portorch.cpp | 11 +- orchagent/port.h | 1 + orchagent/port/portcnt.h | 1 + orchagent/port/porthlpr.cpp | 43 ++++++- orchagent/port/porthlpr.h | 2 + orchagent/port/portschema.h | 1 + orchagent/portsorch.cpp | 145 ++++++++++++++++++----- orchagent/portsorch.h | 12 +- tests/mock_tests/portsorch_ut.cpp | 68 ++++++++++- tests/test_port.py | 1 + tests/test_port_fec_override.py | 18 ++- 11 files changed, 264 insertions(+), 39 deletions(-) diff --git a/orchagent/p4orch/tests/fake_portorch.cpp b/orchagent/p4orch/tests/fake_portorch.cpp index 14138ea8d6..b8a2f56fde 100644 --- a/orchagent/p4orch/tests/fake_portorch.cpp +++ b/orchagent/p4orch/tests/fake_portorch.cpp @@ -537,7 +537,12 @@ bool PortsOrch::getPortPvid(Port &port, sai_uint32_t &pvid) return true; } -bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t fec_mode) +bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t fec_mode, bool override_fec) +{ + return true; +} + +bool PortsOrch::isFecModeSupported(const Port &port, sai_port_fec_mode_t fec_mode) { return true; } @@ -581,12 +586,12 @@ bool PortsOrch::getPortSpeed(sai_object_id_t port_id, sai_uint32_t &speed) return true; } -bool PortsOrch::setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value) +bool PortsOrch::setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value, bool override_fec) { return true; } -bool PortsOrch::setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value) +bool PortsOrch::setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value, bool override_fec) { return true; } diff --git a/orchagent/port.h b/orchagent/port.h index cf79267243..f6b598edeb 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -199,6 +199,7 @@ class Port bool m_intf_cfg = false; // Interface type bool m_adv_intf_cfg = false; // Advertised interface type bool m_fec_cfg = false; // Forward Error Correction (FEC) + bool m_override_fec = false; // Enable Override FEC bool m_pfc_asym_cfg = false; // Asymmetric Priority Flow Control (PFC) bool m_lm_cfg = false; // Forwarding Database (FDB) Learning Mode (LM) bool m_lt_cfg = false; // Link Training (LT) diff --git a/orchagent/port/portcnt.h b/orchagent/port/portcnt.h index c0c3ea359e..2c276370a8 100644 --- a/orchagent/port/portcnt.h +++ b/orchagent/port/portcnt.h @@ -70,6 +70,7 @@ class PortConfig final struct { sai_port_fec_mode_t value; bool is_set = false; + bool override_fec = false; } fec; // Port FEC struct { diff --git a/orchagent/port/porthlpr.cpp b/orchagent/port/porthlpr.cpp index 49d3175d2b..c64e6fac4a 100644 --- a/orchagent/port/porthlpr.cpp +++ b/orchagent/port/porthlpr.cpp @@ -74,7 +74,8 @@ static const std::unordered_map portFecMap = { { PORT_FEC_NONE, SAI_PORT_FEC_MODE_NONE }, { PORT_FEC_RS, SAI_PORT_FEC_MODE_RS }, - { PORT_FEC_FC, SAI_PORT_FEC_MODE_FC } + { PORT_FEC_FC, SAI_PORT_FEC_MODE_FC }, + { PORT_FEC_AUTO, SAI_PORT_FEC_MODE_NONE } }; static const std::unordered_map portFecRevMap = @@ -84,6 +85,14 @@ static const std::unordered_map portFecRevMap { SAI_PORT_FEC_MODE_FC, PORT_FEC_FC } }; +static const std::unordered_map portFecOverrideMap = +{ + { PORT_FEC_NONE, true }, + { PORT_FEC_RS, true }, + { PORT_FEC_FC, true }, + { PORT_FEC_AUTO, false } +}; + static const std::unordered_map portPfcAsymMap = { { PORT_MODE_ON, SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE }, @@ -146,6 +155,30 @@ bool PortHelper::fecToStr(std::string &str, sai_port_fec_mode_t value) const return true; } +bool PortHelper::fecToSaiFecMode(const std::string &str, sai_port_fec_mode_t &value) const +{ + const auto &cit = portFecMap.find(str); + if (cit == portFecMap.cend()) + { + return false; + } + + value = cit->second; + + return true; +} + +bool PortHelper::fecIsOverrideRequired(const std::string &str) const +{ + const auto &cit = portFecMap.find(str); + if (cit == portFecMap.cend()) + { + return false; + } + + return cit->second; + +} std::string PortHelper::getFieldValueStr(const PortConfig &port, const std::string &field) const { static std::string str; @@ -468,8 +501,16 @@ bool PortHelper::parsePortFec(PortConfig &port, const std::string &field, const return false; } + const auto &override_cit = portFecOverrideMap.find(value); + if (override_cit == portFecOverrideMap.cend()) + { + SWSS_LOG_ERROR("Failed to parse field(%s): invalid value(%s) in override map", field.c_str(), value.c_str()); + return false; + } + port.fec.value = cit->second; port.fec.is_set = true; + port.fec.override_fec =override_cit->second; return true; } diff --git a/orchagent/port/porthlpr.h b/orchagent/port/porthlpr.h index f3a86e7054..4bcae7fca5 100644 --- a/orchagent/port/porthlpr.h +++ b/orchagent/port/porthlpr.h @@ -15,6 +15,8 @@ class PortHelper final public: bool fecToStr(std::string &str, sai_port_fec_mode_t value) const; + bool fecToSaiFecMode(const std::string &str, sai_port_fec_mode_t &value) const; + bool fecIsOverrideRequired(const std::string &str) const; std::string getAutonegStr(const PortConfig &port) const; std::string getPortInterfaceTypeStr(const PortConfig &port) const; diff --git a/orchagent/port/portschema.h b/orchagent/port/portschema.h index a01ea7271c..4aabf39fbc 100644 --- a/orchagent/port/portschema.h +++ b/orchagent/port/portschema.h @@ -38,6 +38,7 @@ #define PORT_FEC_NONE "none" #define PORT_FEC_RS "rs" #define PORT_FEC_FC "fc" +#define PORT_FEC_AUTO "auto" #define PORT_LEARN_MODE_DROP "drop" #define PORT_LEARN_MODE_DISABLE "disable" diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 4e347d0f26..951d3ff864 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -88,20 +88,6 @@ typedef std::map> PortSerdesA // constants ---------------------------------------------------------------------------------------------------------- -static map fec_mode_map = -{ - { "none", SAI_PORT_FEC_MODE_NONE }, - { "rs", SAI_PORT_FEC_MODE_RS }, - { "fc", SAI_PORT_FEC_MODE_FC } -}; - -static map fec_mode_reverse_map = -{ - { SAI_PORT_FEC_MODE_NONE, "none" }, - { SAI_PORT_FEC_MODE_RS, "rs" }, - { SAI_PORT_FEC_MODE_FC, "fc" } -}; - static map learn_mode_map = { { "drop", SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DROP }, @@ -526,6 +512,18 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vectorset_port_attribute(port_obj, &attr); if (status != SAI_STATUS_SUCCESS) @@ -1542,7 +1540,7 @@ bool PortsOrch::setPortFecOverride(sai_object_id_t port_obj, bool fec_override) return true; } -bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t fec_mode) +bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t fec_mode, bool override_fec) { SWSS_LOG_ENTER(); @@ -1561,11 +1559,11 @@ bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t fec_mode) } } - if (fec_override_sup && !setPortFecOverride(port.m_port_id, true)) + if (fec_override_sup && !setPortFecOverride(port.m_port_id, override_fec)) { return false; } - setGearboxPortsAttr(port, SAI_PORT_ATTR_FEC_MODE, &fec_mode); + setGearboxPortsAttr(port, SAI_PORT_ATTR_FEC_MODE, &fec_mode, override_fec); SWSS_LOG_NOTICE("Set port %s FEC mode %d", port.m_alias.c_str(), fec_mode); @@ -2462,6 +2460,10 @@ void PortsOrch::initPortSupportedFecModes(const std::string& alias, sai_object_i fecModeList.push_back(fecMode); } + if (!fecModeList.empty() && fec_override_sup) + { + fecModeList.push_back(PORT_FEC_AUTO); + } } std::vector v; @@ -2474,15 +2476,15 @@ void PortsOrch::initPortSupportedFecModes(const std::string& alias, sai_object_i /* * If Gearbox is enabled and this is a Gearbox port then set the attributes accordingly. */ -bool PortsOrch::setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value) +bool PortsOrch::setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value, bool override_fec) { bool status = false; - status = setGearboxPortAttr(port, PHY_PORT_TYPE, id, value); + status = setGearboxPortAttr(port, PHY_PORT_TYPE, id, value, override_fec); if (status == true) { - status = setGearboxPortAttr(port, LINE_PORT_TYPE, id, value); + status = setGearboxPortAttr(port, LINE_PORT_TYPE, id, value, override_fec); } return status; @@ -2492,7 +2494,7 @@ bool PortsOrch::setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void * * If Gearbox is enabled and this is a Gearbox port then set the specific lane attribute. * Note: the appl_db is also updated (Gearbox config_db tables are TBA). */ -bool PortsOrch::setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value) +bool PortsOrch::setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value, bool override_fec) { sai_status_t status = SAI_STATUS_SUCCESS; sai_object_id_t dest_port_id; @@ -2568,7 +2570,7 @@ bool PortsOrch::setGearboxPortAttr(const Port &port, dest_port_type_t port_type, m_gearboxTable->hset(key, speed_attr, to_string(speed)); SWSS_LOG_NOTICE("BOX: Updated APPL_DB key:%s %s %d", key.c_str(), speed_attr.c_str(), speed); } - else if (id == SAI_PORT_ATTR_FEC_MODE && fec_override_sup && !setPortFecOverride(dest_port_id, true)) + else if (id == SAI_PORT_ATTR_FEC_MODE && fec_override_sup && !setPortFecOverride(dest_port_id, override_fec)) { return false; } @@ -3859,8 +3861,14 @@ void PortsOrch::doPortTask(Consumer &consumer) if (pCfg.fec.is_set) { /* reset fec mode upon mode change */ - if (!p.m_fec_cfg || p.m_fec_mode != pCfg.fec.value) + if (!p.m_fec_cfg || p.m_fec_mode != pCfg.fec.value || p.m_override_fec != pCfg.fec.override_fec) { + if (!pCfg.fec.override_fec && !fec_override_sup) + { + SWSS_LOG_ERROR("Auto FEC mode is not supported"); + it = taskMap.erase(it); + continue; + } if (!isFecModeSupported(p, pCfg.fec.value)) { SWSS_LOG_ERROR( @@ -3872,6 +3880,11 @@ void PortsOrch::doPortTask(Consumer &consumer) continue; } + if (!pCfg.fec.override_fec && !p.m_autoneg) + { + SWSS_LOG_NOTICE("Autoneg must be enabled for port fec mode auto to work"); + } + if (p.m_admin_state_up) { /* Bring port down before applying fec mode*/ @@ -3889,7 +3902,7 @@ void PortsOrch::doPortTask(Consumer &consumer) m_portList[p.m_alias] = p; } - if (!setPortFec(p, pCfg.fec.value)) + if (!setPortFec(p, pCfg.fec.value, pCfg.fec.override_fec)) { SWSS_LOG_ERROR( "Failed to set port %s FEC mode %s", @@ -3900,6 +3913,7 @@ void PortsOrch::doPortTask(Consumer &consumer) } p.m_fec_mode = pCfg.fec.value; + p.m_override_fec = pCfg.fec.override_fec; p.m_fec_cfg = true; m_portList[p.m_alias] = p; @@ -7139,6 +7153,22 @@ void PortsOrch::doTask(NotificationConsumer &consumer) { updateDbPortOperSpeed(port, 0); } + sai_port_fec_mode_t fec_mode; + string fec_str; + if (oper_fec_sup && getPortOperFec(port, fec_mode)) + { + if (!m_portHlpr.fecToStr(fec_str, fec_mode)) + { + SWSS_LOG_ERROR("Error unknown fec mode %d while querying port %s fec mode", + static_cast(fec_mode), port.m_alias.c_str()); + fec_str = "N/A"; + } + updateDbPortOperFec(port,fec_str); + } + else + { + updateDbPortOperFec(port, "N/A"); + } } /* update m_portList */ @@ -7222,6 +7252,16 @@ void PortsOrch::updateDbPortOperSpeed(Port &port, sai_uint32_t speed) // cause a port flapping. } +void PortsOrch::updateDbPortOperFec(Port &port, string fec_str) +{ + SWSS_LOG_ENTER(); + + vector tuples; + tuples.emplace_back(std::make_pair("fec", fec_str)); + m_portStateTable.set(port.m_alias, tuples); + +} + /* * sync up orchagent with libsai/ASIC for port state. * @@ -7330,6 +7370,28 @@ bool PortsOrch::getPortOperSpeed(const Port& port, sai_uint32_t& speed) const return true; } +bool PortsOrch::getPortOperFec(const Port& port, sai_port_fec_mode_t &fec_mode) const +{ + SWSS_LOG_ENTER(); + + if (port.m_type != Port::PHY) + { + return false; + } + + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_OPER_PORT_FEC_MODE; + + sai_status_t ret = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); + if (ret != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get oper fec for %s", port.m_alias.c_str()); + return false; + } + + fec_mode = static_cast(attr.value.s32); + return true; +} bool PortsOrch::getPortLinkTrainingRxStatus(const Port &port, sai_port_link_training_rx_status_t &rx_status) { SWSS_LOG_ENTER(); @@ -7646,6 +7708,7 @@ bool PortsOrch::initGearboxPort(Port &port) sai_status_t status; string phyOidStr; int phy_id; + sai_port_fec_mode_t sai_fec; SWSS_LOG_ENTER(); @@ -7699,8 +7762,21 @@ bool PortsOrch::initGearboxPort(Port &port) attrs.push_back(attr); attr.id = SAI_PORT_ATTR_FEC_MODE; - attr.value.s32 = fec_mode_map[m_gearboxPortMap[port.m_index].system_fec]; + if (!m_portHlpr.fecToSaiFecMode(m_gearboxPortMap[port.m_index].system_fec, sai_fec)) + { + SWSS_LOG_ERROR("Invalid system FEC mode %s", m_gearboxPortMap[port.m_index].system_fec.c_str()); + return false; + } + attr.value.s32 = sai_fec; attrs.push_back(attr); + + if (fec_override_sup) + { + attr.id = SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE; + + attr.value.booldata = m_portHlpr.fecIsOverrideRequired(m_gearboxPortMap[port.m_index].system_fec); + attrs.push_back(attr); + } attr.id = SAI_PORT_ATTR_INTERNAL_LOOPBACK_MODE; attr.value.u32 = loopback_mode_map[m_gearboxPortMap[port.m_index].system_loopback]; @@ -7755,9 +7831,22 @@ bool PortsOrch::initGearboxPort(Port &port) attrs.push_back(attr); attr.id = SAI_PORT_ATTR_FEC_MODE; - attr.value.s32 = fec_mode_map[m_gearboxPortMap[port.m_index].line_fec]; + if (!m_portHlpr.fecToSaiFecMode(m_gearboxPortMap[port.m_index].line_fec, sai_fec)) + { + SWSS_LOG_ERROR("Invalid line FEC mode %s", m_gearboxPortMap[port.m_index].line_fec.c_str()); + return false; + } + attr.value.s32 = sai_fec; attrs.push_back(attr); + // FEC override will take effect only when autoneg is enabled + if (fec_override_sup) + { + attr.id = SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE; + attr.value.booldata = m_portHlpr.fecIsOverrideRequired(m_gearboxPortMap[port.m_index].line_fec); + attrs.push_back(attr); + } + attr.id = SAI_PORT_ATTR_MEDIA_TYPE; attr.value.u32 = media_type_map[m_gearboxPortMap[port.m_index].line_media_type]; attrs.push_back(attr); diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index a6009c089c..40f63dad0d 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -17,6 +17,7 @@ #include "events.h" #include "port/porthlpr.h" +#include "port/portschema.h" #define FCS_LEN 4 #define VLAN_TAG_LEN 4 @@ -323,6 +324,7 @@ class PortsOrch : public Orch, public Subject NotificationConsumer* m_portStatusNotificationConsumer; bool fec_override_sup = false; + bool oper_fec_sup = false; swss::SelectableTimer *m_port_state_poller = nullptr; @@ -379,8 +381,8 @@ class PortsOrch : public Orch, public Subject bool setPortTpid(Port &port, sai_uint16_t tpid); bool setPortPvid (Port &port, sai_uint32_t pvid); bool getPortPvid(Port &port, sai_uint32_t &pvid); - bool setPortFec(Port &port, sai_port_fec_mode_t fec_mode); - bool setPortFecOverride(sai_object_id_t port_obj, bool fec_override); + bool setPortFec(Port &port, sai_port_fec_mode_t fec_mode, bool override_fec); + bool setPortFecOverride(sai_object_id_t port_obj, bool override_fec); bool setPortPfcAsym(Port &port, sai_port_priority_flow_control_mode_t pfc_asym); bool getDestPortId(sai_object_id_t src_port_id, dest_port_type_t port_type, sai_object_id_t &des_port_id); @@ -396,8 +398,8 @@ class PortsOrch : public Orch, public Subject void initPortSupportedFecModes(const std::string& alias, sai_object_id_t port_id); task_process_status setPortSpeed(Port &port, sai_uint32_t speed); bool getPortSpeed(sai_object_id_t id, sai_uint32_t &speed); - bool setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value); - bool setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value); + bool setGearboxPortsAttr(const Port &port, sai_port_attr_t id, void *value, bool override_fec=true); + bool setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value, bool override_fec); bool getPortAdvSpeeds(const Port& port, bool remote, std::vector& speed_list); bool getPortAdvSpeeds(const Port& port, bool remote, string& adv_speeds); @@ -464,6 +466,8 @@ class PortsOrch : public Orch, public Subject sai_acl_bind_point_type_t &sai_acl_bind_type); void initGearbox(); bool initGearboxPort(Port &port); + bool getPortOperFec(const Port& port, sai_port_fec_mode_t &fec_mode) const; + void updateDbPortOperFec(Port &port, string fec_str); map m_recircPortRole; diff --git a/tests/mock_tests/portsorch_ut.cpp b/tests/mock_tests/portsorch_ut.cpp index 5e253e7115..c338b9fbeb 100644 --- a/tests/mock_tests/portsorch_ut.cpp +++ b/tests/mock_tests/portsorch_ut.cpp @@ -36,6 +36,8 @@ namespace portsorch_test sai_switch_api_t *pold_sai_switch_api; bool not_support_fetching_fec; + uint32_t _sai_set_port_fec_count; + int32_t _sai_port_fec_mode; vector mock_port_fec_modes = {SAI_PORT_FEC_MODE_RS, SAI_PORT_FEC_MODE_FC}; sai_status_t _ut_stub_sai_get_port_attribute( @@ -61,6 +63,11 @@ namespace portsorch_test status = SAI_STATUS_SUCCESS; } } + else if (attr_count == 1 && attr_list[0].id == SAI_PORT_ATTR_OPER_PORT_FEC_MODE) + { + attr_list[0].value.s32 = _sai_port_fec_mode; + status = SAI_STATUS_SUCCESS; + } else { status = pold_sai_port_api->get_port_attribute(port_id, attr_count, attr_list); @@ -68,8 +75,6 @@ namespace portsorch_test return status; } - uint32_t _sai_set_port_fec_count; - int32_t _sai_port_fec_mode; uint32_t _sai_set_pfc_mode_count; uint32_t _sai_set_admin_state_up_count; uint32_t _sai_set_admin_state_down_count; @@ -1123,6 +1128,65 @@ namespace portsorch_test _unhook_sai_port_api(); } + /* + * Test case: Fetching SAI_PORT_ATTR_OPER_PORT_FEC_MODE + **/ + TEST_F(PortsOrchTest, PortVerifyOperFec) + { + _hook_sai_port_api(); + Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME); + std::deque entries; + + not_support_fetching_fec = false; + auto old_mock_port_fec_modes = mock_port_fec_modes; + mock_port_fec_modes.clear(); + // Get SAI default ports to populate DB + auto ports = ut_helper::getInitialSaiPorts(); + + for (const auto &it : ports) + { + portTable.set(it.first, it.second); + } + + // Set PortConfigDone + portTable.set("PortConfigDone", { { "count", to_string(ports.size()) } }); + + // refill consumer + gPortsOrch->addExistingData(&portTable); + + // Apply configuration : + // create ports + static_cast(gPortsOrch)->doTask(); + + uint32_t current_sai_api_call_count = _sai_set_port_fec_count; + gPortsOrch->oper_fec_sup = true; + + entries.push_back({"Ethernet0", "SET", + { + {"fec", "rs"} + }}); + auto consumer = dynamic_cast(gPortsOrch->getExecutor(APP_PORT_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gPortsOrch)->doTask(); + entries.clear(); + + ASSERT_EQ(_sai_set_port_fec_count, current_sai_api_call_count); + + vector ts; + + gPortsOrch->dumpPendingTasks(ts); + ASSERT_TRUE(ts.empty()); + Port port; + gPortsOrch->getPort("Ethernet0", port); + + sai_port_fec_mode_t fec_mode; + gPortsOrch->getPortOperFec(port, fec_mode); + + ASSERT_EQ(fec_mode, SAI_PORT_FEC_MODE_RS); + + mock_port_fec_modes = old_mock_port_fec_modes; + _unhook_sai_port_api(); + } TEST_F(PortsOrchTest, PortTestSAIFailureHandling) { _hook_sai_port_api(); diff --git a/tests/test_port.py b/tests/test_port.py index c880a88c5a..335b0a604b 100644 --- a/tests/test_port.py +++ b/tests/test_port.py @@ -186,6 +186,7 @@ def test_PortFec(self, dvs, testlog): for fv in fvs: if fv[0] == "SAI_PORT_ATTR_FEC_MODE": assert fv[1] == "SAI_PORT_FEC_MODE_RS" + assert fv[0] != "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE" def test_PortPreemp(self, dvs, testlog): diff --git a/tests/test_port_fec_override.py b/tests/test_port_fec_override.py index acd6b9bbbb..08d960116d 100644 --- a/tests/test_port_fec_override.py +++ b/tests/test_port_fec_override.py @@ -14,17 +14,33 @@ def test_PortFecOverride(self, dvs, testlog): ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") # set fec + fvs = swsscommon.FieldValuePairs([("fec","auto")]) + ptbl.set("Ethernet0", fvs) fvs = swsscommon.FieldValuePairs([("fec","rs")]) ptbl.set("Ethernet4", fvs) + # validate if fec none is pushed to asic db when set first time + port_oid = adb.port_name_map["Ethernet0"] + expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"false"} + adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) + # validate if fec rs is pushed to asic db when set first time port_oid = adb.port_name_map["Ethernet4"] expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_RS", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) + fvs = swsscommon.FieldValuePairs([("fec","none")]) + ptbl.set("Ethernet0", fvs) + ptbl.set("Ethernet4", fvs) + port_oid = adb.port_name_map["Ethernet0"] + expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} + adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) + port_oid = adb.port_name_map["Ethernet4"] + expected_fields = {"SAI_PORT_ATTR_FEC_MODE":"SAI_PORT_FEC_MODE_NONE", "SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE":"true"} + adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields) + # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying def test_nonflaky_dummy(): pass -