Skip to content

Commit 3f0b690

Browse files
authored
[MPLS][CLI] added config/show CLI for MPLS interface, MPLS CRM threshold config, updated CLI reference manual
SONiC CLI support for MPLS: "config interface mpls (add | remove) <if-name>" "show interface mpls [<if-name>]" CRM threshold configuration for mpls_inseg and mpls_nexthop Updated SONiC CLI command reference manual. Added unit tests for all CLI commands
1 parent e8b6c5c commit 3f0b690

13 files changed

+570
-12
lines changed

config/main.py

+50
Original file line numberDiff line numberDiff line change
@@ -3949,6 +3949,56 @@ def reset(ctx, interface_name):
39493949
cmd = "sudo sfputil reset {}".format(interface_name)
39503950
clicommon.run_command(cmd)
39513951

3952+
#
3953+
# 'mpls' subgroup ('config interface mpls ...')
3954+
#
3955+
3956+
@interface.group(cls=clicommon.AbbreviationGroup)
3957+
@click.pass_context
3958+
def mpls(ctx):
3959+
"""Add or remove MPLS"""
3960+
pass
3961+
3962+
#
3963+
# 'add' subcommand
3964+
#
3965+
3966+
@mpls.command()
3967+
@click.argument('interface_name', metavar='<interface_name>', required=True)
3968+
@click.pass_context
3969+
def add(ctx, interface_name):
3970+
"""Add MPLS operation on the interface"""
3971+
config_db = ctx.obj["config_db"]
3972+
if clicommon.get_interface_naming_mode() == "alias":
3973+
interface_name = interface_alias_to_name(config_db, interface_name)
3974+
if interface_name is None:
3975+
ctx.fail("'interface_name' is None!")
3976+
3977+
table_name = get_interface_table_name(interface_name)
3978+
if table_name == "":
3979+
ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan]")
3980+
config_db.set_entry(table_name, interface_name, {"mpls": "enable"})
3981+
3982+
#
3983+
# 'del' subcommand
3984+
#
3985+
3986+
@mpls.command()
3987+
@click.argument('interface_name', metavar='<interface_name>', required=True)
3988+
@click.pass_context
3989+
def remove(ctx, interface_name):
3990+
"""Remove MPLS operation from the interface"""
3991+
config_db = ctx.obj["config_db"]
3992+
if clicommon.get_interface_naming_mode() == "alias":
3993+
interface_name = interface_alias_to_name(config_db, interface_name)
3994+
if interface_name is None:
3995+
ctx.fail("'interface_name' is None!")
3996+
3997+
table_name = get_interface_table_name(interface_name)
3998+
if table_name == "":
3999+
ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan]")
4000+
config_db.set_entry(table_name, interface_name, {"mpls": "disable"})
4001+
39524002
#
39534003
# 'vrf' subgroup ('config interface vrf ...')
39544004
#

crm/main.py

+40-5
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def show_thresholds(self, resource):
7070
if resource == 'all':
7171
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
7272
"nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry",
73-
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry"]:
73+
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry", "mpls_inseg",
74+
"mpls_nexthop"]:
7475
try:
7576
data.append([res, crm_info[res + "_threshold_type"], crm_info[res + "_low_threshold"], crm_info[res + "_high_threshold"]])
7677
except KeyError:
@@ -97,7 +98,8 @@ def get_resources(self, resource):
9798
if crm_stats:
9899
if resource == 'all':
99100
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
100-
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry"]:
101+
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry",
102+
"mpls_inseg", "mpls_nexthop"]:
101103
if 'crm_stats_' + res + "_used" in crm_stats.keys() and 'crm_stats_' + res + "_available" in crm_stats.keys():
102104
data.append([res, crm_stats['crm_stats_' + res + "_used"], crm_stats['crm_stats_' + res + "_available"]])
103105
else:
@@ -262,6 +264,18 @@ def ipv6(ctx):
262264
"""CRM resource IPv6 address-family"""
263265
ctx.obj["crm"].addr_family = 'ipv6'
264266

267+
@thresholds.group()
268+
@click.pass_context
269+
def mpls(ctx):
270+
"""CRM resource MPLS address-family"""
271+
ctx.obj["crm"].addr_family = 'mpls'
272+
273+
@mpls.group()
274+
@click.pass_context
275+
def inseg(ctx):
276+
"""CRM configuration for in-segment resource"""
277+
ctx.obj["crm"].res_type = 'inseg'
278+
265279
@ipv4.group()
266280
@click.pass_context
267281
def route(ctx):
@@ -284,7 +298,7 @@ def nexthop(ctx):
284298
@click.argument('value', type=click.Choice(['percentage', 'used', 'free']))
285299
@click.pass_context
286300
def type(ctx, value):
287-
"""CRM threshod type configuration"""
301+
"""CRM threshold type configuration"""
288302
attr = ''
289303

