7
7
import os
8
8
import time
9
9
import select
10
- from python_sdk_api .sx_api import *
10
+ if 'MLNX_PLATFORM_API_UNIT_TESTING' not in os .environ :
11
+ from python_sdk_api .sx_api import *
12
+ else :
13
+ from mock import MagicMock
14
+ class MockSxFd (object ):
15
+ fd = 99
16
+ new_sx_fd_t_p = MagicMock (return_value = MockSxFd ())
17
+ new_sx_user_channel_t_p = MagicMock ()
11
18
from sonic_py_common .logger import Logger
19
+ from .sfp import SFP
12
20
13
21
# SFP status from PMAOS register
14
22
# 0x1 plug in
22
30
SDK_SFP_STATE_ERR = 0x3
23
31
SDK_SFP_STATE_DIS = 0x4
24
32
25
- # SFP status that will be handled by XCVRD
26
- STATUS_PLUGIN = '1'
27
- STATUS_PLUGOUT = '0'
28
- STATUS_ERR_I2C_STUCK = '2'
29
- STATUS_ERR_BAD_EEPROM = '3'
30
- STATUS_ERR_UNSUPPORTED_CABLE = '4'
31
- STATUS_ERR_HIGH_TEMP = '5'
32
- STATUS_ERR_BAD_CABLE = '6'
33
-
34
33
# SFP status used in this file only, will not expose to XCVRD
35
34
# STATUS_ERROR will be mapped to different status according to the error code
36
35
STATUS_UNKNOWN = '-1'
60
59
'''
61
60
62
61
# SFP errors that will block eeprom accessing
63
- sdk_sfp_err_type_dict = {
64
- 0x2 : STATUS_ERR_I2C_STUCK ,
65
- 0x3 : STATUS_ERR_BAD_EEPROM ,
66
- 0x5 : STATUS_ERR_UNSUPPORTED_CABLE ,
67
- 0x6 : STATUS_ERR_HIGH_TEMP ,
68
- 0x7 : STATUS_ERR_BAD_CABLE
62
+ SDK_SFP_BLOCKING_ERRORS = [
63
+ 0x2 , # SFP.SFP_ERROR_BIT_I2C_STUCK,
64
+ 0x3 , # SFP.SFP_ERROR_BIT_BAD_EEPROM,
65
+ 0x5 , # SFP.SFP_ERROR_BIT_UNSUPPORTED_CABLE,
66
+ 0x6 , # SFP.SFP_ERROR_BIT_HIGH_TEMP,
67
+ 0x7 , # SFP.SFP_ERROR_BIT_BAD_CABLE
68
+ ]
69
+
70
+ SDK_ERRORS_TO_ERROR_BITS = {
71
+ 0x0 : SFP .SFP_ERROR_BIT_POWER_BUDGET_EXCEEDED ,
72
+ 0x1 : SFP .SFP_MLNX_ERROR_BIT_LONGRANGE_NON_MLNX_CABLE ,
73
+ 0x2 : SFP .SFP_ERROR_BIT_I2C_STUCK ,
74
+ 0x3 : SFP .SFP_ERROR_BIT_BAD_EEPROM ,
75
+ 0x4 : SFP .SFP_MLNX_ERROR_BIT_ENFORCE_PART_NUMBER_LIST ,
76
+ 0x5 : SFP .SFP_ERROR_BIT_UNSUPPORTED_CABLE ,
77
+ 0x6 : SFP .SFP_ERROR_BIT_HIGH_TEMP ,
78
+ 0x7 : SFP .SFP_ERROR_BIT_BAD_CABLE ,
79
+ 0x8 : SFP .SFP_MLNX_ERROR_BIT_PMD_TYPE_NOT_ENABLED ,
80
+ 0xc : SFP .SFP_MLNX_ERROR_BIT_PCIE_POWER_SLOT_EXCEEDED
81
+ }
82
+
83
+ SDK_ERRORS_TO_DESCRIPTION = {
84
+ 0x1 : SFP .SFP_MLNX_ERROR_DESCRIPTION_LONGRANGE_NON_MLNX_CABLE ,
85
+ 0x4 : SFP .SFP_MLNX_ERROR_DESCRIPTION_ENFORCE_PART_NUMBER_LIST ,
86
+ 0x8 : SFP .SFP_MLNX_ERROR_DESCRIPTION_PMD_TYPE_NOT_ENABLED ,
87
+ 0xc : SFP .SFP_MLNX_ERROR_DESCRIPTION_PCIE_POWER_SLOT_EXCEEDED
69
88
}
70
89
71
90
sfp_value_status_dict = {
72
- SDK_SFP_STATE_IN : STATUS_PLUGIN ,
73
- SDK_SFP_STATE_OUT : STATUS_PLUGOUT ,
91
+ SDK_SFP_STATE_IN : str ( SFP . SFP_STATUS_BIT_INSERTED ) ,
92
+ SDK_SFP_STATE_OUT : str ( SFP . SFP_STATUS_BIT_REMOVED ) ,
74
93
SDK_SFP_STATE_ERR : STATUS_ERROR ,
75
- SDK_SFP_STATE_DIS : STATUS_PLUGOUT ,
94
+ SDK_SFP_STATE_DIS : str ( SFP . SFP_STATUS_BIT_REMOVED ) ,
76
95
}
77
96
78
97
# system level event/error
@@ -195,7 +214,7 @@ def deinitialize(self):
195
214
delete_sx_fd_t_p (self .rx_fd_p )
196
215
delete_sx_user_channel_t_p (self .user_channel_p )
197
216
198
- def check_sfp_status (self , port_change , timeout ):
217
+ def check_sfp_status (self , port_change , error_dict , timeout ):
199
218
"""
200
219
the meaning of timeout is aligned with select.select, which has the following meaning:
201
220
0: poll, returns without blocked
@@ -233,6 +252,7 @@ def check_sfp_status(self, port_change, timeout):
233
252
break
234
253
235
254
sfp_state = sfp_value_status_dict .get (module_state , STATUS_UNKNOWN )
255
+ error_description = None
236
256
if sfp_state == STATUS_UNKNOWN :
237
257
# in the following sequence, STATUS_UNKNOWN can be returned.
238
258
# so we shouldn't raise exception here.
@@ -247,18 +267,29 @@ def check_sfp_status(self, port_change, timeout):
247
267
248
268
# If get SFP status error(0x3) from SDK, then need to read the error_type to get the detailed error
249
269
if sfp_state == STATUS_ERROR :
250
- if error_type in sdk_sfp_err_type_dict .keys ():
251
- # In SFP at error status case, need to overwrite the sfp_state with the exact error code
252
- sfp_state = sdk_sfp_err_type_dict [error_type ]
253
- else :
254
- # For errors don't block the eeprom accessing, we don't report it to XCVRD
255
- logger .log_info ("SFP error on port but not blocking eeprom read, error_type {}" .format (error_type ))
256
- found += 1
270
+ sfp_state_bits = SDK_ERRORS_TO_ERROR_BITS .get (error_type )
271
+ if sfp_state_bits is None :
272
+ logger .log_error ("Unrecognized error {} detected on ports {}" .format (error_type , port_list ))
273
+ found += 1
257
274
continue
258
275
276
+ if error_type in SDK_SFP_BLOCKING_ERRORS :
277
+ # In SFP at error status case, need to overwrite the sfp_state with the exact error code
278
+ sfp_state_bits |= SFP .SFP_ERROR_BIT_BLOCKING
279
+
280
+ # An error should be always set along with 'INSERTED'
281
+ sfp_state_bits |= SFP .SFP_STATUS_BIT_INSERTED
282
+
283
+ # For vendor specific errors, the description should be returned as well
284
+ error_description = SDK_ERRORS_TO_DESCRIPTION .get (error_type )
285
+
286
+ sfp_state = str (sfp_state_bits )
287
+
259
288
for port in port_list :
260
289
logger .log_info ("SFP on port {} state {}" .format (port , sfp_state ))
261
290
port_change [port + 1 ] = sfp_state
291
+ if error_description :
292
+ error_dict [port + 1 ] = error_description
262
293
found += 1
263
294
264
295
return found != 0
0 commit comments