Skip to content

Commit 1b0d542

Browse files
wendanilguohan
authored andcommitted
show subinterfaces status (sonic-net#642)
* Add sub port interface to intfutil status Signed-off-by: Wenda Ni <[email protected]> * Format change Signed-off-by: Wenda Ni <[email protected]> * Hook 'intfutil status' with show subinterfaces status Signed-off-by: Wenda Ni <[email protected]> * Add 'intfutil status subport' to show only the status of sub port interfaces Signed-off-by: Wenda Ni <[email protected]> * Hook 'intfutil status subport' with 'show subinterfaces status' Signed-off-by: Wenda Ni <[email protected]> * Support intfutil status <sub_port_intf_name> Signed-off-by: Wenda Ni <[email protected]> * Add alias naming mode support Signed-off-by: Wenda Ni <[email protected]> * Address comments Signed-off-by: Wenda Ni <[email protected]> * Address comment: concatenate command line, and validate input Signed-off-by: Wenda Ni <[email protected]> * Address comment: keep show interface status intact Signed-off-by: Wenda Ni <[email protected]> * Add unit test for show interfaces status / intfutil status Signed-off-by: Wenda Ni <[email protected]> * Add unit test for 'show interfaces status --verbose' Signed-off-by: Wenda Ni <[email protected]> * Add unit test for 'show subinterfaces status' / 'intfutil status subport' Signed-off-by: Wenda Ni <[email protected]> * Add unit test for 'show subinterfaces status --verbose' Signed-off-by: Wenda Ni <[email protected]> * Add unit test for single sub interface status show Signed-off-by: Wenda Ni <[email protected]> * Add unit test for '--verbose' single sub interface status show Signed-off-by: Wenda Ni <[email protected]> * Add unit test for showing status of single sub interface in alias naming mode Signed-off-by: Wenda Ni <[email protected]> * Add unit test for '--verbose' status of single sub interface in alias naming mode Signed-off-by: Wenda Ni <[email protected]>
1 parent 8218b09 commit 1b0d542

File tree

5 files changed

+325
-35
lines changed

5 files changed

+325
-35
lines changed

scripts/intfutil

Lines changed: 135 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ from tabulate import tabulate
88
from natsort import natsorted
99
from swsssdk import ConfigDBConnector
1010
from pprint import pprint
11-
11+
import os
12+
13+
# mock the redis for unit test purposes #
14+
try:
15+
if os.environ["UTILITIES_UNIT_TESTING"] == "1":
16+
modules_path = os.path.join(os.path.dirname(__file__), "..")
17+
tests_path = os.path.join(modules_path, "sonic-utilities-tests")
18+
sys.path.insert(0, modules_path)
19+
sys.path.insert(0, tests_path)
20+
import mock_tables.dbconnector
21+
except KeyError:
22+
pass
1223

1324
# ========================== Common interface-utils logic ==========================
1425

@@ -25,6 +36,11 @@ PORT_DESCRIPTION = "description"
2536
PORT_OPTICS_TYPE = "type"
2637
PORT_PFC_ASYM_STATUS = "pfc_asym"
2738

39+
VLAN_SUB_INTERFACE_SEPARATOR = "."
40+
VLAN_SUB_INTERFACE_TYPE = "802.1q-encapsulation"
41+
42+
SUB_PORT = "subport"
43+
2844
def db_connect_configdb():
2945
"""
3046
Connect to configdb
@@ -43,6 +59,15 @@ def get_frontpanel_port_list(config_db):
4359
return front_panel_ports_list
4460

4561

62+
def get_sub_port_intf_list(config_db):
63+
sub_intf_dict = config_db.get_table('VLAN_SUB_INTERFACE')
64+
sub_intf_list = []
65+
for sub_intf in sub_intf_dict.keys():
66+
if isinstance(sub_intf, basestring):
67+
sub_intf_list.append(sub_intf)
68+
return sub_intf_list
69+
70+
4671
def get_interface_vlan_dict(config_db):
4772
"""
4873
Get info from REDIS ConfigDB and create interface to vlan mapping
@@ -93,6 +118,24 @@ def appl_db_keys_get(appl_db, front_panel_ports_list, intf_name):
93118
return appl_db_keys
94119

95120

121+
def appl_db_sub_intf_keys_get(appl_db, sub_intf_list, sub_intf_name):
122+
"""
123+
Get APPL_DB sub port interface keys
124+
"""
125+
if sub_intf_name is None:
126+
appl_db_sub_intf_keys = []
127+
appl_db_intf_keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:*")
128+
if appl_db_intf_keys is not None:
129+
for appl_db_intf_key in appl_db_intf_keys:
130+
if re.split(':', appl_db_intf_key, maxsplit=1)[-1].strip() in sub_intf_list:
131+
appl_db_sub_intf_keys.append(appl_db_intf_key)
132+
elif sub_intf_name in sub_intf_list:
133+
appl_db_sub_intf_keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:%s" % sub_intf_name)
134+
else:
135+
return []
136+
return appl_db_sub_intf_keys
137+
138+
96139
def appl_db_port_status_get(appl_db, intf_name, status_type):
97140
"""
98141
Get the port status
@@ -267,13 +310,42 @@ def appl_db_portchannel_status_get(appl_db, config_db, po_name, status_type, por
267310
return "N/A"
268311
return status
269312

313+
def appl_db_sub_intf_status_get(appl_db, config_db, front_panel_ports_list, portchannel_speed_dict, sub_intf_name, status_type):
314+
sub_intf_sep_idx = sub_intf_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
315+
if sub_intf_sep_idx != -1:
316+
parent_port_name = sub_intf_name[:sub_intf_sep_idx]
317+
vlan_id = sub_intf_name[sub_intf_sep_idx + 1:]
318+
319+
full_intf_table_name = "INTF_TABLE" + ":" + sub_intf_name
320+
321+
if status_type == "vlan":
322+
return vlan_id
323+
324+
if status_type == "admin_status":
325+
status = appl_db.get(appl_db.APPL_DB, full_intf_table_name, status_type)
326+
return status if status is not None else "N/A"
327+
328+
if status_type == "type":
329+
return VLAN_SUB_INTERFACE_TYPE
330+
331+
if status_type == "mtu" or status_type == "speed":
332+
if parent_port_name in front_panel_ports_list:
333+
return appl_db_port_status_get(appl_db, parent_port_name, status_type)
334+
elif parent_port_name in portchannel_speed_dict.keys():
335+
return appl_db_portchannel_status_get(appl_db, config_db, parent_port_name, status_type, portchannel_speed_dict)
336+
else:
337+
return "N/A"
338+
339+
return "N/A"
340+
270341
# ========================== interface-status logic ==========================
271342

272343
header_stat = ['Interface', 'Lanes', 'Speed', 'MTU', 'Alias', 'Vlan', 'Oper', 'Admin', 'Type', 'Asym PFC']
344+
header_stat_sub_intf = ['Sub port interface', 'Speed', 'MTU', 'Vlan', 'Admin', 'Type']
273345

274346
class IntfStatus(object):
275347

276-
def display_intf_status(self, appl_db_keys, front_panel_ports_list, portchannel_speed_dict):
348+
def display_intf_status(self, appl_db_keys, front_panel_ports_list, portchannel_speed_dict, appl_db_sub_intf_keys, sub_intf_list, sub_intf_only):
277349
"""
278350
Generate interface-status output
279351
"""
@@ -286,35 +358,47 @@ class IntfStatus(object):
286358
# Iterate through all the keys and append port's associated state to
287359
# the result table.
288360
#
289-
for i in appl_db_keys:
290-
key = re.split(':', i, maxsplit=1)[-1].strip()
291-
if key in front_panel_ports_list:
292-
table.append((key,
293-
appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS),
294-
appl_db_port_status_get(self.appl_db, key, PORT_SPEED),
295-
appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS),
296-
appl_db_port_status_get(self.appl_db, key, PORT_ALIAS),
297-
config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key),
298-
appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS),
299-
appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS),
300-
state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE),
301-
appl_db_port_status_get(self.appl_db, key, PORT_PFC_ASYM_STATUS)))
302-
# Sorting and tabulating the result table.
303-
for po, value in portchannel_speed_dict.iteritems():
304-
if po:
305-
table.append((po,
306-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_LANES_STATUS, self.portchannel_speed_dict),
307-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_SPEED, self.portchannel_speed_dict),
308-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_MTU_STATUS, self.portchannel_speed_dict),
309-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ALIAS, self.portchannel_speed_dict),
310-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, "vlan", self.portchannel_speed_dict),
311-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPER_STATUS, self.portchannel_speed_dict),
312-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ADMIN_STATUS, self.portchannel_speed_dict),
313-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPTICS_TYPE, self.portchannel_speed_dict),
314-
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_PFC_ASYM_STATUS, self.portchannel_speed_dict)))
361+
if not sub_intf_only:
362+
for i in appl_db_keys:
363+
key = re.split(':', i, maxsplit=1)[-1].strip()
364+
if key in front_panel_ports_list:
365+
table.append((key,
366+
appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS),
367+
appl_db_port_status_get(self.appl_db, key, PORT_SPEED),
368+
appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS),
369+
appl_db_port_status_get(self.appl_db, key, PORT_ALIAS),
370+
config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key),
371+
appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS),
372+
appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS),
373+
state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE),
374+
appl_db_port_status_get(self.appl_db, key, PORT_PFC_ASYM_STATUS)))
375+
376+
for po, value in portchannel_speed_dict.iteritems():
377+
if po:
378+
table.append((po,
379+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_LANES_STATUS, self.portchannel_speed_dict),
380+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_SPEED, self.portchannel_speed_dict),
381+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_MTU_STATUS, self.portchannel_speed_dict),
382+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ALIAS, self.portchannel_speed_dict),
383+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, "vlan", self.portchannel_speed_dict),
384+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPER_STATUS, self.portchannel_speed_dict),
385+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_ADMIN_STATUS, self.portchannel_speed_dict),
386+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_OPTICS_TYPE, self.portchannel_speed_dict),
387+
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_PFC_ASYM_STATUS, self.portchannel_speed_dict)))
388+
else:
389+
for key in appl_db_sub_intf_keys:
390+
sub_intf = re.split(':', key, maxsplit=1)[-1].strip()
391+
if sub_intf in sub_intf_list:
392+
table.append((sub_intf,
393+
appl_db_sub_intf_status_get(self.appl_db, self.config_db, self.front_panel_ports_list, self.portchannel_speed_dict, sub_intf, PORT_SPEED),
394+
appl_db_sub_intf_status_get(self.appl_db, self.config_db, self.front_panel_ports_list, self.portchannel_speed_dict, sub_intf, PORT_MTU_STATUS),
395+
appl_db_sub_intf_status_get(self.appl_db, self.config_db, self.front_panel_ports_list, self.portchannel_speed_dict, sub_intf, "vlan"),
396+
appl_db_sub_intf_status_get(self.appl_db, self.config_db, self.front_panel_ports_list, self.portchannel_speed_dict, sub_intf, PORT_ADMIN_STATUS),
397+
appl_db_sub_intf_status_get(self.appl_db, self.config_db, self.front_panel_ports_list, self.portchannel_speed_dict, sub_intf, PORT_OPTICS_TYPE)))
315398

399+
# Sorting and tabulating the result table.
316400
sorted_table = natsorted(table)
317-
print tabulate(sorted_table, header_stat, tablefmt="simple", stralign='right')
401+
print tabulate(sorted_table, header_stat if not sub_intf_only else header_stat_sub_intf, tablefmt="simple", stralign='right')
318402

319403

320404
def __init__(self, intf_name):
@@ -333,6 +417,20 @@ class IntfStatus(object):
333417
return
334418
if self.config_db is None:
335419
return
420+
421+
sub_intf_only = False
422+
sub_intf_name = intf_name
423+
if intf_name is not None:
424+
if intf_name == SUB_PORT:
425+
intf_name = None
426+
sub_intf_name = None
427+
sub_intf_only = True
428+
else:
429+
sub_intf_sep_idx = intf_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
430+
if sub_intf_sep_idx != -1:
431+
sub_intf_only = True
432+
intf_name = intf_name[:sub_intf_sep_idx]
433+
336434
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db)
337435
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name)
338436
self.int_to_vlan_dict = get_interface_vlan_dict(self.config_db)
@@ -344,9 +442,12 @@ class IntfStatus(object):
344442
self.combined_int_to_vlan_po_dict = merge_dicts(self.int_to_vlan_dict, self.int_po_dict)
345443
self.portchannel_speed_dict = po_speed_dict(self.po_int_dict, self.appl_db)
346444
self.portchannel_keys = self.portchannel_speed_dict.keys()
445+
446+
self.sub_intf_list = get_sub_port_intf_list(self.config_db)
447+
appl_db_sub_intf_keys = appl_db_sub_intf_keys_get(self.appl_db, self.sub_intf_list, sub_intf_name)
347448
if appl_db_keys is None:
348449
return
349-
self.display_intf_status(appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict)
450+
self.display_intf_status(appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict, appl_db_sub_intf_keys, self.sub_intf_list, sub_intf_only)
350451

351452

352453

@@ -392,6 +493,10 @@ class IntfDescription(object):
392493
return
393494
if self.config_db is None:
394495
return
496+
497+
if intf_name is not None and intf_name == SUB_PORT:
498+
intf_name = None
499+
395500
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db)
396501
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name)
397502
if appl_db_keys is None:

show/main.py

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
2424

25+
VLAN_SUB_INTERFACE_SEPARATOR = '.'
26+
2527
try:
2628
# noinspection PyPep8Naming
2729
import ConfigParser as configparser
@@ -74,25 +76,42 @@ def name_to_alias(self, interface_name):
7476
"""Return vendor interface alias if SONiC
7577
interface name is given as argument
7678
"""
79+
vlan_id = ''
80+
sub_intf_sep_idx = -1
7781
if interface_name is not None:
82+
sub_intf_sep_idx = interface_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
83+
if sub_intf_sep_idx != -1:
84+
vlan_id = interface_name[sub_intf_sep_idx + 1:]
85+
# interface_name holds the parent port name
86+
interface_name = interface_name[:sub_intf_sep_idx]
87+
7888
for port_name in self.port_dict.keys():
7989
if interface_name == port_name:
80-
return self.port_dict[port_name]['alias']
90+
return self.port_dict[port_name]['alias'] if sub_intf_sep_idx == -1 \
91+
else self.port_dict[port_name]['alias'] + VLAN_SUB_INTERFACE_SEPARATOR + vlan_id
8192

8293
# interface_name not in port_dict. Just return interface_name
83-
return interface_name
94+
return interface_name if sub_intf_sep_idx == -1 else interface_name + VLAN_SUB_INTERFACE_SEPARATOR + vlan_id
8495

8596
def alias_to_name(self, interface_alias):
8697
"""Return SONiC interface name if vendor
8798
port alias is given as argument
8899
"""
100+
vlan_id = ''
101+
sub_intf_sep_idx = -1
89102
if interface_alias is not None:
103+
sub_intf_sep_idx = interface_alias.find(VLAN_SUB_INTERFACE_SEPARATOR)
104+
if sub_intf_sep_idx != -1:
105+
vlan_id = interface_alias[sub_intf_sep_idx + 1:]
106+
# interface_alias holds the parent port alias
107+
interface_alias = interface_alias[:sub_intf_sep_idx]
108+
90109
for port_name in self.port_dict.keys():
91110
if interface_alias == self.port_dict[port_name]['alias']:
92-
return port_name
111+
return port_name if sub_intf_sep_idx == -1 else port_name + VLAN_SUB_INTERFACE_SEPARATOR + vlan_id
93112

94113
# interface_alias not in port_dict. Just return interface_alias
95-
return interface_alias
114+
return interface_alias if sub_intf_sep_idx == -1 else interface_alias + VLAN_SUB_INTERFACE_SEPARATOR + vlan_id
96115

97116

98117
# Global Config object
@@ -789,6 +808,37 @@ def portchannel(verbose):
789808
cmd = "sudo teamshow"
790809
run_command(cmd, display_cmd=verbose)
791810

811+
#
812+
# 'subinterfaces' group ("show subinterfaces ...")
813+
#
814+
815+
@cli.group(cls=AliasedGroup, default_if_no_args=False)
816+
def subinterfaces():
817+
"""Show details of the sub port interfaces"""
818+
pass
819+
820+
# 'subinterfaces' subcommand ("show subinterfaces status")
821+
@subinterfaces.command()
822+
@click.argument('subinterfacename', type=str, required=False)
823+
@click.option('--verbose', is_flag=True, help="Enable verbose output")
824+
def status(subinterfacename, verbose):
825+
"""Show sub port interface status information"""
826+
cmd = "intfutil status "
827+
828+
if subinterfacename is not None:
829+
sub_intf_sep_idx = subinterfacename.find(VLAN_SUB_INTERFACE_SEPARATOR)
830+
if sub_intf_sep_idx == -1:
831+
print("Invalid sub port interface name")
832+
return
833+
834+
if get_interface_mode() == "alias":
835+
subinterfacename = iface_alias_converter.alias_to_name(subinterfacename)
836+
837+
cmd += subinterfacename
838+
else:
839+
cmd += "subport"
840+
run_command(cmd, display_cmd=verbose)
841+
792842
#
793843
# 'pfc' group ("show pfc ...")
794844
#

0 commit comments

Comments
 (0)