Skip to content

Commit d2c997c

Browse files
authored
Add_intf_range (sonic-net#913)
* Add_intf_range
1 parent f7b7fcb commit d2c997c

File tree

6 files changed

+137
-38
lines changed

6 files changed

+137
-38
lines changed

config/main.py

+34-23
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import ipaddress
1515
from swsssdk import ConfigDBConnector, SonicV2Connector, SonicDBConfig
1616
from minigraph import parse_device_desc_xml
17+
from utilities_common.intf_filter import parse_interface_in_filter
1718

1819
import aaa
1920
import mlnx
@@ -1843,21 +1844,26 @@ def startup(ctx, interface_name):
18431844
if interface_name is None:
18441845
ctx.fail("'interface_name' is None!")
18451846

1846-
if interface_name_is_valid(interface_name) is False:
1847-
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
1847+
intf_fs = parse_interface_in_filter(interface_name)
1848+
if len(intf_fs) == 1 and interface_name_is_valid(interface_name) is False:
1849+
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
18481850

18491851
log_info("'interface startup {}' executing...".format(interface_name))
1852+
port_dict = config_db.get_table('PORT')
1853+
for port_name in port_dict.keys():
1854+
if port_name in intf_fs:
1855+
config_db.mod_entry("PORT", port_name, {"admin_status": "up"})
1856+
1857+
portchannel_list = config_db.get_table("PORTCHANNEL")
1858+
for po_name in portchannel_list.keys():
1859+
if po_name in intf_fs:
1860+
config_db.mod_entry("PORTCHANNEL", po_name, {"admin_status": "up"})
1861+
1862+
subport_list = config_db.get_table("VLAN_SUB_INTERFACE")
1863+
for sp_name in subport_list.keys():
1864+
if sp_name in intf_fs:
1865+
config_db.mod_entry("VLAN_SUB_INTERFACE", sp_name, {"admin_status": "up"})
18501866

1851-
if interface_name.startswith("Ethernet"):
1852-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
1853-
config_db.mod_entry("VLAN_SUB_INTERFACE", interface_name, {"admin_status": "up"})
1854-
else:
1855-
config_db.mod_entry("PORT", interface_name, {"admin_status": "up"})
1856-
elif interface_name.startswith("PortChannel"):
1857-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
1858-
config_db.mod_entry("VLAN_SUB_INTERFACE", interface_name, {"admin_status": "up"})
1859-
else:
1860-
config_db.mod_entry("PORTCHANNEL", interface_name, {"admin_status": "up"})
18611867
#
18621868
# 'shutdown' subcommand
18631869
#
@@ -1874,19 +1880,24 @@ def shutdown(ctx, interface_name):
18741880
if interface_name is None:
18751881
ctx.fail("'interface_name' is None!")
18761882

1877-
if interface_name_is_valid(interface_name) is False:
1883+
intf_fs = parse_interface_in_filter(interface_name)
1884+
if len(intf_fs) == 1 and interface_name_is_valid(interface_name) is False:
18781885
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
18791886

1880-
if interface_name.startswith("Ethernet"):
1881-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
1882-
config_db.mod_entry("VLAN_SUB_INTERFACE", interface_name, {"admin_status": "down"})
1883-
else:
1884-
config_db.mod_entry("PORT", interface_name, {"admin_status": "down"})
1885-
elif interface_name.startswith("PortChannel"):
1886-
if VLAN_SUB_INTERFACE_SEPARATOR in interface_name:
1887-
config_db.mod_entry("VLAN_SUB_INTERFACE", interface_name, {"admin_status": "down"})
1888-
else:
1889-
config_db.mod_entry("PORTCHANNEL", interface_name, {"admin_status": "down"})
1887+
port_dict = config_db.get_table('PORT')
1888+
for port_name in port_dict.keys():
1889+
if port_name in intf_fs:
1890+
config_db.mod_entry("PORT", port_name, {"admin_status": "down"})
1891+
1892+
portchannel_list = config_db.get_table("PORTCHANNEL")
1893+
for po_name in portchannel_list.keys():
1894+
if po_name in intf_fs:
1895+
config_db.mod_entry("PORTCHANNEL", po_name, {"admin_status": "down"})
1896+
1897+
subport_list = config_db.get_table("VLAN_SUB_INTERFACE")
1898+
for sp_name in subport_list.keys():
1899+
if sp_name in intf_fs:
1900+
config_db.mod_entry("VLAN_SUB_INTERFACE", sp_name, {"admin_status": "down"})
18901901

18911902
#
18921903
# 'speed' subcommand

doc/Command-Reference.md

+30-1
Original file line numberDiff line numberDiff line change
@@ -2312,7 +2312,7 @@ Optional argument "-p" specify a period (in seconds) with which to gather counte
23122312
show interfaces counters [-a|--printall] [-p|--period <period>]
23132313
show interfaces counters errors
23142314
show interfaces counters rates
2315-
show interfaces counters rif [-p|--period <period>] <interface_name>
2315+
show interfaces counters rif [-p|--period <period>] [-i <interface_name>]
23162316
```
23172317
23182318
- Example:
@@ -2327,6 +2327,13 @@ Optional argument "-p" specify a period (in seconds) with which to gather counte
23272327
Ethernet16 U 16,679,692,972 13.83 MB/s 0.27% 0 17,605 0 18,206,586,265 17.51 MB/s 0.34% 0 0 0
23282328
Ethernet20 U 47,983,339,172 35.89 MB/s 0.70% 0 2,174 0 58,986,354,359 51.83 MB/s 1.01% 0 0 0
23292329
Ethernet24 U 33,543,533,441 36.59 MB/s 0.71% 0 1,613 0 43,066,076,370 49.92 MB/s 0.97% 0 0 0
2330+
2331+
admin@sonic:~$ show interfaces counters -i Ethernet4,Ethernet12-16
2332+
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
2333+
----------- ------- --------------- ----------- --------- -------- -------- -------- --------------- ----------- --------- -------- -------- --------
2334+
Ethernet4 U 453,838,006,636 632.97 MB/s 12.36% 0 1,636 0 388,299,875,056 529.34 MB/s 10.34% 0 0 0
2335+
Ethernet12 U 458,052,204,029 636.84 MB/s 12.44% 0 17,614 0 388,341,776,615 527.37 MB/s 10.30% 0 0 0
2336+
Ethernet16 U 16,679,692,972 13.83 MB/s 0.27% 0 17,605 0 18,206,586,265 17.51 MB/s 0.34% 0 0 0
23302337
```
23312338
23322339
The "errors" subcommand is used to display the interface errors.
@@ -2527,6 +2534,18 @@ This command displays some more fields such as Lanes, Speed, MTU, Type, Asymmetr
25272534
Ethernet0 101,102 40G 9100 fortyGigE1/1/1 up up
25282535
```
25292536
2537+
- Example (to only display the status for range of interfaces):
2538+
```
2539+
admin@sonic:~$ show interfaces status Ethernet8,Ethernet168-180
2540+
Interface Lanes Speed MTU Alias Oper Admin Type Asym PFC
2541+
----------- ----------------- ------- ----- --------------- ------ ------- ------ ----------
2542+
Ethernet8 49,50,51,52 100G 9100 hundredGigE3 down down N/A N/A
2543+
Ethernet168 9,10,11,12 100G 9100 hundredGigE43 down down N/A N/A
2544+
Ethernet172 13,14,15,16 100G 9100 hundredGigE44 down down N/A N/A
2545+
Ethernet176 109,110,111,112 100G 9100 hundredGigE45 down down N/A N/A
2546+
Ethernet180 105,106,107,108 100G 9100 hundredGigE46 down down N/A N/A
2547+
```
2548+
25302549
**show interfaces transceiver**
25312550
25322551
This command is already explained [here](#Transceivers)
@@ -2720,6 +2739,11 @@ This command is used to administratively shut down either the Physical interface
27202739
admin@sonic:~$ sudo config interface Ethernet63 shutdown
27212740
```
27222741
2742+
shutdown multiple interfaces
2743+
```
2744+
admin@sonic:~$ sudo config interface shutdown Ethernet8,Ethernet16-20,Ethernet32
2745+
```
2746+
27232747
**config interface startup <interface_name> (Versions >= 201904)**
27242748
27252749
**config interface <interface_name> startup (Versions <= 201811)**
@@ -2748,6 +2772,11 @@ This command is used for administratively bringing up the Physical interface or
27482772
admin@sonic:~$ sudo config interface Ethernet63 startup
27492773
```
27502774
2775+
startup multiple interfaces
2776+
```
2777+
admin@sonic:~$ sudo config interface startup Ethernet8,Ethernet16-20,Ethernet32
2778+
```
2779+
27512780
**config interface speed <interface_name> (Versions >= 201904)**
27522781
27532782
**config interface <interface_name> speed (Versions <= 201811)**

scripts/intfutil

+11-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ from tabulate import tabulate
88
from natsort import natsorted
99
from swsssdk import ConfigDBConnector
1010
from pprint import pprint
11+
from utilities_common.intf_filter import parse_interface_in_filter
12+
1113
import os
1214

1315
# mock the redis for unit test purposes #
@@ -345,7 +347,7 @@ header_stat_sub_intf = ['Sub port interface', 'Speed', 'MTU', 'Vlan', 'Admin', '
345347

346348
class IntfStatus(object):
347349

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):
350+
def display_intf_status(self, intf_name, appl_db_keys, front_panel_ports_list, portchannel_speed_dict, appl_db_sub_intf_keys, sub_intf_list, sub_intf_only):
349351
"""
350352
Generate interface-status output
351353
"""
@@ -354,6 +356,8 @@ class IntfStatus(object):
354356
table = []
355357
key = []
356358

359+
intf_fs = parse_interface_in_filter(intf_name)
360+
357361
#
358362
# Iterate through all the keys and append port's associated state to
359363
# the result table.
@@ -362,7 +366,8 @@ class IntfStatus(object):
362366
for i in appl_db_keys:
363367
key = re.split(':', i, maxsplit=1)[-1].strip()
364368
if key in front_panel_ports_list:
365-
table.append((key,
369+
if intf_name is None or key in intf_fs:
370+
table.append((key,
366371
appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS),
367372
appl_db_port_status_get(self.appl_db, key, PORT_SPEED),
368373
appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS),
@@ -376,7 +381,8 @@ class IntfStatus(object):
376381

377382
for po, value in portchannel_speed_dict.iteritems():
378383
if po:
379-
table.append((po,
384+
if intf_name is None or po in intf_fs:
385+
table.append((po,
380386
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_LANES_STATUS, self.portchannel_speed_dict),
381387
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_SPEED, self.portchannel_speed_dict),
382388
appl_db_portchannel_status_get(self.appl_db, self.config_db, po, PORT_MTU_STATUS, self.portchannel_speed_dict),
@@ -434,7 +440,7 @@ class IntfStatus(object):
434440
intf_name = intf_name[:sub_intf_sep_idx]
435441

436442
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db)
437-
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name)
443+
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, None)
438444
self.int_to_vlan_dict = get_interface_vlan_dict(self.config_db)
439445
self.get_raw_po_int_configdb_info = get_raw_portchannel_info(self.config_db)
440446
self.portchannel_list = get_portchannel_list(self.get_raw_po_int_configdb_info)
@@ -449,7 +455,7 @@ class IntfStatus(object):
449455
appl_db_sub_intf_keys = appl_db_sub_intf_keys_get(self.appl_db, self.sub_intf_list, sub_intf_name)
450456
if appl_db_keys is None:
451457
return
452-
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)
458+
self.display_intf_status(intf_name, appl_db_keys, self.front_panel_ports_list, self.portchannel_speed_dict, appl_db_sub_intf_keys, self.sub_intf_list, sub_intf_only)
453459

454460

455461

scripts/portstat

+15-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ from collections import namedtuple, OrderedDict
1818
from natsort import natsorted
1919
from tabulate import tabulate
2020
from utilities_common.netstat import ns_diff, ns_brate, ns_prate, ns_util, table_as_json
21+
from utilities_common.intf_filter import parse_interface_in_filter
2122

2223
PORT_RATE = 40
2324

@@ -128,7 +129,7 @@ class Portstat(object):
128129
else:
129130
return STATUS_NA
130131

131-
def cnstat_print(self, cnstat_dict, use_json, print_all, errors_only, rates_only):
132+
def cnstat_print(self, cnstat_dict, intf_list, use_json, print_all, errors_only, rates_only):
132133
"""
133134
Print the cnstat.
134135
"""
@@ -138,7 +139,8 @@ class Portstat(object):
138139
for key, data in cnstat_dict.iteritems():
139140
if key == 'time':
140141
continue
141-
142+
if intf_list and key not in intf_list:
143+
continue
142144
if print_all:
143145
header = header_all
144146
table.append((key, self.get_port_state(key),
@@ -169,7 +171,7 @@ class Portstat(object):
169171
else:
170172
print tabulate(table, header, tablefmt='simple', stralign='right')
171173

172-
def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, use_json, print_all, errors_only, rates_only):
174+
def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, intf_list, use_json, print_all, errors_only, rates_only):
173175
"""
174176
Print the difference between two cnstat results.
175177
"""
@@ -186,6 +188,8 @@ class Portstat(object):
186188
if key in cnstat_old_dict:
187189
old_cntr = cnstat_old_dict.get(key)
188190

191+
if intf_list and key not in intf_list:
192+
continue
189193
port_speed = self.get_port_speed(key)
190194
if print_all:
191195
header = header_all
@@ -306,6 +310,7 @@ Examples:
306310
parser.add_argument('-R', '--rate', action='store_true', help='Display interface rates')
307311
parser.add_argument('-t', '--tag', type=str, help='Save stats with name TAG', default=None)
308312
parser.add_argument('-p', '--period', type=int, help='Display stats over a specified period (in seconds).', default=0)
313+
parser.add_argument('-i', '--interface', type=str, help='Display stats for interface lists.', default=None)
309314
args = parser.parse_args()
310315

311316
save_fresh_stats = args.clear
@@ -319,7 +324,7 @@ Examples:
319324
uid = str(os.getuid())
320325
wait_time_in_seconds = args.period
321326
print_all = args.all
322-
327+
intf_fs = args.interface
323328
if tag_name is not None:
324329
cnstat_file = uid + "-" + tag_name
325330
else:
@@ -351,13 +356,15 @@ Examples:
351356
os.rmdir(cnstat_dir)
352357
sys.exit(0)
353358

359+
intf_list = parse_interface_in_filter(intf_fs)
360+
354361
portstat = Portstat()
355362
# The cnstat_dict just give an ordered dict of all output.
356363
cnstat_dict = portstat.get_cnstat()
357364

358365
# Now decide what information to display
359366
if raw_stats:
360-
portstat.cnstat_print(cnstat_dict, use_json, print_all, errors_only, rates_only)
367+
portstat.cnstat_print(cnstat_dict, intf_list, use_json, print_all, errors_only, rates_only)
361368
sys.exit(0)
362369

363370
# At this point, either we'll create a file or open an existing one.
@@ -384,21 +391,21 @@ Examples:
384391
try:
385392
cnstat_cached_dict = pickle.load(open(cnstat_fqn_file, 'r'))
386393
print "Last cached time was " + str(cnstat_cached_dict.get('time'))
387-
portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, use_json, print_all, errors_only, rates_only)
394+
portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, intf_list, use_json, print_all, errors_only, rates_only)
388395
except IOError as e:
389396
print e.errno, e
390397
else:
391398
if tag_name:
392399
print "\nFile '%s' does not exist" % cnstat_fqn_file
393400
print "Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name)
394401
else:
395-
portstat.cnstat_print(cnstat_dict, use_json, print_all, errors_only, rates_only)
402+
portstat.cnstat_print(cnstat_dict, intf_list, use_json, print_all, errors_only, rates_only)
396403
else:
397404
#wait for the specified time and then gather the new stats and output the difference.
398405
time.sleep(wait_time_in_seconds)
399406
print "The rates are calculated within %s seconds period" % wait_time_in_seconds
400407
cnstat_new_dict = portstat.get_cnstat()
401-
portstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, use_json, print_all, errors_only, rates_only)
408+
portstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, intf_list, use_json, print_all, errors_only, rates_only)
402409

403410
if __name__ == "__main__":
404411
main()

show/main.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -947,9 +947,10 @@ def status(interfacename, verbose):
947947
@interfaces.group(invoke_without_command=True)
948948
@click.option('-a', '--printall', is_flag=True)
949949
@click.option('-p', '--period')
950+
@click.option('-i', '--interface')
950951
@click.option('--verbose', is_flag=True, help="Enable verbose output")
951952
@click.pass_context
952-
def counters(ctx, verbose, period, printall):
953+
def counters(ctx, verbose, period, interface, printall):
953954
"""Show interface counters"""
954955

955956
if ctx.invoked_subcommand is None:
@@ -959,6 +960,8 @@ def counters(ctx, verbose, period, printall):
959960
cmd += " -a"
960961
if period is not None:
961962
cmd += " -p {}".format(period)
963+
if interface is not None:
964+
cmd += " -i {}".format(interface)
962965

963966
run_command(cmd, display_cmd=verbose)
964967

utilities_common/intf_filter.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Interface filtering functions
2+
3+
SONIC_PORT_NAME_PREFIX = "Ethernet"
4+
SONIC_LAG_NAME_PREFIX = "PortChannel"
5+
6+
def parse_interface_in_filter(intf_filter):
7+
intf_fs = []
8+
9+
if intf_filter is None:
10+
return intf_fs
11+
12+
fs = intf_filter.split(',')
13+
for x in fs:
14+
if '-' in x:
15+
# handle range
16+
if not x.startswith(SONIC_PORT_NAME_PREFIX) and not x.startswith(SONIC_LAG_NAME_PREFIX):
17+
continue
18+
if x.startswith(SONIC_PORT_NAME_PREFIX):
19+
intf = SONIC_PORT_NAME_PREFIX
20+
if x.startswith(SONIC_LAG_NAME_PREFIX):
21+
intf = SONIC_LAG_NAME_PREFIX
22+
start = x.split('-')[0].split(intf,1)[1]
23+
end = x.split('-')[1]
24+
25+
if not start.isdigit() or not end.isdigit():
26+
continue
27+
for i in range(int(start), int(end)+1):
28+
intf_fs.append(intf+str(i))
29+
else:
30+
intf_fs.append(x)
31+
32+
return intf_fs
33+
34+
def interface_in_filter(intf, filter):
35+
if filter is None:
36+
return True
37+
38+
intf_fs = parse_interface_in_filter(filter)
39+
if intf in intf_fs:
40+
return True
41+
42+
return False
43+

0 commit comments

Comments
 (0)