Skip to content

[FEC]Auto FEC initial changes #2893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -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_is_fec_auto = false; // Is FEC mode auto
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)
Expand Down
1 change: 1 addition & 0 deletions orchagent/port/portcnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class PortConfig final
struct {
sai_port_fec_mode_t value;
bool is_set = false;
bool is_auto = false;
} fec; // Port FEC

struct {
Expand Down
19 changes: 5 additions & 14 deletions orchagent/port/porthlpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include <boost/algorithm/string.hpp>

#include "portschema.h"
#include "converter.h"
#include "tokenize.h"
#include "logger.h"
Expand Down Expand Up @@ -70,19 +69,6 @@ static const std::unordered_map<std::string, sai_port_interface_type_t> portInte
{ PORT_INTERFACE_TYPE_XGMII, SAI_PORT_INTERFACE_TYPE_XGMII }
};

static const std::unordered_map<std::string, sai_port_fec_mode_t> 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 }
};

static const std::unordered_map<sai_port_fec_mode_t, std::string> portFecRevMap =
{
{ SAI_PORT_FEC_MODE_NONE, PORT_FEC_NONE },
{ SAI_PORT_FEC_MODE_RS, PORT_FEC_RS },
{ SAI_PORT_FEC_MODE_FC, PORT_FEC_FC }
};

static const std::unordered_map<std::string, sai_port_priority_flow_control_mode_t> portPfcAsymMap =
{
Expand Down Expand Up @@ -471,6 +457,11 @@ bool PortHelper::parsePortFec(PortConfig &port, const std::string &field, const
port.fec.value = cit->second;
port.fec.is_set = true;

if (value == PORT_FEC_AUTO)
{
port.fec.is_auto = true;
}

return true;
}

Expand Down
16 changes: 16 additions & 0 deletions orchagent/port/porthlpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
#include <string>

#include "portcnt.h"
#include "portschema.h"

static const std::unordered_map<std::string, sai_port_fec_mode_t> 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_AUTO, SAI_PORT_FEC_MODE_NONE }
};

static const std::unordered_map<sai_port_fec_mode_t, std::string> portFecRevMap =
{
{ SAI_PORT_FEC_MODE_NONE, PORT_FEC_NONE },
{ SAI_PORT_FEC_MODE_RS, PORT_FEC_RS },
{ SAI_PORT_FEC_MODE_FC, PORT_FEC_FC }
};

class PortHelper final
{
Expand Down
1 change: 1 addition & 0 deletions orchagent/port/portschema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
81 changes: 53 additions & 28 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,6 @@ typedef std::map<sai_port_serdes_attr_t, std::vector<std::uint32_t>> PortSerdesA

// constants ----------------------------------------------------------------------------------------------------------

static map<string, sai_port_fec_mode_t> fec_mode_map =
{
{ "none", SAI_PORT_FEC_MODE_NONE },
{ "rs", SAI_PORT_FEC_MODE_RS },
{ "fc", SAI_PORT_FEC_MODE_FC }
};

static map<sai_port_fec_mode_t, string> fec_mode_reverse_map =
{
{ SAI_PORT_FEC_MODE_NONE, "none" },
{ SAI_PORT_FEC_MODE_RS, "rs" },
{ SAI_PORT_FEC_MODE_FC, "fc" }
};

static map<string, sai_bridge_port_fdb_learning_mode_t> learn_mode_map =
{
{ "drop", SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DROP },
Expand Down Expand Up @@ -1542,7 +1528,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 auto_fec)
{
SWSS_LOG_ENTER();

Expand All @@ -1561,11 +1547,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, !auto_fec))
{
return false;
}
setGearboxPortsAttr(port, SAI_PORT_ATTR_FEC_MODE, &fec_mode);
setGearboxPortsAttr(port, SAI_PORT_ATTR_FEC_MODE, &fec_mode, auto_fec);

SWSS_LOG_NOTICE("Set port %s FEC mode %d", port.m_alias.c_str(), fec_mode);

Expand Down Expand Up @@ -2357,10 +2343,14 @@ void PortsOrch::initPortCapLinkTraining(Port &port)
SWSS_LOG_WARN("Unable to get %s LT support capability", port.m_alias.c_str());
}

