Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 7 additions & 1 deletion config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3533,8 +3533,11 @@ def remove_reasons(counter_name, reasons, verbose):
@click.option('-ymin', metavar='<yellow threshold min>', type=int, help="Set yellow min threshold")
@click.option('-gmax', metavar='<green threshold max>', type=int, help="Set green max threshold")
@click.option('-gmin', metavar='<green threshold min>', type=int, help="Set green min threshold")
@click.option('-rdrop', metavar='<red drop probability>', type=click.IntRange(0, 100), help="Set red drop probability")
@click.option('-ydrop', metavar='<yellow drop probability>', type=click.IntRange(0, 100), help="Set yellow drop probability")
@click.option('-gdrop', metavar='<green drop probability>', type=click.IntRange(0, 100), help="Set green drop probability")
@click.option('-v', '--verbose', is_flag=True, help="Enable verbose output")
def ecn(profile, rmax, rmin, ymax, ymin, gmax, gmin, verbose):
def ecn(profile, rmax, rmin, ymax, ymin, gmax, gmin, rdrop, ydrop, gdrop, verbose):
"""ECN-related configuration tasks"""
log.log_info("'ecn -profile {}' executing...".format(profile))
command = "ecnconfig -p %s" % profile
Expand All @@ -3544,6 +3547,9 @@ def ecn(profile, rmax, rmin, ymax, ymin, gmax, gmin, verbose):
if ymin is not None: command += " -ymin %d" % ymin
if gmax is not None: command += " -gmax %d" % gmax
if gmin is not None: command += " -gmin %d" % gmin
if rdrop is not None: command += " -rdrop %d" % rdrop
if ydrop is not None: command += " -ydrop %d" % ydrop
if gdrop is not None: command += " -gdrop %d" % gdrop
if verbose: command += " -vv"
clicommon.run_command(command, display_cmd=verbose)

Expand Down
66 changes: 51 additions & 15 deletions scripts/ecnconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,25 @@ ECN status:
queue 3: on
"""
import argparse
import json
import os
import sys

import swsssdk
from tabulate import tabulate

# mock the redis for unit test purposes #
try:
if os.environ["UTILITIES_UNIT_TESTING"] == "2":
modules_path = os.path.join(os.path.dirname(__file__), "..")
tests_path = os.path.join(modules_path, "tests")
sys.path.insert(0, modules_path)
sys.path.insert(0, tests_path)
import mock_tables.dbconnector

except KeyError:
pass

WRED_PROFILE_TABLE_NAME = "WRED_PROFILE"
WRED_CONFIG_FIELDS = {
"gmax": "green_max_threshold",
Expand All @@ -78,11 +91,12 @@ lossless_queues = ['3', '4']

class EcnConfig(object):
"""
Process aclstat
Process ecnconfig
"""
def __init__(self, verbose):
def __init__(self, filename, verbose):
self.ports = []
self.queues = []
self.filename = filename
self.verbose = verbose

# Set up db connections
Expand All @@ -109,8 +123,8 @@ class EcnConfig(object):

for profile_name, profile_data in wred_profiles.items():
if profile_name == profile:
return profile_data
return profile_data

return None

def validate_profile_data(self, profile_data):
Expand All @@ -125,17 +139,17 @@ class EcnConfig(object):
if 'threshold' in field:
if value.isdigit() == False:
print("Invalid %s (%s). %s should be an non-negative integer." % (key, value, key))
result = False
result = False

elif 'probability' in field:
if value.isdigit() == False or int(value) < 0 or int(value) > 100:
print("Invalid %s (%s). %s should be an integer between 0 and 100." % (key, value, key))
result = False

if result == False:
return result
return result

# check if min threshold is no larger than max threshold
# check if min threshold is no larger than max threshold
colors = ['g', 'y', 'r']
for color in colors:
if (WRED_CONFIG_FIELDS[color + 'min'] in profile_data and
Expand All @@ -145,11 +159,11 @@ class EcnConfig(object):
max_thresh = int(profile_data[WRED_CONFIG_FIELDS[color + 'max']])

if min_thresh > max_thresh:
print("Invalid %s (%d) and %s (%d). %s should be no smaller than %s" %
print("Invalid %s (%d) and %s (%d). %s should be smaller than %s" %
(color + 'min', min_thresh, color + 'max', max_thresh, color + 'min', color + 'max'))
result = False
result = False

return result
return result

def set_wred_threshold(self, profile, threshold, value):
if os.geteuid() != 0:
Expand All @@ -159,15 +173,23 @@ class EcnConfig(object):
if self.verbose:
print("Setting %s value to %s" % (field, value))
self.db.mod_entry(WRED_PROFILE_TABLE_NAME, profile, {field: value})
if self.filename is not None:
prof_table = self.db.get_table(WRED_PROFILE_TABLE_NAME)
with open(self.filename, "w") as fd:
json.dump(prof_table, fd)

def set_wred_prob(self, profile, drop_color, value):
if os.geteuid() != 0:
sys.exit("Root privileges required for this operation")

field = WRED_CONFIG_FIELDS[drop_color]
if self.verbose:
print("Setting %s value to %s%%" % (field, value))
self.db.mod_entry(WRED_PROFILE_TABLE_NAME, profile, {field: value})
if self.filename is not None:
prof_table = self.db.get_table(WRED_PROFILE_TABLE_NAME)
with open(self.filename, "w") as fd:
json.dump(prof_table, fd)

class EcnQ(object):
"""
Expand Down Expand Up @@ -249,21 +271,35 @@ def main():

