Skip to content

Commit fceef2e

Browse files
authored
[chassis][voq] Clear fabric counters queue/port (#2789)
Added two clear commands for fabric counters queue and fabric counters port. sonic-clear fabriccountersport sonic-clear fabriccountersqueue By issuing the command, the fabric counters are clear and saved. An example is as follow. # show fabric counters port ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR ------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- ---------- ... 0 49 up 1 244 0 0 0 2 2,372,752,496 0 0 50 up 2 315 1 135 0 4 2,522,457,120 4 ... # sonic-clear fabriccountersport Clear and update saved counters port # show fabric counters port ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR ------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- ------------ ... 0 49 up 0 0 0 0 0 0 0 0 0 50 up 0 0 0 0 0 0 0 Signed-off-by: Jie Feng <[email protected]>
1 parent 659ba24 commit fceef2e

File tree

3 files changed

+268
-44
lines changed

3 files changed

+268
-44
lines changed

clear/main.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,18 @@ def queuecounters():
181181
command = ["queuestat", "-c"]
182182
run_command(command)
183183

184+
@cli.command()
185+
def fabriccountersqueue():
186+
"""Clear fabric queue counters"""
187+
command = "fabricstat -C -q"
188+
run_command(command)
189+
190+
@cli.command()
191+
def fabriccountersport():
192+
"""Clear fabric port counters"""
193+
command = "fabricstat -C"
194+
run_command(command)
195+
184196
@cli.command()
185197
def pfccounters():
186198
"""Clear pfc counters"""

scripts/fabricstat

Lines changed: 127 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import argparse
44
from collections import OrderedDict, namedtuple
5+
import json
56
import os
67
import sys
78

89
from utilities_common import constants
10+
from utilities_common.cli import json_serial, UserCache
11+
from utilities_common.netstat import format_number_with_comma, table_as_json, ns_diff, format_prate
912
from natsort import natsorted
1013
from tabulate import tabulate
1114
from sonic_py_common import multi_asic
@@ -32,6 +35,10 @@ FABRIC_PORT_STATUS_TABLE_PREFIX = APP_FABRIC_PORT_TABLE_NAME+"|"
3235
FABRIC_PORT_STATUS_FIELD = "STATUS"
3336
STATUS_NA = 'N/A'
3437

38+
cnstat_dir = 'N/A'
39+
cnstat_fqn_file_port = 'N/A'
40+
cnstat_fqn_file_queue = 'N/A'
41+
3542
class FabricStat(object):
3643
def __init__(self, namespace):
3744
self.db = None
@@ -78,6 +85,12 @@ class FabricStat(object):
7885
"""
7986
assert False, 'Need to override this method'
8087

88+
def save_fresh_stats(self):
89+
"""
90+
Get stat for each port and save.
91+
"""
92+
assert False, 'Need to override this method'
93+
8194
def cnstat_print(self, cnstat_dict, errors_only=False):
8295
"""
8396
Print the counter stat.
@@ -115,6 +128,24 @@ class FabricPortStat(FabricStat):
115128
cnstat_dict[port_name] = PortStat._make(cntr)
116129
return cnstat_dict
117130

131+
def save_fresh_stats(self):
132+
# Get stat for each port and save
133+
counter_port_name_map = self.db.get_all(self.db.COUNTERS_DB, COUNTERS_FABRIC_PORT_NAME_MAP)
134+
if counter_port_name_map is None:
135+
return
136+
cnstat_dict = self.get_cnstat()
137+
asic_name = '0'
138+
if self.namespace:
139+
asic_name = multi_asic.get_asic_id_from_name(self.namespace)
140+
try:
141+
cnstat_fqn_file_port_name = cnstat_fqn_file_port + asic_name
142+
json.dump(cnstat_dict, open(cnstat_fqn_file_port_name, 'w'), default=json_serial)
143+
except IOError as e:
144+
print(e.errno, e)
145+
sys.exit(e.errno)
146+
else:
147+
print("Clear and update saved counters port")
148+
118149
def cnstat_print(self, cnstat_dict, errors_only=False):
119150
if len(cnstat_dict) == 0:
120151
print("Counters %s empty" % self.namespace)
@@ -127,19 +158,44 @@ class FabricPortStat(FabricStat):
127158
asic_name = '0'
128159
if self.namespace:
129160
asic_name = multi_asic.get_asic_id_from_name(self.namespace)
161+
162+
cnstat_fqn_file_port_name = cnstat_fqn_file_port + asic_name
163+
cnstat_cached_dict = {}
164+
if os.path.isfile(cnstat_fqn_file_port_name):
165+
try:
166+
cnstat_cached_dict = json.load(open(cnstat_fqn_file_port_name, 'r'))
167+
except IOError as e:
168+
print(e.errno, e)
169+
130170
for key, data in cnstat_dict.items():
131171
port_id = key[len(PORT_NAME_PREFIX):]
172+
port_name = "PORT" + port_id
173+
# The content in the for each port:
174+
# "IN_CELL, IN_OCTET, OUT_CELL, OUT_OCTET, CRC, FEC_CORRECTABLE, FEC_UNCORRECTABL, SYMBOL_ERR"
175+
# e.g. PORT76 ['0', '0', '36', '6669', '0', '13', '302626', '3']
176+
# Now, set default saved values to 0
177+
diff_cached = ['0', '0', '0', '0', '0', '0', '0', '0']
178+
if port_name in cnstat_cached_dict:
179+
diff_cached = cnstat_cached_dict.get(port_name)
180+
132181
if errors_only:
133182
header = portstat_header_errors_only
134183
table.append((asic_name, port_id, self.get_port_state(key),
135-
data.crc, data.fec_correctable, data.fec_uncorrectable,
136-
data.symbol_err))
184+
ns_diff(data.crc, diff_cached[4]),
185+
ns_diff(data.fec_correctable, diff_cached[5]),
186+
ns_diff(data.fec_uncorrectable, diff_cached[6]),
187+
ns_diff(data.symbol_err, diff_cached[7])))
137188
else:
138189
header = portstat_header_all
139190
table.append((asic_name, port_id, self.get_port_state(key),
140-
data.in_cell, data.in_octet, data.out_cell, data.out_octet,
141-
data.crc, data.fec_correctable, data.fec_uncorrectable,
142-
data.symbol_err))
191+
ns_diff(data.in_cell, diff_cached[0]),
192+
ns_diff(data.in_octet, diff_cached[1]),
193+
ns_diff(data.out_cell, diff_cached[2]),
194+
ns_diff(data.out_octet, diff_cached[3]),
195+
ns_diff(data.crc, diff_cached[4]),
196+
ns_diff(data.fec_correctable, diff_cached[5]),
197+
ns_diff(data.fec_uncorrectable, diff_cached[6]),
198+
ns_diff(data.symbol_err, diff_cached[7])))
143199

