Skip to content

Commit 88bae6d

Browse files
Add support to configure routed subinterface in short name and long name
format Update "show subniterface status" to reflect subinterface in user configured long name and short name format.
1 parent 2b12aad commit 88bae6d

File tree

2 files changed

+123
-2
lines changed

2 files changed

+123
-2
lines changed

config/main.py

+120-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from portconfig import get_child_ports
2121
from socket import AF_INET, AF_INET6
2222
from sonic_py_common import device_info, multi_asic
23-
from sonic_py_common.interface import get_interface_table_name, get_port_table_name
23+
from sonic_py_common.interface import get_interface_table_name, get_port_table_name, intf_get_longname
2424
from utilities_common import util_base
2525
from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector
2626
from utilities_common.db import Db
@@ -5846,6 +5846,125 @@ def smoothing_interval(interval, rates_type):
58465846
for plugin in helper.load_plugins(plugins):
58475847
helper.register_plugin(plugin, config)
58485848

5849+
#
5850+
# 'subinterface' group ('config subinterface ...')
5851+
#
5852+
@config.group()
5853+
@click.pass_context
5854+
@click.option('-s', '--redis-unix-socket-path', help='unix socket path for redis connection')
5855+
def subinterface(ctx, redis_unix_socket_path):
5856+
"""subinterface-related configuration tasks"""
5857+
kwargs = {}
5858+
if redis_unix_socket_path:
5859+
kwargs['unix_socket_path'] = redis_unix_socket_path
5860+
config_db = ConfigDBConnector(**kwargs)
5861+
config_db.connect(wait_for_init=False)
5862+
ctx.obj = {'db': config_db}
5863+
pass
5864+
5865+
def subintf_vlan_check(config_db, parent_intf, vlan):
5866+
subintf_db = config_db.get_table('VLAN_SUB_INTERFACE')
5867+
subintf_names = [k for k in subintf_db if type(k) != tuple]
5868+
for subintf in subintf_names:
5869+
sub_intf_sep_idx = subintf.find(VLAN_SUB_INTERFACE_SEPARATOR)
5870+
if sub_intf_sep_idx == -1:
5871+
continue
5872+
if parent_intf == subintf[:sub_intf_sep_idx]:
5873+
if 'vlan' in subintf_db[subintf]:
5874+
if str(vlan) == subintf_db[subintf]['vlan']:
5875+
return True
5876+
else:
5877+
vlan_id = subintf[sub_intf_sep_idx + 1:]
5878+
if str(vlan) == vlan_id:
5879+
return True
5880+
return False
5881+
5882+
@subinterface.command('add')
5883+
@click.argument('subinterface_name', metavar='<subinterface_name>', required=True)
5884+
@click.argument('vid', metavar='<vid>', required=False, type=click.IntRange(1,4094))
5885+
@click.pass_context
5886+
def add_subinterface(ctx, subinterface_name, vid):
5887+
sub_intf_sep_idx = subinterface_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
5888+
if sub_intf_sep_idx == -1:
5889+
ctx.fail("{} is invalid vlan subinterface".format(subinterface_name))
5890+
5891+
interface_alias = subinterface_name[:sub_intf_sep_idx]
5892+
vlan_id = subinterface_name[sub_intf_sep_idx + 1:]
5893+
if interface_alias is None:
5894+
ctx.fail("{} invalid subinterface".format(interface_alias))
5895+
5896+
if interface_alias.startswith("Po") is True:
5897+
intf_table_name = CFG_PORTCHANNEL_PREFIX
5898+
elif interface_alias.startswith("Eth") is True:
5899+
intf_table_name = 'PORT'
5900+
5901+
config_db = ctx.obj['db']
5902+
port_dict = config_db.get_table(intf_table_name)
5903+
if interface_alias is not None:
5904+
if not port_dict:
5905+
ctx.fail("{} parent interface not found. {} table none".format(interface_alias, intf_table_name))
5906+
if intf_get_longname(interface_alias) not in port_dict.keys():
5907+
ctx.fail("{} parent interface not found".format(subinterface_name))
5908+
5909+
# Validate if parent is portchannel member
5910+
portchannel_member_table = config_db.get_table('PORTCHANNEL_MEMBER')
5911+
if interface_is_in_portchannel(portchannel_member_table, interface_alias):
5912+
ctx.fail("{} is configured as a member of portchannel. Cannot configure subinterface"
5913+
.format(interface_alias))
5914+
5915+
# Validate if parent is vlan member
5916+
vlan_member_table = config_db.get_table('VLAN_MEMBER')
5917+
if interface_is_in_vlan(vlan_member_table, interface_alias):
5918+
ctx.fail("{} is configured as a member of vlan. Cannot configure subinterface"
5919+
.format(interface_alias))
5920+
5921+
sub_intfs = [k for k,v in config_db.get_table('VLAN_SUB_INTERFACE').items() if type(k) != tuple]
5922+
if subinterface_name in sub_intfs:
5923+
ctx.fail("{} already exists".format(subinterface_name))
5924+
5925+
subintf_dict = {}
5926+
if vid is not None:
5927+
subintf_dict.update({"vlan" : vid})
5928+
5929+
if subintf_vlan_check(config_db, intf_get_longname(interface_alias), vid) is True:
5930+
ctx.fail("Vlan {} encap already configured on other subinterface on {}".format(vid, interface_alias))
5931+
5932+
subintf_dict.update({"admin_status" : "up"})
5933+
config_db.set_entry('VLAN_SUB_INTERFACE', subinterface_name, subintf_dict)
5934+
5935+
@subinterface.command('del')
5936+
@click.argument('subinterface_name', metavar='<subinterface_name>', required=True)
5937+
@click.pass_context
5938+
def del_subinterface(ctx, subinterface_name):
5939+
sub_intf_sep_idx = subinterface_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
5940+
if sub_intf_sep_idx == -1:
5941+
ctx.fail("{} is invalid vlan subinterface".format(subinterface_name))
5942+
5943+
config_db = ctx.obj['db']
5944+
#subinterface_name = subintf_get_shortname(subinterface_name)
5945+
if interface_name_is_valid(config_db, subinterface_name) is False:
5946+
ctx.fail("{} is invalid ".format(subinterface_name))
5947+
5948+
subintf_config_db = config_db.get_table('VLAN_SUB_INTERFACE')
5949+
sub_intfs = [k for k,v in subintf_config_db.items() if type(k) != tuple]
5950+
if subinterface_name not in sub_intfs:
5951+
ctx.fail("{} does not exists".format(subinterface_name))
5952+
5953+
ips = {}
5954+
ips = [ k[1] for k in config_db.get_table('VLAN_SUB_INTERFACE') if type(k) == tuple and k[0] == subinterface_name ]
5955+
for ip in ips:
5956+
try:
5957+
ipaddress.ip_network(ip, strict=False)
5958+
config_db.set_entry('VLAN_SUB_INTERFACE', (subinterface_name, ip), None)
5959+
except ValueError:
5960+
ctx.fail("Invalid ip {} found on interface {}".format(ip, subinterface_name))
5961+
5962+
subintf_config_db = config_db.get_table('INTERFACE')
5963+
ips = [ k[1] for k in subintf_config_db if type(k) == tuple and k[0] == subinterface_name ]
5964+
for ip in ips:
5965+
config_db.set_entry('INTERFACE', (subinterface_name, ip), None)
5966+
5967+
config_db.set_entry('VLAN_SUB_INTERFACE', subinterface_name, None)
58495968

