summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/automation/trex_control_plane/stl')
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_imix.py17
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py9
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_path.py5
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_profile.py3
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py3
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py54
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_ext.py2
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py64
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py9
9 files changed, 144 insertions, 22 deletions
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_imix.py b/scripts/automation/trex_control_plane/stl/examples/stl_imix.py
index 56fd3cfd..ecf0fe69 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_imix.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_imix.py
@@ -12,11 +12,12 @@ import argparse
# and attach it to both sides and inject
# at a certain rate for some time
# finally it checks that all packets arrived
-def imix_test (server):
+def imix_test (server, mult):
# create client
c = STLClient(server = server)
+
passed = True
@@ -27,6 +28,7 @@ def imix_test (server):
# take all the ports
c.reset()
+
# map ports - identify the routes
table = stl_map_ports(c)
@@ -37,7 +39,8 @@ def imix_test (server):
print("Mapped ports to sides {0} <--> {1}".format(dir_0, dir_1))
# load IMIX profile
- profile = STLProfile.load_py('../../../../stl/imix.py')
+ profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'imix.py')
+ profile = STLProfile.load_py(profile_file)
streams = profile.get_streams()
# add both streams to ports
@@ -47,9 +50,8 @@ def imix_test (server):
# clear the stats before injecting
c.clear_stats()
- # choose rate and start traffic for 10 seconds on 5 mpps
+ # choose rate and start traffic for 10 seconds
duration = 10
- mult = "30%"
print("Injecting {0} <--> {1} on total rate of '{2}' for {3} seconds".format(dir_0, dir_1, mult, duration))
c.start(ports = (dir_0 + dir_1), mult = mult, duration = duration, total = True)
@@ -107,8 +109,13 @@ parser.add_argument('-s', '--server',
help='Remote trex address',
default='127.0.0.1',
type = str)
+parser.add_argument('-m', '--mult',
+ dest='mult',
+ help='Multiplier of traffic, see Stateless help for more info',
+ default='30%',
+ type = str)
args = parser.parse_args()
# run the tests
-imix_test(args.server)
+imix_test(args.server, args.mult)
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py b/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py
index 05a8777b..05615aeb 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py
@@ -29,14 +29,15 @@ def imix_test (server):
# take all the ports
c.reset()
- dir_0 = [0]
- dir_1 = [1]
+ dir_0 = [0]
+ dir_1 = [1]
print "Mapped ports to sides {0} <--> {1}".format(dir_0, dir_1)
# load IMIX profile
- profile1 = STLProfile.load_py('../../../../stl/imix.py', direction=0)
- profile2 = STLProfile.load_py('../../../../stl/imix.py', direction=1)
+ profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'imix.py')
+ profile1 = STLProfile.load_py(profile_file, direction=0)
+ profile2 = STLProfile.load_py(profile_file, direction=1)
stream1 = profile1.get_streams()
stream2 = profile2.get_streams()
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_path.py b/scripts/automation/trex_control_plane/stl/examples/stl_path.py
index 8f400d23..f1592571 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_path.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_path.py
@@ -1,4 +1,7 @@
-import sys
+import sys, os
# FIXME to the write path for trex_stl_lib
sys.path.insert(0, "../")
+
+STL_PROFILES_PATH = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, 'stl')
+
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_profile.py b/scripts/automation/trex_control_plane/stl/examples/stl_profile.py
index 3ae5f855..16d5238e 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_profile.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_profile.py
@@ -18,8 +18,7 @@ def simple ():
# prepare our ports
c.reset(ports = my_ports)
-
- profile_file = "../../../../stl/udp_1pkt_simple.py"
+ profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'hlt', 'udp_1pkt_simple.py')
try:
profile = STLProfile.load(profile_file)
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py b/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py
index 03909e65..1d4ef250 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py
@@ -29,9 +29,10 @@ def simple ():
print(c.get_port_info(my_ports))
c.ping()
+ profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'udp_1pkt_simple.py')
print("start")
- c.start_line (" -f ../../../../stl/udp_1pkt_simple.py -m 10mpps --port 0 1 ")
+ c.start_line (" -f %s -m 10mpps --port 0 1 " % profile_file)
time.sleep(2);
c.pause_line("--port 0 1");
time.sleep(2);
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
index 9b6a9e25..7fbd2808 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
@@ -852,8 +852,26 @@ class STLClient(object):
return RC_OK()
-
-
+ # remove all RX filters in a safe manner
+ def _remove_rx_filters (self, ports, rx_delay_ms):
+
+ # get the enabled RX ports
+ rx_ports = [port_id for port_id in ports if self.ports[port_id].has_rx_enabled()]
+
+ if not rx_ports:
+ return RC_OK()
+
+ # block while any RX configured port has not yet have it's delay expired
+ while any([not self.ports[port_id].has_rx_delay_expired(rx_delay_ms) for port_id in rx_ports]):
+ time.sleep(0.01)
+
+ # remove RX filters
+ rc = RC()
+ for port_id in rx_ports:
+ rc.add(self.ports[port_id].remove_rx_filters())
+
+ return rc
+
#################################
# ------ private methods ------ #
@@ -1089,6 +1107,7 @@ class STLClient(object):
for port_id, port_obj in self.ports.items()
if port_obj.is_active()]
+
# get paused ports
def get_paused_ports (self):
return [port_id
@@ -1336,7 +1355,7 @@ class STLClient(object):
ports = self._validate_port_list(ports)
self.acquire(ports, force = True)
- self.stop(ports)
+ self.stop(ports, rx_delay_ms = 0)
self.remove_all_streams(ports)
self.clear_stats(ports)
@@ -1537,7 +1556,7 @@ class STLClient(object):
@__api_check(True)
- def stop (self, ports = None):
+ def stop (self, ports = None, rx_delay_ms = 10):
"""
Stop port(s)
@@ -1545,6 +1564,13 @@ class STLClient(object):
ports : list
Ports on which to execute the command
+ rx_delay_ms : int
+ time to wait until RX filters are removed
+ this value should reflect the time it takes
+ packets which were transmitted to arrive
+ to the destination.
+ after this time the RX filters will be removed
+
:raises:
+ :exc:`STLError`
@@ -1563,6 +1589,11 @@ class STLClient(object):
if not rc:
raise STLError(rc)
+ # remove any RX filters
+ rc = self._remove_rx_filters(ports, rx_delay_ms = rx_delay_ms)
+ if not rc:
+ raise STLError(rc)
+
@__api_check(True)
def update (self, ports = None, mult = "1", total = False, force = False):
@@ -1784,7 +1815,7 @@ class STLClient(object):
@__api_check(True)
- def wait_on_traffic (self, ports = None, timeout = 60):
+ def wait_on_traffic (self, ports = None, timeout = 60, rx_delay_ms = 10):
"""
Block until traffic on specified port(s) has ended
@@ -1795,6 +1826,14 @@ class STLClient(object):
timeout : int
timeout in seconds
+ rx_delay_ms : int
+ time to wait until RX filters are removed
+ this value should reflect the time it takes
+ packets which were transmitted to arrive
+ to the destination.
+ after this time the RX filters will be removed
+
+
:raises:
+ :exc:`STLTimeoutError` - in case timeout has expired
+ :exe:'STLError'
@@ -1813,6 +1852,11 @@ class STLClient(object):
if time.time() > expr:
raise STLTimeoutError(timeout)
+ # remove any RX filters
+ rc = self._remove_rx_filters(ports, rx_delay_ms = rx_delay_ms)
+ if not rc:
+ raise STLError(rc)
+
@__api_check(True)
def set_port_attr (self, ports = None, promiscuous = None):
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_ext.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_ext.py
index d6d66ec3..ed0c393d 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_ext.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_ext.py
@@ -9,7 +9,7 @@ TREX_STL_EXT_PATH = os.environ.get('TREX_STL_EXT_PATH')
# take default
if not TREX_STL_EXT_PATH or not os.path.exists(TREX_STL_EXT_PATH):
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
- TREX_STL_EXT_PATH = os.path.normpath(os.path.join(CURRENT_PATH, os.pardir, 'external_libs'))
+ TREX_STL_EXT_PATH = os.path.normpath(os.path.join(CURRENT_PATH, os.pardir, os.pardir, 'external_libs'))
if not os.path.exists(TREX_STL_EXT_PATH):
# ../../../../external_libs
TREX_STL_EXT_PATH = os.path.normpath(os.path.join(CURRENT_PATH, os.pardir, os.pardir, os.pardir, os.pardir, 'external_libs'))
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
index 47124114..049929ae 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
@@ -7,8 +7,8 @@ from .trex_stl_types import *
from . import trex_stl_stats
import base64
-import time
import copy
+from datetime import datetime, timedelta
StreamOnPort = namedtuple('StreamOnPort', ['compiled_stream', 'metadata'])
@@ -61,6 +61,8 @@ class Port(object):
self.port_stats = trex_stl_stats.CPortStats(self)
self.next_available_id = 1
+ self.tx_stopped_ts = None
+ self.has_rx_streams = False
def err(self, msg):
@@ -239,6 +241,9 @@ class Port(object):
'rate' : streams_list[i].get_rate()}
ret.add(RC_OK(data = stream_id))
+
+ self.has_rx_streams = self.has_rx_streams or streams_list[i].has_flow_stats()
+
else:
ret.add(RC(*single_rc))
@@ -283,6 +288,9 @@ class Port(object):
self.state = self.STATE_STREAMS if (len(self.streams) > 0) else self.STATE_IDLE
+ # recheck if any RX stats streams present on the port
+ self.has_rx_streams = any([stream.has_flow_stats() for stream in self.streams])
+
return self.ok() if rc else self.err(rc.err())
@@ -305,6 +313,7 @@ class Port(object):
self.streams = {}
self.state = self.STATE_IDLE
+ self.has_rx_streams = False
return self.ok()
@@ -351,7 +360,7 @@ class Port(object):
# stop traffic
# with force ignores the cached state and sends the command
def stop (self, force = False):
-
+
if not self.is_acquired():
return self.err("port is not owned")
@@ -360,7 +369,6 @@ class Port(object):
if (self.state == self.STATE_IDLE) or (self.state == self.state == self.STATE_STREAMS):
return self.ok()
-
params = {"handler": self.handler,
"port_id": self.port_id}
@@ -370,8 +378,56 @@ class Port(object):
self.state = self.STATE_STREAMS
+ # timestamp for last tx
+ self.tx_stopped_ts = datetime.now()
+
+ return self.ok()
+
+
+ # return True if port has any stream configured with RX stats
+ def has_rx_enabled (self):
+ return self.has_rx_streams
+
+
+ # return true if rx_delay_ms has passed since the last port stop
+ def has_rx_delay_expired (self, rx_delay_ms):
+ assert(self.has_rx_enabled())
+
+ # if active - it's not safe to remove RX filters
+ if self.is_active():
+ return False
+
+ # either no timestamp present or time has already passed
+ return not self.tx_stopped_ts or (datetime.now() - self.tx_stopped_ts) > timedelta(milliseconds = rx_delay_ms)
+
+
+
+ def remove_rx_filters (self):
+ assert(self.has_rx_enabled())
+
+ if not self.is_acquired():
+ return self.err("port is not owned")
+
+ if self.state == self.STATE_DOWN:
+ return self.err("Unable to remove RX filters - port is down")
+
+ if self.state == self.STATE_TX:
+ return self.err("Unable to remove RX filters - port is transmitting")
+
+ if self.state == self.STATE_IDLE:
+ return self.ok()
+
+
+ params = {"handler": self.handler,
+ "port_id": self.port_id}
+
+ rc = self.transmit("remove_rx_filters", params)
+ if rc.bad():
+ return self.err(rc.err())
+
return self.ok()
+
def pause (self):
if not self.is_acquired():
@@ -597,6 +653,8 @@ class Port(object):
################# events handler ######################
def async_event_port_job_done (self):
+ # until thread is locked - order is important
+ self.tx_stopped_ts = datetime.now()
self.state = self.STATE_STREAMS
# rest of the events are used for TUI / read only sessions
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
index e66f917b..78f51ec6 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
@@ -430,6 +430,10 @@ class STLStream(object):
return self.next
+ def has_flow_stats (self):
+ """ Return True if stream was configured with flow stats """
+ return self.fields['flow_stats']['enabled']
+
def get_pkt (self):
""" Get packet as string """
return self.pkt
@@ -828,6 +832,11 @@ class STLProfile(object):
def __str__ (self):
return '\n'.join([str(stream) for stream in self.streams])
+ def is_pauseable (self):
+ return all([x.get_mode() == "Continuous" for x in (self.get_streams())])
+
+ def has_flow_stats (self):
+ return any([x.has_flow_stats() for x in self.get_streams()])
@staticmethod
def load_yaml (yaml_file):