144200
print(tabulate(table, header, tablefmt='simple', stralign='right'))
145201
print()
@@ -166,6 +222,24 @@ class FabricQueueStat(FabricStat):
166222
cnstat_dict[port_queue_name] = QueueStat._make(cntr)
167223
return cnstat_dict
168224

225+
def save_fresh_stats(self):
226+
# Get stat for each port and save
227+
counter_port_name_map = self.db.get_all(self.db.COUNTERS_DB, COUNTERS_FABRIC_PORT_NAME_MAP)
228+
if counter_port_name_map is None:
229+
return
230+
cnstat_dict = self.get_cnstat()
231+
asic_name = '0'
232+
if self.namespace:
233+
asic_name = multi_asic.get_asic_id_from_name(self.namespace)
234+
try:
235+
cnstat_fqn_file_queue_name = cnstat_fqn_file_queue + asic_name
236+
json.dump(cnstat_dict, open(cnstat_fqn_file_queue_name, 'w'), default=json_serial)
237+
except IOError as e:
238+
print(e.errno, e)
239+
sys.exit(e.errno)
240+
else:
241+
print("Clear and update saved counters queue")
242+
169243
def cnstat_print(self, cnstat_dict, errors_only=False):
170244
if len(cnstat_dict) == 0:
171245
print("Counters %s empty" % self.namespace)
@@ -177,11 +251,29 @@ class FabricQueueStat(FabricStat):
177251
asic_name = '0'
178252
if self.namespace:
179253
asic_name = multi_asic.get_asic_id_from_name(self.namespace)
254+
255+
cnstat_fqn_file_queue_name = cnstat_fqn_file_queue + asic_name
256+
cnstat_cached_dict={}
257+
if os.path.isfile(cnstat_fqn_file_queue_name):
258+
try:
259+
cnstat_cached_dict = json.load(open(cnstat_fqn_file_queue_name, 'r'))
260+
except IOError as e:
261+
print(e.errno, e)
262+
180263
for key, data in cnstat_dict.items():
181264
port_name, queue_id = key.split(':')
265+
# The content of saved counters queue for each port:
266+
# portName:queueId CURRENT_LEVEL, WATERMARK_LEVEL, CURRENT_BYTE
267+
# e.g. PORT90:0 ['N/A', 'N/A', 'N/A']
268+
# Now, set default saved values to 0
269+
diff_cached = ['0', '0', '0']
270+
if key in cnstat_cached_dict:
271+
diff_cached = cnstat_cached_dict.get(key)
182272
port_id = port_name[len(PORT_NAME_PREFIX):]
183273
table.append((asic_name, port_id, self.get_port_state(port_name), queue_id,
184-
data.curbyte, data.curlevel, data.watermarklevel))
274+
ns_diff(data.curbyte, diff_cached[2]),
275+
ns_diff(data.curlevel, diff_cached[0]),
276+
ns_diff(data.watermarklevel, diff_cached[1])))
185277

