Skip to content

Commit dc8bc1c

Browse files
authored
[portsorch] Expose supported FEC modes to STABE_DB and check whether FEC mode is supported before setting it (sonic-net#2333)
- What I did Expose supported FEC modes to STATE_DB.PORT_TABLE|<port>.supported_fecs. The orchagent calls get_port_attribute to get attribute SAI_PORT_ATTR_SUPPORTED_FEC_MODE during initialization and then records it into internal data. 1. By default, the supported FEC modes will be returned by SAI and exposed to STATE_DB. Eg. rs,none means only rs and none is supported on the port. The orchagent will check whether the FEC mode is supported on the port before calling the SAI API to set it. The CLI will check whether the FEC mode is in supported_fecs before setting FEC mode on a port to the CONFIG_DB 2. In case the SAI API does not support any FEC mode on the port, N/A will be exposed to STATE_DB The orchagent will deny any FEC setting and prints log. The CLI will deny FEC setting. 3. In case the SAI API get_port_attribute returns Not implemented No check will be performed before setting a FEC mode to SAI on the port. The CLI will check whether the FEC mode is defined before setting it to CONFIG_DB. - Why I did it It is not supported to set FEC mode on some platforms. To avoid error, we need to expose the supported FEC list. - How I verified it Manually test and mock test.
1 parent 4a6f940 commit dc8bc1c

File tree

3 files changed

+342
-12
lines changed

3 files changed

+342
-12
lines changed

orchagent/portsorch.cpp

+108-11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ static map<string, sai_port_fec_mode_t> fec_mode_map =
7777
{ "fc", SAI_PORT_FEC_MODE_FC }
7878
};
7979

80+
static map<sai_port_fec_mode_t, string> fec_mode_reverse_map =
81+
{
82+
{ SAI_PORT_FEC_MODE_NONE, "none" },
83+
{ SAI_PORT_FEC_MODE_RS, "rs" },
84+
{ SAI_PORT_FEC_MODE_FC, "fc" }
85+
};
86+
8087
static map<string, sai_port_priority_flow_control_mode_t> pfc_asym_map =
8188
{
8289
{ "on", SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE },
@@ -1188,27 +1195,39 @@ bool PortsOrch::setPortTpid(sai_object_id_t id, sai_uint16_t tpid)
11881195
return true;
11891196
}
11901197

1191-
1192-
bool PortsOrch::setPortFec(Port &port, sai_port_fec_mode_t mode)
1198+
bool PortsOrch::setPortFec(Port &port, string &mode)
11931199
{
11941200
SWSS_LOG_ENTER();
11951201

1202+
auto searchRef = m_portSupportedFecModes.find(port.m_port_id);
1203+
if (searchRef != m_portSupportedFecModes.end())
1204+
{
1205+
auto &supportedFecModes = searchRef->second;
1206+
if (!supportedFecModes.empty() && (supportedFecModes.find(mode) == supportedFecModes.end()))
1207+
{
1208+
SWSS_LOG_ERROR("Unsupported mode %s on port %s", mode.c_str(), port.m_alias.c_str());
1209+
// We return true becase the caller will keep the item in m_toSync and retry it later if we return false
1210+
// As the FEC mode is not supported it doesn't make sense to retry.
1211+
return true;
1212+
}
1213+
}
1214+
11961215
sai_attribute_t attr;
11971216
attr.id = SAI_PORT_ATTR_FEC_MODE;
1198-
attr.value.s32 = mode;
1217+
attr.value.s32 = port.m_fec_mode;
11991218

12001219
sai_status_t status = sai_port_api->set_port_attribute(port.m_port_id, &attr);
12011220
if (status != SAI_STATUS_SUCCESS)
12021221
{
1203-
SWSS_LOG_ERROR("Failed to set fec mode %d to port pid:%" PRIx64, mode, port.m_port_id);
1222+
SWSS_LOG_ERROR("Failed to set FEC mode %s to port %s", mode.c_str(), port.m_alias.c_str());
12041223
task_process_status handle_status = handleSaiSetStatus(SAI_API_PORT, status);
12051224
if (handle_status != task_success)
12061225
{
12071226
return parseHandleSaiStatusFailure(handle_status);
12081227
}
12091228
}
12101229

1211-
SWSS_LOG_INFO("Set fec mode %d to port pid:%" PRIx64, mode, port.m_port_id);
1230+
SWSS_LOG_NOTICE("Set port %s FEC mode %s", port.m_alias.c_str(), mode.c_str());
12121231

12131232
setGearboxPortsAttr(port, SAI_PORT_ATTR_FEC_MODE, &mode);
12141233

@@ -1985,6 +2004,87 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
19852004
m_portStateTable.set(alias, v);
19862005
}
19872006

