@@ -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+
8087static 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 }
0 commit comments