186278
print(tabulate(table, queuestat_header, tablefmt='simple', stralign='right'))
187279
print()
@@ -214,6 +306,10 @@ class FabricReachability(FabricStat):
214306
return
215307

216308
def main():
309+
global cnstat_dir
310+
global cnstat_fqn_file_port
311+
global cnstat_fqn_file_queue
312+
217313
parser = argparse.ArgumentParser(description='Display the fabric port state and counters',
218314
formatter_class=argparse.RawTextHelpFormatter,
219315
epilog="""
@@ -223,19 +319,40 @@ Examples:
223319
fabricstat -p -n asic0 -e
224320
fabricstat -q
225321
fabricstat -q -n asic0
322+
fabricstat -C
323+
fabricstat -D
226324
""")
227325

228326
parser.add_argument('-q','--queue', action='store_true', help='Display fabric queue stat, otherwise port stat')
229327
parser.add_argument('-r','--reachability', action='store_true', help='Display reachability, otherwise port stat')
230328
parser.add_argument('-n','--namespace', default=None, help='Display fabric ports counters for specific namespace')
231329
parser.add_argument('-e', '--errors', action='store_true', help='Display errors')
330+
parser.add_argument('-C','--clear', action='store_true', help='Copy & clear fabric counters')
331+
parser.add_argument('-D','--delete', action='store_true', help='Delete saved stats')
232332

233333
args = parser.parse_args()
234334
queue = args.queue
235335
reachability = args.reachability
236336
namespace = args.namespace
237337
errors_only = args.errors
238338

339+
save_fresh_stats = args.clear
340+
delete_stats = args.delete
341+
342+
cache = UserCache()
343+
344+
cnstat_dir = cache.get_directory()
345+
346+
cnstat_file = "fabricstatport"
347+
cnstat_fqn_file_port = os.path.join(cnstat_dir, cnstat_file)
348+
349+
cnstat_file = "fabricstatqueue"
350+
cnstat_fqn_file_queue = os.path.join(cnstat_dir, cnstat_file)
351+
352+
if delete_stats:
353+
cache.remove()
354+
sys.exit(0)
355+
239356
def nsStat(ns, errors_only):
240357
if queue:
241358
stat = FabricQueueStat(ns)
@@ -246,7 +363,10 @@ Examples:
246363
else:
247364
stat = FabricPortStat(ns)
248365
cnstat_dict = stat.get_cnstat_dict()
249-
stat.cnstat_print(cnstat_dict, errors_only)
366+
if save_fresh_stats:
367+
stat.save_fresh_stats()
368+
else:
369+
stat.cnstat_print(cnstat_dict, errors_only)
250370

251371
if namespace is None:
252372
# All asics or all fabric asics

0 commit comments

Comments
 (0)