290304
if ctx.obj["crm"].addr_family != None:
@@ -298,7 +312,7 @@ def type(ctx, value):
298312
@click.argument('value', type=click.INT)
299313
@click.pass_context
300314
def low(ctx, value):
301-
"""CRM low threshod configuration"""
315+
"""CRM low threshold configuration"""
302316
attr = ''
303317

304318
if ctx.obj["crm"].addr_family != None:
@@ -312,7 +326,7 @@ def low(ctx, value):
312326
@click.argument('value', type=click.INT)
313327
@click.pass_context
314328
def high(ctx, value):
315-
"""CRM high threshod configuration"""
329+
"""CRM high threshold configuration"""
316330
attr = ''
317331

318332
if ctx.obj["crm"].addr_family != None:
@@ -328,9 +342,13 @@ def high(ctx, value):
328342
nexthop.add_command(type)
329343
nexthop.add_command(low)
330344
nexthop.add_command(high)
345+
inseg.add_command(type)
346+
inseg.add_command(low)
347+
inseg.add_command(high)
331348
ipv6.add_command(route)
332349
ipv6.add_command(neighbor)
333350
ipv6.add_command(nexthop)
351+
mpls.add_command(nexthop)
334352

335353
@thresholds.group()
336354
@click.pass_context
@@ -493,6 +511,21 @@ def ipv6(ctx):
493511
"""CRM resource IPv6 address family"""
494512
ctx.obj["crm"].addr_family = 'ipv6'
495513

514+
@resources.group()
515+
@click.pass_context
516+
def mpls(ctx):
517+
"""CRM resource MPLS address family"""
518+
ctx.obj["crm"].addr_family = 'mpls'
519+
520+
@mpls.command()
521+
@click.pass_context
522+
def inseg(ctx):
523+
"""Show CRM information for in-segment resource"""
524+
if ctx.obj["crm"].cli_mode == 'thresholds':
525+
ctx.obj["crm"].show_thresholds('{0}_inseg'.format(ctx.obj["crm"].addr_family))
526+
elif ctx.obj["crm"].cli_mode == 'resources':
527+
ctx.obj["crm"].show_resources('{0}_inseg'.format(ctx.obj["crm"].addr_family))
528+
496529
@ipv4.command()
497530
@click.pass_context
498531
def route(ctx):
@@ -523,6 +556,7 @@ def nexthop(ctx):
523556
ipv6.add_command(route)
524557
ipv6.add_command(neighbor)
525558
ipv6.add_command(nexthop)
559+
mpls.add_command(nexthop)
526560

527561
@resources.group()
528562
@click.pass_context
@@ -619,6 +653,7 @@ def dnat(ctx):
619653
thresholds.add_command(fdb)
620654
thresholds.add_command(ipv4)
621655
thresholds.add_command(ipv6)
656+
thresholds.add_command(mpls)
622657
thresholds.add_command(nexthop)
623658
thresholds.add_command(ipmc)
624659
thresholds.add_command(snat)

doc/Command-Reference.md

