Skip to content

Commit

Permalink
[pfc] Add command line to enable/disable/show PFC (sonic-net#796)
Browse files Browse the repository at this point in the history
Current PFC cli only allows operators to enable/disable per-port asymmetric PFC. I extend add new commands to 1) enable/disable PFC on a given priority of a given port and 2) check PFC configuration. I also link all these commands to show and config utilities.

Signed-off-by: Wei Bai baiwei0427@gmail.com
Co-authored-by: lguohan <lguohan@gmail.com>
  • Loading branch information
baiwei0427 and lguohan authored Apr 3, 2020
1 parent 798ce2f commit 48c97dd
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 24 deletions.
22 changes: 20 additions & 2 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2158,7 +2158,7 @@ def ecn(profile, rmax, rmin, ymax, ymin, gmax, gmin, verbose):


#
# 'pfc' group ('config pfc ...')
# 'pfc' group ('config interface pfc ...')
#

@interface.group()
Expand All @@ -2169,7 +2169,7 @@ def pfc(ctx):


#
# 'pfc asymmetric' command
# 'pfc asymmetric' ('config interface pfc asymmetric ...')
#

@pfc.command()
Expand All @@ -2185,6 +2185,24 @@ def asymmetric(ctx, interface_name, status):

run_command("pfc config asymmetric {0} {1}".format(status, interface_name))

#
# 'pfc priority' command ('config interface pfc priority ...')
#

@pfc.command()
@click.argument('interface_name', metavar='<interface_name>', required=True)
@click.argument('priority', type=click.Choice([str(x) for x in range(8)]))
@click.argument('status', type=click.Choice(['on', 'off']))
@click.pass_context
def priority(ctx, interface_name, priority, status):
"""Set PFC priority configuration."""
if get_interface_naming_mode() == "alias":
interface_name = interface_alias_to_name(interface_name)
if interface_name is None:
ctx.fail("'interface_name' is None!")

run_command("pfc config priority {0} {1} {2}".format(status, interface_name, priority))

#
# 'platform' group ('config platform ...')
#
Expand Down
87 changes: 87 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2520,6 +2520,34 @@ VLAN interface names take the form of `vlan<vlan_id>`. E.g., VLAN 100 will be na
admin@sonic:~$ sudo config interface vlan100 ip remove 10.11.12.13/24
```

**config interface pfc priority <interface_name> <priority> (on | off)**

This command is used to set PFC on a given priority of a given interface to either "on" or "off". Once it is successfully configured, it will show current losses priorities on the given interface. Otherwise, it will show error information

- Example:
*Versions >= 201904*
```
admin@sonic:~$ sudo config interface pfc priority Ethernet0 3 off
Interface Lossless priorities
----------- ---------------------
Ethernet0 4
admin@sonic:~$ sudo config interface pfc priority Ethernet0 8 off
Usage: pfc config priority [OPTIONS] STATUS INTERFACE PRIORITY
Error: Invalid value for "priority": invalid choice: 8. (choose from 0, 1, 2, 3, 4, 5, 6, 7)
admin@sonic:~$ sudo config interface pfc priority Ethernet101 3 off
Cannot find interface Ethernet101
admin@sonic:~$ sudo config interface pfc priority Ethernet0 3 on
Interface Lossless priorities
----------- ---------------------
Ethernet0 3,4
```

**config interface pfc asymmetric <interface_name> (Versions >= 201904)**

**config interface <interface_name> pfc asymmetric (Versions <= 201811)**
Expand Down Expand Up @@ -4307,6 +4335,65 @@ This command displays the details of Rx & Tx priority-flow-control (pfc) for all
admin@sonic:~$ sonic-clear pfccounters
```
**show pfc asymmetric**
This command displays the status of asymmetric PFC for all interfaces or a given interface.
- Usage:
```
show pfc asymmetric [<interface>]
```
- Example:
```
admin@sonic:~$ show pfc asymmetric
Interface Asymmetric
----------- ------------
Ethernet0 off
Ethernet2 off
Ethernet4 off
Ethernet6 off
Ethernet8 off
Ethernet10 off
Ethernet12 off
Ethernet14 off
admin@sonic:~$ show pfc asymmetric Ethernet0
Interface Asymmetric
----------- ------------
Ethernet0 off
```
**show pfc priority**
This command displays the lossless priorities for all interfaces or a given interface.
- Usage:
```
show pfc priority [<interface>]
```
- Example:
```
admin@sonic:~$ show pfc priority
Interface Lossless priorities
----------- ---------------------
Ethernet0 3,4
Ethernet2 3,4
Ethernet8 3,4
Ethernet10 3,4
Ethernet16 3,4
admin@sonic:~$ show pfc priority Ethernet0
Interface Lossless priorities
----------- ---------------------
Ethernet0 3,4
```
#### Queue And Priority-Group
This sub-section explains the following queue parameters that can be displayed using "show queue" command.
Expand Down
120 changes: 98 additions & 22 deletions pfc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from tabulate import tabulate
from natsort import natsorted

ALL_PRIORITIES = [str(x) for x in range(8)]
PRIORITY_STATUS = ['on', 'off']

def configPfcAsym(interface, pfc_asym):
"""
PFC handler to configure asymmentric PFC.
"""

configdb = swsssdk.ConfigDBConnector()
configdb.connect()

