@@ -77,6 +77,13 @@ static map<string, sai_port_fec_mode_t> fec_mode_map =
77
77
{ " fc" , SAI_PORT_FEC_MODE_FC }
78
78
};
79
79
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
+
80
87
static map<string, sai_port_priority_flow_control_mode_t > pfc_asym_map =
81
88
{
82
89
{ " on" , SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE },
@@ -1188,27 +1195,39 @@ bool PortsOrch::setPortTpid(sai_object_id_t id, sai_uint16_t tpid)
1188
1195
return true ;
1189
1196
}
1190
1197
1191
-
1192
- bool PortsOrch::setPortFec (Port &port, sai_port_fec_mode_t mode)
1198
+ bool PortsOrch::setPortFec (Port &port, string &mode)
1193
1199
{
1194
1200
SWSS_LOG_ENTER ();
1195
1201
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
+
1196
1215
sai_attribute_t attr;
1197
1216
attr.id = SAI_PORT_ATTR_FEC_MODE;
1198
- attr.value .s32 = mode ;
1217
+ attr.value .s32 = port. m_fec_mode ;
1199
1218
1200
1219
sai_status_t status = sai_port_api->set_port_attribute (port.m_port_id , &attr);
1201
1220
if (status != SAI_STATUS_SUCCESS)
1202
1221
{
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 () );
1204
1223
task_process_status handle_status = handleSaiSetStatus (SAI_API_PORT, status);
1205
1224
if (handle_status != task_success)
1206
1225
{
1207
1226
return parseHandleSaiStatusFailure (handle_status);
1208
1227
}
1209
1228
}
1210
1229
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 () );
1212
1231
1213
1232
setGearboxPortsAttr (port, SAI_PORT_ATTR_FEC_MODE, &mode);
1214
1233
@@ -1985,6 +2004,87 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
1985
2004
m_portStateTable.set (alias, v);
1986
2005
}
1987
2006
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
+
1988
2088
/*
1989
2089
* If Gearbox is enabled and this is a Gearbox port then set the attributes accordingly.
1990
2090
*/
@@ -2978,6 +3078,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
2978
3078
}
2979
3079
2980
3080
initPortSupportedSpeeds (get<0 >(it->second ), m_portListLaneMap[it->first ]);
3081
+ initPortSupportedFecModes (get<0 >(it->second ), m_portListLaneMap[it->first ]);
2981
3082
it++;
2982
3083
}
2983
3084
@@ -3326,14 +3427,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
3326
3427
p.m_fec_mode = fec_mode_map[fec_mode];
3327
3428
p.m_fec_cfg = true ;
3328
3429
3329
- if (setPortFec (p, p. m_fec_mode ))
3430
+ if (setPortFec (p, fec_mode ))
3330
3431
{
3331
3432
m_portList[alias] = p;
3332
- SWSS_LOG_NOTICE (" Set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3333
3433
}
3334
3434
else
3335
3435
{
3336
- SWSS_LOG_ERROR (" Failed to set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3337
3436
it++;
3338
3437
continue ;
3339
3438
}
@@ -3343,14 +3442,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
3343
3442
/* Port is already down, setting fec mode*/
3344
3443
p.m_fec_mode = fec_mode_map[fec_mode];
3345
3444
p.m_fec_cfg = true ;
3346
- if (setPortFec (p, p. m_fec_mode ))
3445
+ if (setPortFec (p, fec_mode ))
3347
3446
{
3348
3447
m_portList[alias] = p;
3349
- SWSS_LOG_NOTICE (" Set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3350
3448
}
3351
3449
else
3352
3450
{
3353
- SWSS_LOG_ERROR (" Failed to set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3354
3451
it++;
3355
3452
continue ;
3356
3453
}
0 commit comments