@@ -79,6 +79,13 @@ static map<string, sai_port_fec_mode_t> fec_mode_map =
79
79
{ " fc" , SAI_PORT_FEC_MODE_FC }
80
80
};
81
81
82
+ static map<sai_port_fec_mode_t , string> fec_mode_reverse_map =
83
+ {
84
+ { SAI_PORT_FEC_MODE_NONE, " none" },
85
+ { SAI_PORT_FEC_MODE_RS, " rs" },
86
+ { SAI_PORT_FEC_MODE_FC, " fc" }
87
+ };
88
+
82
89
static map<string, sai_port_priority_flow_control_mode_t > pfc_asym_map =
83
90
{
84
91
{ " on" , SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_SEPARATE },
@@ -1214,27 +1221,39 @@ bool PortsOrch::setPortTpid(sai_object_id_t id, sai_uint16_t tpid)
1214
1221
return true ;
1215
1222
}
1216
1223
1217
-
1218
- bool PortsOrch::setPortFec (Port &port, sai_port_fec_mode_t mode)
1224
+ bool PortsOrch::setPortFec (Port &port, string &mode)
1219
1225
{
1220
1226
SWSS_LOG_ENTER ();
1221
1227
1228
+ auto searchRef = m_portSupportedFecModes.find (port.m_port_id );
1229
+ if (searchRef != m_portSupportedFecModes.end ())
1230
+ {
1231
+ auto &supportedFecModes = searchRef->second ;
1232
+ if (!supportedFecModes.empty () && (supportedFecModes.find (mode) == supportedFecModes.end ()))
1233
+ {
1234
+ SWSS_LOG_ERROR (" Unsupported mode %s on port %s" , mode.c_str (), port.m_alias .c_str ());
1235
+ // We return true becase the caller will keep the item in m_toSync and retry it later if we return false
1236
+ // As the FEC mode is not supported it doesn't make sense to retry.
1237
+ return true ;
1238
+ }
1239
+ }
1240
+
1222
1241
sai_attribute_t attr;
1223
1242
attr.id = SAI_PORT_ATTR_FEC_MODE;
1224
- attr.value .s32 = mode ;
1243
+ attr.value .s32 = port. m_fec_mode ;
1225
1244
1226
1245
sai_status_t status = sai_port_api->set_port_attribute (port.m_port_id , &attr);
1227
1246
if (status != SAI_STATUS_SUCCESS)
1228
1247
{
1229
- SWSS_LOG_ERROR (" Failed to set fec mode %d to port pid:% " PRIx64 , mode, port.m_port_id );
1248
+ SWSS_LOG_ERROR (" Failed to set FEC mode %s to port %s " , mode. c_str () , port.m_alias . c_str () );
1230
1249
task_process_status handle_status = handleSaiSetStatus (SAI_API_PORT, status);
1231
1250
if (handle_status != task_success)
1232
1251
{
1233
1252
return parseHandleSaiStatusFailure (handle_status);
1234
1253
}
1235
1254
}
1236
1255
1237
- SWSS_LOG_INFO (" Set fec mode %d to port pid:% " PRIx64, mode, port. m_port_id );
1256
+ SWSS_LOG_NOTICE (" Set port %s FEC mode %s " , port. m_alias . c_str (), mode. c_str () );
1238
1257
1239
1258
setGearboxPortsAttr (port, SAI_PORT_ATTR_FEC_MODE, &mode);
1240
1259
@@ -2011,6 +2030,7 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
2011
2030
m_portStateTable.set (alias, v);
2012
2031
}
2013
2032
2033
+
2014
2034
void PortsOrch::initPortCapAutoNeg (Port &port)
2015
2035
{
2016
2036
sai_status_t status;
@@ -2040,6 +2060,87 @@ void PortsOrch::initPortCapLinkTraining(Port &port)
2040
2060
SWSS_LOG_WARN (" Unable to get %s LT support capability" , port.m_alias .c_str ());
2041
2061
}
2042
2062
2063
+ void PortsOrch::getPortSupportedFecModes (const std::string& alias, sai_object_id_t port_id, PortSupportedFecModes &supported_fecmodes)
2064
+ {
2065
+ sai_attribute_t attr;
2066
+ sai_status_t status;
2067
+ vector<sai_int32_t > fecModes (fec_mode_reverse_map.size ());
2068
+
2069
+ attr.id = SAI_PORT_ATTR_SUPPORTED_FEC_MODE;
2070
+ attr.value .s32list .count = static_cast <uint32_t >(fecModes.size ());
2071
+ attr.value .s32list .list = fecModes.data ();
2072
+
2073
+ status = sai_port_api->get_port_attribute (port_id, 1 , &attr);
2074
+ fecModes.resize (attr.value .s32list .count );
2075
+ if (status == SAI_STATUS_SUCCESS)
2076
+ {
2077
+ if (fecModes.empty ())
2078
+ {
2079
+ supported_fecmodes.insert (" N/A" );
2080
+ }
2081
+ else
2082
+ {
2083
+ for (auto fecMode : fecModes)
2084
+ {
2085
+ supported_fecmodes.insert (fec_mode_reverse_map[static_cast <sai_port_fec_mode_t >(fecMode)]);
2086
+ }
2087
+ }
2088
+ }
2089
+ else
2090
+ {
2091
+ if (SAI_STATUS_IS_ATTR_NOT_SUPPORTED (status) ||
2092
+ SAI_STATUS_IS_ATTR_NOT_IMPLEMENTED (status) ||
2093
+ status == SAI_STATUS_NOT_IMPLEMENTED)
2094
+ {
2095
+ // unable to validate FEC mode if attribute is not supported on platform
2096
+ SWSS_LOG_NOTICE (" Unable to validate FEC mode for port %s id=%" PRIx64 " due to unsupported by platform" ,
2097
+ alias.c_str (), port_id);
2098
+ }
2099
+ else
2100
+ {
2101
+ SWSS_LOG_ERROR (" Failed to get a list of supported FEC modes for port %s id=%" PRIx64 " . Error=%d" ,
2102
+ alias.c_str (), port_id, status);
2103
+ }
2104
+
2105
+ supported_fecmodes.clear (); // return empty
2106
+ }
2107
+ }
2108
+
2109
+ void PortsOrch::initPortSupportedFecModes (const std::string& alias, sai_object_id_t port_id)
2110
+ {
2111
+ // If port supported speeds map already contains the information, save the SAI call
2112
+ if (m_portSupportedFecModes.count (port_id))
2113
+ {
2114
+ return ;
2115
+ }
2116
+ PortSupportedFecModes supported_fec_modes;
2117
+ getPortSupportedFecModes (alias, port_id, supported_fec_modes);
2118
+ m_portSupportedFecModes[port_id] = supported_fec_modes;
2119
+
2120
+ if (supported_fec_modes.empty ())
2121
+ {
2122
+ // Do not expose "supported_fecs" in case fetching FEC modes is not supported by the vendor
2123
+ SWSS_LOG_INFO (" No supported_fecs exposed to STATE_DB for port %s since fetching supported FEC modes is not supported by the vendor" ,
2124
+ alias.c_str ());
2125
+ return ;
2126
+ }
2127
+
2128
+ vector<FieldValueTuple> v;
2129
+ std::string supported_fec_modes_str;
2130
+ bool first = true ;
2131
+ for (auto fec : supported_fec_modes)
2132
+ {
2133
+ if (first)
2134
+ first = false ;
2135
+ else
2136
+ supported_fec_modes_str += ' ,' ;
2137
+ supported_fec_modes_str += fec;
2138
+ }
2139
+
2140
+ v.emplace_back (std::make_pair (" supported_fecs" , supported_fec_modes_str));
2141
+ m_portStateTable.set (alias, v);
2142
+ }
2143
+
2043
2144
/*
2044
2145
* If Gearbox is enabled and this is a Gearbox port then set the attributes accordingly.
2045
2146
*/
@@ -3105,6 +3206,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
3105
3206
}
3106
3207
3107
3208
initPortSupportedSpeeds (get<0 >(it->second ), m_portListLaneMap[it->first ]);
3209
+ initPortSupportedFecModes (get<0 >(it->second ), m_portListLaneMap[it->first ]);
3108
3210
it++;
3109
3211
}
3110
3212
@@ -3520,14 +3622,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
3520
3622
p.m_fec_mode = fec_mode_map[fec_mode];
3521
3623
p.m_fec_cfg = true ;
3522
3624
3523
- if (setPortFec (p, p. m_fec_mode ))
3625
+ if (setPortFec (p, fec_mode ))
3524
3626
{
3525
3627
m_portList[alias] = p;
3526
- SWSS_LOG_NOTICE (" Set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3527
3628
}
3528
3629
else
3529
3630
{
3530
- SWSS_LOG_ERROR (" Failed to set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3531
3631
it++;
3532
3632
continue ;
3533
3633
}
@@ -3537,14 +3637,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
3537
3637
/* Port is already down, setting fec mode*/
3538
3638
p.m_fec_mode = fec_mode_map[fec_mode];
3539
3639
p.m_fec_cfg = true ;
3540
- if (setPortFec (p, p. m_fec_mode ))
3640
+ if (setPortFec (p, fec_mode ))
3541
3641
{
3542
3642
m_portList[alias] = p;
3543
- SWSS_LOG_NOTICE (" Set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3544
3643
}
3545
3644
else
3546
3645
{
3547
- SWSS_LOG_ERROR (" Failed to set port %s fec to %s" , alias.c_str (), fec_mode.c_str ());
3548
3646
it++;
3549
3647
continue ;
3550
3648
}
0 commit comments