15
15
import threading
16
16
import time
17
17
18
- from enum import Enum
19
18
from sonic_py_common import daemon_base , device_info , logger
20
19
from sonic_py_common import multi_asic
21
20
from swsscommon import swsscommon
22
21
22
+ from .xcvrd_utilities import sfp_status_helper
23
23
from .xcvrd_utilities import y_cable_helper
24
24
except ImportError as e :
25
25
raise ImportError (str (e ) + " - required module not found" )
43
43
TIME_FOR_SFP_READY_SECS = 1
44
44
XCVRD_MAIN_THREAD_SLEEP_SECS = 60
45
45
46
- # SFP status definition, shall be aligned with the definition in get_change_event() of ChassisBase
47
- SFP_STATUS_REMOVED = '0'
48
- SFP_STATUS_INSERTED = '1'
49
-
50
- # SFP error code enum, new elements can be added to the enum if new errors need to be supported.
51
- SFP_STATUS_ERR_ENUM = Enum ('SFP_STATUS_ERR_ENUM' , ['SFP_STATUS_ERR_I2C_STUCK' , 'SFP_STATUS_ERR_BAD_EEPROM' ,
52
- 'SFP_STATUS_ERR_UNSUPPORTED_CABLE' , 'SFP_STATUS_ERR_HIGH_TEMP' ,
53
- 'SFP_STATUS_ERR_BAD_CABLE' ], start = 2 )
54
-
55
- # Convert the error code to string and store them in a set for convenience
56
- errors_block_eeprom_reading = set (str (error_code .value ) for error_code in SFP_STATUS_ERR_ENUM )
57
-
58
46
EVENT_ON_ALL_SFP = '-1'
59
47
# events definition
60
48
SYSTEM_NOT_READY = 'system_not_ready'
@@ -188,11 +176,13 @@ def _wrapper_get_transceiver_change_event(timeout):
188
176
if platform_chassis is not None :
189
177
try :
190
178
status , events = platform_chassis .get_change_event (timeout )
191
- sfp_events = events ['sfp' ]
192
- return status , sfp_events
179
+ sfp_events = events .get ('sfp' )
180
+ sfp_errors = events .get ('sfp_error' )
181
+ return status , sfp_events , sfp_errors
193
182
except NotImplementedError :
194
183
pass
195
- return platform_sfputil .get_transceiver_change_event (timeout )
184
+ status , events = platform_sfputil .get_transceiver_change_event (timeout )
185
+ return status , events , None
196
186
197
187
198
188
def _wrapper_get_sfp_type (physical_port ):
@@ -203,6 +193,14 @@ def _wrapper_get_sfp_type(physical_port):
203
193
pass
204
194
return None
205
195
196
+
197
+ def _wrapper_get_sfp_error_description (physical_port ):
198
+ if platform_chassis :
199
+ try :
200
+ return platform_chassis .get_sfp (physical_port ).get_error_description ()
201
+ except NotImplementedError :
202
+ pass
203
+ return None
206
204
# Remove unnecessary unit from the raw data
207
205
208
206
@@ -553,7 +551,7 @@ def recover_missing_sfp_table_entries(sfp_util, int_tbl, status_tbl, stop_event)
553
551
continue
554
552
555
553
keys = int_tbl [asic_index ].getKeys ()
556
- if logical_port_name not in keys and not detect_port_in_error_status (logical_port_name , status_tbl [asic_index ]):
554
+ if logical_port_name not in keys and not sfp_status_helper . detect_port_in_error_status (logical_port_name , status_tbl [asic_index ]):
557
555
post_port_sfp_info_to_db (logical_port_name , int_tbl [asic_index ], transceiver_dict , stop_event )
558
556
559
557
@@ -791,30 +789,17 @@ def waiting_time_compensation_with_sleep(time_start, time_to_wait):
791
789
# Update port SFP status table on receiving SFP change event
792
790
793
791
794
- def update_port_transceiver_status_table (logical_port_name , status_tbl , status ):
795
- fvs = swsscommon .FieldValuePairs ([('status' , status )])
792
+ def update_port_transceiver_status_table (logical_port_name , status_tbl , status , error_descriptions = 'N/A' ):
793
+ fvs = swsscommon .FieldValuePairs ([('status' , status ), ( 'error' , error_descriptions ) ])
796
794
status_tbl .set (logical_port_name , fvs )
797
795
796
+
798
797
# Delete port from SFP status table
799
798
800
799
801
800
def delete_port_from_status_table (logical_port_name , status_tbl ):
802
801
status_tbl ._del (logical_port_name )
803
802
804
- # Check whether port in error status
805
-
806
-
807
- def detect_port_in_error_status (logical_port_name , status_tbl ):
808
- rec , fvp = status_tbl .get (logical_port_name )
809
- if rec :
810
- status_dict = dict (fvp )
811
- if status_dict ['status' ] in errors_block_eeprom_reading :
812
- return True
813
- else :
814
- return False
815
- else :
816
- return False
817
-
818
803
# Init TRANSCEIVER_STATUS table
819
804
820
805
@@ -844,16 +829,16 @@ def init_port_sfp_status_tbl(stop_event=threading.Event()):
844
829
physical_port_list = logical_port_name_to_physical_port_list (logical_port_name )
845
830
if physical_port_list is None :
846
831
helper_logger .log_error ("No physical ports found for logical port '{}'" .format (logical_port_name ))
847
- update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], SFP_STATUS_REMOVED )
832
+ update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], sfp_status_helper . SFP_STATUS_REMOVED )
848
833
849
834
for physical_port in physical_port_list :
850
835
if stop_event .is_set ():
851
836
break
852
837
853
838
if not _wrapper_get_presence (physical_port ):
854
- update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], SFP_STATUS_REMOVED )
839
+ update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], sfp_status_helper . SFP_STATUS_REMOVED )
855
840
else :
856
- update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], SFP_STATUS_INSERTED )
841
+ update_port_transceiver_status_table (logical_port_name , status_tbl [asic_index ], sfp_status_helper . SFP_STATUS_INSERTED )
857
842
858
843
#
859
844
# Helper classes ===============================================================
@@ -892,7 +877,7 @@ def task_worker(self, y_cable_presence):
892
877
logger .log_warning ("Got invalid asic index for {}, ignored" .format (logical_port_name ))
893
878
continue
894
879
895
- if not detect_port_in_error_status (logical_port_name , status_tbl [asic_index ]):
880
+ if not sfp_status_helper . detect_port_in_error_status (logical_port_name , status_tbl [asic_index ]):
896
881
post_port_dom_info_to_db (logical_port_name , dom_tbl [asic_index ], self .task_stopping_event )
897
882
post_port_dom_threshold_info_to_db (logical_port_name , dom_tbl [asic_index ], self .task_stopping_event )
898
883
if y_cable_presence [0 ] is True :
@@ -1035,7 +1020,7 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
1035
1020
while not stopping_event .is_set ():
1036
1021
next_state = state
1037
1022
time_start = time .time ()
1038
- status , port_dict = _wrapper_get_transceiver_change_event (timeout )
1023
+ status , port_dict , error_dict = _wrapper_get_transceiver_change_event (timeout )
1039
1024
if not port_dict :
1040
1025
continue
1041
1026
helper_logger .log_debug ("Got event {} {} in state {}" .format (status , port_dict , state ))
@@ -1095,11 +1080,11 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
1095
1080
logger .log_warning ("Got invalid asic index for {}, ignored" .format (logical_port ))
1096
1081
continue
1097
1082
1098
- if value == SFP_STATUS_INSERTED :
1083
+ if value == sfp_status_helper . SFP_STATUS_INSERTED :
1099
1084
helper_logger .log_info ("Got SFP inserted event" )
1100
1085
# A plugin event will clear the error state.
1101
1086
update_port_transceiver_status_table (
1102
- logical_port , status_tbl [asic_index ], SFP_STATUS_INSERTED )
1087
+ logical_port , status_tbl [asic_index ], sfp_status_helper . SFP_STATUS_INSERTED )
1103
1088
helper_logger .log_info ("receive plug in and update port sfp status table." )
1104
1089
rc = post_port_sfp_info_to_db (logical_port , int_tbl [asic_index ], transceiver_dict )
1105
1090
# If we didn't get the sfp info, assuming the eeprom is not ready, give a try again.
@@ -1111,28 +1096,36 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
1111
1096
post_port_dom_threshold_info_to_db (logical_port , dom_tbl [asic_index ])
1112
1097
notify_media_setting (logical_port , transceiver_dict , app_port_tbl [asic_index ])
1113
1098
transceiver_dict .clear ()
1114
- elif value == SFP_STATUS_REMOVED :
1099
+ elif value == sfp_status_helper . SFP_STATUS_REMOVED :
1115
1100
helper_logger .log_info ("Got SFP removed event" )
1116
1101
update_port_transceiver_status_table (
1117
- logical_port , status_tbl [asic_index ], SFP_STATUS_REMOVED )
1118
- helper_logger .log_info ("receive plug out and pdate port sfp status table." )
1102
+ logical_port , status_tbl [asic_index ], sfp_status_helper . SFP_STATUS_REMOVED )
1103
+ helper_logger .log_info ("receive plug out and update port sfp status table." )
1119
1104
del_port_sfp_dom_info_from_db (logical_port , int_tbl [asic_index ], dom_tbl [asic_index ])
1120
- elif value in errors_block_eeprom_reading :
1121
- helper_logger .log_info ("Got SFP Error event" )
1122
- # Add port to error table to stop accessing eeprom of it
1123
- # If the port already in the error table, the stored error code will
1124
- # be updated to the new one.
1125
- update_port_transceiver_status_table (logical_port , status_tbl [asic_index ], value )
1126
- helper_logger .log_info ("receive error update port sfp status table." )
1127
- # In this case EEPROM is not accessible, so remove the DOM info
1128
- # since it will be outdated if long time no update.
1129
- # but will keep the interface info in the DB since it static.
1130
- del_port_sfp_dom_info_from_db (logical_port , None , dom_tbl [asic_index ])
1131
-
1132
1105
else :
1133
- # SFP return unkown event, just ignore for now.
1134
- helper_logger .log_warning ("Got unknown event {}, ignored" .format (value ))
1135
- continue
1106
+ try :
1107
+ error_bits = int (value )
1108
+ helper_logger .log_info ("Got SFP error event {}" .format (value ))
1109
+
1110
+ error_descriptions = sfp_status_helper .fetch_generic_error_description (error_bits )
1111
+
1112
+ if sfp_status_helper .has_vendor_specific_error (error_bits ):
1113
+ if error_dict :
1114
+ vendor_specific_error_description = error_dict .get (key )
1115
+ else :
1116
+ vendor_specific_error_description = _wrapper_get_sfp_error_description (key )
1117
+ error_descriptions .append (vendor_specific_error_description )
1118
+
1119
+ # Add error info to database
1120
+ # Any existing error will be replaced by the new one.
1121
+ update_port_transceiver_status_table (logical_port , status_tbl [asic_index ], value , '|' .join (error_descriptions ))
1122
+ helper_logger .log_info ("Receive error update port sfp status table." )
1123
+ # In this case EEPROM is not accessible. The DOM info will be removed since it can be out-of-date.
1124
+ # The interface info remains in the DB since it is static.
1125
+ if sfp_status_helper .is_error_block_eeprom_reading (error_bits ):
1126
+ del_port_sfp_dom_info_from_db (logical_port , None , dom_tbl [asic_index ])
1127
+ except (TypeError , ValueError ) as e :
1128
+ logger .log_error ("Got unrecognized event {}, ignored" .format (value ))
1136
1129
1137
1130
# Since ports could be connected to a mux cable, if there is a change event process the change for being on a Y cable Port
1138
1131
y_cable_helper .change_ports_status_for_y_cable_change_event (
0 commit comments