Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sonic-utilities updates for MPLS #1537

Merged
merged 2 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3936,6 +3936,56 @@ def reset(ctx, interface_name):
cmd = "sudo sfputil reset {}".format(interface_name)
clicommon.run_command(cmd)

#
# 'mpls' subgroup ('config interface mpls ...')
#

@interface.group(cls=clicommon.AbbreviationGroup)
@click.pass_context
def mpls(ctx):
"""Add or remove MPLS"""
pass

#
# 'add' subcommand
#

@mpls.command()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not move mpls into a mpls.py instead of put them in the main.py file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lguohan You asked this same question 3 months ago. I will restate my answer from then: All subgroups, including mpls, of the interface.group are in main.py. The mpls subgroup is very small and a separate file is overkill.

@click.argument('interface_name', metavar='<interface_name>', required=True)
smaheshm marked this conversation as resolved.
Show resolved Hide resolved
@click.pass_context
def add(ctx, interface_name):
"""Add MPLS operation on the interface"""
config_db = ctx.obj["config_db"]
if clicommon.get_interface_naming_mode() == "alias":
interface_name = interface_alias_to_name(config_db, interface_name)
if interface_name is None:
ctx.fail("'interface_name' is None!")

table_name = get_interface_table_name(interface_name)
if table_name == "":
ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan]")
config_db.set_entry(table_name, interface_name, {"mpls": "enable"})

#
# 'del' subcommand
#

@mpls.command()
@click.argument('interface_name', metavar='<interface_name>', required=True)
@click.pass_context
def remove(ctx, interface_name):
"""Remove MPLS operation from the interface"""
config_db = ctx.obj["config_db"]
if clicommon.get_interface_naming_mode() == "alias":
interface_name = interface_alias_to_name(config_db, interface_name)
if interface_name is None:
ctx.fail("'interface_name' is None!")

table_name = get_interface_table_name(interface_name)
if table_name == "":
ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan]")
config_db.set_entry(table_name, interface_name, {"mpls": "disable"})
smaheshm marked this conversation as resolved.
Show resolved Hide resolved

#
# 'vrf' subgroup ('config interface vrf ...')
#
Expand Down
54 changes: 49 additions & 5 deletions crm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def show_thresholds(self, resource):
if resource == 'all':
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
"nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry",
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry"]:
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry", "mpls_inseg",
"mpls_nexthop"]:
try:
data.append([res, crm_info[res + "_threshold_type"], crm_info[res + "_low_threshold"], crm_info[res + "_high_threshold"]])
except KeyError:
Expand All @@ -97,7 +98,8 @@ def get_resources(self, resource):
if crm_stats:
if resource == 'all':
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry"]:
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry",
"mpls_inseg", "mpls_nexthop"]:
if 'crm_stats_' + res + "_used" in crm_stats.keys() and 'crm_stats_' + res + "_available" in crm_stats.keys():
data.append([res, crm_stats['crm_stats_' + res + "_used"], crm_stats['crm_stats_' + res + "_available"]])
else:
Expand Down Expand Up @@ -262,6 +264,18 @@ def ipv6(ctx):
"""CRM resource IPv6 address-family"""
ctx.obj["crm"].addr_family = 'ipv6'

@thresholds.group()
@click.pass_context
def mpls(ctx):
"""CRM resource MPLS address-family"""
ctx.obj["crm"].addr_family = 'mpls'

@mpls.group()
@click.pass_context
def inseg(ctx):
"""CRM configuration for in-segment resource"""
ctx.obj["crm"].res_type = 'inseg'

@ipv4.group()
@click.pass_context
def route(ctx):
Expand All @@ -284,7 +298,7 @@ def nexthop(ctx):
@click.argument('value', type=click.Choice(['percentage', 'used', 'free']))
@click.pass_context
def type(ctx, value):
"""CRM threshod type configuration"""
"""CRM threshold type configuration"""
attr = ''

