summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py198
-rwxr-xr-xscripts/automation/trex_control_plane/client_utils/jsonrpc_client.py22
-rw-r--r--scripts/automation/trex_control_plane/common/trex_types.py18
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py10
-rw-r--r--scripts/stl_test_api/__init__.py82
-rw-r--r--scripts/stl_test_api/trex_stl_api.py93
-rw-r--r--scripts/stl_test_example.py24
7 files changed, 339 insertions, 108 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
index dc39bee6..b7700c7c 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -8,6 +8,7 @@ except ImportError:
import client.outer_packages
from client_utils.jsonrpc_client import JsonRpcClient, BatchMessage
+from client_utils import general_utils
from client_utils.packet_builder import CTRexPktBuilder
import json
@@ -22,30 +23,82 @@ import re
import random
from trex_port import Port
from common.trex_types import *
-
from trex_async_client import CTRexAsyncClient
+# logger API for the client
+class LoggerApi(object):
+ # verbose levels
+ VERBOSE_QUIET = 0
+ VERBOSE_REGULAR = 1
+ VERBOSE_HIGH = 2
+
+ def __init__(self):
+ self.level = LoggerApi.VERBOSE_REGULAR
+
+ def write(self, msg, newline = True):
+ raise Exception("implement this")
+
+ def flush(self):
+ raise Exception("implement this")
+
+ def set_verbose (self, level):
+ if not level in xrange(self.VERBOSE_QUIET, self.VERBOSE_HIGH + 1):
+ raise ValueError("bad value provided for logger")
+
+ self.level = level
+
+ def get_verbose (self):
+ return self.level
+
+
+ def check_verbose (self, level):
+ return (self.level >= level)
+
+
+ def log (self, msg, level = VERBOSE_REGULAR, newline = True):
+ if not self.check_verbose(level):
+ return
+
+ self.write(msg, newline)
+
+
+# default logger - to stdout
+class DefaultLogger(LoggerApi):
+ def write (self, msg, newline = True):
+ if newline:
+ print msg
+ else:
+ print msg,
+
+ def flush (self):
+ sys.stdout.flush()
+
class CTRexStatelessClient(object):
"""docstring for CTRexStatelessClient"""
- # verbose levels
- VERBOSE_QUIET = 0
- VERBOSE_REGULAR = 1
- VERBOSE_HIGH = 2
-
- def __init__(self, username, server="localhost", sync_port = 5050, async_port = 4500, quiet = False, virtual = False):
+ def __init__(self,
+ username = general_utils.get_current_user(),
+ server = "localhost",
+ sync_port = 4501,
+ async_port = 4500,
+ quiet = False,
+ virtual = False,
+ logger = None):
+
super(CTRexStatelessClient, self).__init__()
self.user = username
- self.comm_link = CTRexStatelessClient.CCommLink(server, sync_port, virtual, self.prn_func)
-
- # default verbose level
- if not quiet:
- self.verbose = self.VERBOSE_REGULAR
+ if not logger:
+ self.logger = DefaultLogger()
else:
- self.verbose = self.VERBOSE_QUIET
+ self.logger = logger
+
+ if quiet:
+ self.logger.set_verbose(self.logger.VERBOSE_QUIET)
+
+ self.comm_link = CTRexStatelessClient.CCommLink(server, sync_port, virtual, self.logger)
self.ports = {}
self._connection_info = {"server": server,
@@ -53,9 +106,8 @@ class CTRexStatelessClient(object):
"async_port": async_port}
self.system_info = {}
self.server_version = {}
- self.__err_log = None
- self.async_client = CTRexAsyncClient(server, async_port, self, self.prn_func)
+ self.async_client = CTRexAsyncClient(server, async_port, self, self.logger.log)
self.streams_db = CStreamsDB()
self.global_stats = trex_stats.CGlobalStats(self._connection_info,
@@ -99,7 +151,10 @@ class CTRexStatelessClient(object):
self.events.append("{:<10} - {:^8} - {:}".format(st, prefix, format_text(msg, 'bold')))
if show:
- self.prn_func(format_text("\n{:^8} - {:}".format(prefix, format_text(msg, 'bold'))), redraw_console = True)
+ self.logger.log(format_text("\n\n{:^8} - {:}".format(prefix, format_text(msg, 'bold'))))
+ if self.prompt_redraw_cb and self.logger.check_verbose(self.logger.VERBOSE_REGULAR):
+ self.prompt_redraw_cb()
+
def handle_async_stats_update(self, dump_data):
@@ -243,6 +298,7 @@ class CTRexStatelessClient(object):
# measure time for functions
def timing(f):
def wrap(*args):
+
time1 = time.time()
ret = f(*args)
@@ -251,7 +307,9 @@ class CTRexStatelessClient(object):
return ret
delta = time.time() - time1
- print format_time(delta) + "\n"
+
+ client = args[0]
+ client.logger.log(format_time(delta) + "\n")
return ret
@@ -289,7 +347,6 @@ class CTRexStatelessClient(object):
############ boot up section ################
- # connection sequence
# mode can be RW - read / write, RWF - read write with force , RO - read only
def connect(self, mode = "RW"):
@@ -300,6 +357,7 @@ class CTRexStatelessClient(object):
# clear this flag
self.connected = False
+
# connect sync channel
rc = self.comm_link.connect()
if rc.bad():
@@ -351,8 +409,8 @@ class CTRexStatelessClient(object):
# fallback to read only if failed
if rc.bad():
- rc.annotate(show_status = False)
- print format_text("Switching to read only mode - only few commands will be available", 'bold')
+ self.annotate(rc, show_status = False)
+ self.logger.log(format_text("Switching to read only mode - only few commands will be available", 'bold'))
self.release(self.get_acquired_ports())
self.read_only = True
@@ -458,37 +516,19 @@ class CTRexStatelessClient(object):
for port_id, port_obj in self.ports.iteritems()
if port_obj.is_transmitting()]
- def set_verbose(self, mode):
-
- # on high - enable link verbose
- if mode == self.VERBOSE_HIGH:
- self.comm_link.set_verbose(True)
- else:
- self.comm_link.set_verbose(False)
-
- self.verbose = mode
-
-
- def check_verbose (self, level):
- return (self.verbose >= level)
+ def set_verbose (self, level):
+ self.logger.set_verbose(level)
def get_verbose (self):
- return self.verbose
+ return self.logger.get_verbose()
- def prn_func (self, msg, level = VERBOSE_REGULAR, redraw_console = False):
- if not self.check_verbose(level):
- return
+ def set_prompt_redraw_cb(self, cb):
+ self.prompt_redraw_cb = cb
- if redraw_console and self.prompt_redraw_cb:
- print "\n" + msg + "\n"
- self.prompt_redraw_cb()
- else:
- print msg
- sys.stdout.flush()
+ def annotate (self, rc, desc = None, show_status = True):
- def set_prompt_redraw_cb(self, cb):
- self.prompt_redraw_cb = cb
+ rc.annotate(self.logger.log, desc, show_status)
############# server actions ################
@@ -684,39 +724,38 @@ class CTRexStatelessClient(object):
@timing
def cmd_ping(self):
rc = self.ping()
- rc.annotate("Pinging the server on '{0}' port '{1}': ".format(self.get_connection_ip(), self.get_connection_port()))
+ self.annotate(rc, "Pinging the server on '{0}' port '{1}': ".format(self.get_connection_ip(), self.get_connection_port()))
return rc
def cmd_connect(self, mode = "RW"):
rc = self.connect(mode)
- rc.annotate()
+ self.annotate(rc)
return rc
def cmd_disconnect(self):
rc = self.disconnect()
- rc.annotate()
+ self.annotate(rc)
return rc
# reset
def cmd_reset(self):
- #self.release(self.get_acquired_ports())
rc = self.acquire(force = True)
- rc.annotate("Force acquiring all ports:")
+ self.annotate(rc, "Force acquiring all ports:")
if rc.bad():
return rc
# force stop all ports
rc = self.stop_traffic(self.get_port_ids(), True)
- rc.annotate("Stop traffic on all ports:")
+ self.annotate(rc,"Stop traffic on all ports:")
if rc.bad():
return rc
# remove all streams
rc = self.remove_all_streams(self.get_port_ids())
- rc.annotate("Removing all streams from all ports:")
+ self.annotate(rc,"Removing all streams from all ports:")
if rc.bad():
return rc
@@ -732,11 +771,11 @@ class CTRexStatelessClient(object):
if not active_ports:
msg = "No active traffic on provided ports"
- print format_text(msg, 'bold')
+ self.logger.log(format_text(msg, 'bold'))
return RC_ERR(msg)
rc = self.stop_traffic(active_ports)
- rc.annotate("Stopping traffic on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Stopping traffic on port(s) {0}:".format(port_id_list))
if rc.bad():
return rc
@@ -750,11 +789,11 @@ class CTRexStatelessClient(object):
if not active_ports:
msg = "No active traffic on provided ports"
- print format_text(msg, 'bold')
+ self.logger.log(format_text(msg, 'bold'))
return RC_ERR(msg)
rc = self.update_traffic(mult, active_ports)
- rc.annotate("Updating traffic on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Updating traffic on port(s) {0}:".format(port_id_list))
return rc
@@ -785,11 +824,11 @@ class CTRexStatelessClient(object):
if not active_ports:
msg = "No active traffic on provided ports"
- print format_text(msg, 'bold')
+ self.logger.log(format_text(msg, 'bold'))
return RC_ERR(msg)
rc = self.pause_traffic(active_ports)
- rc.annotate("Pausing traffic on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Pausing traffic on port(s) {0}:".format(port_id_list))
return rc
@@ -802,11 +841,11 @@ class CTRexStatelessClient(object):
if not active_ports:
msg = "No active traffic on porvided ports"
- print format_text(msg, 'bold')
+ self.logger.log(format_text(msg, 'bold'))
return RC_ERR(msg)
rc = self.resume_traffic(active_ports)
- rc.annotate("Resume traffic on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Resume traffic on port(s) {0}:".format(port_id_list))
return rc
@@ -818,7 +857,7 @@ class CTRexStatelessClient(object):
if active_ports:
if not force:
msg = "Port(s) {0} are active - please stop them or add '--force'".format(active_ports)
- print format_text(msg, 'bold')
+ self.logger.log(format_text(msg, 'bold'))
return RC_ERR(msg)
else:
rc = self.cmd_stop(active_ports)
@@ -827,25 +866,25 @@ class CTRexStatelessClient(object):
rc = self.remove_all_streams(port_id_list)
- rc.annotate("Removing all streams from port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Removing all streams from port(s) {0}:".format(port_id_list))
if rc.bad():
return rc
rc = self.add_stream_pack(stream_list, port_id_list)
- rc.annotate("Attaching {0} streams to port(s) {1}:".format(len(stream_list.compiled), port_id_list))
+ self.annotate(rc,"Attaching {0} streams to port(s) {1}:".format(len(stream_list.compiled), port_id_list))
if rc.bad():
return rc
# when not on dry - start the traffic , otherwise validate only
if not dry:
rc = self.start_traffic(mult, duration, port_id_list)
- rc.annotate("Starting traffic on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Starting traffic on port(s) {0}:".format(port_id_list))
return rc
else:
rc = self.validate(port_id_list)
- rc.annotate("Validating traffic profile on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Validating traffic profile on port(s) {0}:".format(port_id_list))
if rc.bad():
return rc
@@ -859,7 +898,7 @@ class CTRexStatelessClient(object):
# validate port(s) profile
def cmd_validate (self, port_id_list):
rc = self.validate(port_id_list)
- rc.annotate("Validating streams on port(s) {0}:".format(port_id_list))
+ self.annotate(rc,"Validating streams on port(s) {0}:".format(port_id_list))
return rc
@@ -922,12 +961,12 @@ class CTRexStatelessClient(object):
if opts.dry:
- print format_text("\n*** DRY RUN ***", 'bold')
+ self.logger.log(format_text("\n*** DRY RUN ***", 'bold'))
if opts.db:
stream_list = self.streams_db.get_stream_pack(opts.db)
rc = RC(stream_list != None)
- rc.annotate("Load stream pack (from DB):")
+ self.annotate(rc,"Load stream pack (from DB):")
if rc.bad():
return RC_ERR("Failed to load stream pack")
@@ -939,11 +978,11 @@ class CTRexStatelessClient(object):
except Exception as e:
s = str(e)
rc=RC_ERR(s)
- rc.annotate()
+ self.annotate(rc)
return rc
rc = RC(stream_list != None)
- rc.annotate("Load stream pack (from file):")
+ self.annotate(rc,"Load stream pack (from file):")
if stream_list == None:
return RC_ERR("Failed to load stream pack")
@@ -1089,7 +1128,7 @@ class CTRexStatelessClient(object):
if not streams:
# we got no streams running
- print format_text("No streams found with desired filter.\n", "bold", "magenta")
+ self.logger.log(format_text("No streams found with desired filter.\n", "bold", "magenta"))
return RC_ERR("No streams found with desired filter.")
else:
# print stats to screen
@@ -1120,7 +1159,7 @@ class CTRexStatelessClient(object):
def cmd_exit_line (self, line):
- print format_text("Exiting\n", 'bold')
+ self.logger.log(format_text("Exiting\n", 'bold'))
# a way to exit
return RC_ERR("exit")
@@ -1139,7 +1178,7 @@ class CTRexStatelessClient(object):
delay_sec = opts.duration if (opts.duration > 0) else 1
- print format_text("Waiting for {0} seconds...\n".format(delay_sec), 'bold')
+ self.logger.log(format_text("Waiting for {0} seconds...\n".format(delay_sec), 'bold'))
time.sleep(delay_sec)
return RC_OK()
@@ -1147,7 +1186,7 @@ class CTRexStatelessClient(object):
# run a script of commands
def run_script_file (self, filename):
- print format_text("\nRunning script file '{0}'...".format(filename), 'bold')
+ self.logger.log(format_text("\nRunning script file '{0}'...".format(filename), 'bold'))
rc = self.cmd_connect()
if rc.bad():
@@ -1179,18 +1218,18 @@ class CTRexStatelessClient(object):
else:
args = ""
- print format_text("Executing line {0} : '{1}'\n".format(index, line))
+ self.logger.log(format_text("Executing line {0} : '{1}'\n".format(index, line)))
if not cmd in cmd_table:
print "\n*** Error at line {0} : '{1}'\n".format(index, line)
- print format_text("unknown command '{0}'\n".format(cmd), 'bold')
+ self.logger.log(format_text("unknown command '{0}'\n".format(cmd), 'bold'))
return False
rc = cmd_table[cmd](args)
if rc.bad():
return False
- print format_text("\n[Done]", 'bold')
+ self.logger.log(format_text("\n[Done]", 'bold'))
return True
@@ -1219,7 +1258,6 @@ class CTRexStatelessClient(object):
self.virtual = virtual
self.server = server
self.port = port
- self.verbose = False
self.rpc_link = JsonRpcClient(self.server, self.port, prn_func)
@property
@@ -1235,10 +1273,6 @@ class CTRexStatelessClient(object):
def get_port (self):
return self.port
- def set_verbose(self, mode):
- self.verbose = mode
- return self.rpc_link.set_verbose(mode)
-
def connect(self):
if not self.virtual:
return self.rpc_link.connect()
diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
index bdae7bd9..a5e01340 100755
--- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
@@ -42,8 +42,8 @@ class BatchMessage(object):
# JSON RPC v2.0 client
class JsonRpcClient(object):
- def __init__ (self, default_server, default_port, prn_func = None):
- self.verbose = False
+ def __init__ (self, default_server, default_port, logger):
+ self.logger = logger
self.connected = False
# default values
@@ -51,7 +51,6 @@ class JsonRpcClient(object):
self.server = default_server
self.id_gen = general_utils.random_id_gen()
- self.prn_func = prn_func
def get_connection_details (self):
rc = {}
@@ -82,10 +81,7 @@ class JsonRpcClient(object):
return pretty_str
def verbose_msg (self, msg):
- if not self.verbose:
- return
-
- print "[verbose] " + msg
+ self.logger.log("[verbose] " + msg, level = self.logger.VERBOSE_HIGH)
# batch messages
@@ -183,10 +179,7 @@ class JsonRpcClient(object):
return RC_OK(response_json["result"])
-
- def set_verbose(self, mode):
- self.verbose = mode
def disconnect (self):
if self.connected:
@@ -198,7 +191,7 @@ class JsonRpcClient(object):
return RC_ERR("Not connected to server")
- def connect(self, server = None, port = None, prn_func = None):
+ def connect(self, server = None, port = None):
if self.connected:
self.disconnect()
@@ -211,10 +204,7 @@ class JsonRpcClient(object):
self.transport = "tcp://{0}:{1}".format(self.server, self.port)
msg = "\nConnecting To RPC Server On {0}".format(self.transport)
- if self.prn_func:
- self.prn_func(msg)
- else:
- print msg
+ self.logger.log(msg)
self.socket = self.context.socket(zmq.REQ)
try:
@@ -245,7 +235,7 @@ class JsonRpcClient(object):
return self.connected
def __del__(self):
- print "Shutting down RPC client\n"
+ self.logger.log("Shutting down RPC client\n")
if hasattr(self, "context"):
self.context.destroy(linger=0)
diff --git a/scripts/automation/trex_control_plane/common/trex_types.py b/scripts/automation/trex_control_plane/common/trex_types.py
index 7c3f04c5..21deffd2 100644
--- a/scripts/automation/trex_control_plane/common/trex_types.py
+++ b/scripts/automation/trex_control_plane/common/trex_types.py
@@ -21,6 +21,9 @@ class RC():
tuple_rc = namedtuple('RC', ['rc', 'data'])
self.rc_list.append(tuple_rc(rc, data))
+ def __nonzero__ (self):
+ return self.good()
+
def add (self, rc):
self.rc_list += rc.rc_list
@@ -38,27 +41,30 @@ class RC():
e = [x.data if not x.rc else "" for x in self.rc_list]
return (e if len(e) > 1 else e[0])
- def annotate (self, desc = None, show_status = True):
+ def __str__ (self):
+ return str(self.data()) if self else str(self.err())
+
+ def annotate (self, log_func, desc = None, show_status = True):
if desc:
- print format_text('\n{:<60}'.format(desc), 'bold'),
+ log_func(format_text('\n{:<60}'.format(desc), 'bold'), newline = False)
else:
- print ""
+ log_func("")
if self.bad():
# print all the errors
print ""
for x in self.rc_list:
if not x.rc:
- print format_text("\n{0}".format(x.data), 'bold')
+ log_func(format_text("\n{0}".format(x.data), 'bold'))
print ""
if show_status:
- print format_text("[FAILED]\n", 'red', 'bold')
+ log_func(format_text("[FAILED]\n", 'red', 'bold'))
else:
if show_status:
- print format_text("[SUCCESS]\n", 'green', 'bold')
+ log_func(format_text("[SUCCESS]\n", 'green', 'bold'))
def RC_OK(data = ""):
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index 2672665c..2ae92fb6 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -153,7 +153,9 @@ class TRexConsole(TRexGeneralCmd):
################### internal section ########################
def prompt_redraw (self):
- sys.stdout.write(self.prompt + readline.get_line_buffer())
+ sys.stdout.write("\n" + self.prompt + readline.get_line_buffer())
+ sys.stdout.flush()
+
def verify_connected(f):
@wraps(f)
@@ -312,12 +314,12 @@ class TRexConsole(TRexGeneralCmd):
elif line == "on":
self.verbose = True
- self.stateless_client.set_verbose(self.stateless_client.VERBOSE_HIGH)
+ self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_HIGH)
print format_text("\nverbose set to on\n", 'green', 'bold')
elif line == "off":
self.verbose = False
- self.stateless_client.set_verbose(self.stateless_client.VERBOSE_REGULAR)
+ self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_REGULAR)
print format_text("\nverbose set to off\n", 'green', 'bold')
else:
@@ -531,7 +533,7 @@ class TRexConsole(TRexGeneralCmd):
save_verbose = self.stateless_client.get_verbose()
- self.stateless_client.set_verbose(self.stateless_client.VERBOSE_QUIET)
+ self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_QUIET)
self.tui.show()
self.stateless_client.set_verbose(save_verbose)
diff --git a/scripts/stl_test_api/__init__.py b/scripts/stl_test_api/__init__.py
new file mode 100644
index 00000000..6df72136
--- /dev/null
+++ b/scripts/stl_test_api/__init__.py
@@ -0,0 +1,82 @@
+import sys
+import os
+import time
+import cStringIO
+
+api_path = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, os.path.join(api_path, '../automation/trex_control_plane/client/'))
+
+from trex_stateless_client import CTRexStatelessClient, LoggerApi
+from common import trex_stats
+
+# a basic test object
+class BasicTestAPI(object):
+
+ # exception class
+ class Failure(Exception):
+ def __init__ (self, rc):
+ self.msg = str(rc)
+
+ def __str__ (self):
+ s = "\n\n******\n"
+ s += "Test has failed.\n\n"
+ s += "Error reported:\n\n {0}\n".format(self.msg)
+ return s
+
+
+ # logger for test
+ class Logger(LoggerApi):
+ def __init__ (self):
+ LoggerApi.__init__(self)
+ self.buffer = cStringIO.StringIO()
+
+ def write (self, msg, newline = True):
+ line = str(msg) + ("\n" if newline else "")
+ self.buffer.write(line)
+
+ #print line
+
+ def flush (self):
+ pass
+
+
+ # main object
+ def __init__ (self, server = "localhost", sync_port = 4501, async_port = 4500):
+ self.logger = BasicTestAPI.Logger()
+ self.client = CTRexStatelessClient(logger = self.logger, sync_port = sync_port, async_port = async_port)
+
+
+ def connect (self):
+ rc = self.client.connect(mode = "RWF")
+ self.__verify_rc(rc)
+
+
+ def disconnect (self):
+ self.client.disconnect()
+
+
+ def __verify_rc (self, rc):
+ if rc.bad():
+ raise self.Failure(rc)
+
+ def inject_profile (self, filename, rate = "1", duration = None):
+ cmd = "-f {0} -m {1}".format(filename, rate)
+ if duration:
+ cmd += " -d {0}".format(duration)
+
+ rc = self.client.cmd_start_line(cmd)
+ self.__verify_rc(rc)
+
+
+ def wait_while_traffic_on (self, timeout = None):
+ while self.client.get_active_ports():
+ time.sleep(0.1)
+
+
+ def get_stats (self):
+ total_stats = trex_stats.CPortStats(None)
+
+ for port in self.client.ports.values():
+ total_stats += port.port_stats
+
+ return total_stats
diff --git a/scripts/stl_test_api/trex_stl_api.py b/scripts/stl_test_api/trex_stl_api.py
new file mode 100644
index 00000000..6d85ee9f
--- /dev/null
+++ b/scripts/stl_test_api/trex_stl_api.py
@@ -0,0 +1,93 @@
+import sys
+import os
+import time
+import cStringIO
+
+api_path = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, os.path.join(api_path, '../automation/trex_control_plane/client/'))
+
+from trex_stateless_client import CTRexStatelessClient, LoggerApi
+
+class BasicTest(object):
+
+ # exception class
+ class Failure(Exception):
+ def __init__ (self, rc):
+ self.rc = rc
+
+ def __str__ (self):
+ s = "\n******\n"
+ s += "Test has failed.\n\n"
+ s += "Error reported:\n\n {0}\n".format(str(self.rc.err()))
+ return s
+
+
+ # logger
+ class Logger(LoggerApi):
+ def __init__ (self):
+ LoggerApi.__init__(self)
+ self.buffer = cStringIO.StringIO()
+
+ def write (self, msg, newline = True):
+ self.buffer.write(str(msg))
+
+ if newline:
+ self.buffer.write("\n")
+
+ def flush (self):
+ pass
+
+
+ def __init__ (self):
+ self.logger = BasicTest.Logger()
+ self.client = CTRexStatelessClient(logger = self.logger)
+
+ def connect (self):
+ rc = self.client.connect(mode = "RWF")
+ __verify_rc(rc)
+
+
+ def disconnect (self):
+ self.client.disconnect()
+
+
+ def __verify_rc (self, rc):
+ if rc.bad():
+ raise self.Failure(rc)
+
+ def inject_profile (self, filename, rate = "1", duration = None):
+ cmd = "-f {0} -m {1}".format(filename, rate)
+ if duration:
+ cmd += " -d {0}".format(duration)
+
+ print cmd
+ rc = self.client.cmd_start_line(cmd)
+ self.__verify_rc(rc)
+
+
+ def wait_while_traffic_on (self, timeout = None):
+ while self.client.get_active_ports():
+ time.sleep(0.1)
+
+
+def start ():
+ test = BasicTest()
+
+ try:
+ test.connect()
+ test.inject_profile("stl/imix_1pkt.yaml", rate = "5gbps", duration = 10)
+ test.wait_while_traffic_on()
+ finally:
+ test.disconnect()
+
+
+def main ():
+ try:
+ start()
+ print "\nTest has passed :)\n"
+ except BasicTest.Failure as e:
+ print e
+
+
+
+#main()
diff --git a/scripts/stl_test_example.py b/scripts/stl_test_example.py
new file mode 100644
index 00000000..689ed316
--- /dev/null
+++ b/scripts/stl_test_example.py
@@ -0,0 +1,24 @@
+from stl_test_api import BasicTestAPI
+
+x = BasicTestAPI()
+
+try:
+ x.connect()
+
+ s = x.get_stats()
+
+ print "input packets before test: %s" % s['ipackets']
+
+ x.inject_profile("stl/imix_1pkt.yaml", rate = "5gbps", duration = 1)
+ x.wait_while_traffic_on()
+
+ s = x.get_stats()
+
+ print "input packets after test: %s" % s['ipackets']
+
+ print "Test passed :-)\n"
+
+finally:
+ x.disconnect()
+
+