Skip to content

Commit fbd0c3b

Browse files
authored
[show][interface] Add changes for show interface flap command (sonic-net#3724)
* [show][interface] Add changes for show interface flap command Signed-off-by: Vaibhav Dahiya <[email protected]> * fix files Signed-off-by: Vaibhav Dahiya <[email protected]> * add ch Signed-off-by: Vaibhav Dahiya <[email protected]> * add ch Signed-off-by: Vaibhav Dahiya <[email protected]> * pep8 Signed-off-by: Vaibhav Dahiya <[email protected]> * fix lines Signed-off-by: Vaibhav Dahiya <[email protected]> * fix test Signed-off-by: Vaibhav Dahiya <[email protected]> * add test vals Signed-off-by: Vaibhav Dahiya <[email protected]> * wrap lines Signed-off-by: Vaibhav Dahiya <[email protected]> * fix tests Signed-off-by: Vaibhav Dahiya <[email protected]> * add fixes Signed-off-by: Vaibhav Dahiya <[email protected]> * fix all Signed-off-by: Vaibhav Dahiya <[email protected]> * fix tests Signed-off-by: Vaibhav Dahiya <[email protected]> * add tests Signed-off-by: Vaibhav Dahiya <[email protected]> * fix nit Signed-off-by: Vaibhav Dahiya <[email protected]> * fix Signed-off-by: Vaibhav Dahiya <[email protected]> * add alll Signed-off-by: Vaibhav Dahiya <[email protected]> * add fd Signed-off-by: Vaibhav Dahiya <[email protected]> --------- Signed-off-by: Vaibhav Dahiya <[email protected]>
1 parent ddccabe commit fbd0c3b

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

show/interfaces/__init__.py

+64
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,70 @@ def mpls(ctx, interfacename, namespace, display):
415415
interfaces.add_command(portchannel.portchannel)
416416

417417

418+
@interfaces.command()
419+
@click.argument('interfacename', required=False)
420+
@click.pass_context
421+
def flap(ctx, interfacename):
422+
"""Show Interface Flap Information <interfacename>"""
423+
424+
namespace = '' # Default namespace
425+
port_dict = multi_asic.get_port_table(namespace=namespace)
426+
427+
# If interfacename is given, validate it
428+
if interfacename:
429+
interfacename = try_convert_interfacename_from_alias(ctx, interfacename)
430+
if interfacename not in port_dict:
431+
ctx.fail("Invalid interface name {}".format(interfacename))
432+
433+
db = SonicV2Connector(host=REDIS_HOSTIP)
434+
db.connect(db.APPL_DB)
435+
436+
# Prepare the table headers and body
437+
header = [
438+
'Interface',
439+
'Flap Count',
440+
'Admin',
441+
'Oper',
442+
'Link Down TimeStamp(UTC)',
443+
'Link Up TimeStamp(UTC)'
444+
]
445+
body = []
446+
447+
# Loop through all ports or the specified port
448+
ports = [interfacename] if interfacename else natsorted(list(port_dict.keys()))
449+
450+
for port in ports:
451+
port_data = db.get_all(db.APPL_DB, f'PORT_TABLE:{port}') or {}
452+
453+
flap_count = port_data.get('flap_count', 'Never')
454+
admin_status = port_data.get('admin_status', 'Unknown').capitalize()
455+
oper_status = port_data.get('oper_status', 'Unknown').capitalize()
456+
457+
# Get timestamps and convert them to UTC format if possible
458+
last_up_time = port_data.get('last_up_time', 'Never')
459+
last_down_time = port_data.get('last_down_time', 'Never')
460+
461+
# Format output row
462+
row = [
463+
port,
464+
flap_count,
465+
admin_status,
466+
oper_status,
467+
f"{last_down_time}" if last_down_time != 'Never' else 'Never',
468+
f"{last_up_time}" if last_up_time != 'Never' else 'Never'
469+
]
470+
471+
body.append(row)
472+
473+
# Sort the body by interface name for consistent display
474+
body = natsorted(body, key=lambda x: x[0])
475+
476+
# Display the formatted table
477+
click.echo(tabulate(body, header))
478+
479+
db.close(db.APPL_DB)
480+
481+
418482
def get_all_port_errors(interfacename):
419483

420484
port_operr_table = {}

tests/interfaces_test.py

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

266+
intf_flap_expected_output_with_data = """\
267+
Interface Flap Count Admin Oper Link Down TimeStamp(UTC) Link Up TimeStamp(UTC)
268+
----------- ------------ ------- ------ -------------------------- ------------------------
269+
Ethernet0 3 Up Down Sat Jan 17 00:04:42 2025 Sat Jan 18 00:08:42 2025
270+
"""
271+
272+
intf_flap_expected_output_with_data_concise = """\
273+
Interface Flap Count Admin Oper Link Down TimeStamp(UTC) Link Up TimeStamp(UTC)
274+
----------- ------------ ------- ------- -------------------------- ------------------------
275+
Ethernet4 Never Unknown Unknown Never Never
276+
"""
277+
278+
intf_flap_expected_output_all_data = """\
279+
Interface Flap Count Admin Oper Link Down TimeStamp(UTC) Link Up TimeStamp(UTC)
280+
----------- ------------ ------- ------- -------------------------- ------------------------
281+
Ethernet0 3 Up Down Sat Jan 17 00:04:42 2025 Sat Jan 18 00:08:42 2025
282+
Ethernet4 Never Unknown Unknown Never Never
283+
Ethernet8 Never Unknown Unknown Never Never
284+
Ethernet12 Never Unknown Unknown Never Never
285+
Ethernet16 7 Up Up Sat Jan 19 00:04:42 2025 Sat Jan 20 00:04:42 2025
286+
Ethernet20 Never Unknown Unknown Never Never
287+
Ethernet24 Never Up Up Never Never
288+
Ethernet28 Never Up Up Never Never
289+
Ethernet32 Never Up Up Never Never
290+
Ethernet36 7 Up Up Never Sat Jan 20 00:04:42 2025
291+
Ethernet40 Never Unknown Unknown Never Never
292+
Ethernet44 Never Unknown Unknown Never Never
293+
Ethernet48 Never Unknown Unknown Never Never
294+
Ethernet52 Never Unknown Unknown Never Never
295+
Ethernet56 Never Unknown Unknown Never Never
296+
Ethernet60 Never Unknown Unknown Never Never
297+
Ethernet64 Never Unknown Unknown Never Never
298+
Ethernet68 Never Unknown Unknown Never Never
299+
Ethernet72 Never Unknown Unknown Never Never
300+
Ethernet76 Never Unknown Unknown Never Never
301+
Ethernet80 Never Unknown Unknown Never Never
302+
Ethernet84 Never Unknown Unknown Never Never
303+
Ethernet88 Never Unknown Unknown Never Never
304+
Ethernet92 Never Unknown Unknown Never Never
305+
Ethernet96 Never Unknown Unknown Never Never
306+
Ethernet100 Never Unknown Unknown Never Never
307+
Ethernet104 Never Unknown Unknown Never Never
308+
Ethernet108 Never Unknown Unknown Never Never
309+
Ethernet112 Never Up Up Never Never
310+
Ethernet116 Never Up Up Never Never
311+
Ethernet120 Never Up Up Never Never
312+
Ethernet124 Never Up Up Never Never
313+
"""
314+
266315
intf_errors_Ethernet64 = """\
267316
Port Errors Count Last timestamp(UTC)
268317
---------------------------- ------- ---------------------
@@ -281,6 +330,7 @@
281330
oper error status 0 Never
282331
signal local error 0 Never
283332
"""
333+
284334
intf_errors_Ethernet16 = """\
285335
Port Errors Count Last timestamp(UTC)
286336
---------------------------- ------- ---------------------
@@ -572,6 +622,45 @@ def test_show_interfaces_switchport_config_in_alias_mode(self):
572622
assert result.exit_code == 0
573623
assert result.output == show_interfaces_switchport_config_in_alias_mode_output
574624

625+
def test_show_intf_flap_no_data(self):
626+
"""Test case for an interface with no flap data."""
627+
runner = CliRunner()
628+
result = runner.invoke(
629+
show.cli.commands["interfaces"].commands["flap"], ["Ethernet5"])
630+
print(result.exit_code)
631+
print(result.output)
632+
assert result.exit_code == 2
633+
634+
def test_show_intf_flap_with_data(self):
635+
"""Test case for an interface with valid flap data."""
636+
runner = CliRunner()
637+
result = runner.invoke(
638+
show.cli.commands["interfaces"].commands["flap"], ["Ethernet0"])
639+
print(result.exit_code)
640+
print(result.output)
641+
assert result.exit_code == 0
642+
assert result.output == intf_flap_expected_output_with_data
643+
644+
def test_show_intf_flap_with_data_concise(self):
645+
"""Test case for an interface with valid flap data."""
646+
runner = CliRunner()
647+
result = runner.invoke(
648+
show.cli.commands["interfaces"].commands["flap"], ["Ethernet4"])
649+
print(result.exit_code)
650+
print(result.output)
651+
assert result.exit_code == 0
652+
assert result.output == intf_flap_expected_output_with_data_concise
653+
654+
def test_show_intf_flap_with_all_ports_data(self):
655+
"""Test case for an interface with valid flap data."""
656+
runner = CliRunner()
657+
result = runner.invoke(
658+
show.cli.commands["interfaces"].commands["flap"])
659+
print(result.exit_code)
660+
print(result.output)
661+
assert result.exit_code == 0
662+
assert result.output == intf_flap_expected_output_all_data
663+
575664
def test_show_intf_errors_filled_data(self):
576665
"""Test case for an interface with filled error data."""
577666
runner = CliRunner()

tests/mock_tables/appl_db.json

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
"interface_type": "CR4",
4545
"adv_interface_types": "CR4,CR2",
4646
"autoneg": "on",
47+
"flap_count": "3",
48+
"last_up_time": "Sat Jan 18 00:08:42 2025",
49+
"last_down_time": "Sat Jan 17 00:04:42 2025",
4750
"link_training": "on"
4851
},
4952
"PORT_TABLE:Ethernet16": {
@@ -55,6 +58,9 @@
5558
"oper_status": "up",
5659
"pfc_asym": "off",
5760
"mtu": "9100",
61+
"flap_count": "7",
62+
"last_up_time": "Sat Jan 20 00:04:42 2025",
63+
"last_down_time": "Sat Jan 19 00:04:42 2025",
5864
"admin_status": "up"
5965
},
6066
"PORT_TABLE:Ethernet36": {
@@ -67,6 +73,8 @@
6773
"pfc_asym": "off",
6874
"mtu": "9100",
6975
"tpid": "0x8100",
76+
"flap_count": "7",
77+
"last_up_time": "Sat Jan 20 00:04:42 2025",
7078
"admin_status": "up"
7179
},
7280
"PORT_TABLE:Ethernet24": {

0 commit comments

Comments
 (0)