summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xlinux_dpdk/ws_main.py16
-rwxr-xr-xscripts/automation/regression/outer_packages.py4
-rw-r--r--scripts/automation/regression/stateless_tests/stl_client_test.py274
-rwxr-xr-xscripts/automation/regression/trex_unit_test.py31
-rw-r--r--scripts/automation/trex_control_plane/doc/_templates/layout.html17
-rwxr-xr-xscripts/automation/trex_control_plane/doc/conf.py2
-rw-r--r--scripts/automation/trex_control_plane/doc_stl/_templates/layout.html17
-rwxr-xr-xscripts/automation/trex_control_plane/stf/examples/stf_example.py53
-rwxr-xr-xscripts/automation/trex_control_plane/stf/examples/stf_path.py4
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/CCustomLogger.py (renamed from scripts/automation/trex_control_plane/stf/CCustomLogger.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/__init__.py (renamed from scripts/automation/trex_control_plane/stf/__init__.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/external_packages.py (renamed from scripts/automation/trex_control_plane/stf/external_packages.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/general_utils.py (renamed from scripts/automation/trex_control_plane/stf/general_utils.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/outer_packages.py (renamed from scripts/automation/trex_control_plane/stf/outer_packages.py)10
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/text_opts.py (renamed from scripts/automation/trex_control_plane/stf/text_opts.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py (renamed from scripts/automation/trex_control_plane/stf/trex_client.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/trex_daemon_server.py (renamed from scripts/automation/trex_control_plane/stf/trex_daemon_server.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/trex_exceptions.py (renamed from scripts/automation/trex_control_plane/stf/trex_exceptions.py)0
-rw-r--r--scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status.py (renamed from scripts/automation/trex_control_plane/stf/trex_status.py)0
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status_e.py (renamed from scripts/automation/trex_control_plane/stf/trex_status_e.py)0
-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
-rwxr-xr-xscripts/run_functional_tests48
-rw-r--r--scripts/stl/flow_stats.py6
-rw-r--r--scripts/stl/udp_1pkt_pcap.py5
-rw-r--r--scripts/stl/udp_1pkt_simple_burst.py24
-rw-r--r--scripts/stl/udp_3pkt_pcap.py9
-rw-r--r--scripts/stl/yaml/imix_1pkt_vm_minus.yaml3
-rw-r--r--src/flow_stat.cpp10
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp21
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h1
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp2
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp19
-rw-r--r--src/stateless/cp/trex_stateless_port.h8
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.cpp25
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.h1
43 files changed, 700 insertions, 76 deletions
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py
index 6310a8c2..ab34fbac 100755
--- a/linux_dpdk/ws_main.py
+++ b/linux_dpdk/ws_main.py
@@ -963,17 +963,25 @@ def release(bld, custom_dir = None):
os.system("cp -rv %s %s " %(src_file,dest_file));
os.system("chmod 755 %s " %(dest_file));
+ rel=get_build_num ()
+
# create client package
os.system('mkdir -p %s/trex_client/external_libs' % exec_p)
- os.system('touch %s/trex_client/__init__.py' % exec_p)
for ext_lib in client_external_libs:
os.system('cp ../scripts/external_libs/%s %s/trex_client/external_libs/ -r' % (ext_lib, exec_p))
os.system('cp ../scripts/automation/trex_control_plane/stf %s/trex_client/ -r' % exec_p)
- os.system('cp ../scripts/automation/trex_control_plane/stl/trex_stl_lib %s/trex_client/stl -r' % exec_p)
- shutil.make_archive(os.path.join(exec_p, 'trex_client'), 'gztar', exec_p, 'trex_client')
+ os.system('cp ../scripts/automation/trex_control_plane/stl %s/trex_client/ -r' % exec_p)
+ with open('%s/trex_client/stl/examples/stl_path.py' % exec_p) as f:
+ stl_path_content = f.read()
+ if 'STL_PROFILES_PATH' not in stl_path_content:
+ raise Exception('Could not find STL_PROFILES_PATH in stl/examples/stl_path.py')
+ stl_path_content = re.sub('STL_PROFILES_PATH.*?\n', "STL_PROFILES_PATH = os.path.join(os.pardir, 'profiles')\n", stl_path_content)
+ with open('%s/trex_client/stl/examples/stl_path.py' % exec_p, 'w') as f:
+ f.write(stl_path_content)
+ os.system('cp ../scripts/stl %s/trex_client/stl/profiles -r' % exec_p)
+ shutil.make_archive(os.path.join(exec_p, 'trex_client_%s' % rel), 'gztar', exec_p, 'trex_client')
os.system('rm -r %s/trex_client' % exec_p)
- rel=get_build_num ()
os.system('cd %s/..;tar --exclude="*.pyc" -zcvf %s/%s.tar.gz %s' %(exec_p,os.getcwd(),rel,rel))
os.system("mv %s/%s.tar.gz %s" % (os.getcwd(),rel,exec_p));
diff --git a/scripts/automation/regression/outer_packages.py b/scripts/automation/regression/outer_packages.py
index bec9fe21..61ddc5cd 100755
--- a/scripts/automation/regression/outer_packages.py
+++ b/scripts/automation/regression/outer_packages.py
@@ -9,6 +9,7 @@ if not TREX_PATH or not os.path.isfile('%s/trex_daemon_server' % TREX_PATH):
TREX_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir, os.pardir))
PATH_TO_PYTHON_LIB = os.path.abspath(os.path.join(TREX_PATH, 'external_libs'))
PATH_TO_CTRL_PLANE = os.path.abspath(os.path.join(TREX_PATH, 'automation', 'trex_control_plane'))
+PATH_STF_API = os.path.abspath(os.path.join(PATH_TO_CTRL_PLANE, 'stf'))
PATH_STL_API = os.path.abspath(os.path.join(PATH_TO_CTRL_PLANE, 'stl'))
@@ -57,8 +58,9 @@ def import_module_list(modules_list):
def import_nightly_modules ():
sys.path.append(TREX_PATH)
- sys.path.append(PATH_TO_CTRL_PLANE)
+ #sys.path.append(PATH_TO_CTRL_PLANE)
sys.path.append(PATH_STL_API)
+ sys.path.append(PATH_STF_API)
import_module_list(NIGHTLY_MODULES)
diff --git a/scripts/automation/regression/stateless_tests/stl_client_test.py b/scripts/automation/regression/stateless_tests/stl_client_test.py
new file mode 100644
index 00000000..132109c0
--- /dev/null
+++ b/scripts/automation/regression/stateless_tests/stl_client_test.py
@@ -0,0 +1,274 @@
+#!/router/bin/python
+from stl_general_test import CStlGeneral_Test, CTRexScenario
+from trex_stl_lib.api import *
+import os, sys
+import glob
+
+
+def get_error_in_percentage (golden, value):
+ return abs(golden - value) / float(golden)
+
+def get_stl_profiles ():
+ profiles_path = os.path.join(CTRexScenario.scripts_path, 'stl/')
+ profiles = glob.glob(profiles_path + "/*.py") + glob.glob(profiles_path + "yaml/*.yaml")
+
+ return profiles
+
+
+class STLClient_Test(CStlGeneral_Test):
+ """Tests for stateless client"""
+
+ def setUp(self):
+ CStlGeneral_Test.setUp(self)
+
+ assert 'bi' in CTRexScenario.stl_ports_map
+
+ self.c = CTRexScenario.stl_trex
+
+ self.tx_port, self.rx_port = CTRexScenario.stl_ports_map['bi'][0]
+
+ self.c.connect()
+ self.c.reset(ports = [self.tx_port, self.rx_port])
+
+ self.pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/IP()/'a_payload_example')
+ self.profiles = get_stl_profiles()
+
+
+ @classmethod
+ def tearDownClass(cls):
+ # connect back at end of tests
+ if not cls.is_connected():
+ CTRexScenario.stl_trex.connect()
+
+
+ def test_basic_connect_disconnect (self):
+ try:
+ self.c.connect()
+ assert self.c.is_connected(), 'client should be connected'
+ self.c.disconnect()
+ assert not self.c.is_connected(), 'client should be disconnected'
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ def test_basic_single_burst (self):
+ try:
+ b1 = STLStream(name = 'burst',
+ packet = self.pkt,
+ mode = STLTXSingleBurst(total_pkts = 100,
+ pps = 1000)
+ )
+
+ for i in range(0, 5):
+ self.c.add_streams([b1], ports = [self.tx_port, self.rx_port])
+
+ self.c.clear_stats()
+ self.c.start(ports = [self.tx_port, self.rx_port])
+
+ assert self.c.ports[self.tx_port].is_transmitting(), 'port should be active'
+ assert self.c.ports[self.rx_port].is_transmitting(), 'port should be active'
+
+ self.c.wait_on_traffic(ports = [self.tx_port, self.rx_port])
+ stats = self.c.get_stats()
+
+ assert self.tx_port in stats
+ assert self.rx_port in stats
+
+ assert stats[self.tx_port]['opackets'] == 100
+ assert stats[self.rx_port]['ipackets'] == 100
+
+ assert stats[self.rx_port]['opackets'] == 100
+ assert stats[self.tx_port]['ipackets'] == 100
+
+ self.c.remove_all_streams(ports = [self.tx_port, self.rx_port])
+
+
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ #
+ def test_basic_multi_burst (self):
+ try:
+ b1 = STLStream(name = 'burst',
+ packet = self.pkt,
+ mode = STLTXMultiBurst(pkts_per_burst = 10,
+ count = 20,
+ pps = 1000)
+ )
+
+ for i in range(0, 5):
+ self.c.add_streams([b1], ports = [self.tx_port, self.rx_port])
+
+ self.c.clear_stats()
+ self.c.start(ports = [self.tx_port, self.rx_port])
+
+ assert self.c.ports[self.tx_port].is_transmitting(), 'port should be active'
+ assert self.c.ports[self.rx_port].is_transmitting(), 'port should be active'
+
+ self.c.wait_on_traffic(ports = [self.tx_port, self.rx_port])
+ stats = self.c.get_stats()
+
+ assert self.tx_port in stats
+ assert self.rx_port in stats
+
+ assert stats[self.tx_port]['opackets'] == 200
+ assert stats[self.rx_port]['ipackets'] == 200
+
+ assert stats[self.rx_port]['opackets'] == 200
+ assert stats[self.tx_port]['ipackets'] == 200
+
+ self.c.remove_all_streams(ports = [self.tx_port, self.rx_port])
+
+
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ #
+ def test_basic_cont (self):
+ pps = 49182
+ duration = 0.1
+ golden = pps * duration
+
+ try:
+ b1 = STLStream(name = 'burst',
+ packet = self.pkt,
+ mode = STLTXCont(pps = pps)
+ )
+
+ for i in range(0, 5):
+ self.c.add_streams([b1], ports = [self.tx_port, self.rx_port])
+
+ self.c.clear_stats()
+ self.c.start(ports = [self.tx_port, self.rx_port], duration = duration)
+
+ assert self.c.ports[self.tx_port].is_transmitting(), 'port should be active'
+ assert self.c.ports[self.rx_port].is_transmitting(), 'port should be active'
+
+ self.c.wait_on_traffic(ports = [self.tx_port, self.rx_port])
+ stats = self.c.get_stats()
+
+ assert self.tx_port in stats
+ assert self.rx_port in stats
+
+ # cont. with duration should be quite percise - 5% error is relaxed enough
+ assert get_error_in_percentage(stats[self.tx_port]['opackets'], golden) < 0.05
+ assert get_error_in_percentage(stats[self.rx_port]['ipackets'], golden) < 0.05
+
+ assert get_error_in_percentage(stats[self.rx_port]['opackets'], golden) < 0.05
+ assert get_error_in_percentage(stats[self.tx_port]['ipackets'], golden) < 0.05
+
+
+ self.c.remove_all_streams(ports = [self.tx_port, self.rx_port])
+
+
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ def test_stress_connect_disconnect (self):
+ try:
+ for i in range(0, 100):
+ self.c.connect()
+ assert self.c.is_connected(), 'client should be connected'
+ self.c.disconnect()
+ assert not self.c.is_connected(), 'client should be disconnected'
+
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+
+ def test_stress_tx (self):
+ try:
+ s1 = STLStream(name = 'stress',
+ packet = self.pkt,
+ mode = STLTXCont(percentage = 60))
+
+ # add both streams to ports
+ self.c.add_streams([s1], ports = [self.tx_port, self.rx_port])
+ for i in range(0, 100):
+
+ self.c.start(ports = [self.tx_port, self.rx_port])
+
+ assert self.c.ports[self.tx_port].is_transmitting(), 'port should be active'
+ assert self.c.ports[self.rx_port].is_transmitting(), 'port should be active'
+
+ self.c.pause(ports = [self.tx_port, self.rx_port])
+
+ assert self.c.ports[self.tx_port].is_paused(), 'port should be paused'
+ assert self.c.ports[self.rx_port].is_paused(), 'port should be paused'
+
+ self.c.resume(ports = [self.tx_port, self.rx_port])
+
+ assert self.c.ports[self.tx_port].is_transmitting(), 'port should be active'
+ assert self.c.ports[self.rx_port].is_transmitting(), 'port should be active'
+
+ self.c.stop(ports = [self.tx_port, self.rx_port])
+
+ assert not self.c.ports[self.tx_port].is_active(), 'port should be idle'
+ assert not self.c.ports[self.rx_port].is_active(), 'port should be idle'
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ def test_all_profiles (self):
+
+ if self.is_virt_nics or not self.is_loopback:
+ print("skipping for non loopback / virtual")
+ return
+
+ try:
+ self.c.set_port_attr(ports = [self.tx_port, self.rx_port], promiscuous = True)
+
+ for profile in self.profiles:
+ print("now testing profile {0}...\n").format(profile)
+
+ p1 = STLProfile.load(profile, port_id = self.tx_port)
+ p2 = STLProfile.load(profile, port_id = self.rx_port)
+
+ if p1.has_flow_stats():
+ print("profile needs RX caps - skipping...")
+ continue
+
+ self.c.add_streams(p1, ports = self.tx_port)
+ self.c.add_streams(p2, ports = self.rx_port)
+
+ self.c.clear_stats()
+
+ self.c.start(ports = [self.tx_port, self.rx_port], mult = "30%")
+ time.sleep(100 / 1000.0)
+
+ if p1.is_pauseable() and p2.is_pauseable():
+ self.c.pause(ports = [self.tx_port, self.rx_port])
+ time.sleep(100 / 1000.0)
+
+ self.c.resume(ports = [self.tx_port, self.rx_port])
+ time.sleep(100 / 1000.0)
+
+ self.c.stop(ports = [self.tx_port, self.rx_port])
+
+ stats = self.c.get_stats()
+
+ assert self.tx_port in stats, '{0} - no stats for TX port'.format(profile)
+ assert self.rx_port in stats, '{0} - no stats for RX port'.format(profile)
+
+ assert stats[self.tx_port]['opackets'] == stats[self.rx_port]['ipackets'], '{0} - number of TX packets differ from RX packets'.format(profile)
+
+ assert stats[self.rx_port]['opackets'] == stats[self.tx_port]['ipackets'], '{0} - number of TX packets differ from RX packets'.format(profile)
+
+ self.c.remove_all_streams(ports = [self.tx_port, self.rx_port])
+
+ except STLError as e:
+ assert False , '{0}'.format(e)
+
+
+ finally:
+ self.c.set_port_attr(ports = [self.tx_port, self.rx_port], promiscuous = False)
diff --git a/scripts/automation/regression/trex_unit_test.py b/scripts/automation/regression/trex_unit_test.py
index fb666382..3b1a25f0 100755
--- a/scripts/automation/regression/trex_unit_test.py
+++ b/scripts/automation/regression/trex_unit_test.py
@@ -36,8 +36,8 @@ import misc_methods
from rednose import RedNose
import termstyle
from trex import CTRexScenario
-from stf.trex_client import *
-from stf.trex_exceptions import *
+from trex_stf_lib.trex_client import *
+from trex_stf_lib.trex_exceptions import *
from trex_stl_lib.api import *
import trex
import socket
@@ -67,10 +67,10 @@ STATEFUL_STOP_COMMAND = './trex_daemon_server stop; sleep 1; ./trex_daemon_serve
STATEFUL_RUN_COMMAND = 'rm /var/log/trex/trex_daemon_server.log; ./trex_daemon_server start; sleep 2; ./trex_daemon_server show'
TREX_FILES = ('_t-rex-64', '_t-rex-64-o', '_t-rex-64-debug', '_t-rex-64-debug-o')
-def trex_remote_command(trex_data, command, background = False, from_scripts = True):
+def trex_remote_command(trex_data, command, background = False, from_scripts = True, timeout = 20):
if from_scripts:
- return misc_methods.run_remote_command(trex_data['trex_name'], ('cd %s; ' % CTRexScenario.scripts_path)+ command, background)
- return misc_methods.run_remote_command(trex_data['trex_name'], command, background)
+ return misc_methods.run_remote_command(trex_data['trex_name'], ('cd %s; ' % CTRexScenario.scripts_path)+ command, background, timeout)
+ return misc_methods.run_remote_command(trex_data['trex_name'], command, background, timeout)
# 1 = running, 0 - not running
def check_trex_running(trex_data):
@@ -183,7 +183,7 @@ class CTRexTestConfiguringPlugin(Plugin):
new_path = '/tmp/trex-scripts'
rsync_template = 'rm -rf /tmp/trex-scripts; mkdir -p %s; rsync -Lc %s /tmp; tar -mxzf /tmp/%s -C %s; mv %s/v*.*/* %s'
rsync_command = rsync_template % (new_path, self.pkg, os.path.basename(self.pkg), new_path, new_path, new_path)
- return_code, stdout, stderr = trex_remote_command(self.configuration.trex, rsync_command, from_scripts = False)
+ return_code, stdout, stderr = trex_remote_command(self.configuration.trex, rsync_command, from_scripts = False, timeout = 300)
if return_code:
print('Failed copying')
sys.exit(-1)
@@ -339,8 +339,9 @@ if __name__ == "__main__":
finally:
save_setup_info()
- if (result == True and not CTRexScenario.is_test_list):
- print(termstyle.green("""
+ if not CTRexScenario.is_test_list:
+ if result == True:
+ print(termstyle.green("""
..::''''::..
.;'' ``;.
:: :: :: ::
@@ -358,8 +359,18 @@ if __name__ == "__main__":
/_/ /_/ |_/___/___(_)
"""))
- sys.exit(0)
- sys.exit(-1)
+ sys.exit(0)
+ else:
+ print(termstyle.red("""
+ /\_/\
+ ( o.o )
+ > ^ <
+
+This cat is sad, test failed.
+ """))
+ sys.exit(-1)
+
+
diff --git a/scripts/automation/trex_control_plane/doc/_templates/layout.html b/scripts/automation/trex_control_plane/doc/_templates/layout.html
new file mode 100644
index 00000000..8c1c709c
--- /dev/null
+++ b/scripts/automation/trex_control_plane/doc/_templates/layout.html
@@ -0,0 +1,17 @@
+{% extends "!layout.html" %}
+
+{% block footer %}
+{{ super() }}
+<script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-75220362-1', 'auto');
+ ga('send', 'pageview');
+
+</script>
+{% endblock %}
+
+
diff --git a/scripts/automation/trex_control_plane/doc/conf.py b/scripts/automation/trex_control_plane/doc/conf.py
index a2641ffc..ec133a1c 100755
--- a/scripts/automation/trex_control_plane/doc/conf.py
+++ b/scripts/automation/trex_control_plane/doc/conf.py
@@ -20,7 +20,7 @@ import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('../stf'))
+sys.path.insert(0, os.path.abspath('../stf/trex_stf_lib'))
sys.path.insert(0, os.path.abspath('../client_utils'))
sys.path.insert(0, os.path.abspath('../examples'))
sys.path.insert(0, os.path.abspath('../common'))
diff --git a/scripts/automation/trex_control_plane/doc_stl/_templates/layout.html b/scripts/automation/trex_control_plane/doc_stl/_templates/layout.html
new file mode 100644
index 00000000..8c1c709c
--- /dev/null
+++ b/scripts/automation/trex_control_plane/doc_stl/_templates/layout.html
@@ -0,0 +1,17 @@
+{% extends "!layout.html" %}
+
+{% block footer %}
+{{ super() }}
+<script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-75220362-1', 'auto');
+ ga('send', 'pageview');
+
+</script>
+{% endblock %}
+
+
diff --git a/scripts/automation/trex_control_plane/stf/examples/stf_example.py b/scripts/automation/trex_control_plane/stf/examples/stf_example.py
new file mode 100755
index 00000000..f6ebffe7
--- /dev/null
+++ b/scripts/automation/trex_control_plane/stf/examples/stf_example.py
@@ -0,0 +1,53 @@
+import argparse
+import stf_path
+from trex_stf_lib.trex_client import CTRexClient
+
+# sample TRex stateless run
+# assuming server daemon is running.
+
+def minimal_stateful_test(server):
+ print('Connecting to %s' % server)
+ trex_client = CTRexClient(server)
+
+ print('Connected, start TRex')
+ trex_client.start_trex(
+ c = 1,
+ m = 700,
+ f = 'cap2/http_simple.yaml',
+ d = 5,
+ l = 1000,
+ trex_development = True,
+ )
+
+ print('Sample until end')
+ result = trex_client.sample_to_run_finish()
+
+ print('Test results:')
+ print(result)
+
+ print('TX by ports:')
+ tx_ptks_dict = result.get_last_value('trex-global.data', 'opackets-*')
+ print(' | '.join(['%s: %s' % (k.split('-')[-1], tx_ptks_dict[k]) for k in sorted(tx_ptks_dict.keys())]))
+
+ print('RX by ports:')
+ rx_ptks_dict = result.get_last_value('trex-global.data', 'ipackets-*')
+ print(' | '.join(['%s: %s' % (k.split('-')[-1], rx_ptks_dict[k]) for k in sorted(rx_ptks_dict.keys())]))
+
+ print('CPU utilization:')
+ print(result.get_value_list('trex-global.data.m_cpu_util'))
+
+ #print('Dump of *latest* result sample, uncomment to see it all')
+ #print(result.get_latest_dump())
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description="Example for TRex Stateful, assuming server daemon is running.")
+ parser.add_argument('-s', '--server',
+ dest='server',
+ help='Remote trex address',
+ default='127.0.0.1',
+ type = str)
+ args = parser.parse_args()
+
+ minimal_stateful_test(args.server)
+
diff --git a/scripts/automation/trex_control_plane/stf/examples/stf_path.py b/scripts/automation/trex_control_plane/stf/examples/stf_path.py
new file mode 100755
index 00000000..bb401148
--- /dev/null
+++ b/scripts/automation/trex_control_plane/stf/examples/stf_path.py
@@ -0,0 +1,4 @@
+import sys
+
+# FIXME to the write path for trex_stf_lib
+sys.path.insert(0, "../")
diff --git a/scripts/automation/trex_control_plane/stf/CCustomLogger.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/CCustomLogger.py
index ecf7d519..ecf7d519 100755
--- a/scripts/automation/trex_control_plane/stf/CCustomLogger.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/CCustomLogger.py
diff --git a/scripts/automation/trex_control_plane/stf/__init__.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/__init__.py
index 5a1da046..5a1da046 100755
--- a/scripts/automation/trex_control_plane/stf/__init__.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/__init__.py
diff --git a/scripts/automation/trex_control_plane/stf/external_packages.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/external_packages.py
index 7353c397..7353c397 100755
--- a/scripts/automation/trex_control_plane/stf/external_packages.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/external_packages.py
diff --git a/scripts/automation/trex_control_plane/stf/general_utils.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/general_utils.py
index d2521f02..d2521f02 100755
--- a/scripts/automation/trex_control_plane/stf/general_utils.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/general_utils.py
diff --git a/scripts/automation/trex_control_plane/stf/outer_packages.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/outer_packages.py
index 5e29f8d6..f8d50ce6 100755
--- a/scripts/automation/trex_control_plane/stf/outer_packages.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/outer_packages.py
@@ -5,8 +5,8 @@ import os
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
-PARENT_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir, 'external_libs'))
-SCRIPTS_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir, os.pardir, os.pardir, 'external_libs'))
+PACKAGE_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir, os.pardir, 'external_libs'))
+SCRIPTS_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir, os.pardir, os.pardir, os.pardir, 'external_libs'))
CLIENT_MODULES = ['enum34-1.0.4',
'jsonrpclib-pelix-0.2.5',
@@ -22,9 +22,9 @@ def import_module_list(ext_libs_path):
raise Exception('Library %s is absent in path %s' % (p, ext_libs_path))
sys.path.insert(1, full_path)
-if os.path.exists(PARENT_PATH):
- import_module_list(PARENT_PATH)
+if os.path.exists(PACKAGE_PATH):
+ import_module_list(PACKAGE_PATH)
elif os.path.exists(SCRIPTS_PATH):
import_module_list(SCRIPTS_PATH)
else:
- raise Exception('Could not find external libs in path: %s' % [PARENT_PATH, SCRIPTS_PATH])
+ raise Exception('Could not find external libs in path: %s' % [PACKAGE_PATH, SCRIPTS_PATH])
diff --git a/scripts/automation/trex_control_plane/stf/text_opts.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/text_opts.py
index 78a0ab1f..78a0ab1f 100755
--- a/scripts/automation/trex_control_plane/stf/text_opts.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/text_opts.py
diff --git a/scripts/automation/trex_control_plane/stf/trex_client.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py
index 919253d1..919253d1 100755
--- a/scripts/automation/trex_control_plane/stf/trex_client.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py
diff --git a/scripts/automation/trex_control_plane/stf/trex_daemon_server.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_daemon_server.py
index 9784d42a..9784d42a 100755
--- a/scripts/automation/trex_control_plane/stf/trex_daemon_server.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_daemon_server.py
diff --git a/scripts/automation/trex_control_plane/stf/trex_exceptions.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_exceptions.py
index 0de38411..0de38411 100755
--- a/scripts/automation/trex_control_plane/stf/trex_exceptions.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_exceptions.py
diff --git a/scripts/automation/trex_control_plane/stf/trex_status.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status.py
index f132720c..f132720c 100644
--- a/scripts/automation/trex_control_plane/stf/trex_status.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status.py
diff --git a/scripts/automation/trex_control_plane/stf/trex_status_e.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status_e.py
index 79a25acc..79a25acc 100755
--- a/scripts/automation/trex_control_plane/stf/trex_status_e.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_status_e.py
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):
diff --git a/scripts/run_functional_tests b/scripts/run_functional_tests
index 6212b40b..9ec1bd39 100755
--- a/scripts/run_functional_tests
+++ b/scripts/run_functional_tests
@@ -1,30 +1,36 @@
#!/bin/bash
-source find_python.sh --python2
-cd automation/regression
-# Python 2
-echo Python2 test
-$PYTHON trex_unit_test.py --functional $@
-if [ $? -eq 0 ]; then
- printf "\n$PYTHON test succeeded\n\n"
-else
- printf "\n*** $PYTHON test failed\n\n"
- exit -1
+if [[ $@ =~ '--python2' || ! $@ =~ '--python3' ]]; then
+ source find_python.sh --python2
+ cd automation/regression
+
+ # Python 2
+ echo Python2 test
+ $PYTHON trex_unit_test.py --functional $@
+ if [ $? -eq 0 ]; then
+ printf "\n$PYTHON test succeeded\n\n"
+ else
+ printf "\n*** $PYTHON test failed\n\n"
+ exit -1
+ fi
+ cd -
fi
-cd -
-source find_python.sh --python3
-cd -
+if [[ $@ =~ '--python3' || ! $@ =~ '--python2' ]]; then
+ source find_python.sh --python3
+ cd automation/regression
-# Python 3
-echo Python3 test
-$PYTHON trex_unit_test.py --functional $@
-if [ $? -eq 0 ]; then
- printf "\n$PYTHON test succeeded\n\n"
-else
- printf "\n*** $PYTHON test failed\n\n"
- exit -1
+ # Python 3
+ echo Python3 test
+ $PYTHON trex_unit_test.py --functional $@
+ if [ $? -eq 0 ]; then
+ printf "\n$PYTHON test succeeded\n\n"
+ else
+ printf "\n*** $PYTHON test failed\n\n"
+ exit -1
+ fi
+ cd -
fi
diff --git a/scripts/stl/flow_stats.py b/scripts/stl/flow_stats.py
index 69e1166c..cbb5ac21 100644
--- a/scripts/stl/flow_stats.py
+++ b/scripts/stl/flow_stats.py
@@ -1,15 +1,17 @@
from trex_stl_lib.api import *
+import os
# stream from pcap file. continues pps 10 in sec
+CP = os.path.join(os.path.dirname(__file__))
class STLS1(object):
def get_streams (self, direction = 0, **kwargs):
- return [STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"), # path relative to pwd
+ return [STLStream(packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_64B_no_crc.pcap")), # path relative to pwd
mode = STLTXCont(pps=1000),
flow_stats = STLFlowStats(pg_id = 7)),
- STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_594B_no_crc.pcap"), # path relative to pwd
+ STLStream(packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_594B_no_crc.pcap")), # path relative to pwd
mode = STLTXCont(pps=5000),
flow_stats = STLFlowStats(pg_id = 12))
]
diff --git a/scripts/stl/udp_1pkt_pcap.py b/scripts/stl/udp_1pkt_pcap.py
index 9fb0e269..2a364810 100644
--- a/scripts/stl/udp_1pkt_pcap.py
+++ b/scripts/stl/udp_1pkt_pcap.py
@@ -1,11 +1,14 @@
from trex_stl_lib.api import *
+import os
# stream from pcap file. continues pps 10 in sec
+CP = os.path.join(os.path.dirname(__file__))
+
class STLS1(object):
def get_streams (self, direction = 0, **kwargs):
- return [STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"), # path relative to pwd
+ return [STLStream(packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_64B_no_crc.pcap")),
mode = STLTXCont(pps=10)) ] #rate continues, could be STLTXSingleBurst,STLTXMultiBurst
diff --git a/scripts/stl/udp_1pkt_simple_burst.py b/scripts/stl/udp_1pkt_simple_burst.py
new file mode 100644
index 00000000..bf485ab0
--- /dev/null
+++ b/scripts/stl/udp_1pkt_simple_burst.py
@@ -0,0 +1,24 @@
+from trex_stl_lib.api import *
+
+class STLS1(object):
+
+ def create_stream (self):
+ return STLStream(
+ packet =
+ STLPktBuilder(
+ pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
+ UDP(dport=12,sport=1025)/(10*'x')
+ ),
+ mode = STLTXSingleBurst(total_pkts = 1))
+
+ def get_streams (self, direction = 0, **kwargs):
+ # create 1 stream
+ return [ self.create_stream() ]
+
+
+# dynamic load - used for trex console or simulator
+def register():
+ return STLS1()
+
+
+
diff --git a/scripts/stl/udp_3pkt_pcap.py b/scripts/stl/udp_3pkt_pcap.py
index fd2c609e..19ff46bc 100644
--- a/scripts/stl/udp_3pkt_pcap.py
+++ b/scripts/stl/udp_3pkt_pcap.py
@@ -1,26 +1,29 @@
from trex_stl_lib.api import *
+import os
# stream from pcap file. continues pps 10 in sec
+CP = os.path.join(os.path.dirname(__file__))
+
class STLS1(object):
def create_stream (self):
return STLProfile( [ STLStream( isg = 10.0, # star in delay
name ='S0',
- packet = STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"),
+ packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_64B_no_crc.pcap")),
mode = STLTXSingleBurst( pps = 10, total_pkts = 10),
next = 'S1'), # point to next stream
STLStream( self_start = False, # stream is disabled enable trow S0
name ='S1',
- packet = STLPktBuilder(pkt ="stl/yaml/udp_594B_no_crc.pcap"),
+ packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_594B_no_crc.pcap")),
mode = STLTXSingleBurst( pps = 10, total_pkts = 20),
next = 'S2' ),
STLStream( self_start = False, # stream is disabled enable trow S0
name ='S2',
- packet = STLPktBuilder(pkt ="stl/yaml/udp_1518B_no_crc.pcap"),
+ packet = STLPktBuilder(pkt = os.path.join(CP, "yaml/udp_1518B_no_crc.pcap")),
mode = STLTXSingleBurst( pps = 10, total_pkts = 30 )
)
]).get_streams()
diff --git a/scripts/stl/yaml/imix_1pkt_vm_minus.yaml b/scripts/stl/yaml/imix_1pkt_vm_minus.yaml
index e83cfdd0..6d5345df 100644
--- a/scripts/stl/yaml/imix_1pkt_vm_minus.yaml
+++ b/scripts/stl/yaml/imix_1pkt_vm_minus.yaml
@@ -18,7 +18,8 @@
"min_value" : 1000,
"name" : "l3_src",
"op" : "inc",
- "size" : 2,
+ "step": 1,
+ "size" : 4,
"type" : "flow_var"
},
{
diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp
index 49654970..20cab376 100644
--- a/src/flow_stat.cpp
+++ b/src/flow_stat.cpp
@@ -642,6 +642,12 @@ int CFlowStatRuleMgr::start_stream(TrexStream * stream) {
m_user_id_map.start_stream(user_id, hw_id);
m_hw_id_map.map(hw_id, user_id);
add_hw_rule(hw_id, m_user_id_map.l4_proto(user_id));
+ // clear hardware counters. Just in case we have garbage from previous iteration
+ rx_per_flow_t rx_counter;
+ tx_per_flow_t tx_counter;
+ for (uint8_t port = 0; port < m_num_ports; port++) {
+ m_api->get_flow_stats(port, &rx_counter, (void *)&tx_counter, hw_id, hw_id, true);
+ }
}
}
@@ -683,8 +689,8 @@ int CFlowStatRuleMgr::stop_stream(TrexStream * stream) {
throw TrexException("Called stop_stream, but no stream was added");
if (stream->m_rx_check.m_hw_id >= MAX_FLOW_STATS) {
- printf("Trying to stop stream with high hw_id %d\n", stream->m_rx_check.m_hw_id);
- throw TrexException("Trying to stop stream which is not started (maybe stop was called twice?)");
+ // We allow stopping while already stopped. Will not hurt us.
+ return 0;
}
stream->m_rx_check.m_hw_id = HW_ID_FREE;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index ea24c33a..40719325 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -590,6 +590,27 @@ TrexRpcCmdStopTraffic::_run(const Json::Value &params, Json::Value &result) {
}
/***************************
+ * remove all hardware filters
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdRemoveRXFilters::_run(const Json::Value &params, Json::Value &result) {
+
+ uint8_t port_id = parse_port(params, result);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
+
+ try {
+ port->remove_rx_filters();
+ } catch (const TrexException &ex) {
+ generate_execute_err(result, ex.what());
+ }
+
+ result["result"] = Json::objectValue;
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
* get all streams
*
**************************/
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index c4b01b85..dbf90fef 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -116,6 +116,7 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 3, false);
TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 4, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveRXFilters, "remove_rx_filters", 1, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdPauseTraffic, "pause_traffic", 1, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdResumeTraffic, "resume_traffic", 1, true);
diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index e1bd3eee..c9b41595 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -61,6 +61,8 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
register_command(new TrexRpcCmdResumeTraffic());
register_command(new TrexRpcCmdUpdateTraffic());
+ register_command(new TrexRpcCmdRemoveRXFilters());
+
register_command(new TrexRpcCmdValidate());
}
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 90589d7a..6a33fcee 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -272,6 +272,22 @@ TrexStatelessPort::stop_traffic(void) {
}
/**
+ * remove all RX filters from port
+ *
+ * @author imarom (28-Mar-16)
+ */
+void
+TrexStatelessPort::remove_rx_filters(void) {
+ /* only valid when IDLE or with streams and not TXing */
+ verify_state(PORT_STATE_STREAMS);
+
+ for (auto entry : m_stream_table) {
+ get_stateless_obj()->m_rx_flow_stat.stop_stream(entry.second);
+ }
+
+}
+
+/**
* when a port stops, perform various actions
*
*/
@@ -287,9 +303,6 @@ TrexStatelessPort::common_port_stop_actions(bool async) {
get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STOPPED, data);
}
- for (auto entry : m_stream_table) {
- get_stateless_obj()->m_rx_flow_stat.stop_stream(entry.second);
- }
}
void
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index 7e1838d4..7aa3bfa8 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -178,6 +178,14 @@ public:
void stop_traffic(void);
/**
+ * remove all RX filters
+ * valid only when port is stopped
+ *
+ * @author imarom (28-Mar-16)
+ */
+ void remove_rx_filters(void);
+
+ /**
* pause traffic
* throws TrexException in case of an error
*/
diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp
index 929ad7fa..42889f0a 100644
--- a/src/stateless/rx/trex_stateless_rx_core.cpp
+++ b/src/stateless/rx/trex_stateless_rx_core.cpp
@@ -55,6 +55,7 @@ void CRxCoreStateless::idle_state_loop() {
int counter = 0;
while (m_state == STATE_IDLE) {
+ flush_rx();
bool had_msg = periodic_check_for_cp_messages();
if (had_msg) {
counter = 0;
@@ -162,6 +163,30 @@ void CRxCoreStateless::try_rx_queues() {
}
}
+// exactly the same as try_rx, without the handle_rx_pkt
+// purpose is to flush rx queues when core is in idle state
+void CRxCoreStateless::flush_rx() {
+ rte_mbuf_t * rx_pkts[64];
+ int i, total_pkts = 0;
+ for (i = 0; i < m_max_ports; i++) {
+ CLatencyManagerPerPort * lp = &m_ports[i];
+ rte_mbuf_t * m;
+ m_cpu_dp_u.start_work();
+ /* try to read 64 packets clean up the queue */
+ uint16_t cnt_p = lp->m_io->rx_burst(rx_pkts, 64);
+ total_pkts += cnt_p;
+ if (cnt_p) {
+ int j;
+ for (j = 0; j < cnt_p; j++) {
+ m = rx_pkts[j];
+ rte_pktmbuf_free(m);
+ }
+ /* commit only if there was work to do ! */
+ m_cpu_dp_u.commit();
+ }/* if work */
+ }// all ports
+}
+
int CRxCoreStateless::try_rx() {
rte_mbuf_t * rx_pkts[64];
int i, total_pkts = 0;
diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h
index 5ab12f4e..81eca38a 100644
--- a/src/stateless/rx/trex_stateless_rx_core.h
+++ b/src/stateless/rx/trex_stateless_rx_core.h
@@ -62,6 +62,7 @@ class CRxCoreStateless {
void idle_state_loop();
void handle_rx_pkt(CLatencyManagerPerPort * lp, rte_mbuf_t * m);
void handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r);
+ void flush_rx();
int try_rx();
void try_rx_queues();
bool is_flow_stat_id(uint16_t id);