+77
Original file line numberDiff line numberDiff line change
@@ -3095,6 +3095,7 @@ Subsequent pages explain each of these commands in detail.
30953095
breakout Show Breakout Mode information by interfaces
30963096
counters Show interface counters
30973097
description Show interface status, protocol and...
3098+
mpls Show Interface MPLS status
30983099
naming_mode Show interface naming_mode status
30993100
neighbor Show neighbor related information
31003101
portchannel Show PortChannel information
@@ -3334,6 +3335,36 @@ This command displays the key fields of the interfaces such as Operational Statu
33343335
Ethernet4 down up hundredGigE1/2 T0-2:hundredGigE1/30
33353336
```
33363337
3338+
**show interfaces mpls**
3339+
3340+
This command is used to display the configured MPLS state for the list of configured interfaces.
3341+
3342+
- Usage:
3343+
```
3344+
show interfaces mpls [<interface_name>]
3345+
```
3346+
3347+
- Example:
3348+
```
3349+
admin@sonic:~$ show interfaces mpls
3350+
Interface MPLS State
3351+
----------- ------------
3352+
Ethernet0 disable
3353+
Ethernet4 enable
3354+
Ethernet8 enable
3355+
Ethernet12 disable
3356+
Ethernet16 disable
3357+
Ethernet20 disable
3358+
```
3359+
3360+
- Example (to only display the MPLS state for interface Ethernet4):
3361+
```
3362+
admin@sonic:~$ show interfaces mpls Ethernet4
3363+
Interface MPLS State
3364+
----------- ------------
3365+
Ethernet4 enable
3366+
```
3367+
33373368
**show interfaces tpid**
33383369
33393370
This command displays the key fields of the interfaces such as Operational Status, Administrative Status, Alias and TPID.
@@ -3479,6 +3510,7 @@ This sub-section explains the following list of configuration on the interfaces.
34793510
8) advertised-speeds - to set interface advertised speeds
34803511
9) advertised-types - to set interface advertised types
34813512
10) type - to set interface type
3513+
11) mpls - To add or remove MPLS operation for the interface
34823514
34833515
From 201904 release onwards, the “config interface” command syntax is changed and the format is as follows:
34843516
@@ -3951,6 +3983,51 @@ For details please refer [dynamic buffer management](#dynamic-buffer-management)
39513983
39523984
Go Back To [Beginning of the document](#) or [Beginning of this section](#interfaces)
39533985
3986+
**config interface mpls add <interface_name> (Versions >= 202106)**
3987+
3988+
This command is used for adding MPLS operation on the interface.
3989+
MPLS operation for either physical, portchannel, or VLAN interface can be configured using this command.
3990+
3991+
3992+
- Usage:
3993+
```
3994+
sudo config interface mpls add --help
3995+
Usage: config interface mpls add [OPTIONS] <interface_name>
3996+
3997+
Add MPLS operation on the interface
3998+
3999+
Options:
4000+
-?, -h, --help Show this message and exit.
4001+
```
4002+
4003+
- Example:
4004+
```
4005+
admin@sonic:~$ sudo config interface mpls add Ethernet4
4006+
```
4007+
4008+
**config interface mpls remove <interface_name> (Versions >= 202106)**
4009+
4010+
This command is used for removing MPLS operation on the interface.
4011+
MPLS operation for either physical, portchannel, or VLAN interface can be configured using this command.
4012+
4013+
- Usage:
4014+
```
4015+
sudo config interface mpls remove --help
4016+
Usage: config interface mpls remove [OPTIONS] <interface_name>
4017+
4018+
Remove MPLS operation from the interface
4019+
4020+
Options:
4021+
-?, -h, --help Show this message and exit.
4022+
```
4023+
4024+
- Example:
4025+
```
4026+
admin@sonic:~$ sudo config interface mpls remove Ethernet4
4027+
```
4028+
4029+
Go Back To [Beginning of the document](#) or [Beginning of this section](#interfaces)
4030+
39544031
## Interface Naming Mode
39554032
39564033
### Interface naming mode show commands

show/interfaces/__init__.py

+45-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from tabulate import tabulate
1010
from sonic_py_common import multi_asic
1111
from sonic_py_common import device_info
12-
from swsscommon.swsscommon import ConfigDBConnector
12+
from swsscommon.swsscommon import ConfigDBConnector, SonicV2Connector
1313
from portconfig import get_child_ports
1414
import sonic_platform_base.sonic_sfp.sfputilhelper
1515

@@ -321,6 +321,50 @@ def expected(db, interfacename):
321321

322322
click.echo(tabulate(body, header))
323323

324+
# 'mpls' subcommand ("show interfaces mpls")
325+
@interfaces.command()
326+
@click.argument('interfacename', required=False)
327+
@click.pass_context
328+
def mpls(ctx, interfacename):
329+
"""Show Interface MPLS status"""
330+
331+
appl_db = SonicV2Connector()
332+
appl_db.connect(appl_db.APPL_DB)
333+
334+
if interfacename is not None:
335+
interfacename = try_convert_interfacename_from_alias(ctx, interfacename)
336+
337+
# Fetching data from appl_db for intfs
338+
keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:*")
339+
intfs_data = {}
340+
for key in keys if keys else []:
341+
tokens = key.split(":")
342+
# Skip INTF_TABLE entries with address information
343+
if len(tokens) != 2:
344+
continue
345+
346+
if (interfacename is not None) and (interfacename != tokens[1]):
347+
continue
348+
349+
mpls = appl_db.get(appl_db.APPL_DB, key, 'mpls')
350+
if mpls is None or mpls == '':
351+
intfs_data.update({tokens[1]: 'disable'})
352+
else:
353+
intfs_data.update({tokens[1]: mpls})
354+
355+
header = ['Interface', 'MPLS State']
356+
body = []
357+
358+
# Output name and alias for all interfaces
359+
for intf_name in natsorted(list(intfs_data.keys())):
360+
if clicommon.get_interface_naming_mode() == "alias":
361+
alias = clicommon.InterfaceAliasConverter().name_to_alias(intf_name)
362+
body.append([alias, intfs_data[intf_name]])
363+
else:
364+
body.append([intf_name, intfs_data[intf_name]])
365+
366+
click.echo(tabulate(body, header))
367+
324368
interfaces.add_command(portchannel.portchannel)
325369

326370
#

0 commit comments

Comments
 (0)