Expand All @@ -22,11 +23,6 @@ def showPfcAsym(interface):
"""
PFC handler to display asymmetric PFC information.
"""

i = {}
table = []
key = []

header = ('Interface', 'Asymmetric')

configdb = swsssdk.ConfigDBConnector()
Expand All @@ -37,7 +33,10 @@ def showPfcAsym(interface):
else:
db_keys = configdb.keys(configdb.CONFIG_DB, 'PORT|*')

table = []

for i in db_keys or [None]:
key = None
if i:
key = i.split('|')[-1]

Expand All @@ -51,37 +50,114 @@ def showPfcAsym(interface):
print tabulate(sorted_table, headers=header, tablefmt="simple", missingval="")
print '\n'

def configPfcPrio(status, interface, priority):
configdb = swsssdk.ConfigDBConnector()
configdb.connect()

@click.group()
def cli():
if interface not in configdb.get_keys('PORT_QOS_MAP'):
print 'Cannot find interface {0}'.format(interface)
return

"""Current lossless priorities on the interface"""
entry = configdb.get_entry('PORT_QOS_MAP', interface)
enable_prio = entry.get('pfc_enable').split(',')

"""Avoid '' in enable_prio"""
enable_prio = [x.strip() for x in enable_prio if x.strip()]

if status == 'on' and priority in enable_prio:
print 'Priority {0} has already been enabled on {1}'.format(priority, interface)
return

if status == 'off' and priority not in enable_prio:
print 'Priority {0} is not enabled on {1}'.format(priority, interface)
return

if status == 'on':
enable_prio.append(priority)

else:
enable_prio.remove(priority)

enable_prio.sort()
configdb.mod_entry("PORT_QOS_MAP", interface, {'pfc_enable': ','.join(enable_prio)})

"""Show the latest PFC configuration"""
showPfcPrio(interface)

def showPfcPrio(interface):
"""
Utility entry point.
PFC handler to display PFC enabled priority information.
"""
header = ('Interface', 'Lossless priorities')
table = []

configdb = swsssdk.ConfigDBConnector()
configdb.connect()

"""Get all the interfaces with QoS map information"""
intfs = configdb.get_keys('PORT_QOS_MAP')

"""The user specifies an interface but we cannot find it"""
if interface and interface not in intfs:
print 'Cannot find interface {0}'.format(interface)
return

if interface:
intfs = [interface]

for intf in intfs:
entry = configdb.get_entry('PORT_QOS_MAP', intf)
table.append([intf, entry.get('pfc_enable', 'N/A')])

sorted_table = natsorted(table)
print '\n'
print tabulate(sorted_table, headers=header, tablefmt="simple", missingval="")
print '\n'

@click.group()
def cli():
"""PFC Command Line"""
pass


@cli.group()
def config():
"""Config PFC information"""
"""Config PFC"""
pass


@config.command()
@click.argument('status', type=click.Choice(['on', 'off']))
@click.argument('interface', type=click.STRING)
def asymmetric(status, interface):
"""Set asymmetric PFC configuration."""
configPfcAsym(interface, status)


@cli.group()
def show():
"""Show PFC information"""
pass

@click.command()
@click.argument('status', type=click.Choice(PRIORITY_STATUS))
@click.argument('interface', type=click.STRING)
def configAsym(status, interface):
"""Configure asymmetric PFC on a given port."""
configPfcAsym(interface, status)

@show.command()
@click.command()
@click.argument('status', type=click.Choice(PRIORITY_STATUS))
@click.argument('interface', type=click.STRING)
@click.argument('priority', type=click.Choice(ALL_PRIORITIES))
def configPrio(status, interface, priority):
"""Configure PFC on a given priority."""
configPfcPrio(status, interface, priority)

@click.command()
@click.argument('interface', type=click.STRING, required=False)
def asymmetric(interface):
def showAsym(interface):
"""Show asymmetric PFC information"""
showPfcAsym(interface)

@click.command()
@click.argument('interface', type=click.STRING, required=False)
def showPrio(interface):
"""Show PFC priority information"""
showPfcPrio(interface)

config.add_command(configAsym, "asymmetric")
config.add_command(configPrio, "priority")
show.add_command(showAsym, "asymmetric")
show.add_command(showPrio, "priority")
26 changes: 26 additions & 0 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,32 @@ def counters(verbose):

run_command(cmd, display_cmd=verbose)

@pfc.command()
@click.argument('interface', type=click.STRING, required=False)
def priority(interface):
"""Show pfc priority"""
cmd = 'pfc show priority'
if interface is not None and get_interface_mode() == "alias":
interface = iface_alias_converter.alias_to_name(interface)

if interface is not None:
cmd += ' {0}'.format(interface)

run_command(cmd)

@pfc.command()
@click.argument('interface', type=click.STRING, required=False)
def asymmetric(interface):
"""Show asymmetric pfc"""
cmd = 'pfc show asymmetric'
if interface is not None and get_interface_mode() == "alias":
interface = iface_alias_converter.alias_to_name(interface)

if interface is not None:
cmd += ' {0}'.format(interface)

run_command(cmd)

# 'pfcwd' subcommand ("show pfcwd...")
@cli.group(cls=AliasedGroup, default_if_no_args=False)
def pfcwd():
Expand Down

0 comments on commit 48c97dd

Please sign in to comment.