parser.add_argument('command', nargs='?', choices=['on', 'off'], type=str, help='turn on/off ecn', default=None)
parser.add_argument('-q', '--queue', type=str, help='specify queue index list: 3,4', default=None)
parser.add_argument('-f', '--filename', help='file used by mock tests', type=str, default=None)

if os.environ.get("UTILITIES_UNIT_TESTING", "0") == "2":
sys.argv.extend(['-f', '/tmp/ecnconfig'])

args = parser.parse_args()

try:
if args.list or args.profile:
prof_cfg = EcnConfig(args.verbose)
prof_cfg = EcnConfig(args.filename, args.verbose)
if args.list:
if len(sys.argv) > (3 if args.verbose else 2):
arg_len_max = 2
if args.verbose:
arg_len_max += 1
if args.filename:
arg_len_max += 2
if len(sys.argv) > arg_len_max:
raise Exception("Input arguments error. No set options allowed when -l[ist] specified")
prof_cfg.list()
elif args.profile:
if len(sys.argv) < (5 if args.verbose else 4):
arg_len_min = 4
if args.verbose:
arg_len_min += 1
if args.filename:
arg_len_min += 2
if len(sys.argv) < arg_len_min:
raise Exception("Input arguments error. Specify at least one threshold parameter to set")

# get current configuration data
# get current configuration data
wred_profile_data = prof_cfg.get_profile_data(args.profile)
if wred_profile_data is None:
raise Exception("Input arguments error. Invalid WRED profile %s" % (args.profile))
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
'mock_tables/asic2/*.json',
'filter_fdb_input/*',
'pfcwd_input/*',
'wm_input/*']
'wm_input/*',
'ecn_input/*']
},
scripts=[
'scripts/aclshow',
Expand Down
8 changes: 4 additions & 4 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from utilities_common.db import Db

from . import acl
from . import bgp_common
from . import bgp_common
from . import chassis_modules
from . import dropcounters
from . import feature
Expand Down Expand Up @@ -1449,11 +1449,11 @@ def policer(policer_name, verbose):
# 'ecn' command ("show ecn")
#
@cli.command('ecn')
def ecn():
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def ecn(verbose):
"""Show ECN configuration"""
cmd = "ecnconfig -l"
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, text=True)
click.echo(proc.stdout.read())
run_command(cmd, display_cmd=verbose)


#
Expand Down
Empty file added tests/ecn_input/__init__.py
Empty file.
105 changes: 105 additions & 0 deletions tests/ecn_input/ecn_test_vectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
ecn_show_config_output="""\
Profile: AZURE_LOSSLESS
----------------------- -------
red_max_threshold 2097152
wred_green_enable true
ecn ecn_all
green_min_threshold 1048576
red_min_threshold 1048576
wred_yellow_enable true
yellow_min_threshold 1048576
green_max_threshold 2097152
green_drop_probability 5
yellow_max_threshold 2097152
wred_red_enable true
yellow_drop_probability 5
red_drop_probability 5
----------------------- -------

"""

testData = {
'ecn_show_config' : {'cmd' : ['show'],
'args' : [],
'rc' : 0,
'rc_output': ecn_show_config_output
},
'ecn_cfg_gmin' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-gmin', '1048600'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,green_min_threshold,1048600']
},
'ecn_cfg_gmax' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-gmax', '2097153'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,green_max_threshold,2097153']
},
'ecn_cfg_ymin' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-ymin', '1048600'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,yellow_min_threshold,1048600']
},
'ecn_cfg_ymax' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-ymax', '2097153'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,yellow_max_threshold,2097153']
},
'ecn_cfg_rmin' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rmin', '1048600'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,red_min_threshold,1048600']
},
'ecn_cfg_rmax' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rmax', '2097153'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,red_max_threshold,2097153']
},
'ecn_cfg_rdrop' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rdrop', '10'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,red_drop_probability,10']
},
'ecn_cfg_ydrop' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-ydrop', '11'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,yellow_drop_probability,11']
},
'ecn_cfg_gdrop' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-gdrop', '12'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,green_drop_probability,12']
},
'ecn_cfg_multi_set' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-gdrop', '12', '-gmax', '2097153'],
'rc' : 0,
'cmp_args' : ['AZURE_LOSSLESS,green_drop_probability,12',
'AZURE_LOSSLESS,green_max_threshold,2097153'
]
},
'ecn_cfg_gmin_gmax_invalid' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-gmax', '2097153', '-gmin', '2097154'],
'rc' : 1,
'rc_msg' : 'Invalid gmin (2097154) and gmax (2097153). gmin should be smaller than gmax'
},
'ecn_cfg_ymin_ymax_invalid' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-ymax', '2097153', '-ymin', '2097154'],
'rc' : 1,
'rc_msg' : 'Invalid ymin (2097154) and ymax (2097153). ymin should be smaller than ymax'
},
'ecn_cfg_rmin_rmax_invalid' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rmax', '2097153', '-rmin', '2097154'],
'rc' : 1,
'rc_msg' : 'Invalid rmin (2097154) and rmax (2097153). rmin should be smaller than rmax'
},
'ecn_cfg_rmax_invalid' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rmax', '-2097153'],
'rc' : 1,
'rc_msg' : 'Invalid rmax (-2097153). rmax should be an non-negative integer'
},
'ecn_cfg_rdrop_invalid' : {'cmd' : ['config'],
'args' : ['-profile', 'AZURE_LOSSLESS', '-rdrop', '105'],
'rc' : 1,
'rc_msg' : 'Invalid value for "-rdrop": 105 is not in the valid range of 0 to 100'
}

}
Loading