Skip to content

Commit

Permalink
JIRA-SONIC-1512: Broadcast Unknown-multicast and Unknown-unicast Stor…
Browse files Browse the repository at this point in the history
…m-control (sonic-net#928)

CLICK CLI - Configuration and show commands for BUM Storm-control feature.

configuration commands
----------------------
config interface storm-control broadcast add Ethernet0 10000
config interface storm-control unknown-multicast add Ethernet0 10000
config interface storm-control unknown-unicast add Ethernet0 10000

config interface storm-control broadcast del Ethernet0
config interface storm-control unknown-multicast del Ethernet0
config interface storm-control unknown-unicast del Ethernet0

show commands
-------------
show storm-control all
show storm-control interface Ethernet0

Sample output
-------------
show storm-control interface Ethernet0
+------------------+-------------------+---------------+
| Interface Name   | Storm Type        |   Rate (kbps) |
+==================+===================+===============+
| Ethernet0        | broadcast         |         10000 |
+------------------+-------------------+---------------+
| Ethernet0        | unknown-unicast   |         10000 |
+------------------+-------------------+---------------+
| Ethernet0        | unknown-multicast |         10000 |
+------------------+-------------------+---------------+
  • Loading branch information
mohan-selvaraj authored and kuanyu99 committed Nov 13, 2020
1 parent 9fdb39b commit 8a80a13
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 1 deletion.
150 changes: 150 additions & 0 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,72 @@ def _change_hostname(hostname):
run_command('sed -i "/\s{}$/d" /etc/hosts'.format(current_hostname), display_cmd=True)
run_command('echo "127.0.0.1 {}" >> /etc/hosts'.format(hostname), display_cmd=True)

def storm_control_interface_validate(port_name):
if get_interface_naming_mode() == "alias":
port_name = interface_alias_to_name(port_name)
if port_name is None:
click.echo("'port_name' is None!")
return False

if (port_name.startswith("Ethernet")):
if interface_name_is_valid(port_name) is False:
click.echo("Interface name %s is invalid. Please enter a valid interface name" %(port_name))
return False
else:
click.echo("Storm-control is supported only on Ethernet interfaces. Not supported on %s" %(port_name))
return False

return True

def storm_control_bps_validate(bps):
# if bps not in range(0,100000000001):
# click.echo("bps value must be in range 0-100000000000")
# return False
return True

def storm_control_set_entry(port_name, kbps, storm_type):

if storm_control_interface_validate(port_name) is False:
return False

if storm_control_bps_validate(kbps) is False:
return False

config_db = ConfigDBConnector()
config_db.connect()
key = port_name + '|' + storm_type
entry = config_db.get_entry('PORT_STORM_CONTROL',key)

if len(entry) == 0:
config_db.set_entry('PORT_STORM_CONTROL', key, {'kbps':kbps})
else:
kbps_value = int(entry.get('kbps',0))
click.echo("Existing value of bps %d"%(kbps_value))
if kbps_value != kbps:
config_db.mod_entry('PORT_STORM_CONTROL',key,{'kbps':kbps})

return True

def storm_control_delete_entry(port_name, storm_type):

if storm_control_interface_validate(port_name) is False:
return False

config_db = ConfigDBConnector()
config_db.connect()
key = port_name + '|' + storm_type
entry = config_db.get_entry('PORT_STORM_CONTROL',key)

if len(entry) == 0:
click.echo("%s storm-control not enabled on interface %s"%(storm_type, port_name))
return False
else:
config_db.set_entry('PORT_STORM_CONTROL',key,None)
click.echo("deleted %s storm-control from interface %s"%(storm_type, port_name))

return True


def _clear_qos():
QOS_TABLE_NAMES = [
'TC_TO_PRIORITY_GROUP_MAP',
Expand Down Expand Up @@ -3690,6 +3756,90 @@ def enable(enable):
command = "ztp enable"
run_command(command, display_cmd=True)

@interface.group('storm-control')
@click.pass_context
def storm_control(ctx):
""" Configure storm-control"""
pass

@storm_control.group('broadcast')
def broadcast():
""" Configure broadcast storm-control"""
pass

@broadcast.command('add')
@click.argument('port_name',metavar='<port_name>', required=True)
@click.argument('kbps',metavar='<kbps_value>', required=True, type=click.IntRange(0,100000000))
@click.pass_context
def add_broadcast_storm(ctx,port_name,kbps):
print"add broadcast storm-control"

if storm_control_set_entry(port_name, kbps, 'broadcast') is False:
ctx.fail("Unable to add broadcast storm-control")

@broadcast.command('del')
@click.argument('port_name',metavar='<port_name>', required=True)
#@click.argument('bps',metavar='<bps_value>', required=True, type=int)
@click.pass_context
#def del_broadcast_storm(ctx,port_name,bps):
def del_broadcast_storm(ctx,port_name):
print"del broadcast storm-control"

if storm_control_delete_entry(port_name, 'broadcast') is False:
ctx.fail("Unable to delete broadcast storm-control")

@storm_control.group('unknown-unicast')
def unknown_unicast():
""" Configure unknown-unicast storm-control"""
pass

@unknown_unicast.command('add')
@click.argument('port_name',metavar='<port_name>', required=True)
@click.argument('kbps',metavar='<kbps_value>', required=True, type=click.IntRange(0,100000000))
@click.pass_context
def add_unknown_unicast_storm(ctx,port_name,kbps):
print"add unknown-unicast storm-control"

if storm_control_set_entry(port_name, kbps, 'unknown-unicast') is False:
ctx.fail("Unable to add unknown-unicast storm-control")

@unknown_unicast.command('del')
@click.argument('port_name',metavar='<port_name>', required=True)
#@click.argument('bps',metavar='<bps_value>', required=True, type=int)
@click.pass_context
#def del_unknown_unicast_storm(ctx,port_name,bps):
def del_unknown_unicast_storm(ctx,port_name):
print"del unknown-unicast storm-control"

if storm_control_delete_entry(port_name, 'unknown-unicast') is False:
ctx.fail("Unable to delete unknown-unicast storm-control")

@storm_control.group('unknown-multicast')
def unknown_multicast():
""" Configure unknown-multicast storm-control"""
pass

@unknown_multicast.command('add')
@click.argument('port_name',metavar='<port_name>', required=True)
@click.argument('kbps',metavar='<kbps_value>', required=True, type=click.IntRange(0,100000000))
@click.pass_context
def add_unknown_multicast_storm(ctx,port_name,kbps):
print"add unknown-multicast storm-control"

if storm_control_set_entry(port_name, kbps, 'unknown-multicast') is False:
ctx.fail("Unable to add unknown-multicast storm-control")

@unknown_multicast.command('del')
@click.argument('port_name',metavar='<port_name>', required=True)
#@click.argument('bps',metavar='<bps_value>', required=True, type=int)
@click.pass_context
#def del_unknown_multicast_storm(ctx,port_name,bps):
def del_unknown_multicast_storm(ctx,port_name):
print"del unknown-multicast storm-control"

if storm_control_delete_entry(port_name, 'unknown-multicast') is False:
ctx.fail("Unable to delete unknown-multicast storm-control")

#
# 'syslog' group ('config syslog ...')
#
Expand Down
67 changes: 66 additions & 1 deletion show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,6 @@ def alias(interfacename):

click.echo(tabulate(body, header))


#
# 'breakout' group ###
#
Expand Down Expand Up @@ -908,6 +907,72 @@ def currrent_mode(ctx, interface):
body.append([name, str(curBrkout_tbl[name]['brkout_mode'])])
click.echo(tabulate(body, header, tablefmt="grid"))

@cli.group('storm-control')
def storm_control():
""" show storm-control """
pass

@storm_control.command('all')
def storm_control_all():
""" Show storm-control """

header = ['Interface Name', 'Storm Type', 'Rate (kbps)']
body = []

config_db = ConfigDBConnector()
config_db.connect()

table = config_db.get_table('PORT_STORM_CONTROL')

#To avoid further looping below
if not table:
return

sorted_table = natsorted(table)

for storm_key in sorted_table:
interface_name = storm_key[0]
storm_type = storm_key[1]
#interface_name, storm_type = storm_key.split(':')
data = config_db.get_entry('PORT_STORM_CONTROL', storm_key)

if not data:
return

kbps = data['kbps']

body.append([interface_name, storm_type, kbps])

click.echo(tabulate(body, header, tablefmt="grid"))

@storm_control.command('interface')
@click.argument('interfacename', required=True)
def storm_control_interface(interfacename):
""" Show storm-control """

storm_type_list = ['broadcast','unknown-unicast','unknown-multicast']

header = ['Interface Name', 'Storm Type', 'Rate (kbps)']
body = []

config_db = ConfigDBConnector()
config_db.connect()

table = config_db.get_table('PORT_STORM_CONTROL')

#To avoid further looping below
if not table:
return

for storm_type in storm_type_list:
storm_key = interfacename + '|' + storm_type
data = config_db.get_entry('PORT_STORM_CONTROL', storm_key)

if data:
kbps = data['kbps']
body.append([interfacename, storm_type, kbps])

click.echo(tabulate(body, header, tablefmt="grid"))

#
# 'neighbor' group ###
Expand Down

0 comments on commit 8a80a13

Please sign in to comment.