diff --git a/scripts/intfstat b/scripts/intfstat index 79087f5852..6d3a73bb2a 100755 --- a/scripts/intfstat +++ b/scripts/intfstat @@ -11,7 +11,6 @@ import argparse import datetime import sys import os -import sys import time # mock the redis for unit test purposes # @@ -28,15 +27,37 @@ except KeyError: from collections import namedtuple, OrderedDict from natsort import natsorted from tabulate import tabulate -from utilities_common.netstat import ns_diff, ns_brate, ns_prate, table_as_json, STATUS_NA, format_brate, format_prate, format_util +from utilities_common.netstat import ns_diff, table_as_json, STATUS_NA, format_brate, format_prate from swsscommon.swsscommon import SonicV2Connector -nstat_fields = ("rx_b_ok", "rx_p_ok", "tx_b_ok", "tx_p_ok",\ - "rx_b_err", "rx_p_err", "tx_b_err", "tx_p_err") +nstat_fields = ( + "rx_b_ok", + "rx_p_ok", + "tx_b_ok", + "tx_p_ok", + "rx_b_err", + "rx_p_err", + "tx_b_err", + "tx_p_err" +) + NStats = namedtuple("NStats", nstat_fields) -header = ['IFACE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_ERR', - 'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_ERR'] +header = [ + 'IFACE', + 'RX_OK', + 'RX_BPS', + 'RX_PPS', + 'RX_ERR', + 'TX_OK', + 'TX_BPS', + 'TX_PPS', + 'TX_ERR' +] + +rates_key_list = [ 'RX_BPS', 'RX_PPS', 'TX_BPS', 'TX_PPS'] +ratestat_fields = ("rx_bps", "rx_pps", "tx_bps", "tx_pps") +RateStats = namedtuple("RateStats", ratestat_fields) counter_names = ( 'SAI_ROUTER_INTERFACE_STAT_IN_OCTETS', @@ -49,18 +70,9 @@ counter_names = ( 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS' ) - COUNTER_TABLE_PREFIX = "COUNTERS:" +RATES_TABLE_PREFIX = "RATES:" COUNTERS_RIF_NAME_MAP = "COUNTERS_RIF_NAME_MAP" -COUNTERS_RIF_TYPE_MAP = "COUNTERS_RIF_TYPE_MAP" - -INTERFACE_TABLE_PREFIX = "PORT_TABLE:" -INTF_STATUS_VALUE_UP = 'UP' -INTF_STATUS_VALUE_DOWN = 'DOWN' - -INTF_STATE_UP = 'U' -INTF_STATE_DOWN = 'D' -INTF_STATE_DISABLED = 'X' class Intfstat(object): def __init__(self): @@ -85,13 +97,28 @@ class Intfstat(object): cntr = NStats._make(fields) return cntr + def get_rates(table_id): + """ + Get the rates from specific table. + """ + fields = ["0","0","0","0"] + for pos, name in enumerate(rates_key_list): + full_table_id = RATES_TABLE_PREFIX + table_id + counter_data = self.db.get(self.db.COUNTERS_DB, full_table_id, name) + if counter_data is None: + fields[pos] = STATUS_NA + elif fields[pos] != STATUS_NA: + fields[pos] = float(counter_data) + cntr = RateStats._make(fields) + return cntr + # Build a dictionary of the stats cnstat_dict = OrderedDict() cnstat_dict['time'] = datetime.datetime.now() + ratestat_dict = OrderedDict() # Get the info from database - counter_rif_name_map = self.db.get_all(self.db.COUNTERS_DB, COUNTERS_RIF_NAME_MAP); - + counter_rif_name_map = self.db.get_all(self.db.COUNTERS_DB, COUNTERS_RIF_NAME_MAP) if counter_rif_name_map is None: print("No %s in the DB!" % COUNTERS_RIF_NAME_MAP) @@ -103,49 +130,15 @@ class Intfstat(object): if rif: cnstat_dict[rif] = get_counters(counter_rif_name_map[rif]) - return cnstat_dict + ratestat_dict[rif] = get_rates(counter_rif_name_map[rif]) + return cnstat_dict, ratestat_dict for rif in natsorted(counter_rif_name_map): cnstat_dict[rif] = get_counters(counter_rif_name_map[rif]) - return cnstat_dict + ratestat_dict[rif] = get_rates(counter_rif_name_map[rif]) + return cnstat_dict, ratestat_dict - def get_intf_state(self, port_name): - """ - Get the port state - """ - full_table_id = PORT_STATUS_TABLE_PREFIX + port_name - admin_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_ADMIN_STATUS_FIELD) - oper_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_OPER_STATUS_FIELD) - if admin_state is None or oper_state is None: - return STATUS_NA - elif admin_state.upper() == PORT_STATUS_VALUE_DOWN: - return PORT_STATE_DISABLED - elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_UP: - return PORT_STATE_UP - elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_DOWN: - return PORT_STATE_DOWN - else: - return STATUS_NA - - def get_intf_speed(self, port_name): - """ - Get the Intf speed - """ - full_table_id = PORT_STATUS_TABLE_PREFIX + port_name - admin_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_ADMIN_STATUS_FIELD) - oper_state = self.db.get(self.db.APPL_DB, full_table_id, PORT_OPER_STATUS_FIELD) - if admin_state is None or oper_state is None: - return STATUS_NA - elif admin_state.upper() == PORT_STATUS_VALUE_DOWN: - return PORT_STATE_DISABLED - elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_UP: - return PORT_STATE_UP - elif admin_state.upper() == PORT_STATUS_VALUE_UP and oper_state.upper() == PORT_STATUS_VALUE_DOWN: - return PORT_STATE_DOWN - else: - return STATUS_NA - - def cnstat_print(self, cnstat_dict, use_json): + def cnstat_print(self, cnstat_dict, ratestat_dict, use_json): """ Print the cnstat. """ @@ -155,8 +148,17 @@ class Intfstat(object): if key == 'time': continue - table.append((key, data.rx_p_ok, STATUS_NA, STATUS_NA, data.rx_p_err, - data.tx_p_ok, STATUS_NA, STATUS_NA, data.tx_p_err)) + rates = ratestat_dict.get(key, RateStats._make([STATUS_NA] * len(rates_key_list))) + + table.append((key, + data.rx_p_ok, + format_brate(rates.rx_bps), + format_prate(rates.rx_pps), + data.rx_p_err, + data.tx_p_ok, + format_brate(rates.tx_bps), + format_prate(rates.tx_pps), + data.tx_p_err)) if use_json: print(table_as_json(table, header)) @@ -164,7 +166,7 @@ class Intfstat(object): else: print(tabulate(table, header, tablefmt='simple', stralign='right')) - def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, use_json): + def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, ratestat_dict, use_json): """ Print the difference between two cnstat results. """ @@ -180,32 +182,29 @@ class Intfstat(object): if key in cnstat_old_dict: old_cntr = cnstat_old_dict.get(key) + rates = ratestat_dict.get(key, RateStats._make([STATUS_NA] * len(rates_key_list))) + if old_cntr is not None: table.append((key, ns_diff(cntr.rx_p_ok, old_cntr.rx_p_ok), - ns_brate(cntr.rx_b_ok, old_cntr.rx_b_ok, time_gap), - ns_prate(cntr.rx_p_ok, old_cntr.rx_p_ok, time_gap), + format_brate(rates.rx_bps), + format_prate(rates.rx_pps), ns_diff(cntr.rx_p_err, old_cntr.rx_p_err), ns_diff(cntr.tx_p_ok, old_cntr.tx_p_ok), - ns_brate(cntr.tx_b_ok, old_cntr.tx_b_ok, time_gap), - ns_prate(cntr.tx_p_ok, old_cntr.tx_p_ok, time_gap), + format_brate(rates.tx_bps), + format_prate(rates.tx_pps), ns_diff(cntr.tx_p_err, old_cntr.tx_p_err))) else: - old_cntr = NStats._make([0] * len(nstat_fields)) - - rates = ratestat_dict.get(key, RateStats._make([STATUS_NA]*len(ratestat_fields))) + table.append((key, + cntr.rx_p_ok, + format_brate(rates.rx_bps), + format_prate(rates.rx_pps), + cntr.rx_p_err, + cntr.tx_p_ok, + format_brate(rates.tx_bps), + format_prate(rates.tx_pps), + cntr.tx_p_err)) - table.append((key, - ns_diff(cntr.rx_p_ok, old_cntr.rx_p_ok), - format_brate(rates.rx_bps), - format_prate(rates.rx_pps), - format_util(rates.rx_bps, speed), - ns_diff(cntr.rx_p_err, old_cntr.rx_p_err), - ns_diff(cntr.tx_p_ok, old_cntr.tx_p_ok), - format_brate(rates.tx_bps), - format_prate(rates.tx_pps), - format_util(rates.tx_bps, speed), - ns_diff(cntr.tx_p_err, old_cntr.tx_p_err))) if use_json: print(table_as_json(table, header)) else: @@ -317,7 +316,7 @@ def main(): sys.exit(0) intfstat = Intfstat() - cnstat_dict = intfstat.get_cnstat(rif=interface_name) + cnstat_dict, ratestat_dict = intfstat.get_cnstat(rif=interface_name) # At this point, either we'll create a file or open an existing one. if not os.path.exists(cnstat_dir): @@ -344,7 +343,7 @@ def main(): if interface_name: intfstat.cnstat_single_interface(interface_name, cnstat_dict, cnstat_cached_dict) else: - intfstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json) + intfstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, ratestat_dict, use_json) except IOError as e: print(e.errno, e) else: @@ -355,16 +354,16 @@ def main(): if interface_name: intfstat.cnstat_single_interface(interface_name, cnstat_dict, None) else: - intfstat.cnstat_print(cnstat_dict, use_json) + intfstat.cnstat_print(cnstat_dict, ratestat_dict, use_json) else: #wait for the specified time and then gather the new stats and output the difference. time.sleep(wait_time_in_seconds) print("The rates are calculated within %s seconds period" % wait_time_in_seconds) - cnstat_new_dict = intfstat.get_cnstat(rif=interface_name) + cnstat_new_dict, ratestat_dict = intfstat.get_cnstat(rif=interface_name) if interface_name: intfstat.cnstat_single_interface(interface_name, cnstat_new_dict, cnstat_dict) else: - intfstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, use_json) + intfstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, ratestat_dict, use_json) if __name__ == "__main__": main() diff --git a/scripts/portstat b/scripts/portstat index 1743ff72fa..1df579b984 100755 --- a/scripts/portstat +++ b/scripts/portstat @@ -14,7 +14,6 @@ import sys import time from collections import OrderedDict, namedtuple - from natsort import natsorted from tabulate import tabulate from sonic_py_common import multi_asic @@ -36,11 +35,8 @@ except KeyError: from utilities_common import constants from utilities_common.intf_filter import parse_interface_in_filter -import utilities_common.multi_asic as multi_asic_util -from utilities_common.netstat import (ns_diff, table_as_json, format_brate, - format_prate, format_util, rates_key_list, - RateStats, ratestat_fields) - +import utilities_common.multi_asic as multi_asic_util +from utilities_common.netstat import ns_diff, table_as_json, format_brate, format_prate, format_util PORT_RATE = 40 @@ -56,12 +52,16 @@ NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\ tx_uca, tx_mca, tx_bca, tx_all,\ rx_jbr, rx_frag, rx_usize, rx_ovrrun") header_all = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR', - 'TX_OK', 'TX_BPS', 'Tx_PPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] + 'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] header_std = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_OK', 'TX_BPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] header_errors_only = ['IFACE', 'STATE', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_ERR', 'TX_DRP', 'TX_OVR'] header_rates_only = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_UTIL'] +rates_key_list = [ 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_BPS', 'TX_PPS', 'TX_UTIL' ] +ratestat_fields = ("rx_bps", "rx_pps", "rx_util", "tx_bps", "tx_pps", "tx_util") +RateStats = namedtuple("RateStats", ratestat_fields) + """ The order and count of statistics mentioned below needs to be in sync with the values in portstat script So, any fields added/deleted in here should be reflected in portstat script also @@ -262,19 +262,36 @@ class Portstat(object): rates = ratestat_dict.get(key, RateStats._make([STATUS_NA] * len(rates_key_list))) if print_all: header = header_all - table.append((key, self.get_port_state(key), - data.rx_ok, STATUS_NA, STATUS_NA, STATUS_NA, data.rx_err, - data.rx_drop, data.rx_ovr, - data.tx_ok, STATUS_NA, STATUS_NA, STATUS_NA, data.tx_err, - data.tx_drop, data.tx_ovr)) + table.append((key, + self.get_port_state(key), + data.rx_ok, + format_brate(rates.rx_bps), + format_prate(rates.rx_pps), + format_util(rates.rx_bps, port_speed), + data.rx_err, + data.rx_drop, + data.rx_ovr, + data.tx_ok, + format_brate(rates.tx_bps), + format_prate(rates.tx_pps), + format_util(rates.tx_bps, port_speed), + data.tx_err, + data.tx_drop, + data.tx_ovr)) elif errors_only: header = header_errors_only - table.append((key, self.get_port_state(key), - data.rx_err, data.rx_drop, data.rx_ovr, - data.tx_err, data.tx_drop, data.tx_ovr)) + table.append((key, + self.get_port_state(key), + data.rx_err, + data.rx_drop, + data.rx_ovr, + data.tx_err, + data.tx_drop, + data.tx_ovr)) elif rates_only: header = header_rates_only - table.append((key, self.get_port_state(key), + table.append((key, + self.get_port_state(key), data.rx_ok, format_brate(rates.rx_bps), format_prate(rates.rx_pps), @@ -285,11 +302,20 @@ class Portstat(object): format_util(rates.tx_bps, port_speed))) else: header = header_std - table.append((key, self.get_port_state(key), - data.rx_ok, STATUS_NA, STATUS_NA, data.rx_err, - data.rx_drop, data.rx_ovr, - data.tx_ok, STATUS_NA, STATUS_NA, data.tx_err, - data.tx_drop, data.tx_ovr)) + table.append((key, + self.get_port_state(key), + data.rx_ok, + format_brate(rates.rx_bps), + format_util(rates.rx_bps, port_speed), + data.rx_err, + data.rx_drop, + data.rx_ovr, + data.tx_ok, + format_brate(rates.tx_bps), + format_util(rates.tx_bps, port_speed), + data.tx_err, + data.tx_drop, + data.tx_ovr)) if use_json: print(table_as_json(table, header)) @@ -386,24 +412,26 @@ class Portstat(object): port_speed = self.get_port_speed(key) if print_all: header = header_all - table.append((key, self.get_port_state(key), - ns_diff(cntr.rx_ok, old_cntr.rx_ok), - format_brate(rates.rx_bps), - format_prate(rates.rx_pps), - format_util(rates.rx_bps, port_speed), - ns_diff(cntr.rx_err, old_cntr.rx_err), - ns_diff(cntr.rx_drop, old_cntr.rx_drop), - ns_diff(cntr.rx_ovr, old_cntr.rx_ovr), - ns_diff(cntr.tx_ok, old_cntr.tx_ok), - format_brate(rates.tx_bps), - format_prate(rates.tx_pps), - format_util(rates.tx_bps, port_speed), - ns_diff(cntr.tx_err, old_cntr.tx_err), - ns_diff(cntr.tx_drop, old_cntr.tx_drop), - ns_diff(cntr.tx_ovr, old_cntr.tx_ovr))) + table.append((key, + self.get_port_state(key), + ns_diff(cntr.rx_ok, old_cntr.rx_ok), + format_brate(rates.rx_bps), + format_prate(rates.rx_pps), + format_util(rates.rx_bps, port_speed), + ns_diff(cntr.rx_err, old_cntr.rx_err), + ns_diff(cntr.rx_drop, old_cntr.rx_drop), + ns_diff(cntr.rx_ovr, old_cntr.rx_ovr), + ns_diff(cntr.tx_ok, old_cntr.tx_ok), + format_brate(rates.tx_bps), + format_prate(rates.tx_pps), + format_util(rates.tx_bps, port_speed), + ns_diff(cntr.tx_err, old_cntr.tx_err), + ns_diff(cntr.tx_drop, old_cntr.tx_drop), + ns_diff(cntr.tx_ovr, old_cntr.tx_ovr))) elif errors_only: header = header_errors_only - table.append((key, self.get_port_state(key), + table.append((key, + self.get_port_state(key), ns_diff(cntr.rx_err, old_cntr.rx_err), ns_diff(cntr.rx_drop, old_cntr.rx_drop), ns_diff(cntr.rx_ovr, old_cntr.rx_ovr), @@ -412,7 +440,8 @@ class Portstat(object): ns_diff(cntr.tx_ovr, old_cntr.tx_ovr))) elif rates_only: header = header_rates_only - table.append((key, self.get_port_state(key), + table.append((key, + self.get_port_state(key), ns_diff(cntr.rx_ok, old_cntr.rx_ok), format_brate(rates.rx_bps), format_prate(rates.rx_pps), @@ -423,19 +452,20 @@ class Portstat(object): format_util(rates.tx_bps, port_speed))) else: header = header_std - table.append((key, self.get_port_state(key), - ns_diff(cntr.rx_ok, old_cntr.rx_ok), - format_brate(rates.rx_bps), - format_util(rates.rx_bps, port_speed), - ns_diff(cntr.rx_err, old_cntr.rx_err), - ns_diff(cntr.rx_drop, old_cntr.rx_drop), - ns_diff(cntr.rx_ovr, old_cntr.rx_ovr), - ns_diff(cntr.tx_ok, old_cntr.tx_ok), - format_brate(rates.tx_bps), - format_util(rates.tx_bps, port_speed), - ns_diff(cntr.tx_err, old_cntr.tx_err), - ns_diff(cntr.tx_drop, old_cntr.tx_drop), - ns_diff(cntr.tx_ovr, old_cntr.tx_ovr))) + table.append((key, + self.get_port_state(key), + ns_diff(cntr.rx_ok, old_cntr.rx_ok), + format_brate(rates.rx_bps), + format_util(rates.rx_bps, port_speed), + ns_diff(cntr.rx_err, old_cntr.rx_err), + ns_diff(cntr.rx_drop, old_cntr.rx_drop), + ns_diff(cntr.rx_ovr, old_cntr.rx_ovr), + ns_diff(cntr.tx_ok, old_cntr.tx_ok), + format_brate(rates.tx_bps), + format_util(rates.tx_bps, port_speed), + ns_diff(cntr.tx_err, old_cntr.tx_err), + ns_diff(cntr.tx_drop, old_cntr.tx_drop), + ns_diff(cntr.tx_ovr, old_cntr.tx_ovr))) if use_json: print(table_as_json(table, header)) diff --git a/tests/intfstat_test.py b/tests/intfstat_test.py index c220993188..cdf84ee695 100644 --- a/tests/intfstat_test.py +++ b/tests/intfstat_test.py @@ -2,7 +2,11 @@ import os import traceback +import show.main as show +import clear.main as clear + from click.testing import CliRunner +from .mock_tables import dbconnector test_path = os.path.dirname(os.path.abspath(__file__)) modules_path = os.path.dirname(test_path) @@ -10,20 +14,99 @@ sys.path.insert(0, test_path) sys.path.insert(0, modules_path) -from .mock_tables import dbconnector +show_interfaces_counters_rif_output="""\ + IFACE RX_OK RX_BPS RX_PPS RX_ERR TX_OK TX_BPS TX_PPS TX_ERR +--------------- ------- ----------- -------- -------- ------- ---------- -------- -------- + Ethernet20 4 3.00 B/s 4.00/s 2 8 754.00 B/s 8.00/s 6 +PortChannel0001 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0002 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0003 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +PortChannel0004 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 + Vlan1000 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +""" -import show.main as show -import clear.main as clear +show_interfaces_counters_rif_output_verbose="""\ +Running command: intfstat + IFACE RX_OK RX_BPS RX_PPS RX_ERR TX_OK TX_BPS TX_PPS TX_ERR +--------------- ------- ----------- -------- -------- ------- ---------- -------- -------- + Ethernet20 4 3.00 B/s 4.00/s 2 8 754.00 B/s 8.00/s 6 +PortChannel0001 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0002 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0003 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +PortChannel0004 883 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 + Vlan1000 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +""" -show_interfaces_counters_rif_output="""\ - IFACE RX_OK RX_BPS RX_PPS RX_ERR TX_OK TX_BPS TX_PPS TX_ERR ---------------- ------- -------- -------- -------- ------- -------- -------- -------- - Ethernet20 4 N/A N/A 2 8 N/A N/A 6 -PortChannel0001 883 N/A N/A 0 0 N/A N/A 0 -PortChannel0002 883 N/A N/A 0 0 N/A N/A 0 -PortChannel0003 0 N/A N/A 0 0 N/A N/A 0 -PortChannel0004 883 N/A N/A 0 0 N/A N/A 0 - Vlan1000 0 N/A N/A 0 0 N/A N/A 0 +show_interfaces_counters_rif_period="""\ +The rates are calculated within 3 seconds period + IFACE RX_OK RX_BPS RX_PPS RX_ERR TX_OK TX_BPS TX_PPS TX_ERR +--------------- ------- ----------- -------- -------- ------- ---------- -------- -------- + Ethernet20 0 3.00 B/s 4.00/s 0 0 754.00 B/s 8.00/s 0 +PortChannel0001 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0002 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0003 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +PortChannel0004 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 + Vlan1000 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +""" + +show_interfaces_counters_rif_period_single_intf="""\ +The rates are calculated within 3 seconds period +Ethernet20 +---------- + + RX: + 0 packets + 0 bytes + 0 error packets + 0 error bytes + TX: + 0 packets + 0 bytes + 0 error packets + 0 error bytes +""" + +show_interfaces_counters_rif_single_intf="""\ +Ethernet20 +---------- + + RX: + 4 packets + 3 bytes + 2 error packets + 1128 error bytes + TX: + 8 packets + 754 bytes + 6 error packets + 5 error bytes +""" + +show_interfaces_counters_rif_clear_single_intf="""\ +Ethernet20 +---------- + + RX: + 0 packets + 0 bytes + 0 error packets + 0 error bytes + TX: + 0 packets + 0 bytes + 0 error packets + 0 error bytes +""" + +show_interfaces_counters_rif_clear="""\ + IFACE RX_OK RX_BPS RX_PPS RX_ERR TX_OK TX_BPS TX_PPS TX_ERR +--------------- ------- ----------- -------- -------- ------- ---------- -------- -------- + Ethernet20 0 3.00 B/s 4.00/s 0 0 754.00 B/s 8.00/s 0 +PortChannel0001 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0002 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 +PortChannel0003 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 +PortChannel0004 0 594.71 KB/s 0.00/s 0 0 883.00 B/s 0.00/s 0 + Vlan1000 0 0.00 B/s 0.00/s 0 0 0.00 B/s 0.00/s 0 """ class TestIntfstat(object): @@ -46,38 +129,25 @@ def test_verbose(self): runner = CliRunner() result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], ["--verbose"]) print(result.output) - assert result.output.split('\n')[0] == "Running command: intfstat" + assert result.output == show_interfaces_counters_rif_output_verbose def test_period(self): runner = CliRunner() result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], ["-p3"]) print(result.output) - assert result.output.split('\n')[0] == "The rates are calculated within 3 seconds period" + assert result.output == show_interfaces_counters_rif_period def test_period_single_interface(self): runner = CliRunner() result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], ["Ethernet20", "-p3"]) print(result.output) - assert result.output.split('\n')[0] == "The rates are calculated within 3 seconds period" + assert result.output == show_interfaces_counters_rif_period_single_intf def test_single_intfs(self): runner = CliRunner() result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], ["Ethernet20"]) - expected = """Ethernet20 ----------- - - RX: - 4 packets - 3 bytes - 2 error packets - 1128 error bytes - TX: - 8 packets - 754 bytes - 6 error packets - 5 error bytes -""" - assert result.output == expected + print(result.output) + assert result.output == show_interfaces_counters_rif_single_intf def test_clear_single_intfs(self): runner = CliRunner() @@ -85,23 +155,11 @@ def test_clear_single_intfs(self): print(result.stdout) assert result.exit_code == 0 result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], ["Ethernet20"]) - expected = """Ethernet20 ----------- - - RX: - 0 packets - 0 bytes - 0 error packets - 0 error bytes - TX: - 0 packets - 0 bytes - 0 error packets - 0 error bytes -""" + print(result.output) + assert 'Last cached time was' in result.output.split('\n')[0] + assert show_interfaces_counters_rif_clear_single_intf in result.output # remove the counters snapshot show.run_command("intfstat -D") - assert expected in result.output def test_clear(self): runner = CliRunner() @@ -110,7 +168,8 @@ def test_clear(self): assert result.exit_code == 0 result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["rif"], []) print(result.stdout) - + assert 'Last cached time was' in result.output.split('\n')[0] + assert show_interfaces_counters_rif_clear in result.output # remove the counters snapshot show.run_command("intfstat -D") diff --git a/tests/mock_tables/counters_db.json b/tests/mock_tables/counters_db.json index 131ebcdfcd..fc86425583 100644 --- a/tests/mock_tables/counters_db.json +++ b/tests/mock_tables/counters_db.json @@ -409,7 +409,6 @@ "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0", "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", "SAI_QUEUE_STAT_DROPPED_BYTES": "0", - "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", "SAI_QUEUE_STAT_BYTES": "0", "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "0" }, @@ -424,7 +423,6 @@ "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0", "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", "SAI_QUEUE_STAT_DROPPED_BYTES": "0", - "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", "SAI_QUEUE_STAT_BYTES": "0", "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "0" }, @@ -486,6 +484,42 @@ "TX_BPS": "13.37e6", "TX_PPS": "9000" }, + "RATES:oid:0x600000000065f": { + "RX_BPS": "3", + "RX_PPS": "4", + "TX_BPS": "754", + "TX_PPS": "8" + }, + "RATES:oid:0x60000000005a1": { + "RX_BPS": "608985", + "RX_PPS": "0", + "TX_BPS": "883", + "TX_PPS": "0" + }, + "RATES:oid:0x60000000005a2": { + "RX_BPS": "608985", + "RX_PPS": "0", + "TX_BPS": "883", + "TX_PPS": "0" + }, + "RATES:oid:0x600000000063c": { + "RX_BPS": "0", + "RX_PPS": "0", + "TX_BPS": "0", + "TX_PPS": "0" + }, + "RATES:oid:0x600000000063d": { + "RX_BPS": "608985", + "RX_PPS": "0", + "TX_BPS": "883", + "TX_PPS": "0" + }, + "RATES:oid:0x60000000005a3": { + "RX_BPS": "0", + "RX_PPS": "0", + "TX_BPS": "0", + "TX_PPS": "0" + }, "COUNTERS_RIF_NAME_MAP": { "Ethernet20": "oid:0x600000000065f", "PortChannel0001": "oid:0x60000000005a1", diff --git a/tests/portstat_test.py b/tests/portstat_test.py index c06dcd7e0b..d79e421507 100644 --- a/tests/portstat_test.py +++ b/tests/portstat_test.py @@ -12,25 +12,25 @@ scripts_path = os.path.join(modules_path, "scripts") intf_counters_before_clear = """\ - IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR ---------- ------- ------- -------- --------- -------- -------- -------- ------- -------- --------- -------- -------- -------- -Ethernet0 D 8 N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A -Ethernet4 N/A 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A -Ethernet8 N/A 6 N/A N/A 100 10 N/A 60 N/A N/A N/A N/A N/A + IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR +--------- ------- ------- ------------ --------- -------- -------- -------- ------- ----------- --------- -------- -------- -------- +Ethernet0 D 8 0.00 B/s 0.00% 10 100 N/A 10 0.00 B/s 0.00% N/A N/A N/A +Ethernet4 N/A 4 200.00 KB/s 0.00% 0 1000 N/A 40 200.05 KB/s 0.00% N/A N/A N/A +Ethernet8 N/A 6 1318.36 KB/s 0.03% 100 10 N/A 60 12.75 MB/s 0.25% N/A N/A N/A """ intf_counters_ethernet4 = """\ - IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR ---------- ------- ------- -------- --------- -------- -------- -------- ------- -------- --------- -------- -------- -------- -Ethernet4 N/A 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A + IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR +--------- ------- ------- ----------- --------- -------- -------- -------- ------- ----------- --------- -------- -------- -------- +Ethernet4 N/A 4 200.00 KB/s 0.00% 0 1000 N/A 40 200.05 KB/s 0.00% N/A N/A N/A """ intf_counters_all = """\ - IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS Tx_PPS TX_UTIL TX_ERR TX_DRP TX_OVR ---------- ------- ------- -------- -------- --------- -------- -------- -------- ------- -------- -------- --------- -------- -------- -------- -Ethernet0 D 8 N/A N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A N/A -Ethernet4 N/A 4 N/A N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A N/A -Ethernet8 N/A 6 N/A N/A N/A 100 10 N/A 60 N/A N/A N/A N/A N/A N/A + IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_PPS TX_UTIL TX_ERR TX_DRP TX_OVR +--------- ------- ------- ------------ --------- --------- -------- -------- -------- ------- ----------- --------- --------- -------- -------- -------- +Ethernet0 D 8 0.00 B/s 0.00/s 0.00% 10 100 N/A 10 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet4 N/A 4 200.00 KB/s 200.00/s 0.00% 0 1000 N/A 40 200.05 KB/s 201.00/s 0.00% N/A N/A N/A +Ethernet8 N/A 6 1318.36 KB/s 9000.00/s 0.03% 100 10 N/A 60 12.75 MB/s 9000.00/s 0.25% N/A N/A N/A """ intf_counters_period = """\ @@ -55,54 +55,54 @@ multi_asic_external_intf_counters = """\ IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR --------- ------- ------- -------- --------- -------- -------- -------- ------- -------- --------- -------- -------- -------- -Ethernet0 U 8 N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A -Ethernet4 U 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A +Ethernet0 U 8 0.00 B/s 0.00% 10 100 N/A 10 0.00 B/s 0.00% N/A N/A N/A +Ethernet4 U 4 0.00 B/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00% N/A N/A N/A """ multi_asic_all_intf_counters = """\ IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR -------------- ------- ------- -------- --------- -------- -------- -------- ------- -------- --------- -------- -------- -------- - Ethernet0 U 8 N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A - Ethernet4 U 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A - Ethernet-BP0 U 6 N/A N/A 0 1000 N/A 60 N/A N/A N/A N/A N/A - Ethernet-BP4 U 8 N/A N/A 0 1000 N/A 80 N/A N/A N/A N/A N/A -Ethernet-BP256 U 8 N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A -Ethernet-BP260 U 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A + Ethernet0 U 8 0.00 B/s 0.00% 10 100 N/A 10 0.00 B/s 0.00% N/A N/A N/A + Ethernet4 U 4 0.00 B/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00% N/A N/A N/A + Ethernet-BP0 U 6 0.00 B/s 0.00% 0 1000 N/A 60 0.00 B/s 0.00% N/A N/A N/A + Ethernet-BP4 U 8 0.00 B/s 0.00% 0 1000 N/A 80 0.00 B/s 0.00% N/A N/A N/A +Ethernet-BP256 U 8 0.00 B/s 0.00% 10 100 N/A 10 0.00 B/s 0.00% N/A N/A N/A +Ethernet-BP260 U 4 0.00 B/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00% N/A N/A N/A """ multi_asic_intf_counters_asic0 = """\ IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR ------------ ------- ------- -------- --------- -------- -------- -------- ------- -------- --------- -------- -------- -------- - Ethernet0 U 8 N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A - Ethernet4 U 4 N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A -Ethernet-BP0 U 6 N/A N/A 0 1000 N/A 60 N/A N/A N/A N/A N/A -Ethernet-BP4 U 8 N/A N/A 0 1000 N/A 80 N/A N/A N/A N/A N/A + Ethernet0 U 8 0.00 B/s 0.00% 10 100 N/A 10 0.00 B/s 0.00% N/A N/A N/A + Ethernet4 U 4 0.00 B/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00% N/A N/A N/A +Ethernet-BP0 U 6 0.00 B/s 0.00% 0 1000 N/A 60 0.00 B/s 0.00% N/A N/A N/A +Ethernet-BP4 U 8 0.00 B/s 0.00% 0 1000 N/A 80 0.00 B/s 0.00% N/A N/A N/A """ multi_asic_external_intf_counters_printall = """\ - IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS Tx_PPS TX_UTIL TX_ERR TX_DRP TX_OVR + IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_PPS TX_UTIL TX_ERR TX_DRP TX_OVR --------- ------- ------- -------- -------- --------- -------- -------- -------- ------- -------- -------- --------- -------- -------- -------- -Ethernet0 U 8 N/A N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A N/A -Ethernet4 U 4 N/A N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A N/A +Ethernet0 U 8 0.00 B/s 0.00/s 0.00% 10 100 N/A 10 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet4 U 4 0.00 B/s 0.00/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00/s 0.00% N/A N/A N/A """ multi_asic_intf_counters_printall = """\ - IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS Tx_PPS TX_UTIL TX_ERR TX_DRP TX_OVR + IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_PPS TX_UTIL TX_ERR TX_DRP TX_OVR -------------- ------- ------- -------- -------- --------- -------- -------- -------- ------- -------- -------- --------- -------- -------- -------- - Ethernet0 U 8 N/A N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A N/A - Ethernet4 U 4 N/A N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A N/A - Ethernet-BP0 U 6 N/A N/A N/A 0 1000 N/A 60 N/A N/A N/A N/A N/A N/A - Ethernet-BP4 U 8 N/A N/A N/A 0 1000 N/A 80 N/A N/A N/A N/A N/A N/A -Ethernet-BP256 U 8 N/A N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A N/A -Ethernet-BP260 U 4 N/A N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A N/A + Ethernet0 U 8 0.00 B/s 0.00/s 0.00% 10 100 N/A 10 0.00 B/s 0.00/s 0.00% N/A N/A N/A + Ethernet4 U 4 0.00 B/s 0.00/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00/s 0.00% N/A N/A N/A + Ethernet-BP0 U 6 0.00 B/s 0.00/s 0.00% 0 1000 N/A 60 0.00 B/s 0.00/s 0.00% N/A N/A N/A + Ethernet-BP4 U 8 0.00 B/s 0.00/s 0.00% 0 1000 N/A 80 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet-BP256 U 8 0.00 B/s 0.00/s 0.00% 10 100 N/A 10 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet-BP260 U 4 0.00 B/s 0.00/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00/s 0.00% N/A N/A N/A """ multi_asic_intf_counters_asic0_printall = """\ - IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS Tx_PPS TX_UTIL TX_ERR TX_DRP TX_OVR + IFACE STATE RX_OK RX_BPS RX_PPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_PPS TX_UTIL TX_ERR TX_DRP TX_OVR ------------ ------- ------- -------- -------- --------- -------- -------- -------- ------- -------- -------- --------- -------- -------- -------- - Ethernet0 U 8 N/A N/A N/A 10 100 N/A 10 N/A N/A N/A N/A N/A N/A - Ethernet4 U 4 N/A N/A N/A 0 1000 N/A 40 N/A N/A N/A N/A N/A N/A -Ethernet-BP0 U 6 N/A N/A N/A 0 1000 N/A 60 N/A N/A N/A N/A N/A N/A -Ethernet-BP4 U 8 N/A N/A N/A 0 1000 N/A 80 N/A N/A N/A N/A N/A N/A + Ethernet0 U 8 0.00 B/s 0.00/s 0.00% 10 100 N/A 10 0.00 B/s 0.00/s 0.00% N/A N/A N/A + Ethernet4 U 4 0.00 B/s 0.00/s 0.00% 0 1000 N/A 40 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet-BP0 U 6 0.00 B/s 0.00/s 0.00% 0 1000 N/A 60 0.00 B/s 0.00/s 0.00% N/A N/A N/A +Ethernet-BP4 U 8 0.00 B/s 0.00/s 0.00% 0 1000 N/A 80 0.00 B/s 0.00/s 0.00% N/A N/A N/A """ multi_asic_intf_counters_period = """\ The rates are calculated within 3 seconds period diff --git a/utilities_common/netstat.py b/utilities_common/netstat.py index 0e903eb769..e1863229c9 100755 --- a/utilities_common/netstat.py +++ b/utilities_common/netstat.py @@ -1,19 +1,10 @@ # network statistics utility functions # import json -from collections import namedtuple STATUS_NA = 'N/A' PORT_RATE = 40 -rates_key_list = [ 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_BPS', 'TX_PPS', 'TX_UTIL' ] -ratestat_fields = ("rx_bps", "rx_pps", "rx_util", "tx_bps", "tx_pps", "tx_util") -RateStats = namedtuple("RateStats", ratestat_fields) - -COUNTERS_PORT_NAME_MAP = "COUNTERS_PORT_NAME_MAP" -COUNTERS_RIF_NAME_MAP = "COUNTERS_RIF_NAME_MAP" -RATES_TABLE_PREFIX = "RATES:" - def ns_diff(newstr, oldstr): """ Calculate the diff. @@ -88,6 +79,7 @@ def format_prate(rate): if rate == STATUS_NA: return STATUS_NA else: + #TODO what does it mean /s maybe p/s packets per seconds return "{:.2f}".format(float(rate))+'/s' def format_util(brate, port_rate=PORT_RATE):