58505969
if __name__ == '__main__':
58515970
config()

scripts/intfutil

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from tabulate import tabulate
1010
from utilities_common import constants
1111
from utilities_common import multi_asic as multi_asic_util
1212
from utilities_common.intf_filter import parse_interface_in_filter
13+
from sonic_py_common.interface import intf_get_longname
1314

1415
# mock the redis for unit test purposes #
1516
try:
@@ -313,12 +314,13 @@ def appl_db_portchannel_status_get(appl_db, config_db, po_name, status_type, por
313314
def appl_db_sub_intf_status_get(appl_db, config_db, front_panel_ports_list, portchannel_speed_dict, sub_intf_name, status_type):
314315
sub_intf_sep_idx = sub_intf_name.find(VLAN_SUB_INTERFACE_SEPARATOR)
315316
if sub_intf_sep_idx != -1:
316-
parent_port_name = sub_intf_name[:sub_intf_sep_idx]
317+
parent_port_name = intf_get_longname(sub_intf_name[:sub_intf_sep_idx])
317318
vlan_id = sub_intf_name[sub_intf_sep_idx + 1:]
318319

319320
full_intf_table_name = "INTF_TABLE" + ":" + sub_intf_name
320321

321322
if status_type == "vlan":
323+
vlan_id = appl_db.get(appl_db.APPL_DB, full_intf_table_name, status_type)
322324
return vlan_id
323325

324326
if status_type == "admin_status":

0 commit comments

Comments
 (0)