Skip to content

Commit ddccabe

Browse files
authored
[show][interface] Add changes for show interface errors command (sonic-net#3721)
* [show][interface] Add changes for interface errors command Signed-off-by: Vaibhav Dahiya <[email protected]> * remove redundant lines Signed-off-by: Vaibhav Dahiya <[email protected]> * add correction Signed-off-by: Vaibhav Dahiya <[email protected]> * back reverted Signed-off-by: Vaibhav Dahiya <[email protected]> * add ch Signed-off-by: Vaibhav Dahiya <[email protected]> * fix static Signed-off-by: Vaibhav Dahiya <[email protected]> * add phg Signed-off-by: Vaibhav Dahiya <[email protected]> * add prest Signed-off-by: Vaibhav Dahiya <[email protected]> * add fgr Signed-off-by: Vaibhav Dahiya <[email protected]> * add all Signed-off-by: Vaibhav Dahiya <[email protected]> * remove all redundant spaces Signed-off-by: Vaibhav Dahiya <[email protected]> * add key Signed-off-by: Vaibhav Dahiya <[email protected]> * add cgre Signed-off-by: Vaibhav Dahiya <[email protected]> --------- Signed-off-by: Vaibhav Dahiya <[email protected]>
1 parent be870a6 commit ddccabe

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

show/interfaces/__init__.py

+68
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,74 @@ def mpls(ctx, interfacename, namespace, display):
414414

415415
interfaces.add_command(portchannel.portchannel)
416416

417+
418+
def get_all_port_errors(interfacename):
419+
420+
port_operr_table = {}
421+
db = SonicV2Connector(host=REDIS_HOSTIP)
422+
db.connect(db.STATE_DB)
423+
424+
# Retrieve the errors data from the PORT_OPERR_TABLE
425+
port_operr_table = db.get_all(db.STATE_DB, 'PORT_OPERR_TABLE|{}'.format(interfacename))
426+
db.close(db.STATE_DB)
427+
428+
return port_operr_table
429+
430+
431+
@interfaces.command()
432+
@click.argument('interfacename', required=True)
433+
@click.pass_context
434+
def errors(ctx, interfacename):
435+
"""Show Interface Erorrs <interfacename>"""
436+
# Try to convert interface name from alias
437+
interfacename = try_convert_interfacename_from_alias(click.get_current_context(), interfacename)
438+
439+
port_operr_table = get_all_port_errors(interfacename)
440+
441+
# Define a list of all potential errors
442+
ALL_PORT_ERRORS = [
443+
"oper_error_status",
444+
"mac_local_fault",
445+
"mac_remote_fault",
446+
"fec_sync_loss",
447+
"fec_alignment_loss",
448+
"high_ser_error",
449+
"high_ber_error",
450+
"data_unit_crc_error",
451+
"data_unit_misalignment_error",
452+
"signal_local_error",
453+
"crc_rate",
454+
"data_unit_size",
455+
"code_group_error",
456+
"no_rx_reachability"
457+
]
458+
459+
# Prepare the table headers and body
460+
header = ['Port Errors', 'Count', 'Last timestamp(UTC)']
461+
body = []
462+
463+
# Populate the table body with all errors, defaulting missing ones to 0 and Never
464+
for error in ALL_PORT_ERRORS:
465+
count_key = f"{error}_count"
466+
time_key = f"{error}_time"
467+
468+
if port_operr_table is not None:
469+
count = port_operr_table.get(count_key, "0") # Default count to '0'
470+
timestamp = port_operr_table.get(time_key, "Never") # Default timestamp to 'Never'
471+
else:
472+
count = "0"
473+
timestamp = "Never"
474+
475+
# Add to table
476+
body.append([error.replace('_', ' '), count, timestamp])
477+
478+
# Sort the body for consistent display
479+
body.sort(key=lambda x: x[0])
480+
481+
# Display the formatted table
482+
click.echo(tabulate(body, header))
483+
484+
417485
#
418486
# transceiver group (show interfaces trasceiver ...)
419487
#

tests/interfaces_test.py

+120
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,82 @@
263263
PortChannel1001 trunk 4000
264264
"""
265265

266+
intf_errors_Ethernet64 = """\
267+
Port Errors Count Last timestamp(UTC)
268+
---------------------------- ------- ---------------------
269+
code group error 0 Never
270+
crc rate 0 Never
271+
data unit crc error 0 Never
272+
data unit misalignment error 0 Never
273+
data unit size 0 Never
274+
fec alignment loss 0 Never
275+
fec sync loss 0 Never
276+
high ber error 0 Never
277+
high ser error 0 Never
278+
mac local fault 26 2025-01-17 18:40:56
279+
mac remote fault 14483 2025-01-17 19:51:12
280+
no rx reachability 0 Never
281+
oper error status 0 Never
282+
signal local error 0 Never
283+
"""
284+
intf_errors_Ethernet16 = """\
285+
Port Errors Count Last timestamp(UTC)
286+
---------------------------- ------- ---------------------
287+
code group error 0 Never
288+
crc rate 0 Never
289+
data unit crc error 0 Never
290+
data unit misalignment error 0 Never
291+
data unit size 0 Never
292+
fec alignment loss 0 Never
293+
fec sync loss 0 Never
294+
high ber error 0 Never
295+
high ser error 0 Never
296+
mac local fault 0 Never
297+
mac remote fault 0 Never
298+
no rx reachability 0 Never
299+
oper error status 0 Never
300+
signal local error 0 Never
301+
"""
302+
303+
intf_errors_Ethernet32 = """\
304+
Port Errors Count Last timestamp(UTC)
305+
---------------------------- ------- ---------------------
306+
code group error 0 Never
307+
crc rate 0 Never
308+
data unit crc error 0 Never
309+
data unit misalignment error 0 Never
310+
data unit size 0 Never
311+
fec alignment loss 0 Never
312+
fec sync loss 3 2025-01-16 13:45:20
313+
high ber error 1 2025-01-16 14:30:10
314+
high ser error 0 Never
315+
mac local fault 5 2025-01-16 12:05:34
316+
mac remote fault 0
317+
no rx reachability 0 Never
318+
oper error status 0 Never
319+
signal local error 0 Never
320+
"""
321+
322+
intf_errors_Ethernet48 = """\
323+
Port Errors Count Last timestamp(UTC)
324+
---------------------------- ------- ---------------------
325+
code group error 0 Never
326+
crc rate 0 Never
327+
data unit crc error 0 Never
328+
data unit misalignment error 0 Never
329+
data unit size 0 Never
330+
fec alignment loss 0 Never
331+
fec sync loss 0 Never
332+
high ber error 0 Never
333+
high ser error 0 Never
334+
mac local fault 0
335+
mac remote fault 0
336+
no rx reachability 0 Never
337+
oper error status 0 Never
338+
signal local error 0 Never
339+
"""
340+
341+
266342

267343
class TestInterfaces(object):
268344
@classmethod
@@ -496,6 +572,50 @@ def test_show_interfaces_switchport_config_in_alias_mode(self):
496572
assert result.exit_code == 0
497573
assert result.output == show_interfaces_switchport_config_in_alias_mode_output
498574

575+
def test_show_intf_errors_filled_data(self):
576+
"""Test case for an interface with filled error data."""
577+
runner = CliRunner()
578+
result = runner.invoke(
579+
show.cli.commands["interfaces"].commands["errors"], ["Ethernet64"]
580+
)
581+
print(result.exit_code)
582+
print(result.output)
583+
assert result.exit_code == 0
584+
assert result.output == intf_errors_Ethernet64
585+
586+
def test_show_intf_errors_empty_data(self):
587+
"""Test case for an interface with no error data."""
588+
runner = CliRunner()
589+
result = runner.invoke(
590+
show.cli.commands["interfaces"].commands["errors"], ["Ethernet16"]
591+
)
592+
print(result.exit_code)
593+
print(result.output)
594+
assert result.exit_code == 0
595+
assert result.output == intf_errors_Ethernet16
596+
597+
def test_show_intf_errors_partial_data(self):
598+
"""Test case for an interface with partial error data."""
599+
runner = CliRunner()
600+
result = runner.invoke(
601+
show.cli.commands["interfaces"].commands["errors"], ["Ethernet32"]
602+
)
603+
print(result.exit_code)
604+
print(result.output)
605+
assert result.exit_code == 0
606+
assert result.output == intf_errors_Ethernet32
607+
608+
def test_show_intf_errors_default_values(self):
609+
"""Test case for an interface with default values."""
610+
runner = CliRunner()
611+
result = runner.invoke(
612+
show.cli.commands["interfaces"].commands["errors"], ["Ethernet48"]
613+
)
614+
print(result.exit_code)
615+
print(result.output)
616+
assert result.exit_code == 0
617+
assert result.output == intf_errors_Ethernet48
618+
499619
@classmethod
500620
def teardown_class(cls):
501621
print("TEARDOWN")

tests/mock_tables/state_db.json

+27
Original file line numberDiff line numberDiff line change
@@ -1684,5 +1684,32 @@
16841684
},
16851685
"STP_TABLE|GLOBAL": {
16861686
"max_stp_inst": "510"
1687+
},
1688+
"PORT_OPERR_TABLE|Ethernet72": {
1689+
},
1690+
"PORT_OPERR_TABLE|Ethernet64": {
1691+
"oper_error_status": "2",
1692+
"mac_remote_fault_count": "14483",
1693+
"mac_remote_fault_time": "2025-01-17 19:51:12",
1694+
"mac_local_fault_count": "26",
1695+
"mac_local_fault_time": "2025-01-17 18:40:56"
1696+
},
1697+
"PORT_OPERR_TABLE|Ethernet32": {
1698+
"oper_error_status": "0",
1699+
"mac_remote_fault_count": "0",
1700+
"mac_remote_fault_time": "",
1701+
"mac_local_fault_count": "5",
1702+
"mac_local_fault_time": "2025-01-16 12:05:34",
1703+
"fec_sync_loss_count": "3",
1704+
"fec_sync_loss_time": "2025-01-16 13:45:20",
1705+
"high_ber_error_count": "1",
1706+
"high_ber_error_time": "2025-01-16 14:30:10"
1707+
},
1708+
"PORT_OPERR_TABLE|Ethernet48": {
1709+
"oper_error_status": "0",
1710+
"mac_remote_fault_count": "0",
1711+
"mac_remote_fault_time": "",
1712+
"mac_local_fault_count": "0",
1713+
"mac_local_fault_time": ""
16871714
}
16881715
}

0 commit comments

Comments
 (0)