@@ -308,6 +308,25 @@ static char* hostif_vlan_tag[] = {
308308 [SAI_HOSTIF_VLAN_TAG_ORIGINAL] = " SAI_HOSTIF_VLAN_TAG_ORIGINAL"
309309};
310310
311+ const std::unordered_map<sai_port_error_status_t , std::string> PortOperErrorEvent::db_key_errors =
312+ {
313+ // SAI port oper error status to error name mapping
314+ { SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT, " mac_local_fault" },
315+ { SAI_PORT_ERROR_STATUS_MAC_REMOTE_FAULT, " mac_remote_fault" },
316+ { SAI_PORT_ERROR_STATUS_FEC_SYNC_LOSS, " fec_sync_loss" },
317+ { SAI_PORT_ERROR_STATUS_FEC_LOSS_ALIGNMENT_MARKER, " fec_alignment_loss" },
318+ { SAI_PORT_ERROR_STATUS_HIGH_SER, " high_ser_error" },
319+ { SAI_PORT_ERROR_STATUS_HIGH_BER, " high ber_error" },
320+ { SAI_PORT_ERROR_STATUS_CRC_RATE, " crc_rate" },
321+ { SAI_PORT_ERROR_STATUS_DATA_UNIT_CRC_ERROR, " data_unit_crc_error" },
322+ { SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE, " data_unit_size" },
323+ { SAI_PORT_ERROR_STATUS_DATA_UNIT_MISALIGNMENT_ERROR, " data_unit_misalignment_error" },
324+ { SAI_PORT_ERROR_STATUS_CODE_GROUP_ERROR, " code_group_error" },
325+ { SAI_PORT_ERROR_STATUS_SIGNAL_LOCAL_ERROR, " signal_local_error" },
326+ { SAI_PORT_ERROR_STATUS_NO_RX_REACHABILITY, " no_rx_reachability" }
327+ };
328+
329+
311330// functions ----------------------------------------------------------------------------------------------------------
312331
313332static bool isValidPortTypeForLagMember (const Port& port)
@@ -509,6 +528,7 @@ bool PortsOrch::checkPathTracingCapability()
509528PortsOrch::PortsOrch (DBConnector *db, DBConnector *stateDb, vector<table_name_with_pri_t > &tableNames, DBConnector *chassisAppDb) :
510529 Orch(db, tableNames),
511530 m_portStateTable(stateDb, STATE_PORT_TABLE_NAME),
531+ m_portOpErrTable(stateDb, STATE_PORT_OPER_ERR_TABLE_NAME),
512532 port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false ),
513533 gb_port_stat_manager(true ,
514534 PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ,
@@ -808,6 +828,26 @@ void PortsOrch::initializeCpuPort()
808828 SWSS_LOG_NOTICE (" Get CPU port pid:%" PRIx64, this ->m_cpuPort .m_port_id );
809829}
810830
831+ // Creating mapping of various port oper errors for error handling
832+ void PortsOrch::initializePortOperErrors (Port &port)
833+ {
834+ SWSS_LOG_ENTER ();
835+
836+ SWSS_LOG_NOTICE (" Initialize port oper errors for port %s" , port.m_alias .c_str ());
837+
838+ for (auto & error : PortOperErrorEvent::db_key_errors)
839+ {
840+ const sai_port_error_status_t error_status = error.first ;
841+ std::string error_name = error.second ;
842+
843+ port.m_portOperErrorToEvent [error_status] = PortOperErrorEvent (error_status, error_name);
844+ SWSS_LOG_NOTICE (" Initialize port %s error %s flag=0x%" PRIx32,
845+ port.m_alias .c_str (),
846+ error_name.c_str (),
847+ error_status);
848+ }
849+ }
850+
811851void PortsOrch::initializePorts ()
812852{
813853 SWSS_LOG_ENTER ();
@@ -3351,6 +3391,26 @@ void PortsOrch::updateDbPortFlapCount(Port& port, sai_port_oper_status_t pstatus
33513391 m_portTable->set (port.m_alias , tuples);
33523392}
33533393
3394+ void PortsOrch::updateDbPortOperError (Port& port, PortOperErrorEvent *pevent)
3395+ {
3396+ SWSS_LOG_ENTER ();
3397+
3398+ auto key = pevent->getDbKey ();
3399+ vector<FieldValueTuple> tuples;
3400+ FieldValueTuple tup1 (" oper_error_status" , std::to_string (port.m_oper_error_status ));
3401+ tuples.push_back (tup1);
3402+
3403+ size_t count = pevent->getErrorCount ();
3404+ FieldValueTuple tup2 (key + " _count" , std::to_string (count));
3405+ tuples.push_back (tup2);
3406+
3407+ auto time = pevent->getEventTime ();
3408+ FieldValueTuple tup3 (key + " _time" , time);
3409+ tuples.push_back (tup3);
3410+
3411+ m_portOpErrTable.set (port.m_alias , tuples);
3412+ }
3413+
33543414void PortsOrch::updateDbPortOperStatus (const Port& port, sai_port_oper_status_t status) const
33553415{
33563416 SWSS_LOG_ENTER ();
@@ -4613,6 +4673,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
46134673 /* create host_tx_ready field in state-db */
46144674 initHostTxReadyState (p);
46154675
4676+ initializePortOperErrors (p);
4677+
46164678 // Restore admin status if the port was brought down
46174679 if (admin_status != p.m_admin_state_up )
46184680 {
@@ -8019,12 +8081,14 @@ void PortsOrch::doTask(NotificationConsumer &consumer)
80198081
80208082 for (uint32_t i = 0 ; i < count; i++)
80218083 {
8084+ Port port;
80228085 sai_object_id_t id = portoperstatus[i].port_id ;
80238086 sai_port_oper_status_t status = portoperstatus[i].port_state ;
8087+ sai_port_error_status_t port_oper_err = portoperstatus[i].port_error_status ;
80248088
8025- SWSS_LOG_NOTICE (" Get port state change notification id:%" PRIx64 " status:%d" , id, status);
8026-
8027- Port port ;
8089+ SWSS_LOG_NOTICE (" Get port state change notification id:%" PRIx64 " status:%d "
8090+ " oper_error_status:0x% " PRIx32,
8091+ id, status, port_oper_err) ;
80288092
80298093 if (!getPort (id, port))
80308094 {
@@ -8061,6 +8125,11 @@ void PortsOrch::doTask(NotificationConsumer &consumer)
80618125 {
80628126 updateDbPortOperFec (port, " N/A" );
80638127 }
8128+ } else {
8129+ if (port_oper_err)
8130+ {
8131+ updatePortErrorStatus (port, port_oper_err);
8132+ }
80648133 }
80658134
80668135 /* update m_portList */
@@ -8089,6 +8158,53 @@ void PortsOrch::doTask(NotificationConsumer &consumer)
80898158
80908159}
80918160
8161+ void PortsOrch::updatePortErrorStatus (Port &port, sai_port_error_status_t errstatus)
8162+ {
8163+ size_t errors = 0 ;
8164+ string db_port_error_name;
8165+ PortOperErrorEvent *portOperErrorEvent = nullptr ;
8166+ size_t error_count = PortOperErrorEvent::db_key_errors.size ();
8167+
8168+ SWSS_LOG_NOTICE (" Port %s error state set from 0x%" PRIx32 " -> 0x%" PRIx32,
8169+ port.m_alias .c_str (),
8170+ port.m_oper_error_status ,
8171+ errstatus);
8172+
8173+ port.m_oper_error_status = errstatus;
8174+
8175+ // Iterate through all the port oper errors
8176+ while ((errstatus >> errors) && (errors < error_count))
8177+ {
8178+ sai_port_error_status_t error_status = static_cast <sai_port_error_status_t >(errstatus & (1 << errors));
8179+
8180+ if (port.m_portOperErrorToEvent .find (error_status) == port.m_portOperErrorToEvent .end ())
8181+ {
8182+ ++errors;
8183+ continue ;
8184+ }
8185+
8186+ portOperErrorEvent = &port.m_portOperErrorToEvent [error_status];
8187+
8188+ if (portOperErrorEvent->isErrorSet (errstatus))
8189+ {
8190+ SWSS_LOG_NOTICE (" Port %s oper error event: %s occurred" ,
8191+ port.m_alias .c_str (),
8192+ portOperErrorEvent->getDbKey ().c_str ());
8193+ portOperErrorEvent->recordEventTime ();
8194+ portOperErrorEvent->incrementErrorCount ();
8195+ updateDbPortOperError (port, portOperErrorEvent);
8196+ }
8197+ else
8198+ {
8199+ SWSS_LOG_WARN (" Port %s port oper error %s not updated in DB" ,
8200+ port.m_alias .c_str (),
8201+ portOperErrorEvent->getDbKey ().c_str ());
8202+ }
8203+
8204+ ++errors;
8205+ }
8206+ }
8207+
80928208void PortsOrch::updatePortOperStatus (Port &port, sai_port_oper_status_t status)
80938209{
80948210 SWSS_LOG_NOTICE (" Port %s oper state set from %s to %s" ,
0 commit comments