diff --git a/scripts/fabricstat b/scripts/fabricstat index fd2abc6a3..5d7148cd8 100755 --- a/scripts/fabricstat +++ b/scripts/fabricstat @@ -35,6 +35,11 @@ PORT_NAME_PREFIX = 'PORT' COUNTER_TABLE_PREFIX = COUNTERS_TABLE+":" FABRIC_PORT_STATUS_TABLE_PREFIX = APP_FABRIC_PORT_TABLE_NAME+"|" FABRIC_PORT_STATUS_FIELD = "STATUS" +# ISOLATE_REASON values from orchagent fabricportsorch.cpp: +# none | config | permanent | crc_errors | fec_uncorrectable | +# crc_errors,fec_uncorrectable | auto | unknown | +# link_event_counters_reset | admin_unisolate +FABRIC_PORT_ISOLATE_REASON_FIELD = "ISOLATE_REASON" STATUS_NA = 'N/A' cnstat_dir = 'N/A' @@ -119,6 +124,29 @@ portstat_header_all = ['ASIC', 'PORT', 'STATE', portstat_header_errors_only = ['ASIC', 'PORT', 'STATE', 'CRC', 'FEC_CORRECTABLE', 'FEC_UNCORRECTABLE', 'SYMBOL_ERR'] + +def _fabric_port_counter_diff_int(newstr, oldstr): + """Same numeric delta as ns_diff (non-raw); None if new is N/A.""" + if newstr == STATUS_NA: + return None + if oldstr == STATUS_NA: + oldstr = '0' + try: + new, old = int(newstr), int(oldstr) + except (TypeError, ValueError): + return 0 + return max(0, new - old) + + +def _fabric_port_row_has_nonzero_counter(diffs): + for x in diffs: + if x is None: + return True + if x != 0: + return True + return False + + class FabricPortStat(FabricStat): def get_cnstat(self): counter_port_name_map = self.db.get_all(self.db.COUNTERS_DB, COUNTERS_FABRIC_PORT_NAME_MAP) @@ -149,7 +177,7 @@ class FabricPortStat(FabricStat): else: print("Clear and update saved counters port") - def cnstat_print(self, cnstat_dict, errors_only=False): + def cnstat_print(self, cnstat_dict, errors_only=False, nonzero_only=False): if len(cnstat_dict) == 0: print("Counters %s empty" % self.namespace) return @@ -178,11 +206,20 @@ class FabricPortStat(FabricStat): # e.g. PORT76 ['0', '0', '36', '6669', '0', '13', '302626', '3'] # Now, set default saved values to 0 diff_cached = ['0', '0', '0', '0', '0', '0', '0', '0'] + # If the stats was not cleared before, the cnstat_cached_dict will be empty if port_name in cnstat_cached_dict: diff_cached = cnstat_cached_dict.get(port_name) if errors_only: header = portstat_header_errors_only + diffs = [ + _fabric_port_counter_diff_int(data.crc, diff_cached[4]), + _fabric_port_counter_diff_int(data.fec_correctable, diff_cached[5]), + _fabric_port_counter_diff_int(data.fec_uncorrectable, diff_cached[6]), + _fabric_port_counter_diff_int(data.symbol_err, diff_cached[7]), + ] + if nonzero_only and not _fabric_port_row_has_nonzero_counter(diffs): + continue table.append((asic_name, port_id, self.get_port_state(key), ns_diff(data.crc, diff_cached[4]), ns_diff(data.fec_correctable, diff_cached[5]), @@ -190,6 +227,18 @@ class FabricPortStat(FabricStat): ns_diff(data.symbol_err, diff_cached[7]))) else: header = portstat_header_all + diffs = [ + _fabric_port_counter_diff_int(data.in_cell, diff_cached[0]), + _fabric_port_counter_diff_int(data.in_octet, diff_cached[1]), + _fabric_port_counter_diff_int(data.out_cell, diff_cached[2]), + _fabric_port_counter_diff_int(data.out_octet, diff_cached[3]), + _fabric_port_counter_diff_int(data.crc, diff_cached[4]), + _fabric_port_counter_diff_int(data.fec_correctable, diff_cached[5]), + _fabric_port_counter_diff_int(data.fec_uncorrectable, diff_cached[6]), + _fabric_port_counter_diff_int(data.symbol_err, diff_cached[7]), + ] + if nonzero_only and not _fabric_port_row_has_nonzero_counter(diffs): + continue table.append((asic_name, port_id, self.get_port_state(key), ns_diff(data.in_cell, diff_cached[0]), ns_diff(data.in_octet, diff_cached[1]), @@ -200,6 +249,8 @@ class FabricPortStat(FabricStat): ns_diff(data.fec_uncorrectable, diff_cached[6]), ns_diff(data.symbol_err, diff_cached[7]))) + if nonzero_only and len(table) == 0: + return print(tabulate(table, header, tablefmt='simple', stralign='right')) print() @@ -244,7 +295,7 @@ class FabricQueueStat(FabricStat): else: print("Clear and update saved counters queue") - def cnstat_print(self, cnstat_dict, errors_only=False): + def cnstat_print(self, cnstat_dict, errors_only=False, nonzero_only=False): if len(cnstat_dict) == 0: print("Counters %s empty" % self.namespace) return @@ -274,11 +325,20 @@ class FabricQueueStat(FabricStat): if key in cnstat_cached_dict: diff_cached = cnstat_cached_dict.get(key) port_id = port_name[len(PORT_NAME_PREFIX):] + diffs = [ + _fabric_port_counter_diff_int(data.curbyte, diff_cached[2]), + _fabric_port_counter_diff_int(data.curlevel, diff_cached[0]), + _fabric_port_counter_diff_int(data.watermarklevel, diff_cached[1]), + ] + if nonzero_only and not _fabric_port_row_has_nonzero_counter(diffs): + continue table.append((asic_name, port_id, self.get_port_state(port_name), queue_id, ns_diff(data.curbyte, diff_cached[2]), ns_diff(data.curlevel, diff_cached[0]), ns_diff(data.watermarklevel, diff_cached[1]))) + if nonzero_only and len(table) == 0: + return print(tabulate(table, queuestat_header, tablefmt='simple', stralign='right')) print() @@ -298,8 +358,9 @@ class FabricCapacity(FabricStat): fabric_capacity_data = self.db.get_all(self.db.STATE_DB, "FABRIC_CAPACITY_TABLE|FABRIC_CAPACITY_DATA") operational_fap_capacity = 0 operational_fabric_capacity = 0 - operational_fabric_links = 0; - total_fabric_links = 0; + operational_fabric_links = 0 + isolated_fabric_links = 0 + total_fabric_links = 0 ratio = 0 last_event = "None" last_time = "Never" @@ -312,6 +373,8 @@ class FabricCapacity(FabricStat): total_fabric_links = int(fabric_capacity_data['number_of_links']) if "operating_links" in fabric_capacity_data: operational_fabric_links = int(fabric_capacity_data['operating_links']) + if "isolated_links" in fabric_capacity_data: + isolated_fabric_links = int(fabric_capacity_data['isolated_links']) if "warning_threshold" in fabric_capacity_data: th = fabric_capacity_data['warning_threshold'] th = th + "%" @@ -336,7 +399,9 @@ class FabricCapacity(FabricStat): asic_name = self.namespace # Update the table to print - self.table_cnt.append((asic_name, operational_fabric_links, total_fabric_links, ratio, last_event, last_time)) + self.table_cnt.append( + (asic_name, operational_fabric_links, isolated_fabric_links, + total_fabric_links, ratio, last_event, last_time)) class FabricReachability(FabricStat): def reachability_print(self): @@ -366,6 +431,10 @@ class FabricReachability(FabricStat): return class FabricIsolation(FabricStat): + def __init__(self, namespace, nonzero_only=False): + super(FabricIsolation, self).__init__(namespace) + self.nonzero_only = nonzero_only + def isolation_print(self): # Connect to database self.db = multi_asic.connect_to_all_dbs_for_ns(self.namespace) @@ -380,7 +449,7 @@ class FabricIsolation(FabricStat): port_number = int(port_key.replace("FABRIC_PORT_TABLE|PORT", "")) port_dict.update({port_number: port_data}) # Create ordered table of fabric ports. - header = ["Local Link", "Auto Isolated", "Manual Isolated", "Isolated"] + header = ["Local Link", "Auto Isolated", "Manual Isolated", "Isolated", "Isolate Reason"] body = [] for port_number in sorted(port_dict.keys()): auto_isolated = 0 @@ -388,18 +457,36 @@ class FabricIsolation(FabricStat): isolated = 0 port_data = port_dict[port_number] if "AUTO_ISOLATED" in port_data: - auto_isolated = port_data["AUTO_ISOLATED"] + auto_isolated = int(port_data["AUTO_ISOLATED"]) if "CONFIG_ISOLATED" in port_data: - manual_isolated = port_data["CONFIG_ISOLATED"] + manual_isolated = int(port_data["CONFIG_ISOLATED"]) if "ISOLATED" in port_data: - isolated = port_data["ISOLATED"] - body.append((port_number, auto_isolated, manual_isolated, isolated)); + isolated = int(port_data["ISOLATED"]) + isolate_reason = "" + if FABRIC_PORT_ISOLATE_REASON_FIELD in port_data: + isolate_reason = port_data[FABRIC_PORT_ISOLATE_REASON_FIELD] + if self.nonzero_only and auto_isolated == 0 and manual_isolated == 0 and isolated == 0: + continue + body.append((port_number, auto_isolated, manual_isolated, isolated, isolate_reason)) + if self.nonzero_only and len(body) == 0: + return if self.namespace: print(f"\n{self.namespace}") print(tabulate(body, header, tablefmt='simple', stralign='right')) return class FabricRate(FabricStat): + def __init__(self, namespace, nonzero_only=False): + super(FabricRate, self).__init__(namespace) + self.nonzero_only = nonzero_only + + @staticmethod + def _rate_mbps_nonzero(rx_mbps, tx_mbps): + try: + return float(rx_mbps) != 0.0 or float(tx_mbps) != 0.0 + except (TypeError, ValueError): + return True + def rate_print(self): # Connect to database self.db = multi_asic.connect_to_all_dbs_for_ns(self.namespace) @@ -413,13 +500,6 @@ class FabricRate(FabricStat): port_number = int(port_key.replace("FABRIC_PORT_TABLE|PORT", "")) port_dict.update({port_number: port_data}) # Create ordered table of fabric ports. - rxRate = 0 - rxData = 0 - txRate = 0 - txData = 0 - time = 0 - local_time = "" - # RX data , Tx data , Time are for testing asic = "asic0" if self.namespace: asic = self.namespace @@ -427,18 +507,17 @@ class FabricRate(FabricStat): body = [] for port_number in sorted(port_dict.keys()): port_data = port_dict[port_number] + rxRate = 0 + txRate = 0 if "OLD_RX_RATE_AVG" in port_data: rxRate = port_data["OLD_RX_RATE_AVG"] - if "OLD_RX_DATA" in port_data: - rxData = port_data["OLD_RX_DATA"] if "OLD_TX_RATE_AVG" in port_data: txRate = port_data["OLD_TX_RATE_AVG"] - if "OLD_TX_DATA" in port_data: - txData = port_data["OLD_TX_DATA"] - if "LAST_TIME" in port_data: - time = int(port_data["LAST_TIME"]) - local_time = datetime.fromtimestamp(time) - body.append((asic, port_number, rxRate, txRate)); + if self.nonzero_only and not self._rate_mbps_nonzero(rxRate, txRate): + continue + body.append((asic, port_number, rxRate, txRate)) + if self.nonzero_only and len(body) == 0: + return click.echo() click.echo(tabulate(body, header, tablefmt='simple', stralign='right')) @@ -456,10 +535,14 @@ Examples: fabricstat -p -n asic0 -e fabricstat -q fabricstat -q -n asic0 + fabricstat -q -nz fabricstat -c fabricstat -c -n asic0 fabricstat -s fabricstat -s -n asic0 + fabricstat -s -nz + fabricstat -i -nz + fabricstat -nz fabricstat -C fabricstat -D """) @@ -470,6 +553,9 @@ Examples: parser.add_argument('-e', '--errors', action='store_true', help='Display errors') parser.add_argument('-c','--capacity',action='store_true', help='Display fabric capacity') parser.add_argument('-i','--isolation', action='store_true', help='Display fabric ports isolation status') + parser.add_argument('-nz', '--nonzero', action='store_true', + help='Port, queue (-q) or rate (-s): show only rows with non-zero counter/rate ' + '(rows with N/A are always shown). Not used with capacity or reachability.') parser.add_argument('-s','--rate', action='store_true', help='Display fabric counters rate') parser.add_argument('-C','--clear', action='store_true', help='Copy & clear fabric counters') parser.add_argument('-D','--delete', action='store_true', help='Delete saved stats') @@ -479,6 +565,7 @@ Examples: reachability = args.reachability capacity_status = args.capacity isolation_status = args.isolation + nonzero_only = args.nonzero rate = args.rate namespace = args.namespace errors_only = args.errors @@ -508,11 +595,11 @@ Examples: stat.reachability_print() return elif isolation_status: - stat = FabricIsolation(ns) + stat = FabricIsolation(ns, nonzero_only) stat.isolation_print() return elif rate: - stat = FabricRate(ns) + stat = FabricRate(ns, nonzero_only) stat.rate_print() return else: @@ -521,14 +608,16 @@ Examples: if save_fresh_stats: stat.save_fresh_stats() else: - stat.cnstat_print(cnstat_dict, errors_only) + stat.cnstat_print(cnstat_dict, errors_only, nonzero_only) if capacity_status: # show fabric capacity command capacity_header = [] table_cnt = [] threshold = [] - capacity_header = ["ASIC", "Operating\nLinks", "Total #\nof Links", "%", "Last Event", "Last Time"] + capacity_header = [ + "ASIC", "Operating\nLinks", "Isolated\nLinks", "Total #\nof Links", + "% Operating\nLinks", "Last Event", "Last Time"] if namespace is None: # All asics or all fabric asics multi_asic = multi_asic_util.MultiAsic() diff --git a/show/fabric.py b/show/fabric.py index 898c76114..bc9b2dd8d 100644 --- a/show/fabric.py +++ b/show/fabric.py @@ -33,13 +33,17 @@ def capacity(namespace, errors): @fabric.group(invoke_without_command=True) @multi_asic_util.multi_asic_click_option_namespace @click.option('-e', '--errors', is_flag=True) -def isolation(namespace, errors): +@click.option('-nz', '--nonzero', is_flag=True, + help='Show only fabric links with non-zero isolation counters') +def isolation(namespace, errors, nonzero): """Show fabric isolation status""" cmd = ['fabricstat', '-i'] if namespace is not None: cmd += ['-n', str(namespace)] if errors: cmd += ["-e"] + if nonzero: + cmd += ['-nz'] clicommon.run_command(cmd) @fabric.group(invoke_without_command=True) @@ -57,30 +61,42 @@ def reachability(namespace, errors): @counters.command() @multi_asic_util.multi_asic_click_option_namespace @click.option('-e', '--errors', is_flag=True) -def port(namespace, errors): +@click.option('-nz', '--nonzero', is_flag=True, + help='Show only fabric ports with a non-zero counter delta') +def port(namespace, errors, nonzero): """Show fabric port stat""" cmd = ["fabricstat"] if namespace is not None: cmd += ['-n', str(namespace)] if errors: cmd += ["-e"] + if nonzero: + cmd += ['-nz'] clicommon.run_command(cmd) @counters.command() @multi_asic_util.multi_asic_click_option_namespace -def queue(namespace): +@click.option('-nz', '--nonzero', is_flag=True, + help='Show only fabric queue rows with a non-zero counter delta') +def queue(namespace, nonzero): """Show fabric queue stat""" cmd = ['fabricstat', '-q'] if namespace is not None: cmd += ['-n', str(namespace)] + if nonzero: + cmd += ['-nz'] clicommon.run_command(cmd) @counters.command() @multi_asic_util.multi_asic_click_option_namespace -def rate(namespace): +@click.option('-nz', '--nonzero', is_flag=True, + help='Show only fabric links with non-zero Rx or Tx rate') +def rate(namespace, nonzero): """Show fabric counters rate""" cmd = ['fabricstat', '-s'] if namespace is not None: cmd += ['-n', str(namespace)] + if nonzero: + cmd += ['-nz'] clicommon.run_command(cmd) diff --git a/tests/fabricstat_test.py b/tests/fabricstat_test.py index a8a334cb9..9591b715b 100644 --- a/tests/fabricstat_test.py +++ b/tests/fabricstat_test.py @@ -17,7 +17,7 @@ 0 0 up 6 1,113 0 0 0 5 1,759,692,040 5 0 1 down 0 0 0 0 0 0 58,977,677,898 0 0 2 up 2 371 0 0 0 0 1,769,448,760 0 - 0 3 down 0 0 0 0 0 0 58,976,477,608 0 + 0 3 down 0 0 0 0 0 0 0 0 0 4 up 10 1,855 0 0 0 73 1,763,293,100 73 0 5 down 0 0 0 0 0 44,196 58,975,150,569 0 0 6 up 4 742 0 0 0 10 1,763,174,090 0 @@ -27,28 +27,63 @@ ------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- -------------- 1 0 up 16 2,968 0 0 0 0 1,763,890,500 0 1 1 down 0 0 0 0 0 0 105,269,481,425 0 - 1 2 down 0 0 0 0 0 0 105,268,895,944 0 + 1 2 down 0 0 0 0 0 0 0 0 1 3 down 0 0 0 0 0 0 105,268,290,607 0 1 4 up 14 2,597 0 0 0 0 1,762,188,940 0 1 5 down 0 0 0 0 0 968 105,267,020,477 0 1 6 down 0 0 0 0 0 53,192,703,023 1,422,986 41,913,682,074 - 1 7 down 0 0 0 0 0 0 105,264,567,398 0 + 1 7 down 0 0 0 0 0 0 0 0 + +""" # noqa: E501 + +multi_asic_fabric_counters_nonzero = """\ + ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR +------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- ------------ + 0 0 up 6 1,113 0 0 0 5 1,759,692,040 5 + 0 1 down 0 0 0 0 0 0 58,977,677,898 0 + 0 2 up 2 371 0 0 0 0 1,769,448,760 0 + 0 4 up 10 1,855 0 0 0 73 1,763,293,100 73 + 0 5 down 0 0 0 0 0 44,196 58,975,150,569 0 + 0 6 up 4 742 0 0 0 10 1,763,174,090 0 + 0 7 up 10 1,855 0 0 0 187 1,768,439,529 1,331 + + ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR +------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- -------------- + 1 0 up 16 2,968 0 0 0 0 1,763,890,500 0 + 1 1 down 0 0 0 0 0 0 105,269,481,425 0 + 1 3 down 0 0 0 0 0 0 105,268,290,607 0 + 1 4 up 14 2,597 0 0 0 0 1,762,188,940 0 + 1 5 down 0 0 0 0 0 968 105,267,020,477 0 + 1 6 down 0 0 0 0 0 53,192,703,023 1,422,986 41,913,682,074 + +""" # noqa: E501 -""" multi_asic_fabric_counters_asic0 = """\ ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR ------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- ------------ 0 0 up 6 1,113 0 0 0 5 1,759,692,040 5 0 1 down 0 0 0 0 0 0 58,977,677,898 0 0 2 up 2 371 0 0 0 0 1,769,448,760 0 - 0 3 down 0 0 0 0 0 0 58,976,477,608 0 + 0 3 down 0 0 0 0 0 0 0 0 0 4 up 10 1,855 0 0 0 73 1,763,293,100 73 0 5 down 0 0 0 0 0 44,196 58,975,150,569 0 0 6 up 4 742 0 0 0 10 1,763,174,090 0 0 7 up 10 1,855 0 0 0 187 1,768,439,529 1,331 -""" +""" # noqa: E501 + +multi_asic_fabric_counters_nonzero_asic0 = """\ + ASIC PORT STATE IN_CELL IN_OCTET OUT_CELL OUT_OCTET CRC FEC_CORRECTABLE FEC_UNCORRECTABLE SYMBOL_ERR +------ ------ ------- --------- ---------- ---------- ----------- ----- ----------------- ------------------- ------------ + 0 0 up 6 1,113 0 0 0 5 1,759,692,040 5 + 0 1 down 0 0 0 0 0 0 58,977,677,898 0 + 0 2 up 2 371 0 0 0 0 1,769,448,760 0 + 0 4 up 10 1,855 0 0 0 73 1,763,293,100 73 + 0 5 down 0 0 0 0 0 44,196 58,975,150,569 0 + 0 6 up 4 742 0 0 0 10 1,763,174,090 0 + 0 7 up 10 1,855 0 0 0 187 1,768,439,529 1,331 +""" # noqa: E501 clear_counter = """\ Clear and update saved counters port""" @@ -64,7 +99,7 @@ 0 6 up 0 0 0 0 0 0 0 0 0 7 up 0 0 0 0 0 0 0 0 -""" +""" # noqa: E501 fabric_invalid_asic_error = """ValueError: Unknown Namespace asic99""" @@ -107,6 +142,33 @@ """ +multi_asic_fabric_counters_queue_nz = """\ + ASIC PORT STATE QUEUE_ID CURRENT_BYTE CURRENT_LEVEL WATERMARK_LEVEL +------ ------ ------- ---------- -------------- --------------- ----------------- + 0 0 up 0 763 12 20 + 0 2 up 0 104 8 8 + 0 4 up 0 1,147 14 22 + 0 6 up 0 527 8 10 + 0 7 up 0 1,147 14 17 + + ASIC PORT STATE QUEUE_ID CURRENT_BYTE CURRENT_LEVEL WATERMARK_LEVEL +------ ------ ------- ---------- -------------- --------------- ----------------- + 1 0 up 0 1,942 18 24 + 1 4 up 0 1,362 15 24 + +""" + +multi_asic_fabric_counters_queue_nz_asic0 = """\ + ASIC PORT STATE QUEUE_ID CURRENT_BYTE CURRENT_LEVEL WATERMARK_LEVEL +------ ------ ------- ---------- -------------- --------------- ----------------- + 0 0 up 0 763 12 20 + 0 2 up 0 104 8 8 + 0 4 up 0 1,147 14 22 + 0 6 up 0 527 8 10 + 0 7 up 0 1,147 14 17 + +""" + multi_asic_fabric_counters_queue_asic0_clear = """\ ASIC PORT STATE QUEUE_ID CURRENT_BYTE CURRENT_LEVEL WATERMARK_LEVEL ------ ------ ------- ---------- -------------- --------------- ----------------- @@ -154,62 +216,87 @@ multi_asic_fabric_capacity = """\ Monitored fabric capacity threshold: 100% - ASIC Operating Total # % Last Event Last Time - Links of Links ------- ----------- ---------- ---- ------------ ----------- - asic0 5 8 62.5 None Never - asic1 2 8 25 None Never + ASIC Operating Isolated Total # % Operating Last Event Last Time + Links Links of Links Links +------ ----------- ---------- ---------- ------------- ------------ ----------- + asic0 5 3 8 62.5 None Never + asic1 2 1 8 25 None Never """ multi_asic_fabric_capacity_asic0 = """\ Monitored fabric capacity threshold: 100% - ASIC Operating Total # % Last Event Last Time - Links of Links ------- ----------- ---------- ---- ------------ ----------- - asic0 5 8 62.5 None Never + ASIC Operating Isolated Total # % Operating Last Event Last Time + Links Links of Links Links +------ ----------- ---------- ---------- ------------- ------------ ----------- + asic0 5 3 8 62.5 None Never """ multi_asic_fabric_isolation = """\ asic0 - Local Link Auto Isolated Manual Isolated Isolated ------------- --------------- ----------------- ---------- - 0 0 0 0 + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ----------------- + 0 1 0 0 crc_errors 2 0 0 0 - 4 0 0 0 - 6 0 0 0 + 4 0 1 0 config + 6 1 0 1 fec_uncorrectable 7 0 0 0 asic1 - Local Link Auto Isolated Manual Isolated Isolated ------------- --------------- ----------------- ---------- + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ---------------- 0 0 0 0 - 4 0 0 0 + 4 0 1 0 config """ multi_asic_fabric_isolation_asic0 = """\ asic0 - Local Link Auto Isolated Manual Isolated Isolated ------------- --------------- ----------------- ---------- - 0 0 0 0 + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ----------------- + 0 1 0 0 crc_errors 2 0 0 0 - 4 0 0 0 - 6 0 0 0 + 4 0 1 0 config + 6 1 0 1 fec_uncorrectable 7 0 0 0 """ +multi_asic_fabric_isolation_nz = """\ + +asic0 + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ----------------- + 0 1 0 0 crc_errors + 4 0 1 0 config + 6 1 0 1 fec_uncorrectable + +asic1 + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ---------------- + 4 0 1 0 config +""" + +multi_asic_fabric_isolation_nz_asic0 = """\ + +asic0 + Local Link Auto Isolated Manual Isolated Isolated Isolate Reason +------------ --------------- ----------------- ---------- ----------------- + 0 1 0 0 crc_errors + 4 0 1 0 config + 6 1 0 1 fec_uncorrectable +""" + multi_asic_fabric_rate = """\ ASIC Link ID Rx Data Mbps Tx Data Mbps ------ --------- -------------- -------------- asic0 0 0 19.8 - asic0 1 0 19.8 + asic0 1 0 0 asic0 2 0 39.8 - asic0 3 0 39.8 + asic0 3 0 0 asic0 4 0 39.8 - asic0 5 0 39.8 + asic0 5 0 0 asic0 6 0 39.3 asic0 7 0 39.3 @@ -225,16 +312,27 @@ asic1 7 0 0 """ +multi_asic_fabric_rate_nonzero = """\ + + ASIC Link ID Rx Data Mbps Tx Data Mbps +------ --------- -------------- -------------- + asic0 0 0 19.8 + asic0 2 0 39.8 + asic0 4 0 39.8 + asic0 6 0 39.3 + asic0 7 0 39.3 +""" + multi_asic_fabric_rate_asic0 = """\ ASIC Link ID Rx Data Mbps Tx Data Mbps ------ --------- -------------- -------------- asic0 0 0 19.8 - asic0 1 0 19.8 + asic0 1 0 0 asic0 2 0 39.8 - asic0 3 0 39.8 + asic0 3 0 0 asic0 4 0 39.8 - asic0 5 0 39.8 + asic0 5 0 0 asic0 6 0 39.3 asic0 7 0 39.3 """ @@ -256,6 +354,13 @@ def test_single_show_fabric_counters(self): assert return_code == 0 assert result == multi_asic_fabric_counters_asic0 + def test_single_show_fabric_counters_nonzero(self): + return_code, result = get_result_and_return_code(['fabricstat', '-nz']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_counters_nonzero_asic0 + def test_single_clear_fabric_counters(self): return_code, result = get_result_and_return_code(['fabricstat', '-C']) print("return_code: {}".format(return_code)) @@ -303,6 +408,20 @@ def test_multi_show_fabric_counters_asic(self): assert return_code == 0 assert result == multi_asic_fabric_counters_asic0 + def test_multi_show_fabric_counters_nonzero(self): + return_code, result = get_result_and_return_code(['fabricstat', '-nz']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_counters_nonzero + + def test_multi_show_fabric_counters_nonzero_asic(self): + return_code, result = get_result_and_return_code(['fabricstat', '-nz', '-n', 'asic0']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_counters_nonzero_asic0 + def test_multi_asic_invalid_asic(self): return_code, result = get_result_and_return_code(['fabricstat', '-n', 'asic99']) print("return_code: {}".format(return_code)) @@ -324,6 +443,20 @@ def test_multi_show_fabric_counters_queue_asic(self): assert return_code == 0 assert result == multi_asic_fabric_counters_queue_asic0 + def test_multi_show_fabric_counters_queue_nonzero(self): + return_code, result = get_result_and_return_code(['fabricstat', '-q', '-nz']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_counters_queue_nz + + def test_multi_show_fabric_counters_queue_nonzero_asic(self): + return_code, result = get_result_and_return_code(['fabricstat', '-q', '-nz', '-n', 'asic0']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_counters_queue_nz_asic0 + def test_multi_show_fabric_counters_queue_clear(self): return_code, result = get_result_and_return_code(['fabricstat', '-C', '-q']) print("return_code: {}".format(return_code)) @@ -387,6 +520,20 @@ def test_multi_show_fabric_isolation_asic(self): assert return_code == 0 assert result == multi_asic_fabric_isolation_asic0 + def test_multi_show_fabric_isolation_nonzero(self): + return_code, result = get_result_and_return_code(['fabricstat', '-i', '-nz']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_isolation_nz + + def test_multi_show_fabric_isolation_nonzero_asic(self): + return_code, result = get_result_and_return_code(['fabricstat', '-i', '-nz', '-n', 'asic0']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_isolation_nz_asic0 + def test_mutli_show_fabric_rate(self): return_code, result = get_result_and_return_code(['fabricstat', '-s']) print("return_code: {}".format(return_code)) @@ -394,6 +541,13 @@ def test_mutli_show_fabric_rate(self): assert return_code == 0 assert result == multi_asic_fabric_rate + def test_multi_show_fabric_rate_nonzero(self): + return_code, result = get_result_and_return_code(['fabricstat', '-s', '-nz']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_rate_nonzero + def test_multi_show_fabric_rate_asic(self): return_code, result = get_result_and_return_code(['fabricstat', '-s', '-n', 'asic0']) print("return_code: {}".format(return_code)) @@ -401,6 +555,13 @@ def test_multi_show_fabric_rate_asic(self): assert return_code == 0 assert result == multi_asic_fabric_rate_asic0 + def test_multi_show_fabric_rate_nonzero_asic(self): + return_code, result = get_result_and_return_code(['fabricstat', '-s', '-nz', '-n', 'asic0']) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == multi_asic_fabric_rate_nonzero + @classmethod def teardown_class(cls): print("TEARDOWN") diff --git a/tests/mock_tables/asic0/counters_db.json b/tests/mock_tables/asic0/counters_db.json index 8e7eb5650..f9dd6930e 100644 --- a/tests/mock_tables/asic0/counters_db.json +++ b/tests/mock_tables/asic0/counters_db.json @@ -2392,7 +2392,7 @@ "SAI_PORT_STAT_IF_IN_ERRORS": "0", "SAI_PORT_STAT_IF_IN_FABRIC_DATA_UNITS": "0", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "0", - "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "58976477608", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "0", "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS:oid:0x1000000000147": { diff --git a/tests/mock_tables/asic0/state_db.json b/tests/mock_tables/asic0/state_db.json index 1e1e7547f..ec319c572 100644 --- a/tests/mock_tables/asic0/state_db.json +++ b/tests/mock_tables/asic0/state_db.json @@ -255,6 +255,8 @@ }, "FABRIC_PORT_TABLE|PORT0" : { "STATUS": "up", + "AUTO_ISOLATED": "1", + "ISOLATE_REASON": "crc_errors", "REMOTE_MOD": "0", "REMOTE_PORT": "79", "OLD_RX_RATE_AVG": "0", @@ -281,6 +283,8 @@ }, "FABRIC_PORT_TABLE|PORT4" : { "STATUS": "up", + "CONFIG_ISOLATED": "1", + "ISOLATE_REASON": "config", "REMOTE_MOD": "0", "REMOTE_PORT": "85", "OLD_RX_RATE_AVG": "0", @@ -294,6 +298,9 @@ }, "FABRIC_PORT_TABLE|PORT6" : { "STATUS": "up", + "AUTO_ISOLATED": "1", + "ISOLATED": "1", + "ISOLATE_REASON": "fec_uncorrectable", "REMOTE_MOD": "0", "REMOTE_PORT": "84", "OLD_RX_RATE_AVG": "0", @@ -334,6 +341,7 @@ "fabric_capacity": "221580", "missing_capacity": "132948", "operating_links": "5", + "isolated_links": "3", "number_of_links": "8", "warning_threshold": "100" }, diff --git a/tests/mock_tables/asic1/counters_db.json b/tests/mock_tables/asic1/counters_db.json index 254221020..7f0dacdc3 100644 --- a/tests/mock_tables/asic1/counters_db.json +++ b/tests/mock_tables/asic1/counters_db.json @@ -1132,7 +1132,7 @@ "SAI_PORT_STAT_IF_IN_ERRORS": "0", "SAI_PORT_STAT_IF_IN_FABRIC_DATA_UNITS": "0", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "0", - "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "105268895944", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "0", "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS:oid:0x1000000000146": { @@ -1182,7 +1182,7 @@ "SAI_PORT_STAT_IF_IN_ERRORS": "0", "SAI_PORT_STAT_IF_IN_FABRIC_DATA_UNITS": "0", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "0", - "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "105264567398", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "0", "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS_FABRIC_QUEUE_NAME_MAP" : { diff --git a/tests/mock_tables/asic1/state_db.json b/tests/mock_tables/asic1/state_db.json index a1afd80bd..c65faf014 100644 --- a/tests/mock_tables/asic1/state_db.json +++ b/tests/mock_tables/asic1/state_db.json @@ -259,6 +259,8 @@ }, "FABRIC_PORT_TABLE|PORT4" : { "STATUS": "up", + "CONFIG_ISOLATED": "1", + "ISOLATE_REASON": "config", "REMOTE_MOD": "0", "REMOTE_PORT": "75" }, @@ -275,6 +277,7 @@ "fabric_capacity": "88632", "missing_capacity": "265896", "operating_links": "2", + "isolated_links": "1", "number_of_links": "8", "warning_threshold": "100" }, diff --git a/tests/mock_tables/counters_db.json b/tests/mock_tables/counters_db.json index f7bd4faef..9d9dad4f7 100644 --- a/tests/mock_tables/counters_db.json +++ b/tests/mock_tables/counters_db.json @@ -2164,7 +2164,7 @@ "SAI_PORT_STAT_IF_IN_ERRORS": "0", "SAI_PORT_STAT_IF_IN_FABRIC_DATA_UNITS": "0", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "0", - "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "58976477608", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "0", "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS:oid:0x1000000000147": { diff --git a/tests/mock_tables/state_db.json b/tests/mock_tables/state_db.json index 4d8db65a3..ff547e300 100644 --- a/tests/mock_tables/state_db.json +++ b/tests/mock_tables/state_db.json @@ -1759,6 +1759,7 @@ "fabric_capacity": "88632", "missing_capacity": "265896", "operating_links": "2", + "isolated_links": "1", "number_of_links": "8", "warning_threshold": "100" }, diff --git a/tests/show_test.py b/tests/show_test.py index e3287df67..7385d91a7 100644 --- a/tests/show_test.py +++ b/tests/show_test.py @@ -334,6 +334,58 @@ def test_queue(self, mock_run_command): assert result.exit_code == 0 mock_run_command.assert_called_once_with(["fabricstat", '-q', '-n', 'asic0']) + @patch('utilities_common.cli.run_command') + @patch.object(click.Choice, 'convert', MagicMock(return_value='asic0')) + def test_port_nonzero(self, mock_run_command): + runner = CliRunner() + result = runner.invoke( + show.cli.commands['fabric'].commands['counters'].commands['port'], + ['-n', 'asic0', '-e', '-nz'], + ) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + mock_run_command.assert_called_once_with(["fabricstat", '-n', 'asic0', '-e', '-nz']) + + @patch('utilities_common.cli.run_command') + @patch.object(click.Choice, 'convert', MagicMock(return_value='asic0')) + def test_queue_nonzero(self, mock_run_command): + runner = CliRunner() + result = runner.invoke( + show.cli.commands['fabric'].commands['counters'].commands['queue'], + ['-n', 'asic0', '-nz'], + ) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + mock_run_command.assert_called_once_with(["fabricstat", '-q', '-n', 'asic0', '-nz']) + + @patch('utilities_common.cli.run_command') + @patch.object(click.Choice, 'convert', MagicMock(return_value='asic0')) + def test_rate_nonzero(self, mock_run_command): + runner = CliRunner() + result = runner.invoke( + show.cli.commands['fabric'].commands['counters'].commands['rate'], + ['-n', 'asic0', '-nz'], + ) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + mock_run_command.assert_called_once_with(["fabricstat", '-s', '-n', 'asic0', '-nz']) + + @patch('utilities_common.cli.run_command') + @patch.object(click.Choice, 'convert', MagicMock(return_value='asic0')) + def test_isolation_nonzero(self, mock_run_command): + runner = CliRunner() + result = runner.invoke( + show.cli.commands['fabric'].commands['isolation'], + ['-n', 'asic0', '-nz'], + ) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + mock_run_command.assert_called_once_with(["fabricstat", '-i', '-n', 'asic0', '-nz']) + def teardown(self): print('TEAR DOWN')