diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index c6c6f2003a..fdff48d5c7 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -4894,6 +4894,7 @@ Optional argument "-p" specify a period (in seconds) with which to gather counte show interfaces counters rates show interfaces counters rif [-p|--period ] [-i ] show interfaces counters fec-histogram [-i ] + show interfaces counters fec-stats ``` - Example: @@ -5039,6 +5040,18 @@ In a FEC histogram, "bins" represent ranges of errors or specific categories of BIN15: 0 ``` +The "fec-stats" subcommand is used to disply the interface fec related statistic. + +- Example: + ``` + admin@ctd615:~$ show interfaces counters fec-stats + IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR FEC_PRE_BER FEC_POST_BER + ----------- ------- ---------- ------------ ---------------- ------------- -------------- + Ethernet0 U 0 0 0 1.48e-20 0.00e+00 + Ethernet8 U 0 0 0 1.98e-19 0.00e+00 + Ethernet16 U 0 0 0 1.77e-20 0.00e+00 + ``` + **show interfaces description** @@ -13907,4 +13920,4 @@ enabled Login You are on All access and/or use are subject to monitoring. Help: https://sonic-net.github.io/SONiC/ -``` \ No newline at end of file +``` diff --git a/tests/portstat_test.py b/tests/portstat_test.py index 9c6f94d96a..e7499b94fd 100644 --- a/tests/portstat_test.py +++ b/tests/portstat_test.py @@ -35,11 +35,11 @@ """ intf_fec_counters = """\ - IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR ---------- ------- ---------- ------------ ---------------- -Ethernet0 D 130,402 3 4 -Ethernet4 N/A 110,412 1 0 -Ethernet8 N/A 100,317 0 0 + IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR FEC_PRE_BER FEC_POST_BER +--------- ------- ---------- ------------ ---------------- ------------- -------------- +Ethernet0 D 130,402 3 4 N/A N/A +Ethernet4 N/A 110,412 1 0 N/A N/A +Ethernet8 N/A 100,317 0 0 N/A N/A """ intf_fec_counters_fec_hist = """\ diff --git a/utilities_common/netstat.py b/utilities_common/netstat.py index 21b1a0faeb..e32e28c745 100755 --- a/utilities_common/netstat.py +++ b/utilities_common/netstat.py @@ -108,6 +108,16 @@ def format_prate(rate): return "{:.2f}".format(float(rate))+'/s' +def format_fec_ber(rate): + """ + Show the ber rate. + """ + if rate == STATUS_NA: + return STATUS_NA + else: + return "{:.2e}".format(float(rate)) + + def format_util(brate, port_rate): """ Calculate the util. diff --git a/utilities_common/portstat.py b/utilities_common/portstat.py index 8fcbc6b0d9..d28584682a 100644 --- a/utilities_common/portstat.py +++ b/utilities_common/portstat.py @@ -11,7 +11,8 @@ from utilities_common import constants 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, format_number_with_comma, format_util_directly + format_util, format_number_with_comma, format_util_directly, \ + format_fec_ber """ The order and count of statistics mentioned below needs to be in sync with the values in portstat script @@ -32,11 +33,11 @@ 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_fec_only = ['IFACE', 'STATE', 'FEC_CORR', 'FEC_UNCORR', 'FEC_SYMBOL_ERR'] +header_fec_only = ['IFACE', 'STATE', 'FEC_CORR', 'FEC_UNCORR', 'FEC_SYMBOL_ERR', 'FEC_PRE_BER', 'FEC_POST_BER'] 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") +rates_key_list = ['RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_BPS', 'TX_PPS', 'TX_UTIL', 'FEC_PRE_BER', 'FEC_POST_BER'] +ratestat_fields = ("rx_bps", "rx_pps", "rx_util", "tx_bps", "tx_pps", "tx_util", "fec_pre_ber", "fec_post_ber") RateStats = namedtuple("RateStats", ratestat_fields) """ @@ -194,10 +195,13 @@ def collect_stat_from_lc(self): tx_err = self.db.get(self.db.CHASSIS_STATE_DB, key, "tx_err") tx_drop = self.db.get(self.db.CHASSIS_STATE_DB, key, "tx_drop") tx_ovr = self.db.get(self.db.CHASSIS_STATE_DB, key, "tx_ovr") + fec_pre_ber = self.db.get(self.db.CHASSIS_STATE_DB, key, "fec_pre_ber") + fec_post_ber = self.db.get(self.db.CHASSIS_STATE_DB, key, "fec_post_ber") port_alias = key.split("|")[-1] cnstat_dict[port_alias] = NStats._make([rx_ok, rx_err, rx_drop, rx_ovr, tx_ok, tx_err, tx_drop, tx_ovr] + [STATUS_NA] * (len(NStats._fields) - 8))._asdict() - ratestat_dict[port_alias] = RateStats._make([rx_bps, rx_pps, rx_util, tx_bps, tx_pps, tx_util]) + ratestat_dict[port_alias] = RateStats._make([rx_bps, rx_pps, rx_util, tx_bps, + tx_pps, tx_util, fec_pre_ber, fec_post_ber]) self.cnstat_dict.update(cnstat_dict) self.ratestat_dict.update(ratestat_dict) @@ -238,7 +242,7 @@ def get_rates(table_id): """ Get the rates from specific table. """ - fields = ["0", "0", "0", "0", "0", "0"] + fields = ["0", "0", "0", "0", "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) @@ -363,7 +367,9 @@ def cnstat_print(self, cnstat_dict, ratestat_dict, intf_list, use_json, print_al table.append((key, self.get_port_state(key), format_number_with_comma(data['fec_corr']), format_number_with_comma(data['fec_uncorr']), - format_number_with_comma(data['fec_symbol_err']))) + format_number_with_comma(data['fec_symbol_err']), + format_fec_ber(rates.fec_pre_ber), + format_fec_ber(rates.fec_post_ber))) elif rates_only: header = header_rates_only table.append((key, self.get_port_state(key),