if ctx.obj["crm"].addr_family != None:
Expand All @@ -298,7 +312,7 @@ def type(ctx, value):
@click.argument('value', type=click.INT)
@click.pass_context
def low(ctx, value):
"""CRM low threshod configuration"""
"""CRM low threshold configuration"""
attr = ''

if ctx.obj["crm"].addr_family != None:
Expand All @@ -312,7 +326,7 @@ def low(ctx, value):
@click.argument('value', type=click.INT)
@click.pass_context
def high(ctx, value):
"""CRM high threshod configuration"""
"""CRM high threshold configuration"""
attr = ''

if ctx.obj["crm"].addr_family != None:
Expand All @@ -328,9 +342,13 @@ def high(ctx, value):
nexthop.add_command(type)
nexthop.add_command(low)
nexthop.add_command(high)
inseg.add_command(type)
inseg.add_command(low)
inseg.add_command(high)
ipv6.add_command(route)
ipv6.add_command(neighbor)
ipv6.add_command(nexthop)
mpls.add_command(nexthop)

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

@resources.group()
@click.pass_context
def mpls(ctx):
"""CRM resource MPLS address family"""
ctx.obj["crm"].addr_family = 'mpls'

@mpls.command()
@click.pass_context
def inseg(ctx):
"""Show CRM information for in-segment resource"""
if ctx.obj["crm"].cli_mode == 'thresholds':
ctx.obj["crm"].show_thresholds('{0}_inseg'.format(ctx.obj["crm"].addr_family))
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('{0}_inseg'.format(ctx.obj["crm"].addr_family))

@ipv4.command()
@click.pass_context
def route(ctx):
Expand Down Expand Up @@ -520,9 +553,19 @@ def nexthop(ctx):
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('{0}_nexthop'.format(ctx.obj["crm"].addr_family))

@mpls.command()
@click.pass_context
def inseg(ctx):
"""Show CRM information for in-segment resource"""
if ctx.obj["crm"].cli_mode == 'thresholds':
ctx.obj["crm"].show_thresholds('{0}_inseg'.format(ctx.obj["crm"].addr_family))
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('{0}_inseg'.format(ctx.obj["crm"].addr_family))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand why this is a repeat of line 520-528

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smaheshm This cut-n-paste remnant has been removed.

ipv6.add_command(route)
ipv6.add_command(neighbor)
ipv6.add_command(nexthop)
mpls.add_command(nexthop)

@resources.group()
@click.pass_context
Expand Down Expand Up @@ -619,6 +662,7 @@ def dnat(ctx):
thresholds.add_command(fdb)
thresholds.add_command(ipv4)
thresholds.add_command(ipv6)
thresholds.add_command(mpls)
thresholds.add_command(nexthop)
thresholds.add_command(ipmc)
thresholds.add_command(snat)
Expand Down
77 changes: 77 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -3095,6 +3095,7 @@ Subsequent pages explain each of these commands in detail.
breakout Show Breakout Mode information by interfaces
counters Show interface counters
description Show interface status, protocol and...
mpls Show Interface MPLS status
naming_mode Show interface naming_mode status
neighbor Show neighbor related information
portchannel Show PortChannel information
Expand Down Expand Up @@ -3334,6 +3335,36 @@ This command displays the key fields of the interfaces such as Operational Statu
Ethernet4 down up hundredGigE1/2 T0-2:hundredGigE1/30
```

**show interfaces mpls**

This command is used to display the configured MPLS state for the list of configured interfaces.

- Usage:
```
show interfaces mpls [<interface_name>]
```

- Example:
```
admin@sonic:~$ show interfaces mpls
Interface MPLS State
----------- ------------
Ethernet0 disable
Ethernet4 enable
Ethernet8 enable
Ethernet12 disable
Ethernet16 disable
Ethernet20 disable
```

- Example (to only display the MPLS state for interface Ethernet4):
```
admin@sonic:~$ show interfaces mpls Ethernet4
Interface MPLS State
----------- ------------
Ethernet4 enable
```

**show interfaces tpid**

This command displays the key fields of the interfaces such as Operational Status, Administrative Status, Alias and TPID.
Expand Down Expand Up @@ -3479,6 +3510,7 @@ This sub-section explains the following list of configuration on the interfaces.
8) advertised-speeds - to set interface advertised speeds
9) advertised-types - to set interface advertised types
10) type - to set interface type
11) mpls - To add or remove MPLS operation for the interface

From 201904 release onwards, the “config interface” command syntax is changed and the format is as follows:

Expand Down Expand Up @@ -3951,6 +3983,51 @@ For details please refer [dynamic buffer management](#dynamic-buffer-management)

Go Back To [Beginning of the document](#) or [Beginning of this section](#interfaces)

**config interface mpls add <interface_name> (Versions >= 202106)**

This command is used for adding MPLS operation on the interface.
MPLS operation for either physical, portchannel, or VLAN interface can be configured using this command.


- Usage:
```
sudo config interface mpls add --help
Usage: config interface mpls add [OPTIONS] <interface_name>

