From 7840b1411369b925013711a421066a83310fe114 Mon Sep 17 00:00:00 2001 From: "Sridhar K. N. Rao" Date: Wed, 25 Jan 2017 15:36:25 +0530 Subject: pkt_gen: STC - RFC 2889 Address Learning and Caching Support This patch adds RFC-2889 address-learning-rate test and address-caching-capacity tests. The patch includes following changes 1. 01_testcases.conf: testcase definitions are added for new tests 2. results_constants.py: 3 new results constants are added, removed unsupported constants 3. testcenter-rfc2889-rest.py: Added support to these two new tests. Removed un-necessary synchronization of db-file. 5 new configuration parameters are added - which are explained in (4). 4. trafficgen.rst: Configuration description for rfc2889 tests are added. Stale information is removed. 5. testcenter.py: Support for two new tests are added. Separate functions for results analysis and parameter settings are added. 6. traffic_controller_rfc2889.py: Calls to functions in testcenter.py, based on the traffic_type, are added. Removed trailing whitespaces from trafficgen.rst JIRA: VSPERF-395 Change-Id: Ie6ca87519b7736e7410d7f0e60904579934af24a Signed-off-by: Sridhar K. N. Rao --- conf/01_testcases.conf | 22 ++- core/results/results_constants.py | 8 +- core/traffic_controller_rfc2889.py | 12 +- docs/configguide/trafficgen.rst | 93 +++++++++- .../pkt_gen/testcenter/testcenter-rfc2889-rest.py | 120 +++++++++---- tools/pkt_gen/testcenter/testcenter.py | 191 ++++++++++++++++----- 6 files changed, 353 insertions(+), 93 deletions(-) diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf index bdaeb4da..b30afc8f 100755 --- a/conf/01_testcases.conf +++ b/conf/01_testcases.conf @@ -95,7 +95,27 @@ PERFORMANCE_TESTS = [ "Description": "LTD.Forwarding.RFC2889.MaxForwardingRate", "Parameters" : { "TRAFFIC" : { - "traffic_type" : "rfc2889", + "traffic_type" : "rfc2889_forwarding", + }, + }, + }, + { + "Name": "phy2phy_learning", + "Deployment": "p2p", + "Description": "LTD.AddrLearning.RFC2889.AddrLearningRate", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_learning", + }, + }, + }, + { + "Name": "phy2phy_caching", + "Deployment": "p2p", + "Description": "LTD.AddrCaching.RFC2889.AddrCachingCapacity", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_caching", }, }, }, diff --git a/core/results/results_constants.py b/core/results/results_constants.py index 864712bc..2c733fe4 100644 --- a/core/results/results_constants.py +++ b/core/results/results_constants.py @@ -58,11 +58,11 @@ class ResultsConstants(object): SCAL_STREAM_COUNT = 'stream_count' SCAL_STREAM_TYPE = 'match_type' SCAL_PRE_INSTALLED_FLOWS = 'pre-installed_flows' - # RFC2889 Forwarding, Address-Caching and Congestion + # RFC2889 Forwarding, Address-Caching and Address-Learning FORWARDING_RATE_FPS = 'forwarding_rate_fps' - ADDRS_COUNT_FLOOD_COUNT_RATIO = 'addrs_count_flood_count_ratio' - CONGESTION_CONTROL_EXISTS = 'congestion_control_exists' - PORTS_MAP = 'ports_map' + CACHING_CAPACITY_ADDRS = 'caching_capacity_addrs' + ADDR_LEARNED_PERCENT = 'addr_learned_percent' + OPTIMAL_LEARNING_RATE_FPS = 'optimal_learning_rate_fps' TEST_RUN_TIME = "test_execution_time" diff --git a/core/traffic_controller_rfc2889.py b/core/traffic_controller_rfc2889.py index 210d5f5f..05955e65 100644 --- a/core/traffic_controller_rfc2889.py +++ b/core/traffic_controller_rfc2889.py @@ -50,13 +50,13 @@ class TrafficControllerRFC2889(TrafficController, IResults): else: traffic['l2'] = {'framesize': packet_size} - if traffic['traffic_type'] == 'caching': + if traffic['traffic_type'] == 'rfc2889_caching': result = self._traffic_gen_class.send_rfc2889_caching( - traffic, trials=self._trials, duration=self._duration) - elif traffic['traffic_type'] == 'congestion': - result = self._traffic_gen_class.send_rfc2889_congestion( - traffic, duration=self._duration) - else: + traffic, tests=self._trials, duration=self._duration) + elif traffic['traffic_type'] == 'rfc2889_learning': + result = self._traffic_gen_class.send_rfc2889_learning( + traffic, tests=self._trials, duration=self._duration) + elif traffic['traffic_type'] == 'rfc2889_forwarding': result = self._traffic_gen_class.send_rfc2889_forwarding( traffic, tests=self._trials, duration=self._duration) diff --git a/docs/configguide/trafficgen.rst b/docs/configguide/trafficgen.rst index b66a1787..d1880f00 100644 --- a/docs/configguide/trafficgen.rst +++ b/docs/configguide/trafficgen.rst @@ -410,22 +410,23 @@ RFC 2544 tests using the REST interface. Configuration: ~~~~~~~~~~~~~~ -The mandatory configurations are enlisted below. 1. The Labserver and license server addresses. These parameters applies to - all the tests and are mandatory. + all the tests, and are mandatory for all tests. .. code-block:: console TRAFFICGEN_STC_LAB_SERVER_ADDR = " " TRAFFICGEN_STC_LICENSE_SERVER_ADDR = " " + TRAFFICGEN_STC_PYTHON2_PATH = " " + TRAFFICGEN_STC_TESTCENTER_PATH = " " + TRAFFICGEN_STC_TEST_SESSION_NAME = " " + TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX = " " 2. For RFC2544 tests, the following parameters are mandatory - .. code-block:: console - TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME = " " TRAFFICGEN_STC_EAST_CHASSIS_ADDR = " " TRAFFICGEN_STC_EAST_SLOT_NUM = " " TRAFFICGEN_STC_EAST_PORT_NUM = " " @@ -436,13 +437,91 @@ The mandatory configurations are enlisted below. TRAFFICGEN_STC_WEST_PORT_NUM = " " TRAFFICGEN_STC_WEST_INTF_ADDR = " " TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME + +3. RFC2889 tests: Currently, the forwarding, address-caching, and + address-learning-rate tests of RFC2889 are supported. + The testcenter-rfc2889-rest.py script implements the rfc2889 tests. + The configuration for RFC2889 involves test-case definition, and parameter + definition, as described below. New results-constants, as shown below, are + added to support these tests. + +Example of testcase definition for RFC2889 tests: + +.. code-block:: python + + { + "Name": "phy2phy_forwarding", + "Deployment": "p2p", + "Description": "LTD.Forwarding.RFC2889.MaxForwardingRate", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_forwarding", + }, + }, + } -3. For RFC2889 tests, specifying the locations of the ports is mandatory. +For RFC2889 tests, specifying the locations for the monitoring ports is mandatory. +Necessary parameters are: .. code-block:: console + TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME + TRAFFICGEN_STC_EAST_CHASSIS_ADDR = " " + TRAFFICGEN_STC_EAST_SLOT_NUM = " " + TRAFFICGEN_STC_EAST_PORT_NUM = " " + TRAFFICGEN_STC_EAST_INTF_ADDR = " " + TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_WEST_CHASSIS_ADDR = "" + TRAFFICGEN_STC_WEST_SLOT_NUM = " " + TRAFFICGEN_STC_WEST_PORT_NUM = " " + TRAFFICGEN_STC_WEST_INTF_ADDR = " " + TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_VERBOSE = "True" + TRAFFICGEN_STC_RFC2889_LOCATIONS="//10.1.1.1/1/1,//10.1.1.1/2/2" + +Other Configurations are : + +.. code-block:: console + + TRAFFICGEN_STC_RFC2889_MIN_LR = 1488 + TRAFFICGEN_STC_RFC2889_MAX_LR = 14880 + TRAFFICGEN_STC_RFC2889_MIN_ADDRS = 1000 + TRAFFICGEN_STC_RFC2889_MAX_ADDRS = 65536 + TRAFFICGEN_STC_RFC2889_AC_LR = 1000 + +The first 2 values are for address-learning test where as other 3 values are +for the Address caching capacity test. LR: Learning Rate. AC: Address Caching. +Maximum value for address is 16777216. Whereas, maximum for LR is 4294967295. + +Results for RFC2889 Tests: Forwarding tests outputs following values: + +.. code-block:: console + + TX_RATE_FPS : "Transmission Rate in Frames/sec" + THROUGHPUT_RX_FPS: "Received Throughput Frames/sec" + TX_RATE_MBPS : " Transmission rate in MBPS" + THROUGHPUT_RX_MBPS: "Received Throughput in MBPS" + TX_RATE_PERCENT: "Transmission Rate in Percentage" + FRAME_LOSS_PERCENT: "Frame loss in Percentage" + FORWARDING_RATE_FPS: " Maximum Forwarding Rate in FPS" + + +Whereas, the address caching test outputs following values, + +.. code-block:: console + + CACHING_CAPACITY_ADDRS = 'Number of address it can cache' + ADDR_LEARNED_PERCENT = 'Percentage of address successfully learned' + +and address learning test outputs just a single value: + +.. code-block:: console + + OPTIMAL_LEARNING_RATE_FPS = 'Optimal learning rate in fps' - TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME = " " - TRAFFICGEN_STC_RFC2889_LOCATIONS= " " +Note that 'FORWARDING_RATE_FPS', 'CACHING_CAPACITY_ADDRS', +'ADDR_LEARNED_PERCENT' and 'OPTIMAL_LEARNING_RATE_FPS' are the new +result-constants added to support RFC2889 tests. .. _`Xena Networks`: diff --git a/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py index ddb64562..523d9d31 100644 --- a/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py +++ b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py @@ -15,7 +15,7 @@ ''' @author Spirent Communications -This test automates the RFC2544 tests using the Spirent +This test automates the RFC2889 tests using the Spirent TestCenter REST APIs. This test supports Python 3.4 ''' @@ -92,9 +92,9 @@ def main(): optional_named.add_argument("--metric", required=False, help=("One among - Forwarding,\ - Address Caching and Congestion"), + Address Caching and Learning"), choices=["forwarding", "caching", - "congestion"], + "learning"], default="forwarding", dest="metric") optional_named.add_argument("--test_session_name", @@ -103,7 +103,6 @@ def main(): help=("The friendly name to identify " "the Spirent Lab Server test session"), dest="test_session_name") - optional_named.add_argument("--test_user_name", required=False, default="Rfc2889Usr", @@ -147,6 +146,42 @@ def main(): default=[256], help="A comma-delimited list of frame sizes", dest="frame_size_list") + optional_named.add_argument("--min_learning_rate", + type=positive_int, + required=False, + default=1488, + help="Lowest learning rate for test", + dest="min_learning_rate") + optional_named.add_argument("--max_learning_rate", + type=positive_int, + required=False, + default=14880, + help="Highest learning rate for test", + dest="max_learning_rate") + optional_named.add_argument("--min_num_addrs", + type=positive_int, + required=False, + default=1, + help="lowest number of addrs sent to DUT", + dest="min_num_addrs") + optional_named.add_argument("--max_num_addrs", + type=positive_int, + required=False, + default=1000, + help="Highest number of addrs sent to DUT", + dest="max_num_addrs") + optional_named.add_argument("--ac_learning_rate", + type=positive_int, + required=False, + default=1000, + help="Number of learning frames per sec", + dest="ac_learning_rate") + optional_named.add_argument("--frame_size", + type=positive_int, + required=False, + default=64, + help="Frame size for address test", + dest="frame_size") parser.add_argument("-v", "--verbose", required=False, @@ -187,7 +222,7 @@ def main(): if args.verbose: logger.debug("license_mgr = %s", license_mgr) stc.create("LicenseServer", under=license_mgr, attributes={ - "server": args.license_server_addr}) + "server": args.license_server_addr}) # Create the root project object if args.verbose: @@ -224,12 +259,27 @@ def main(): "GenParams": gen_params}) if args.verbose: - logger.debug("Set up the RFC2889 Forwarding test...") - stc.perform("Rfc2889SetupMaxForwardingRateTestCommand", - params={"Duration": args.trial_duration_sec, - "FrameSizeList": args.frame_size_list, - "NumOfTrials": args.num_trials, - "TrafficPattern": args.traffic_pattern}) + logger.debug("Set up the RFC2889 test...") + + if args.metric == "learning": + stc.perform("Rfc2889SetupAddressLearningRateTestCommand", + params={"FrameSize": args.frame_size, + "MinLearningRate": args.min_learning_rate, + "MaxLearningRate": args.max_learning_rate, + "NumOfTrials": args.num_trials}) + elif args.metric == "caching": + stc.perform("Rfc2889SetupAddressCachingCapacityTestCommand", + params={"FrameSize": args.frame_size, + "MinNumAddrs": args.min_num_addrs, + "MaxNumAddrs": args.max_num_addrs, + "LearningRate": args.ac_learning_rate, + "NumOfTrials": args.num_trials}) + else: + stc.perform("Rfc2889SetupMaxForwardingRateTestCommand", + params={"Duration": args.trial_duration_sec, + "FrameSizeList": args.frame_size_list, + "NumOfTrials": args.num_trials, + "TrafficPattern": args.traffic_pattern}) # Save the configuration stc.perform("SaveToTcc", params={"Filename": "2889.tcc"}) @@ -259,28 +309,34 @@ def main(): logger.debug("The lab server results database is %s", lab_server_resultsdb) - stc.perform("CSSynchronizeFiles", - params={"DefaultDownloadDir": args.results_dir}) - - resultsdb = args.results_dir + \ - lab_server_resultsdb.split("/Results")[1] - - if not os.path.exists(resultsdb): - resultsdb = lab_server_resultsdb - logger.info("Failed to create the local summary DB file, using" - " the remote DB file instead.") + if args.metric == "learning": + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889AddressLearningRateTestResultDetailed" + "SummaryView")})) + elif args.metric == "caching": + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889AddressCachingCapacityTestResult" + "DetailedSummaryView")})) else: - logger.info( - "The local summary DB file has been saved to %s", resultsdb) - - resultsdict = ( - stc.perform("QueryResult", - params={ - "DatabaseConnectionString": - resultsdb, - "ResultPath": - ("RFC2889MaxForwardingRateTestResultDetailed" - "SummaryView")})) + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889MaxForwardingRateTestResultDetailed" + "SummaryView")})) + if args.verbose: logger.debug("resultsdict[\"Columns\"]: %s", resultsdict["Columns"]) diff --git a/tools/pkt_gen/testcenter/testcenter.py b/tools/pkt_gen/testcenter/testcenter.py index 701d451c..4412b13a 100644 --- a/tools/pkt_gen/testcenter/testcenter.py +++ b/tools/pkt_gen/testcenter/testcenter.py @@ -115,22 +115,52 @@ def get_rfc2544_custom_settings(framesize, custom_tr, tests): return args -def get_rfc2889_settings(framesize, tests, duration): +def get_rfc2889_common_settings(framesize, tests, metric): + """ + Return RFC2889 common Settings + """ + new_metric = metric.replace('rfc2889_', '') args = [settings.getValue("TRAFFICGEN_STC_PYTHON2_PATH"), os.path.join( settings.getValue("TRAFFICGEN_STC_TESTCENTER_PATH"), settings.getValue( "TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME")), - "--lab_server_addr", - settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"), - "--license_server_addr", - settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"), - "--location_list", - settings.getValue("TRAFFICGEN_STC_RFC2889_LOCATIONS"), - "--frame_size_list", - str(framesize), - "--num_trials", - str(tests)] + "--lab_server_addr", + settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"), + "--license_server_addr", + settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"), + "--location_list", + settings.getValue("TRAFFICGEN_STC_RFC2889_LOCATIONS"), + "--test_session_name", + settings.getValue("TRAFFICGEN_STC_TEST_SESSION_NAME"), + "--results_dir", + settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + "--csv_results_file_prefix", + settings.getValue("TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX"), + "--frame_size_list", + str(framesize), + "--metric", + str(new_metric), + "--num_trials", + str(tests)] + + return args + + +def get_rfc2889_custom_settings(): + """ + Return RFC2889 Custom Settings + """ + args = ["--min_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_LR"), + "--max_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_LR"), + "--min_num_addrs", + settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_ADDRS"), + "--max_num_addrs", + settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_ADDRS"), + "--ac_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_AC_LR")] return args @@ -158,19 +188,35 @@ class TestCenter(trafficgen.ITrafficGenerator): """ return None - def send_rfc2889_congestion(self, traffic=None, tests=1, duration=20): + def get_rfc2889_addr_learning_results(self, filename): """ - Do nothing. + Reads the CSV file and return the results """ - return None + result = {} + with open(filename, "r") as csvfile: + csvreader = csv.DictReader(csvfile) + for row in csvreader: + self._logger.info("Row: %s", row) + learn_rate = float(row["OptimalLearningRate"]) + result[ResultsConstants.OPTIMAL_LEARNING_RATE_FPS] = learn_rate + return result - def send_rfc2889_caching(self, traffic=None, tests=1, duration=20): + def get_rfc2889_addr_caching_results(self, filename): """ - Do nothing. + Reads the CSV file and return the results """ - return None + result = {} + with open(filename, "r") as csvfile: + csvreader = csv.DictReader(csvfile) + for row in csvreader: + self._logger.info("Row: %s", row) + caching_cap = float(row["RxFrameCount"]) + learn_per = (100.0 - (float(row["PercentFrameLoss(%)"]))) + result[ResultsConstants.CACHING_CAPACITY_ADDRS] = caching_cap + result[ResultsConstants.ADDR_LEARNED_PERCENT] = learn_per + return result - def get_rfc2889_results(self, filename): + def get_rfc2889_forwarding_results(self, filename): """ Reads the CSV file and return the results """ @@ -200,6 +246,90 @@ class TestCenter(trafficgen.ITrafficGenerator): row["ForwardingRate(fps)"]) return result + def send_rfc2889_forwarding(self, traffic=None, tests=1, duration=20): + """ + Send traffic per RFC2889 Forwarding test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_forwarding_results(filec) + + def send_rfc2889_caching(self, traffic=None, tests=1, duration=20): + """ + Send as per RFC2889 Addr-Caching test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + common_args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + custom_args = get_rfc2889_custom_settings() + args = common_args + custom_args + + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_addr_caching_results(filec) + + def send_rfc2889_learning(self, traffic=None, tests=1, duration=20): + """ + Send traffic per RFC2889 Addr-Learning test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + common_args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + custom_args = get_rfc2889_custom_settings() + args = common_args + custom_args + + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_addr_learning_results(filec) + def get_rfc2544_results(self, filename): """ Reads the CSV file and return the results @@ -272,31 +402,6 @@ class TestCenter(trafficgen.ITrafficGenerator): return self.get_rfc2544_results(filec) - def send_rfc2889_forwarding(self, traffic=None, tests=1, duration=20): - """ - Send traffic per RFC2544 throughput test specifications. - """ - framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") - if traffic and 'l2' in traffic: - if 'framesize' in traffic['l2']: - framesize = traffic['l2']['framesize'] - args = get_rfc2889_settings(framesize, tests, duration) - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": - args.append("--verbose") - verbose = True - self._logger.debug("Arguments used to call test: %s", args) - subprocess.check_call(args) - - filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), - settings.getValue( - "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + - ".csv") - - if verbose: - self._logger.debug("file: %s", filec) - - return self.get_rfc2889_results(filec) - def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20, lossrate=0.0): """ -- cgit 1.2.3-korg