2007+
void PortsOrch::getPortSupportedFecModes(const std::string& alias, sai_object_id_t port_id, PortSupportedFecModes &supported_fecmodes)
2008+
{
2009+
sai_attribute_t attr;
2010+
sai_status_t status;
2011+
vector<sai_int32_t> fecModes(fec_mode_reverse_map.size());
2012+
2013+
attr.id = SAI_PORT_ATTR_SUPPORTED_FEC_MODE;
2014+
attr.value.s32list.count = static_cast<uint32_t>(fecModes.size());
2015+
attr.value.s32list.list = fecModes.data();
2016+
2017+
status = sai_port_api->get_port_attribute(port_id, 1, &attr);
2018+
fecModes.resize(attr.value.s32list.count);
2019+
if (status == SAI_STATUS_SUCCESS)
2020+
{
2021+
if (fecModes.empty())
2022+
{
2023+
supported_fecmodes.insert("N/A");
2024+
}
2025+
else
2026+
{
2027+
for(auto fecMode : fecModes)
2028+
{
2029+
supported_fecmodes.insert(fec_mode_reverse_map[static_cast<sai_port_fec_mode_t>(fecMode)]);
2030+
}
2031+
}
2032+
}
2033+
else
2034+
{
2035+
if (SAI_STATUS_IS_ATTR_NOT_SUPPORTED(status) ||
2036+
SAI_STATUS_IS_ATTR_NOT_IMPLEMENTED(status) ||
2037+
status == SAI_STATUS_NOT_IMPLEMENTED)
2038+
{
2039+
// unable to validate FEC mode if attribute is not supported on platform
2040+
SWSS_LOG_NOTICE("Unable to validate FEC mode for port %s id=%" PRIx64 " due to unsupported by platform",
2041+
alias.c_str(), port_id);
2042+
}
2043+
else
2044+
{
2045+
SWSS_LOG_ERROR("Failed to get a list of supported FEC modes for port %s id=%" PRIx64 ". Error=%d",
2046+
alias.c_str(), port_id, status);
2047+
}
2048+
2049+
supported_fecmodes.clear(); // return empty
2050+
}
2051+
}
2052+
2053+
void PortsOrch::initPortSupportedFecModes(const std::string& alias, sai_object_id_t port_id)
2054+
{
2055+
// If port supported speeds map already contains the information, save the SAI call
2056+
if (m_portSupportedFecModes.count(port_id))
2057+
{
2058+
return;
2059+
}
2060+
PortSupportedFecModes supported_fec_modes;
2061+
getPortSupportedFecModes(alias, port_id, supported_fec_modes);
2062+
m_portSupportedFecModes[port_id] = supported_fec_modes;
2063+
2064+
if (supported_fec_modes.empty())
2065+
{
2066+
// Do not expose "supported_fecs" in case fetching FEC modes is not supported by the vendor
2067+
SWSS_LOG_INFO("No supported_fecs exposed to STATE_DB for port %s since fetching supported FEC modes is not supported by the vendor",
2068+
alias.c_str());
2069+
return;
2070+
}
2071+
2072+
vector<FieldValueTuple> v;
2073+
std::string supported_fec_modes_str;
2074+
bool first = true;
2075+
for(auto fec : supported_fec_modes)
2076+
{
2077+
if (first)
2078+
first = false;
2079+
else
2080+
supported_fec_modes_str += ',';
2081+
supported_fec_modes_str += fec;
2082+
}
2083+
2084+
v.emplace_back(std::make_pair("supported_fecs", supported_fec_modes_str));
2085+
m_portStateTable.set(alias, v);
2086+
}
2087+
19882088
/*
19892089
* If Gearbox is enabled and this is a Gearbox port then set the attributes accordingly.
19902090
*/
@@ -2978,6 +3078,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
29783078
}
29793079

