aboutsummaryrefslogtreecommitdiffstats
path: root/tools/pkt_gen
diff options
context:
space:
mode:
authorSridhar K. N. Rao <sridhar.rao@spirent.com>2016-09-14 22:42:05 +0530
committerSridhar K. N. Rao <sridhar.rao@spirent.com>2016-09-21 14:24:02 +0530
commit1e1138cdc36ab308568e51314d967f7d13bdacc5 (patch)
tree4ec52ee6ff10bd2c94ece2f3e99f9bbedc643d71 /tools/pkt_gen
parentacdb444a54124834acdde45107062eaf1452c119 (diff)
pkt_gen: Spirent Testcenter RFC 2889 Support
The changes/additions, apart from spirent testcenter-specific, also includes to some files in conf (01_testcase and 03_traffic) and core (result- constants, traffic_controller and component_factory) folders. Currently, only RFC2889 Forwarding testcase is supported. Incorporated following review suggestions: 1. Log level fixes 2. Removing unused function in results_constants.py 3. Added documentation to docs/configguide/trafficgen.rst. Userguide will be updated once other RFC2889 tests are implemented. 4. string matching in component_factory. 5. Remove Trailing Whitespaces JIRA: VSPERF-286 Change-Id: I0195720ab2f8cf2c3a5aa490d66166bdca0afcb0 Signed-off-by: Sridhar K. N. Rao <sridhar.rao@spirent.com>
Diffstat (limited to 'tools/pkt_gen')
-rw-r--r--tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py304
-rw-r--r--tools/pkt_gen/testcenter/testcenter.py86
2 files changed, 390 insertions, 0 deletions
diff --git a/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py
new file mode 100644
index 00000000..cfa425e8
--- /dev/null
+++ b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py
@@ -0,0 +1,304 @@
+# Copyright 2016 Spirent Communications.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+'''
+@author Spirent Communications
+
+This test automates the RFC2544 tests using the Spirent
+TestCenter REST APIs. This test supports Python 3.4
+
+'''
+import argparse
+import logging
+import os
+
+# Logger Configuration
+logger = logging.getLogger(__name__)
+
+
+def create_dir(path):
+ """Create the directory as specified in path """
+ if not os.path.exists(path):
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ logger.error("Failed to create directory %s: %s", path, str(e))
+ raise
+
+
+def write_query_results_to_csv(results_path, csv_results_file_prefix,
+ query_results):
+ """ Write the results of the query to the CSV """
+ create_dir(results_path)
+ filec = os.path.join(results_path, csv_results_file_prefix + ".csv")
+ with open(filec, "wb") as f:
+ f.write(query_results["Columns"].replace(" ", ",") + "\n")
+ for row in (query_results["Output"].replace("} {", ",").
+ replace("{", "").replace("}", "").split(",")):
+ f.write(row.replace(" ", ",") + "\n")
+
+
+def positive_int(value):
+ """ Positive Integer type for Arguments """
+ ivalue = int(value)
+ if ivalue <= 0:
+ raise argparse.ArgumentTypeError(
+ "%s is an invalid positive int value" % value)
+ return ivalue
+
+
+def percent_float(value):
+ """ Floating type for Arguments """
+ pvalue = float(value)
+ if pvalue < 0.0 or pvalue > 100.0:
+ raise argparse.ArgumentTypeError(
+ "%s not in range [0.0, 100.0]" % pvalue)
+ return pvalue
+
+
+def main():
+ """ Read the arguments, Invoke Test and Return the results"""
+ parser = argparse.ArgumentParser()
+ # Required parameters
+ required_named = parser.add_argument_group("required named arguments")
+ required_named.add_argument("--lab_server_addr",
+ required=True,
+ help=("The IP address of the "
+ "Spirent Lab Server"),
+ dest="lab_server_addr")
+ required_named.add_argument("--license_server_addr",
+ required=True,
+ help=("The IP address of the Spirent "
+ "License Server"),
+ dest="license_server_addr")
+ required_named.add_argument("--location_list",
+ required=True,
+ help=("A comma-delimited list of test port "
+ "locations"),
+ dest="location_list")
+ # Optional parameters
+ optional_named = parser.add_argument_group("optional named arguments")
+ optional_named.add_argument("--metric",
+ required=False,
+ help=("One among - Forwarding,\
+ Address Caching and Congestion"),
+ choices=["forwarding", "caching",
+ "congestion"],
+ default="forwarding",
+ dest="metric")
+ optional_named.add_argument("--test_session_name",
+ required=False,
+ default="Rfc2889Ses",
+ 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",
+ help=("The friendly name to identify the "
+ "Spirent Lab Server test user"),
+ dest="test_user_name")
+ optional_named.add_argument("--results_dir",
+ required=False,
+ default="./Results",
+ help="The directory to copy results to",
+ dest="results_dir")
+ optional_named.add_argument("--csv_results_file_prefix",
+ required=False,
+ default="Rfc2889MaxFor",
+ help="The prefix for the CSV results files",
+ dest="csv_results_file_prefix")
+ optional_named.add_argument("--num_trials",
+ type=positive_int,
+ required=False,
+ default=1,
+ help=("The number of trials to execute during "
+ "the test"),
+ dest="num_trials")
+ optional_named.add_argument("--trial_duration_sec",
+ type=positive_int,
+ required=False,
+ default=60,
+ help=("The duration of each trial executed "
+ "during the test"),
+ dest="trial_duration_sec")
+ optional_named.add_argument("--traffic_pattern",
+ required=False,
+ choices=["BACKBONE", "MESH", "PAIR"],
+ default="MESH",
+ help="The traffic pattern between endpoints",
+ dest="traffic_pattern")
+ optional_named.add_argument("--frame_size_list",
+ type=lambda s: [int(item)
+ for item in s.split(',')],
+ required=False,
+ default=[256],
+ help="A comma-delimited list of frame sizes",
+ dest="frame_size_list")
+ parser.add_argument("-v",
+ "--verbose",
+ required=False,
+ default=True,
+ help="More output during operation when present",
+ action="store_true",
+ dest="verbose")
+ args = parser.parse_args()
+
+ if args.verbose:
+ logger.debug("Creating results directory")
+ create_dir(args.results_dir)
+ locationList = [str(item) for item in args.location_list.split(',')]
+
+ session_name = args.test_session_name
+ user_name = args.test_user_name
+
+ try:
+ # Load Spirent REST Library
+ from stcrestclient import stchttp
+
+ stc = stchttp.StcHttp(args.lab_server_addr)
+ session_id = stc.new_session(user_name, session_name)
+ stc.join_session(session_id)
+ except RuntimeError as e:
+ logger.error(e)
+ raise
+
+ # Retrieve and display the server information
+ if args.verbose:
+ logger.debug("SpirentTestCenter system version: %s",
+ stc.get("system1", "version"))
+
+ try:
+ if args.verbose:
+ logger.debug("Bring up license server")
+ license_mgr = stc.get("system1", "children-licenseservermanager")
+ if args.verbose:
+ logger.debug("license_mgr = %s", license_mgr)
+ stc.create("LicenseServer", under=license_mgr, attributes={
+ "server": args.license_server_addr})
+
+ # Create the root project object
+ if args.verbose:
+ logger.debug("Creating project ...")
+ project = stc.get("System1", "children-Project")
+
+ # Create ports
+ if args.verbose:
+ logger.debug("Creating ports ...")
+
+ for location in locationList:
+ stc.perform("CreateAndReservePorts", params={"locationList":
+ location,
+ "RevokeOwner":
+ "FALSE"})
+
+ port_list_get = stc.get("System1.project", "children-port")
+
+ if args.verbose:
+ logger.debug("Adding Host Gen PArams")
+ gen_params = stc.create("EmulatedDeviceGenParams",
+ under=project,
+ attributes={"Port": port_list_get})
+
+ # Create the DeviceGenEthIIIfParams object
+ stc.create("DeviceGenEthIIIfParams",
+ under=gen_params)
+ # Configuring Ipv4 interfaces
+ stc.create("DeviceGenIpv4IfParams",
+ under=gen_params)
+
+ stc.perform("DeviceGenConfigExpand",
+ params={"DeleteExisting": "No",
+ "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})
+
+ # Save the configuration
+ stc.perform("SaveToTcc", params={"Filename": "2889.tcc"})
+ # Connect to the hardware...
+ stc.perform("AttachPorts", params={"portList": stc.get(
+ "system1.project", "children-port"), "autoConnect": "TRUE"})
+ # Apply configuration.
+ if args.verbose:
+ logger.debug("Apply configuration...")
+ stc.apply()
+
+ if args.verbose:
+ logger.debug("Starting the sequencer...")
+ stc.perform("SequencerStart")
+
+ # Wait for sequencer to finish
+ logger.info(
+ "Starting test... Please wait for the test to complete...")
+ stc.wait_until_complete()
+ logger.info("The test has completed... Saving results...")
+
+ # Determine what the results database filename is...
+ lab_server_resultsdb = stc.get(
+ "system1.project.TestResultSetting", "CurrentResultFileName")
+
+ if args.verbose:
+ 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]
+
+ logger.info(
+ "The local summary DB file has been saved to %s", resultsdb)
+
+ resultsdict = (
+ stc.perform("QueryResult",
+ params={
+ "DatabaseConnectionString":
+ resultsdb,
+ "ResultPath":
+ ("RFC2889MaxForwardingRateTestResultDetailed"
+ "SummaryView")}))
+ if args.verbose:
+ logger.debug("resultsdict[\"Columns\"]: %s",
+ resultsdict["Columns"])
+ logger.debug("resultsdict[\"Output\"]: %s", resultsdict["Output"])
+ logger.debug("Result paths: %s",
+ stc.perform("GetTestResultSettingPaths"))
+
+ # Write results to csv
+ if args.verbose:
+ logger.debug("Writing CSV file to results directory %s",
+ args.results_dir)
+ write_query_results_to_csv(
+ args.results_dir, args.csv_results_file_prefix, resultsdict)
+
+ except RuntimeError as err:
+ logger.error(err)
+
+ if args.verbose:
+ logger.debug("Destroy session on lab server")
+
+ stc.end_session()
+
+ logger.info("Test complete!")
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/pkt_gen/testcenter/testcenter.py b/tools/pkt_gen/testcenter/testcenter.py
index a6cea2e1..701d451c 100644
--- a/tools/pkt_gen/testcenter/testcenter.py
+++ b/tools/pkt_gen/testcenter/testcenter.py
@@ -115,6 +115,25 @@ def get_rfc2544_custom_settings(framesize, custom_tr, tests):
return args
+def get_rfc2889_settings(framesize, tests, duration):
+ 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)]
+ return args
+
+
class TestCenter(trafficgen.ITrafficGenerator):
"""
Spirent TestCenter
@@ -139,6 +158,48 @@ class TestCenter(trafficgen.ITrafficGenerator):
"""
return None
+ def send_rfc2889_congestion(self, traffic=None, tests=1, duration=20):
+ """
+ Do nothing.
+ """
+ return None
+
+ def send_rfc2889_caching(self, traffic=None, tests=1, duration=20):
+ """
+ Do nothing.
+ """
+ return None
+
+ def get_rfc2889_results(self, filename):
+ """
+ Reads the CSV file and return the results
+ """
+ result = {}
+ with open(filename, "r") as csvfile:
+ csvreader = csv.DictReader(csvfile)
+ for row in csvreader:
+ self._logger.info("Row: %s", row)
+ duration = int((float(row["TxSignatureFrameCount"])) /
+ (float(row["OfferedLoad(fps)"])))
+ tx_fps = (float(row["OfferedLoad(fps)"]))
+ rx_fps = float((float(row["RxFrameCount"])) /
+ float(duration))
+ tx_mbps = ((tx_fps * float(row["FrameSize"])) /
+ (1000000.0))
+ rx_mbps = ((rx_fps * float(row["FrameSize"])) /
+ (1000000.0))
+ result[ResultsConstants.TX_RATE_FPS] = tx_fps
+ result[ResultsConstants.THROUGHPUT_RX_FPS] = rx_fps
+ result[ResultsConstants.TX_RATE_MBPS] = tx_mbps
+ result[ResultsConstants.THROUGHPUT_RX_MBPS] = rx_mbps
+ result[ResultsConstants.TX_RATE_PERCENT] = float(
+ row["OfferedLoad(%)"])
+ result[ResultsConstants.FRAME_LOSS_PERCENT] = float(
+ row["PercentFrameLoss(%)"])
+ result[ResultsConstants.FORWARDING_RATE_FPS] = float(
+ row["ForwardingRate(fps)"])
+ return result
+
def get_rfc2544_results(self, filename):
"""
Reads the CSV file and return the results
@@ -211,6 +272,31 @@ 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):
"""