9
9
#############################################################################
10
10
11
11
try :
12
- import sys
13
- import re
12
+ import json
14
13
import os
14
+ import re
15
+ import sys
15
16
import subprocess
16
- import json
17
+ import time
17
18
from sonic_platform_base .chassis_base import ChassisBase
18
19
from helper import APIHelper
19
20
except ImportError as e :
25
26
NUM_THERMAL = 11
26
27
NUM_SFP = 56
27
28
NUM_COMPONENT = 7
29
+
30
+ SFP_PORT_START = 1
31
+ SFP_PORT_END = 48
32
+ QSFP_PORT_START = 49
33
+ QSFP_PORT_END = 56
34
+
28
35
REBOOT_CAUSE_REG = "0xA106"
29
36
TLV_EEPROM_I2C_BUS = 0
30
37
TLV_EEPROM_I2C_ADDR = 56
31
38
32
39
BASE_CPLD_PLATFORM = "questone2bd.cpldb"
33
40
BASE_GETREG_PATH = "/sys/devices/platform/{}/getreg" .format (BASE_CPLD_PLATFORM )
34
41
42
+ SWITCH_BRD_PLATFORM = "questone2bd.switchboard"
43
+ PORT_INFO_PATH = "/sys/devices/platform/{}/SFF" .format (SWITCH_BRD_PLATFORM )
44
+ PATH_INT_SYSFS = "{0}/{port_name}/{type_prefix}_isr_flags"
45
+ PATH_INTMASK_SYSFS = "{0}/{port_name}/{type_prefix}_isr_mask"
46
+ PATH_PRS_SYSFS = "{0}/{port_name}/{prs_file_name}"
35
47
36
48
class Chassis (ChassisBase ):
37
49
"""Platform-specific Chassis class"""
@@ -40,12 +52,14 @@ def __init__(self):
40
52
ChassisBase .__init__ (self )
41
53
self ._api_helper = APIHelper ()
42
54
self .sfp_module_initialized = False
55
+ self .POLL_INTERVAL = 1
43
56
44
57
if not self ._api_helper .is_host ():
45
58
self .__initialize_fan ()
46
59
self .__initialize_psu ()
47
60
self .__initialize_eeprom ()
48
61
self .__initialize_thermals ()
62
+ self .__initialize_interrupts ()
49
63
else :
50
64
self .__initialize_components ()
51
65
@@ -85,6 +99,46 @@ def __initialize_components(self):
85
99
component = Component (index )
86
100
self ._component_list .append (component )
87
101
102
+ def __initialize_interrupts (self ):
103
+ # Initial Interrupt MASK for QSFP, SFP
104
+ sfp_info_obj = {}
105
+
106
+ present_en = 0x10
107
+ Rxlos_IntL_en = 0x01
108
+ event_mask = present_en
109
+
110
+ for index in range (NUM_SFP ):
111
+ port_num = index + 1
112
+ if port_num in range (SFP_PORT_START , SFP_PORT_END + 1 ):
113
+ port_name = "SFP{}" .format (str (port_num - SFP_PORT_START + 1 ))
114
+ port_type = "sfp"
115
+ sysfs_prs_file = "{}_modabs" .format (port_type )
116
+ elif port_num in range (QSFP_PORT_START , QSFP_PORT_END + 1 ):
117
+ port_name = "QSFP{}" .format (str (port_num - QSFP_PORT_START + 1 ))
118
+ port_type = "qsfp"
119
+ sysfs_prs_file = "{}_modprs" .format (port_type )
120
+
121
+ sfp_info_obj [index ] = {}
122
+ sfp_info_obj [index ]['intmask_sysfs' ] = PATH_INTMASK_SYSFS .format (
123
+ PORT_INFO_PATH ,
124
+ port_name = port_name ,
125
+ type_prefix = port_type )
126
+
127
+ sfp_info_obj [index ]['int_sysfs' ] = PATH_INT_SYSFS .format (
128
+ PORT_INFO_PATH ,
129
+ port_name = port_name ,
130
+ type_prefix = port_type )
131
+
132
+ sfp_info_obj [index ]['prs_sysfs' ] = PATH_PRS_SYSFS .format (
133
+ PORT_INFO_PATH ,
134
+ port_name = port_name ,
135
+ prs_file_name = sysfs_prs_file )
136
+
137
+ self ._api_helper .write_file (
138
+ sfp_info_obj [index ]["intmask_sysfs" ], hex (event_mask ))
139
+
140
+ self .sfp_info_obj = sfp_info_obj
141
+
88
142
def get_base_mac (self ):
89
143
"""
90
144
Retrieves the base MAC address for the chassis
@@ -260,3 +314,83 @@ def get_status(self):
260
314
A boolean value, True if device is operating properly, False if not
261
315
"""
262
316
return True
317
+
318
+ ##############################################################
319
+ ###################### Event methods #########################
320
+ ##############################################################
321
+
322
+ def __is_port_device_present (self , port_idx ):
323
+ prs_path = self .sfp_info_obj [port_idx ]["prs_sysfs" ]
324
+ is_present = 1 - int (self ._api_helper .read_txt_file (prs_path ))
325
+ return is_present
326
+
327
+ def __update_port_event_object (self , interrup_devices ):
328
+ port_dict = {}
329
+ event_obj = {'sfp' :port_dict }
330
+ for port_idx in interrup_devices :
331
+ device_id = str (port_idx + 1 )
332
+ port_dict [device_id ] = str (self .__is_port_device_present (port_idx ))
333
+
334
+ if len (port_dict ):
335
+ event_obj ['sfp' ] = port_dict
336
+
337
+ return event_obj
338
+
339
+ def __check_all_port_interrupt_event (self ):
340
+ interrupt_devices = {}
341
+ for i in range (NUM_SFP ):
342
+ int_sysfs = self .sfp_info_obj [i ]["int_sysfs" ]
343
+ interrupt_flags = self ._api_helper .read_txt_file (int_sysfs )
344
+ if interrupt_flags != '0x00' :
345
+ interrupt_devices [i ] = 1
346
+ return interrupt_devices
347
+
348
+ def get_change_event (self , timeout = 0 ):
349
+ """
350
+ Returns a nested dictionary containing all devices which have
351
+ experienced a change at chassis level
352
+ Args:
353
+ timeout: Timeout in milliseconds (optional). If timeout == 0,
354
+ this method will block until a change is detected.
355
+ Returns:
356
+ (bool, dict):
357
+ - True if call successful, False if not;
358
+ - A nested dictionary where key is a device type,
359
+ value is a dictionary with key:value pairs in the
360
+ format of {'device_id':'device_event'},
361
+ where device_id is the device ID for this device and
362
+ device_event,
363
+ status='1' represents device inserted,
364
+ status='0' represents device removed.
365
+ Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
366
+ indicates that fan 0 has been removed, fan 2
367
+ has been inserted and sfp 11 has been removed.
368
+ """
369
+ if timeout == 0 :
370
+ timer = self .POLL_INTERVAL
371
+ while True :
372
+ interrupt_devices = self .__check_all_port_interrupt_event ()
373
+ if len (interrupt_devices ):
374
+ break
375
+ else :
376
+ time .sleep (timer )
377
+ events_dict = self .__update_port_event_object (interrupt_devices )
378
+ return (True , events_dict )
379
+ else :
380
+ timeout = timeout / float (1000 )
381
+ timer = min (timeout , self .POLL_INTERVAL )
382
+
383
+ while True :
384
+ start_time = time .time ()
385
+ interrupt_devices = self .__check_all_port_interrupt_event ()
386
+ if len (interrupt_devices ):
387
+ break
388
+
389
+ if timeout <= 0 :
390
+ break
391
+ else :
392
+ time .sleep (timer )
393
+ elasped_time = time .time () - start_time
394
+ timeout = round (timeout - elasped_time , 3 )
395
+ events_dict = self .__update_port_event_object (interrupt_devices )
396
+ return (True , events_dict )
0 commit comments