29803080
initPortSupportedSpeeds(get<0>(it->second), m_portListLaneMap[it->first]);
3081+
initPortSupportedFecModes(get<0>(it->second), m_portListLaneMap[it->first]);
29813082
it++;
29823083
}
29833084

@@ -3326,14 +3427,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
33263427
p.m_fec_mode = fec_mode_map[fec_mode];
33273428
p.m_fec_cfg = true;
33283429

3329-
if (setPortFec(p, p.m_fec_mode))
3430+
if (setPortFec(p, fec_mode))
33303431
{
33313432
m_portList[alias] = p;
3332-
SWSS_LOG_NOTICE("Set port %s fec to %s", alias.c_str(), fec_mode.c_str());
33333433
}
33343434
else
33353435
{
3336-
SWSS_LOG_ERROR("Failed to set port %s fec to %s", alias.c_str(), fec_mode.c_str());
33373436
it++;
33383437
continue;
33393438
}
@@ -3343,14 +3442,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
33433442
/* Port is already down, setting fec mode*/
33443443
p.m_fec_mode = fec_mode_map[fec_mode];
33453444
p.m_fec_cfg = true;
3346-
if (setPortFec(p, p.m_fec_mode))
3445+
if (setPortFec(p, fec_mode))
33473446
{
33483447
m_portList[alias] = p;
3349-
SWSS_LOG_NOTICE("Set port %s fec to %s", alias.c_str(), fec_mode.c_str());
33503448
}
33513449
else
33523450
{
3353-
SWSS_LOG_ERROR("Failed to set port %s fec to %s", alias.c_str(), fec_mode.c_str());
33543451
it++;
33553452
continue;
33563453
}

orchagent/portsorch.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define PG_DROP_STAT_COUNTER_FLEX_COUNTER_GROUP "PG_DROP_STAT_COUNTER"
2828

2929
typedef std::vector<sai_uint32_t> PortSupportedSpeeds;
30+
typedef std::set<std::string> PortSupportedFecModes;
3031

3132
static const map<sai_port_oper_status_t, string> oper_status_strings =
3233
{
@@ -209,6 +210,8 @@ class PortsOrch : public Orch, public Subject
209210
unique_ptr<Table> m_gbcounterTable;
210211

211212
std::map<sai_object_id_t, PortSupportedSpeeds> m_portSupportedSpeeds;
213+
// Supported FEC modes on the system side.
214+
std::map<sai_object_id_t, PortSupportedFecModes> m_portSupportedFecModes;
212215

213216
bool m_initDone = false;
214217
Port m_cpuPort;
@@ -305,7 +308,7 @@ class PortsOrch : public Orch, public Subject
305308
bool setPortTpid(sai_object_id_t id, sai_uint16_t tpid);
306309
bool setPortPvid (Port &port, sai_uint32_t pvid);
307310
bool getPortPvid(Port &port, sai_uint32_t &pvid);
308-
bool setPortFec(Port &port, sai_port_fec_mode_t mode);
311+
bool setPortFec(Port &port, std::string &mode);
309312
bool setPortPfcAsym(Port &port, string pfc_asym);
310313
bool getDestPortId(sai_object_id_t src_port_id, dest_port_type_t port_type, sai_object_id_t &des_port_id);
311314

@@ -314,6 +317,9 @@ class PortsOrch : public Orch, public Subject
314317
bool isSpeedSupported(const std::string& alias, sai_object_id_t port_id, sai_uint32_t speed);
315318
void getPortSupportedSpeeds(const std::string& alias, sai_object_id_t port_id, PortSupportedSpeeds &supported_speeds);
316319
void initPortSupportedSpeeds(const std::string& alias, sai_object_id_t port_id);
320+
// Get supported FEC modes on system side
321+
void getPortSupportedFecModes(const std::string& alias, sai_object_id_t port_id, PortSupportedFecModes &supported_fecmodes);
322+
void initPortSupportedFecModes(const std::string& alias, sai_object_id_t port_id);
317323
task_process_status setPortSpeed(Port &port, sai_uint32_t speed);
318324
bool getPortSpeed(sai_object_id_t id, sai_uint32_t &speed);
319325
bool setGearboxPortsAttr(Port &port, sai_port_attr_t id, void *value);

0 commit comments

Comments
 (0)