Skip to content

Commit 595c2aa

Browse files
authored
Utilities Changes for DHCP DoS Mitigation Feature (sonic-net#3301)
What I did Added config interface dhcp-mitigation-rate add/del and show interfaces dhcp-mitigation-rate commands for DHCP mitigation rate attribute in config_db and added support for new attribute in DB Migrator How I did it Add/del commands add/remove interface DHCP rate limits defined by the user to PORT_TABLE in config_db and show command reads and displays DHCP rate limits on interfaces in the form of a table
1 parent a3d15bc commit 595c2aa

File tree

9 files changed

+647
-60
lines changed

9 files changed

+647
-60
lines changed

config/main.py

+99
Original file line numberDiff line numberDiff line change
@@ -5278,6 +5278,105 @@ def loopback_action(ctx, interface_name, action):
52785278
table_name = get_interface_table_name(interface_name)
52795279
config_db.mod_entry(table_name, interface_name, {"loopback_action": action})
52805280

5281+
#
5282+
# 'dhcp-mitigation-rate' subgroup ('config interface dhcp-mitigation-rate ...')
5283+
#
5284+
5285+
5286+
@interface.group(cls=clicommon.AbbreviationGroup, name='dhcp-mitigation-rate')
5287+
@click.pass_context
5288+
def dhcp_mitigation_rate(ctx):
5289+
"""Set interface DHCP rate limit attribute"""
5290+
pass
5291+
5292+
#
5293+
# 'add' subcommand
5294+
#
5295+
5296+
5297+
@dhcp_mitigation_rate.command(name='add')
5298+
@click.argument('interface_name', metavar='<interface_name>', required=True)
5299+
@click.argument('packet_rate', metavar='<DHCP packet rate>', required=True, type=int)
5300+
@click.pass_context
5301+
@clicommon.pass_db
5302+
def add_dhcp_mitigation_rate(db, ctx, interface_name, packet_rate):
5303+
"""Add a new DHCP mitigation rate on an interface"""
5304+
# Get the config_db connector
5305+
config_db = ValidatedConfigDBConnector(db.cfgdb)
5306+
5307+
if clicommon.get_interface_naming_mode() == "alias":
5308+
interface_name = interface_alias_to_name(config_db, interface_name)
5309+
5310+
if clicommon.is_valid_port(config_db, interface_name):
5311+
pass
5312+
elif clicommon.is_valid_portchannel(config_db, interface_name):
5313+
ctx.fail("{} is a PortChannel!".format(interface_name))
5314+
else:
5315+
ctx.fail("{} does not exist".format(interface_name))
5316+
5317+
if packet_rate <= 0:
5318+
ctx.fail("DHCP rate limit is not valid. \nIt must be greater than 0.")
5319+
5320+
port_data = config_db.get_entry('PORT', interface_name)
5321+
5322+
if 'dhcp_rate_limit' in port_data:
5323+
rate = port_data["dhcp_rate_limit"]
5324+
else:
5325+
rate = '0'
5326+
5327+
if rate != '0':
5328+
ctx.fail("{} has DHCP rate limit configured. \nRemove it to add new DHCP rate limit.".format(interface_name))
5329+
5330+
try:
5331+
config_db.mod_entry('PORT', interface_name, {"dhcp_rate_limit": "{}".format(str(packet_rate))})
5332+
except ValueError as e:
5333+
ctx.fail("{} invalid or does not exist. Error: {}".format(interface_name, e))
5334+
5335+
#
5336+
# 'del' subcommand
5337+
#
5338+
5339+
5340+
@dhcp_mitigation_rate.command(name='del')
5341+
@click.argument('interface_name', metavar='<interface_name>', required=True)
5342+
@click.argument('packet_rate', metavar='<DHCP packet rate>', required=True, type=int)
5343+
@click.pass_context
5344+
@clicommon.pass_db
5345+
def del_dhcp_mitigation_rate(db, ctx, interface_name, packet_rate):
5346+
"""Delete an existing DHCP mitigation rate on an interface"""
5347+
# Get the config_db connector
5348+
config_db = ValidatedConfigDBConnector(db.cfgdb)
5349+
5350+
if clicommon.get_interface_naming_mode() == "alias":
5351+
interface_name = interface_alias_to_name(config_db, interface_name)
5352+
5353+
if clicommon.is_valid_port(config_db, interface_name):
5354+
pass
5355+
elif clicommon.is_valid_portchannel(config_db, interface_name):
5356+
ctx.fail("{} is a PortChannel!".format(interface_name))
5357+
else:
5358+
ctx.fail("{} does not exist".format(interface_name))
5359+
5360+
if packet_rate <= 0:
5361+
ctx.fail("DHCP rate limit is not valid. \nIt must be greater than 0.")
5362+
5363+
port_data = config_db.get_entry('PORT', interface_name)
5364+
5365+
if 'dhcp_rate_limit' in port_data:
5366+
rate = port_data["dhcp_rate_limit"]
5367+
else:
5368+
rate = '0'
5369+
5370+
if rate != str(packet_rate):
5371+
ctx.fail("{} DHCP rate limit does not exist on {}.".format(packet_rate, interface_name))
5372+
5373+
port_data["dhcp_rate_limit"] = "0"
5374+
5375+
try:
5376+
config_db.mod_entry('PORT', interface_name, {"dhcp_rate_limit": "0"})
5377+
except ValueError as e:
5378+
ctx.fail("{} invalid or does not exist. Error: {}".format(interface_name, e))
5379+
52815380
#
52825381
# buffer commands and utilities
52835382
#

scripts/db_migrator.py

+13
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,18 @@ def migrate_config_db_port_table_for_auto_neg(self):
510510
elif value['autoneg'] == '0':
511511
self.configDB.set(self.configDB.CONFIG_DB, '{}|{}'.format(table_name, key), 'autoneg', 'off')
512512

513+
def migrate_config_db_port_table_for_dhcp_rate_limit(self):
514+
port_table_name = 'PORT'
515+
port_table = self.configDB.get_table(port_table_name)
516+
517+
for p_key, p_value in port_table.items():
518+
if 'dhcp_rate_limit' in p_value:
519+
self.configDB.set(self.configDB.CONFIG_DB, '{}|{}'.format(port_table_name, p_key),
520+
'dhcp_rate_limit', p_value['dhcp_rate_limit'])
521+
else:
522+
self.configDB.set(self.configDB.CONFIG_DB, '{}|{}'.format(port_table_name, p_key),
523+
'dhcp_rate_limit', '300')
524+
513525
def migrate_qos_db_fieldval_reference_remove(self, table_list, db, db_num, db_delimeter):
514526
for pair in table_list:
515527
table_name, fields_list = pair
@@ -1062,6 +1074,7 @@ def version_3_0_0(self):
10621074
"""
10631075
log.log_info('Handling version_3_0_0')
10641076
self.migrate_config_db_port_table_for_auto_neg()
1077+
self.migrate_config_db_port_table_for_dhcp_rate_limit()
10651078
self.set_version('version_3_0_1')
10661079
return 'version_3_0_1'
10671080

0 commit comments

Comments
 (0)