Skip to content

Commit

Permalink
[show][interface][counters] Add proposal and changes for fec-histogra…
Browse files Browse the repository at this point in the history
…m for interface counters fec-histogram subcommand (#3519)

* [show][interface][counters] Add proposal and changes for fec-histogram
for show int counters fec-histogram subcommand

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add implementation

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add changes

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add changes

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add UT

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* fix test

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* correct doc

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add changes

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add cosmetic fix

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add fixes

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* pep 8

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

* add indentation

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>

---------

Signed-off-by: Vaibhav Dahiya <vdahiya@microsoft.com>
  • Loading branch information
vdahiya12 authored and mssonicbld committed Sep 20, 2024
1 parent be6d620 commit d3e9968
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 1 deletion.
34 changes: 34 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4732,6 +4732,7 @@ Optional argument "-p" specify a period (in seconds) with which to gather counte
show interfaces counters errors
show interfaces counters rates
show interfaces counters rif [-p|--period <period>] [-i <interface_name>]
show interfaces counters fec-histogram [-i <interface_name>]
```

- Example:
Expand Down Expand Up @@ -4849,6 +4850,39 @@ Optionally, you can specify a period (in seconds) with which to gather counters
admin@sonic:~$ sonic-clear rifcounters
```

The "fec-histogram" subcommand is used to display the fec histogram for the port.

When data is transmitted, it's broken down into units called codewords. FEC algorithms add extra data to each codeword that can be used to detect and correct errors in transmission.
In a FEC histogram, "bins" represent ranges of errors or specific categories of errors. For instance, Bin0 might represent codewords with no errors, while Bin1 could represent codewords with a single bit error, and so on. The histogram shows how many codewords fell into each bin. A high number in the higher bins might indicate a problem with the transmission link, such as signal degradation.
- Example:
```
admin@str-s6000-acs-11:/usr/bin$ show interface counters fec-histogram -i <PORT>
Symbol Errors Per Codeword Codewords
-------------------------- ---------
BIN0: 1000000
BIN1: 900000
BIN2: 800000
BIN3: 700000
BIN4: 600000
BIN5: 500000
BIN6: 400000
BIN7: 300000
BIN8: 0
BIN9: 0
BIN10: 0
BIN11: 0
BIN12: 0
BIN13: 0
BIN14: 0
BIN15: 0
```
**show interfaces description**
This command displays the key fields of the interfaces such as Operational Status, Administrative Status, Alias and Description.
Expand Down
70 changes: 70 additions & 0 deletions show/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

HWSKU_JSON = 'hwsku.json'

REDIS_HOSTIP = "127.0.0.1"

# Read given JSON file
def readJsonFile(fileName):
try:
Expand Down Expand Up @@ -646,6 +648,74 @@ def fec_stats(verbose, period, namespace, display):

clicommon.run_command(cmd, display_cmd=verbose)


def get_port_oid_mapping():
''' Returns dictionary of all ports interfaces and their OIDs. '''
db = SonicV2Connector(host=REDIS_HOSTIP)
db.connect(db.COUNTERS_DB)

port_oid_map = db.get_all(db.COUNTERS_DB, 'COUNTERS_PORT_NAME_MAP')

db.close(db.COUNTERS_DB)

return port_oid_map


def fetch_fec_histogram(port_oid_map, target_port):
''' Fetch and display FEC histogram for the given port. '''
asic_db = SonicV2Connector(host=REDIS_HOSTIP)
asic_db.connect(asic_db.ASIC_DB)

config_db = ConfigDBConnector()
config_db.connect()

counter_db = SonicV2Connector(host=REDIS_HOSTIP)
counter_db.connect(counter_db.COUNTERS_DB)

if target_port not in port_oid_map:
click.echo('Port {} not found in COUNTERS_PORT_NAME_MAP'.format(target_port), err=True)
raise click.Abort()

port_oid = port_oid_map[target_port]
asic_db_kvp = counter_db.get_all(counter_db.COUNTERS_DB, 'COUNTERS:{}'.format(port_oid))

if asic_db_kvp is not None:

fec_errors = {f'BIN{i}': asic_db_kvp.get
(f'SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S{i}', '0') for i in range(16)}

# Prepare the data for tabulation
table_data = [(bin_label, error_value) for bin_label, error_value in fec_errors.items()]

# Define headers
headers = ["Symbol Errors Per Codeword", "Codewords"]

# Print FEC histogram using tabulate
click.echo(tabulate(table_data, headers=headers))
else:
click.echo('No kvp found in ASIC DB for port {}, exiting'.format(target_port), err=True)
raise click.Abort()

asic_db.close(asic_db.ASIC_DB)
config_db.close(config_db.CONFIG_DB)
counter_db.close(counter_db.COUNTERS_DB)


# 'fec-histogram' subcommand ("show interfaces counters fec-histogram")
@counters.command('fec-histogram')
@multi_asic_util.multi_asic_click_options
@click.argument('interfacename', required=True)
def fec_histogram(interfacename, namespace, display):
"""Show interface counters fec-histogram"""
port_oid_map = get_port_oid_mapping()

# Try to convert interface name from alias
interfacename = try_convert_interfacename_from_alias(click.get_current_context(), interfacename)

# Fetch and display the FEC histogram
fetch_fec_histogram(port_oid_map, interfacename)


# 'rates' subcommand ("show interfaces counters rates")
@counters.command()
@click.option('-p', '--period')
Expand Down
18 changes: 17 additions & 1 deletion tests/mock_tables/counters_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,23 @@
"SAI_PORT_STAT_ETHER_STATS_JABBERS": "0",
"SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "130402",
"SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "3",
"SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "4"
"SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "4",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S0": "1000000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S1": "900000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S2": "800000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S3": "700000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S4": "600000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S5": "500000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S6": "400000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S7": "300000",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S8": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S9": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S10": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S11": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S12": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S13": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S14": "0",
"SAI_PORT_STAT_IF_IN_FEC_CODEWORD_ERRORS_S15": "0"
},
"COUNTERS:oid:0x1000000000013": {
"SAI_PORT_STAT_IF_IN_UCAST_PKTS": "4",
Expand Down
30 changes: 30 additions & 0 deletions tests/portstat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@
Ethernet8 N/A 100,317 0 0
"""

intf_fec_counters_fec_hist = """\
Symbol Errors Per Codeword Codewords
---------------------------- -----------
BIN0 1000000
BIN1 900000
BIN2 800000
BIN3 700000
BIN4 600000
BIN5 500000
BIN6 400000
BIN7 300000
BIN8 0
BIN9 0
BIN10 0
BIN11 0
BIN12 0
BIN13 0
BIN14 0
BIN15 0
"""

intf_fec_counters_period = """\
The rates are calculated within 3 seconds period
IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR
Expand Down Expand Up @@ -337,6 +358,15 @@ def test_show_intf_fec_counters(self):
assert return_code == 0
assert result == intf_fec_counters

def test_show_intf_counters_fec_histogram(self):
runner = CliRunner()
result = runner.invoke(
show.cli.commands["interfaces"].commands["counters"].commands["fec-histogram"], ["Ethernet0"])
print(result.exit_code)
print(result.output)
assert result.exit_code == 0
assert result.output == intf_fec_counters_fec_hist

def test_show_intf_fec_counters_period(self):
runner = CliRunner()
result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["fec-stats"],
Expand Down

0 comments on commit d3e9968

Please sign in to comment.