22import utilities_common .cli as clicommon
33import utilities_common .multi_asic as multi_asic_util
44from sonic_py_common import multi_asic
5- from swsscommon .swsscommon import SonicV2Connector , ConfigDBConnector
5+ from swsscommon .swsscommon import SonicV2Connector , ConfigDBConnector , APP_FABRIC_PORT_TABLE_NAME
6+
7+ FABRIC_PORT_STATUS_TABLE_PREFIX = APP_FABRIC_PORT_TABLE_NAME + "|"
8+
69
710#
811# 'config fabric ...'
@@ -66,19 +69,13 @@ def isolate(portid, namespace):
6669#
6770@port .command ()
6871@click .argument ('portid' , metavar = '<portid>' , required = True )
72+ @click .option ('-f' , '--force' , is_flag = True , default = False , help = 'Force to unisolate a link even if it is auto isolated.' )
6973@multi_asic_util .multi_asic_click_option_namespace
70- def unisolate (portid , namespace ):
74+ def unisolate (portid , namespace , force ):
7175 """FABRIC PORT unisolate <portid>"""
7276
7377 ctx = click .get_current_context ()
7478
75- if not portid .isdigit ():
76- ctx .fail ("Invalid portid" )
77-
78- n_asics = multi_asic .get_num_asics ()
79- if n_asics > 1 and namespace is None :
80- ctx .fail ('Must specify asic' )
81-
8279 # Connect to config database
8380 config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
8481 config_db .connect ()
@@ -87,6 +84,37 @@ def unisolate(portid, namespace):
8784 state_db = SonicV2Connector (use_unix_socket_path = True , namespace = namespace )
8885 state_db .connect (state_db .STATE_DB , False )
8986
87+ n_asics = multi_asic .get_num_asics ()
88+ if n_asics > 1 and namespace is None :
89+ ctx .fail ( 'Must specify asic' )
90+
91+ # If "all" is specified then unisolate all ports.
92+ if portid == "all" :
93+ port_keys = state_db .keys (state_db .STATE_DB , FABRIC_PORT_STATUS_TABLE_PREFIX + '*' )
94+ for port_key in port_keys :
95+ port_data = state_db .get_all (state_db .STATE_DB , port_key )
96+ if "REMOTE_PORT" in port_data :
97+ port_number = int ( port_key .replace ( "FABRIC_PORT_TABLE|PORT" , "" ) )
98+
99+ # Make sure configuration data exists
100+ portName = f'Fabric{ port_number } '
101+ portConfigData = config_db .get_all (config_db .CONFIG_DB , "FABRIC_PORT|" + portName )
102+ if not bool ( portConfigData ):
103+ ctx .fail ( "Fabric monitor configuration data not present" )
104+
105+ # Update entry
106+ config_db .mod_entry ( "FABRIC_PORT" , portName , {'isolateStatus' : False } )
107+ if force :
108+ forceShutCnt = int ( portConfigData ['forceUnisolateStatus' ] )
109+ forceShutCnt += 1
110+ config_db .mod_entry ( "FABRIC_PORT" , portName ,
111+ {'forceUnisolateStatus' : forceShutCnt })
112+
113+ return
114+
115+ if not portid .isdigit ():
116+ ctx .fail ( "Invalid portid" )
117+
90118 # check if the port is actually in use
91119 portName = f'PORT{ portid } '
92120 portStateData = state_db .get_all (state_db .STATE_DB , "FABRIC_PORT_TABLE|" + portName )
@@ -102,6 +130,15 @@ def unisolate(portid, namespace):
102130 # Update entry
103131 config_db .mod_entry ("FABRIC_PORT" , portName , {'isolateStatus' : False })
104132
133+ if force :
134+ forceShutCnt = int ( portConfigData ['forceUnisolateStatus' ] )
135+ forceShutCnt += 1
136+ config_db .mod_entry ( "FABRIC_PORT" , portName ,
137+ {'forceUnisolateStatus' : forceShutCnt })
138+
139+ click .echo ("Force unisolate the link." )
140+ click .echo ("It will clear all fabric link monitoring status for this link!" )
141+
105142#
106143# 'config fabric port monitor ...'
107144#
@@ -157,6 +194,39 @@ def error_threshold(crccells, rxcells, namespace):
157194 config_db .mod_entry ("FABRIC_MONITOR" , "FABRIC_MONITOR_DATA" ,
158195 {'monErrThreshCrcCells' : crccells , 'monErrThreshRxCells' : rxcells })
159196
197+ def setFabricPortMonitorState (state , namespace , ctx ):
198+ """ set the fabric port monitor state"""
199+ # Connect to config database
200+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
201+ config_db .connect ()
202+
203+ # Make sure configuration data exists
204+ monitorData = config_db .get_all (config_db .CONFIG_DB , "FABRIC_MONITOR|FABRIC_MONITOR_DATA" )
205+ if not bool (monitorData ):
206+ ctx .fail ("Fabric monitor configuration data not present" )
207+
208+ # Update entry
209+ config_db .mod_entry ("FABRIC_MONITOR" , "FABRIC_MONITOR_DATA" ,
210+ {'monState' : state })
211+
212+ #
213+ # 'config fabric port montior state <enable/disable>'
214+ #
215+ @monitor .command ()
216+ @click .argument ('state' , metavar = '<state>' , required = True )
217+ @multi_asic_util .multi_asic_click_option_namespace
218+ def state (state , namespace ):
219+ """FABRIC PORT MONITOR STATE configuration tasks"""
220+ ctx = click .get_current_context ()
221+
222+ n_asics = multi_asic .get_num_asics ()
223+ if n_asics > 1 and namespace is None :
224+ ns_list = multi_asic .get_namespace_list ()
225+ for namespace in ns_list :
226+ setFabricPortMonitorState (state , namespace , ctx )
227+ else :
228+ setFabricPortMonitorState (state , namespace , ctx )
229+
160230#
161231# 'config fabric port monitor poll ...'
162232#
@@ -245,3 +315,45 @@ def recovery(pollcount, namespace):
245315 {"monPollThreshRecovery" : pollcount })
246316
247317
318+ #
319+ # 'config fabric monitor ...'
320+ #
321+ @fabric .group (cls = clicommon .AbbreviationGroup , name = 'monitor' )
322+ def capacity_monitor ():
323+ """FABRIC MONITOR configuration tasks"""
324+ pass
325+
326+ #
327+ # 'config fabric monitor capacity...'
328+ #
329+ @capacity_monitor .group (cls = clicommon .AbbreviationGroup )
330+ def capacity ():
331+ """FABRIC MONITOR CAPACITY configuration tasks"""
332+ pass
333+
334+ #
335+ # 'config fabric monitor capacity threshold <capcityThresh>'
336+ #
337+ @capacity .command ()
338+ @click .argument ('capacitythreshold' , metavar = '<capacityThreshold>' , required = True , type = int )
339+ def threshold (capacitythreshold ):
340+ """FABRIC CAPACITY MONITOR THRESHOLD configuration tasks"""
341+ ctx = click .get_current_context ()
342+
343+ if capacitythreshold < 5 or capacitythreshold > 250 :
344+ ctx .fail ("threshold must be in range 5...250" )
345+
346+ namespaces = multi_asic .get_namespace_list ()
347+ for idx , namespace in enumerate (namespaces , start = 1 ):
348+ # Connect to config database
349+ config_db = ConfigDBConnector (use_unix_socket_path = True , namespace = namespace )
350+ config_db .connect ()
351+
352+ # Make sure configuration data exists
353+ monitorData = config_db .get_all (config_db .CONFIG_DB , "FABRIC_MONITOR|FABRIC_MONITOR_DATA" )
354+ if not bool (monitorData ):
355+ ctx .fail ("Fabric monitor configuration data not present" )
356+
357+ # Update entry
358+ config_db .mod_entry ("FABRIC_MONITOR" , "FABRIC_MONITOR_DATA" ,
359+ {"monCapacityThreshWarn" : capacitythreshold })
0 commit comments