Add MPLS operation on the interface

Options:
-?, -h, --help Show this message and exit.
```

- Example:
```
admin@sonic:~$ sudo config interface mpls add Ethernet4
```

**config interface mpls remove <interface_name> (Versions >= 202106)**

This command is used for removing MPLS operation on the interface.
MPLS operation for either physical, portchannel, or VLAN interface can be configured using this command.

- Usage:
```
sudo config interface mpls remove --help
Usage: config interface mpls remove [OPTIONS] <interface_name>

Remove MPLS operation from the interface

Options:
-?, -h, --help Show this message and exit.
```

- Example:
```
admin@sonic:~$ sudo config interface mpls remove Ethernet4
```

Go Back To [Beginning of the document](#) or [Beginning of this section](#interfaces)

## Interface Naming Mode

### Interface naming mode show commands
Expand Down
46 changes: 45 additions & 1 deletion show/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from tabulate import tabulate
from sonic_py_common import multi_asic
from sonic_py_common import device_info
from swsscommon.swsscommon import ConfigDBConnector
from swsscommon.swsscommon import ConfigDBConnector, SonicV2Connector
from portconfig import get_child_ports
import sonic_platform_base.sonic_sfp.sfputilhelper

Expand Down Expand Up @@ -321,6 +321,50 @@ def expected(db, interfacename):

click.echo(tabulate(body, header))

# 'mpls' subcommand ("show interfaces mpls")
@interfaces.command()
@click.argument('interfacename', required=False)
@click.pass_context
def mpls(ctx, interfacename):
"""Show Interface MPLS status"""

appl_db = SonicV2Connector()
smaheshm marked this conversation as resolved.
Show resolved Hide resolved
appl_db.connect(appl_db.APPL_DB)

if interfacename is not None:
interfacename = try_convert_interfacename_from_alias(ctx, interfacename)

# Fetching data from appl_db for intfs
keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:*")
intfs_data = {}
for key in keys if keys else []:
tokens = key.split(":")
# Skip INTF_TABLE entries with address information
if len(tokens) != 2:
continue

if (interfacename is not None) and (interfacename != tokens[1]):
continue

mpls = appl_db.get(appl_db.APPL_DB, key, 'mpls')
if mpls is None or mpls == '':
intfs_data.update({tokens[1]: 'disable'})
else:
intfs_data.update({tokens[1]: mpls})

header = ['Interface', 'MPLS State']
body = []

# Output name and alias for all interfaces
for intf_name in natsorted(list(intfs_data.keys())):
if clicommon.get_interface_naming_mode() == "alias":
alias = clicommon.InterfaceAliasConverter().name_to_alias(intf_name)
body.append([alias, intfs_data[intf_name]])
else:
body.append([intf_name, intfs_data[intf_name]])

smaheshm marked this conversation as resolved.
Show resolved Hide resolved
click.echo(tabulate(body, header))

interfaces.add_command(portchannel.portchannel)

#
Expand Down
Loading