bool PortsOrch::isFecModeSupported(const Port &port, sai_port_fec_mode_t fec_mode)
bool PortsOrch::isFecModeSupported(const Port &port, sai_port_fec_mode_t fec_mode, bool is_auto)
{
initPortSupportedFecModes(port.m_alias, port.m_port_id);

if (is_auto && !fec_override_sup)
{
return false;
}
const auto &obj = m_portSupportedFecModes.at(port.m_port_id);

if (!obj.supported)
Expand Down Expand Up @@ -2462,6 +2452,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<FieldValueTuple> v;
Expand All @@ -2474,15 +2468,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 auto_fec)
{
bool status = false;

status = setGearboxPortAttr(port, PHY_PORT_TYPE, id, value);
status = setGearboxPortAttr(port, PHY_PORT_TYPE, id, value, auto_fec);

if (status == true)
{
status = setGearboxPortAttr(port, LINE_PORT_TYPE, id, value);
status = setGearboxPortAttr(port, LINE_PORT_TYPE, id, value, auto_fec);
}

return status;
Expand All @@ -2492,7 +2486,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 auto_fec)
{
sai_status_t status = SAI_STATUS_SUCCESS;
sai_object_id_t dest_port_id;
Expand Down Expand Up @@ -2568,7 +2562,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, !auto_fec))
{
return false;
}
Expand Down Expand Up @@ -3867,9 +3861,9 @@ 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_is_fec_auto != pCfg.fec.is_auto)
{
if (!isFecModeSupported(p, pCfg.fec.value))
if (!isFecModeSupported(p, pCfg.fec.value, pCfg.fec.is_auto))
{
SWSS_LOG_ERROR(
"Unsupported port %s FEC mode %s",
Expand Down Expand Up @@ -3897,7 +3891,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.is_auto))
{
SWSS_LOG_ERROR(
"Failed to set port %s FEC mode %s",
Expand All @@ -3908,6 +3902,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
}

p.m_fec_mode = pCfg.fec.value;
p.m_is_fec_auto = pCfg.fec.is_auto;
p.m_fec_cfg = true;
m_portList[p.m_alias] = p;

Expand Down Expand Up @@ -7635,8 +7630,23 @@ 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];
attr.value.s32 = portFecMap.at(m_gearboxPortMap[port.m_index].system_fec);
attrs.push_back(attr);

if (fec_override_sup)
{
attr.id = SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE;

if (m_gearboxPortMap[port.m_index].system_fec == PORT_FEC_AUTO)
{
attr.value.booldata = false;
}
else
{
attr.value.booldata = true;
}
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];
Expand Down Expand Up @@ -7691,9 +7701,24 @@ 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];
attr.value.s32 = portFecMap.at(m_gearboxPortMap[port.m_index].line_fec);
attrs.push_back(attr);

if (fec_override_sup)
{
attr.id = SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE;

if (m_gearboxPortMap[port.m_index].system_fec == PORT_FEC_AUTO)
{
attr.value.booldata = false;
}
else
{
attr.value.booldata = true;
}
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);
Expand Down
9 changes: 5 additions & 4 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "events.h"

#include "port/porthlpr.h"
#include "port/portschema.h"

#define FCS_LEN 4
#define VLAN_TAG_LEN 4
Expand Down Expand Up @@ -379,7 +380,7 @@ 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 setPortFec(Port &port, sai_port_fec_mode_t fec_mode, bool auto_fec);
bool setPortFecOverride(sai_object_id_t port_obj, bool fec_override);
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);
Expand All @@ -391,13 +392,13 @@ class PortsOrch : public Orch, public Subject
void getPortSupportedSpeeds(const std::string& alias, sai_object_id_t port_id, PortSupportedSpeeds &supported_speeds);
void initPortSupportedSpeeds(const std::string& alias, sai_object_id_t port_id);
// Get supported FEC modes on system side
bool isFecModeSupported(const Port &port, sai_port_fec_mode_t fec_mode);
bool isFecModeSupported(const Port &port, sai_port_fec_mode_t fec_mode, bool is_auto);
sai_status_t getPortSupportedFecModes(PortSupportedFecModes &supported_fecmodes, sai_object_id_t port_id);
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 auto_fec=false);
bool setGearboxPortAttr(const Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value, bool auto_fec);

bool getPortAdvSpeeds(const Port& port, bool remote, std::vector<sai_uint32_t>& speed_list);
bool getPortAdvSpeeds(const Port& port, bool remote, string& adv_speeds);
Expand Down
1 change: 1 addition & 0 deletions tests/test_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand Down
18 changes: 17 additions & 1 deletion tests/test_port_fec_override.py
Original file line number Diff line number Diff line change
Expand Up @@ -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