summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-11-09 11:20:28 +0200
committerHanoh Haim <hhaim@cisco.com>2015-11-09 11:20:28 +0200
commit82280f7c87fabed60d83643bd9ec2c79cac34668 (patch)
tree62916038bc3650e161c53bc1f9a44df02dca8fe3
parent7c9355cc198ee897de9cd2d60e88a232ce1fa405 (diff)
parentc6d2cb0554ebc39142fb433040a968714a7ec24f (diff)
Merge branch 'rpc_intg1'
-rwxr-xr-xVERSION2
-rwxr-xr-xlinux/ws_main.py59
-rwxr-xr-xlinux_dpdk/ws_main.py11
-rw-r--r--scripts/automation/trex_control_plane/client/trex_async_client.py203
-rwxr-xr-x[-rw-r--r--]scripts/automation/trex_control_plane/client/trex_hltapi.py297
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py557
-rwxr-xr-xscripts/automation/trex_control_plane/client_utils/general_utils.py18
-rwxr-xr-xscripts/automation/trex_control_plane/client_utils/jsonrpc_client.py34
-rwxr-xr-xscripts/automation/trex_control_plane/common/text_opts.py100
-rwxr-xr-xscripts/automation/trex_control_plane/common/trex_streams.py15
-rwxr-xr-xscripts/automation/trex_control_plane/console/parsing_opts.py103
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py685
-rw-r--r--scripts/automation/trex_control_plane/console/trex_status.py447
-rwxr-xr-xscripts/automation/trex_control_plane/examples/stateless_example.py30
-rw-r--r--scripts/cap2/many_client_example.yaml42
-rwxr-xr-xscripts/exp/dns-0-ex.erfbin2080 -> 1872 bytes
-rw-r--r--scripts/exp/dns-0.erfbin2080 -> 1872 bytes
-rwxr-xr-xscripts/exp/dns_e-0-ex.erfbin2080 -> 1872 bytes
-rw-r--r--scripts/exp/dns_e-0.erfbin2080 -> 1872 bytes
-rwxr-xr-xscripts/exp/dns_flip-0-ex.erfbin2080 -> 1872 bytes
-rw-r--r--scripts/exp/dns_flip-0.erfbin2080 -> 1872 bytes
-rwxr-xr-xscripts/exp/dns_ipv6-0-ex.erfbin2560 -> 2304 bytes
-rw-r--r--scripts/exp/dns_ipv6-0.erfbin2560 -> 2304 bytes
-rwxr-xr-xscripts/exp/dns_one_server-0-ex.erfbin4160 -> 3952 bytes
-rw-r--r--scripts/exp/dns_one_server-0.erfbin4160 -> 3952 bytes
-rwxr-xr-xscripts/exp/dns_p-0-ex.erfbin2080 -> 1872 bytes
-rw-r--r--scripts/exp/dns_p-0.erfbin2080 -> 1872 bytes
-rwxr-xr-xscripts/exp/dyn_pyld1-0-ex.erfbin2080 -> 1872 bytes
-rw-r--r--scripts/exp/dyn_pyld1-0.erfbin2080 -> 1872 bytes
-rwxr-xr-xscripts/exp/imix-0-ex.erfbin62872 -> 62784 bytes
-rw-r--r--scripts/exp/imix-0.erfbin62872 -> 62784 bytes
-rwxr-xr-xscripts/exp/imix_v6-0-ex.erfbin65480 -> 65376 bytes
-rw-r--r--scripts/exp/imix_v6-0.erfbin65480 -> 65376 bytes
-rwxr-xr-xscripts/exp/limit_single_pkt-0-ex.erfbin5368 -> 5192 bytes
-rw-r--r--scripts/exp/limit_single_pkt-0.erfbin5368 -> 5192 bytes
-rwxr-xr-xscripts/exp/sfr2-0-ex.erfbin1830944 -> 1731712 bytes
-rw-r--r--scripts/exp/sfr2-0.erfbin1830944 -> 1731712 bytes
-rwxr-xr-xsrc/bp_gtest.cpp27
-rwxr-xr-xsrc/bp_sim.cpp330
-rwxr-xr-xsrc/bp_sim.h191
-rwxr-xr-xsrc/common/Network/Packet/IPHeader.cpp2
-rwxr-xr-xsrc/common/Network/Packet/TCPHeader.cpp2
-rwxr-xr-xsrc/common/c_common.h2
-rw-r--r--src/gtest/rpc_test.cpp9
-rw-r--r--src/gtest/trex_stateless_gtest.cpp6
-rwxr-xr-xsrc/gtest/tuple_gen_test.cpp8
-rw-r--r--src/internal_api/trex_platform_api.h134
-rwxr-xr-xsrc/main.cpp48
-rwxr-xr-xsrc/main_dpdk.cpp670
-rw-r--r--src/mock/trex_platform_api_mock.cpp49
-rw-r--r--src/mock/trex_rpc_server_mock.cpp129
-rwxr-xr-xsrc/msg_manager.cpp13
-rwxr-xr-xsrc/msg_manager.h20
-rwxr-xr-xsrc/nat_check.cpp4
-rwxr-xr-xsrc/nat_check.h10
-rwxr-xr-xsrc/os_time.h20
-rwxr-xr-xsrc/pal/linux/mbuf.h3
-rwxr-xr-xsrc/platform_cfg.cpp10
-rwxr-xr-xsrc/platform_cfg.h15
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp57
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp110
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h9
-rw-r--r--src/rpc-server/trex_rpc_async_server.cpp4
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp6
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp3
-rwxr-xr-xsrc/rx_check.cpp24
-rwxr-xr-xsrc/rx_check.h7
-rwxr-xr-xsrc/rx_check_header.cpp10
-rw-r--r--src/stateless/cp/trex_stateless.cpp162
-rw-r--r--src/stateless/cp/trex_stateless.h76
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp156
-rw-r--r--src/stateless/cp/trex_stateless_port.h84
-rw-r--r--src/stateless/cp/trex_stream.cpp17
-rw-r--r--src/stateless/cp/trex_stream.h17
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp106
-rw-r--r--src/stateless/cp/trex_streams_compiler.h79
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp242
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h125
-rw-r--r--src/stateless/dp/trex_stream_node.h105
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.cpp78
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.h101
-rw-r--r--src/stub/trex_stateless_stub.cpp23
-rwxr-xr-xsrc/time_histogram.cpp6
-rwxr-xr-xsrc/tuple_gen.h3
-rwxr-xr-xsrc/utl_json.cpp4
-rwxr-xr-xsrc/utl_yaml.cpp2
86 files changed, 4214 insertions, 1707 deletions
diff --git a/VERSION b/VERSION
index 8ce21723..a0f6ba44 100755
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-v1.78
+v1.78-intg1
diff --git a/linux/ws_main.py b/linux/ws_main.py
index eac46ac7..d020411a 100755
--- a/linux/ws_main.py
+++ b/linux/ws_main.py
@@ -91,12 +91,20 @@ def configure(conf):
conf.load('g++')
verify_cc_version(conf.env)
+bp_sim_main = SrcGroup(dir='src',
+ src_list=['main.cpp'])
+
+bp_sim_gtest = SrcGroup(dir='src',
+ src_list=[
+ 'bp_gtest.cpp',
+ 'gtest/tuple_gen_test.cpp',
+ 'gtest/nat_test.cpp',
+ 'gtest/trex_stateless_gtest.cpp'
+ ])
main_src = SrcGroup(dir='src',
src_list=[
- 'main.cpp',
'bp_sim.cpp',
- 'bp_gtest.cpp',
'os_time.cpp',
'rx_check.cpp',
'tuple_gen.cpp',
@@ -110,9 +118,6 @@ main_src = SrcGroup(dir='src',
'utl_cpuu.cpp',
'msg_manager.cpp',
- 'gtest/tuple_gen_test.cpp',
- 'gtest/nat_test.cpp',
- 'gtest/trex_stateless_gtest.cpp',
'pal/linux/pal_utl.cpp',
'pal/linux/mbuf.cpp'
@@ -146,7 +151,9 @@ stateless_src = SrcGroup(dir='src/stateless/',
'cp/trex_stream_vm.cpp',
'cp/trex_stateless.cpp',
'cp/trex_stateless_port.cpp',
- 'dp/trex_stateless_dp_core.cpp'
+ 'cp/trex_streams_compiler.cpp',
+ 'dp/trex_stateless_dp_core.cpp',
+ 'messaging/trex_stateless_messaging.cpp',
])
# RPC code
rpc_server_src = SrcGroup(dir='src/rpc-server/',
@@ -168,9 +175,8 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/',
rpc_server_mock_src = SrcGroup(dir='src/mock/',
src_list=[
'trex_rpc_server_mock.cpp',
+ 'trex_platform_api_mock.cpp',
'../gtest/rpc_test.cpp',
- '../pal/linux/mbuf.cpp',
- '../os_time.cpp',
])
# JSON package
@@ -179,12 +185,6 @@ json_src = SrcGroup(dir='external_libs/json',
'jsoncpp.cpp'
])
-rpc_server_mock = SrcGroups([cmn_src,
- rpc_server_src,
- rpc_server_mock_src,
- stateless_src,
- json_src
- ])
yaml_src = SrcGroup(dir='external_libs/yaml-cpp/src/',
src_list=[
@@ -216,11 +216,31 @@ yaml_src = SrcGroup(dir='external_libs/yaml-cpp/src/',
'stream.cpp',
'tag.cpp']);
+
+rpc_server_mock = SrcGroups([
+ main_src,
+ cmn_src,
+ rpc_server_src,
+ rpc_server_mock_src,
+ stateless_src,
+ json_src,
+ yaml_src,
+ net_src,
+ ])
+
+# REMOVE ME - need to decide if stateless is part of bp sim or not
+bp_hack_for_compile = SrcGroup(dir='/src/stub/',
+ src_list=['trex_stateless_stub.cpp'
+ ])
+
bp =SrcGroups([
+ bp_sim_main,
+ bp_sim_gtest,
main_src,
cmn_src ,
net_src ,
yaml_src,
+ bp_hack_for_compile,
]);
@@ -242,6 +262,7 @@ includes_path =''' ../src/pal/linux/
../src/rpc-server/
../src/stateless/cp/
../src/stateless/dp/
+ ../src/stateless/messaging/
../external_libs/json/
../external_libs/zmq/include/
../external_libs/yaml-cpp/include/
@@ -372,13 +393,13 @@ class build_option:
build_types = [
- #build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_32, is_pie = False),
- build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_64, is_pie = False),
- #build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_32, is_pie = False),
- build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False),
+ build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_64, is_pie = False,
+ flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing']),
+ build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False,
+ flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing']),
build_option(name = "mock-rpc-server", use = ['zmq'], src = rpc_server_mock, debug_mode= DEBUG_,platform = PLATFORM_64, is_pie = False,
- flags = ['-DTREX_RPC_MOCK_SERVER', '-Wall', '-Wno-sign-compare', '-Werror'],
+ flags = ['-DTREX_RPC_MOCK_SERVER', '-Wall', '-Werror', '-Wno-sign-compare'],
rpath = ['.']),
]
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py
index 61a9d4f3..c8cbb38a 100755
--- a/linux_dpdk/ws_main.py
+++ b/linux_dpdk/ws_main.py
@@ -158,7 +158,9 @@ stateless_src = SrcGroup(dir='src/stateless/',
'cp/trex_stream_vm.cpp',
'cp/trex_stateless.cpp',
'cp/trex_stateless_port.cpp',
- 'dp/trex_stateless_dp_core.cpp'
+ 'cp/trex_streams_compiler.cpp',
+ 'dp/trex_stateless_dp_core.cpp',
+ 'messaging/trex_stateless_messaging.cpp'
])
# JSON package
json_src = SrcGroup(dir='external_libs/json',
@@ -415,6 +417,7 @@ includes_path =''' ../src/pal/linux_dpdk/
../src/rpc-server/
../src/stateless/cp/
../src/stateless/dp/
+ ../src/stateless/messaging/
../external_libs/yaml-cpp/include/
../external_libs/zmq/include/
@@ -579,6 +582,12 @@ class build_option:
# support c++ 2011
flags += ['-std=c++0x']
+ flags += ['-Wall',
+ '-Werror',
+ '-Wno-literal-suffix',
+ '-Wno-sign-compare',
+ '-Wno-strict-aliasing']
+
return (flags)
def get_c_flags (self):
diff --git a/scripts/automation/trex_control_plane/client/trex_async_client.py b/scripts/automation/trex_control_plane/client/trex_async_client.py
new file mode 100644
index 00000000..72cce5aa
--- /dev/null
+++ b/scripts/automation/trex_control_plane/client/trex_async_client.py
@@ -0,0 +1,203 @@
+#!/router/bin/python
+
+try:
+ # support import for Python 2
+ import outer_packages
+except ImportError:
+ # support import for Python 3
+ import client.outer_packages
+from client_utils.jsonrpc_client import JsonRpcClient, BatchMessage
+
+import json
+import threading
+import time
+import datetime
+import zmq
+import re
+
+from common.trex_stats import *
+from common.trex_streams import *
+
+# basic async stats class
+class TrexAsyncStats(object):
+ def __init__ (self):
+ self.ref_point = None
+ self.current = {}
+ self.last_update_ts = datetime.datetime.now()
+
+ def __format_num (self, size, suffix = ""):
+
+ for unit in ['','K','M','G','T','P']:
+ if abs(size) < 1000.0:
+ return "%3.2f %s%s" % (size, unit, suffix)
+ size /= 1000.0
+
+ return "NaN"
+
+ def update (self, snapshot):
+
+ #update
+ self.last_update_ts = datetime.datetime.now()
+
+ self.current = snapshot
+
+ if self.ref_point == None:
+ self.ref_point = self.current
+
+
+ def get (self, field, format = False, suffix = ""):
+
+ if not field in self.current:
+ return "N/A"
+
+ if not format:
+ return self.current[field]
+ else:
+ return self.__format_num(self.current[field], suffix)
+
+
+ def get_rel (self, field, format = False, suffix = ""):
+ if not field in self.current:
+ return "N/A"
+
+ if not format:
+ return (self.current[field] - self.ref_point[field])
+ else:
+ return self.__format_num(self.current[field] - self.ref_point[field], suffix)
+
+
+ # return true if new data has arrived in the past 2 seconds
+ def is_online (self):
+ delta_ms = (datetime.datetime.now() - self.last_update_ts).total_seconds() * 1000
+ return (delta_ms < 2000)
+
+# describes the general stats provided by TRex
+class TrexAsyncStatsGeneral(TrexAsyncStats):
+ def __init__ (self):
+ super(TrexAsyncStatsGeneral, self).__init__()
+
+
+# per port stats
+class TrexAsyncStatsPort(TrexAsyncStats):
+ def __init__ (self):
+ super(TrexAsyncStatsPort, self).__init__()
+
+ def get_stream_stats (self, stream_id):
+ return None
+
+# stats manager
+class TrexAsyncStatsManager():
+ def __init__ (self):
+
+ self.general_stats = TrexAsyncStatsGeneral()
+ self.port_stats = {}
+
+
+ def get_general_stats (self):
+ return self.general_stats
+
+ def get_port_stats (self, port_id):
+
+ if not str(port_id) in self.port_stats:
+ return None
+
+ return self.port_stats[str(port_id)]
+
+ def update (self, snapshot):
+
+ if snapshot['name'] == 'trex-global':
+ self.__handle_snapshot(snapshot['data'])
+ else:
+ # for now ignore the rest
+ return
+
+ def __handle_snapshot (self, snapshot):
+
+ general_stats = {}
+ port_stats = {}
+
+ # filter the values per port and general
+ for key, value in snapshot.iteritems():
+
+ # match a pattern of ports
+ m = re.search('(.*)\-([0-8])', key)
+ if m:
+
+ port_id = m.group(2)
+ field_name = m.group(1)
+
+ if not port_id in port_stats:
+ port_stats[port_id] = {}
+
+ port_stats[port_id][field_name] = value
+
+ else:
+ # no port match - general stats
+ general_stats[key] = value
+
+ # update the general object with the snapshot
+ self.general_stats.update(general_stats)
+
+ # update all ports
+ for port_id, data in port_stats.iteritems():
+
+ if not port_id in self.port_stats:
+ self.port_stats[port_id] = TrexAsyncStatsPort()
+
+ self.port_stats[port_id].update(data)
+
+
+
+
+
+class CTRexAsyncClient():
+ def __init__ (self, port):
+
+ self.port = port
+
+ self.raw_snapshot = {}
+
+ self.stats = TrexAsyncStatsManager()
+
+
+ self.tr = "tcp://localhost:{0}".format(self.port)
+ print "\nConnecting To ZMQ Publisher At {0}".format(self.tr)
+
+ self.active = True
+ self.t = threading.Thread(target = self._run)
+
+ # kill this thread on exit and don't add it to the join list
+ self.t.setDaemon(True)
+ self.t.start()
+
+
+ def _run (self):
+
+ # Socket to talk to server
+ self.context = zmq.Context()
+ self.socket = self.context.socket(zmq.SUB)
+
+ self.socket.connect(self.tr)
+ self.socket.setsockopt(zmq.SUBSCRIBE, '')
+
+ while self.active:
+ msg = json.loads(self.socket.recv_string())
+
+ key = msg['name']
+ self.raw_snapshot[key] = msg['data']
+
+ self.stats.update(msg)
+
+
+ def get_stats (self):
+ return self.stats
+
+ def get_raw_snapshot (self):
+ #return str(self.stats.global_stats.get('m_total_tx_bytes')) + " / " + str(self.stats.global_stats.get_rel('m_total_tx_bytes'))
+ return self.raw_snapshot
+
+
+ def stop (self):
+ self.active = False
+ self.t.join()
+
diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py
index 46c283f8..92768ca4 100644..100755
--- a/scripts/automation/trex_control_plane/client/trex_hltapi.py
+++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py
@@ -2,16 +2,305 @@
import trex_root_path
from client_utils.packet_builder import CTRexPktBuilder
+from trex_stateless_client import CTRexStatelessClient
+from common.trex_streams import *
+from client_utils.general_utils import id_count_gen
+import dpkt
-print "done!"
class CTRexHltApi(object):
def __init__(self):
- pass
+ self.trex_client = None
+ self.connected = False
+ # self._stream_db = CStreamList()
+ self._port_data = {}
+
+ # ----- session functions ----- #
+
+ def connect(self, device, port_list, username, port=5050, reset=False, break_locks=False):
+ ret_dict = {"status": 0}
+ self.trex_client = CTRexStatelessClient(username, device, port)
+ res_ok, msg = self.trex_client.connect()
+ if not res_ok:
+ self.trex_client = None
+ ret_dict.update({"log": msg})
+ return ret_dict
+ # arrived here, connection successfully created with server
+ # next, try acquiring ports of TRex
+ port_list = self.parse_port_list(port_list)
+ response = self.trex_client.acquire(port_list, force=break_locks)
+ res_ok, log = CTRexHltApi.process_response(port_list, response)
+ if not res_ok:
+ self.trex_client.disconnect()
+ self.trex_client = None
+ ret_dict.update({"log": log})
+ # TODO: should revert taken ports?!
+ return ret_dict
+ # arrived here, all desired ports were successfully acquired
+ print log
+ if reset:
+ # remove all port traffic configuration from TRex
+ response = self.trex_client.remove_all_streams(port_list)
+ res_ok, log = CTRexHltApi.process_response(port_list, response)
+ if not res_ok:
+ self.trex_client.disconnect()
+ self.trex_client = None
+ ret_dict.update({"log": log})
+ return ret_dict
+ print log
+ port_handle = {device: {port: port # since only supporting single TRex at the moment, 1:1 map
+ for port in port_list}
+ }
+ ret_dict.update({"status": 1,
+ "log": None,
+ "port_handle": port_handle,
+ "offline": 0}) # ports are online
+ self.connected = True
+ self._port_data_init(port_list)
+ return ret_dict
+
+ def cleanup_session(self, port_list, maintain_lock=False):
+ ret_dict = {"status": 0}
+ if not maintain_lock:
+ # release taken ports
+ if port_list == "all":
+ port_list = self.trex_client.get_acquired_ports()
+ else:
+ port_list = self.parse_port_list(port_list)
+ response = self.trex_client.release(port_list)
+ res_ok, log = CTRexHltApi.process_response(port_list, response)
+ print log
+ if not res_ok:
+ ret_dict.update({"log": log})
+ return ret_dict
+ ret_dict.update({"status": 1,
+ "log": None})
+ self.trex_client.disconnect()
+ self.trex_client = None
+ self.connected = False
+ return ret_dict
+
+ def interface_config(self, port_handle, mode="config"):
+ ALLOWED_MODES = ["config", "modify", "destroy"]
+ if mode not in ALLOWED_MODES:
+ raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES))
+ # pass this function for now...
+ return {"status": 1, "log": None}
+
+ # ----- traffic functions ----- #
+ def traffic_config(self, mode, port_handle,
+ l2_encap="ethernet_ii", mac_src="00:00:01:00:00:01", mac_dst="00:00:00:00:00:00",
+ l3_protocol="ipv4", ip_src_addr="0.0.0.0", ip_dst_addr="192.0.0.1", l3_length=110,
+ transmit_mode="continuous", rate_pps=100,
+ **kwargs):
+ ALLOWED_MODES = ["create", "modify", "remove", "enable", "disable", "reset"]
+ if mode not in ALLOWED_MODES:
+ raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES))
+ if mode == "create":
+ # create a new stream with desired attributes, starting by creating packet
+ try:
+ packet = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst,
+ l3_protocol, ip_src_addr, ip_dst_addr, l3_length)
+ # set transmission attributes
+ tx_mode = CTxMode(transmit_mode, rate_pps, **kwargs)
+ # set rx_stats
+ rx_stats = CRxStats() # defaults with disabled
+ # join the generated data into stream
+ stream_obj = CStream()
+ stream_obj_params = {"enabled": True,
+ "self_start": True,
+ "next_stream_id": -1,
+ "isg": 0.0,
+ "mode": tx_mode,
+ "rx_stats": rx_stats,
+ "packet": packet} # vm is excluded from this list since CTRexPktBuilder obj is passed
+ stream_obj.load_data(**stream_obj_params)
+ except Exception as e:
+ # some exception happened during the stream creation
+ return {"status": 0, "log": str(e)}
+ # try adding the stream, until free stream_id is found
+ port_data = self._port_data.get(port_handle)
+ id_candidate = None
+ # TODO: change this to better implementation
+ while True:
+ id_candidate = port_data["stream_id_gen"].next()
+ response = self.trex_client.add_stream(stream_id=id_candidate,
+ stream_obj=stream_obj,
+ port_id=port_handle)
+ res_ok, log = CTRexHltApi.process_response(port_handle, response)
+ if res_ok:
+ # found non-taken stream_id on server
+ # save it for modifying needs
+ port_data["streams"].update({id_candidate: stream_obj})
+ break
+ else:
+ # proceed to another iteration to use another id
+ continue
+ return {"status": 1,
+ "stream_id": id_candidate,
+ "log": None}
+ else:
+ raise NotImplementedError("mode '{0}' is not supported yet on TRex".format(mode))
+
+ def traffic_control(self, action, port_handle):
+ ALLOWED_ACTIONS = ["clear_stats", "run", "stop", "sync_run"]
+ if action not in ALLOWED_ACTIONS:
+ raise ValueError("action must be one of the following values: {actions}".format(actions=ALLOWED_ACTIONS))
+ # ret_dict = {"status": 0, "stopped": 1}
+ port_list = self.parse_port_list(port_handle)
+ if action == "run":
+ response = self.trex_client.start_traffic(port_id=port_list)
+ res_ok, log = CTRexHltApi.process_response(port_list, response)
+ if res_ok:
+ return {"status": 1,
+ "stopped": 0,
+ "log": None}
+ elif action == "stop":
+ response = self.trex_client.stop_traffic(port_id=port_list)
+ res_ok, log = CTRexHltApi.process_response(port_list, response)
+ if res_ok:
+ return {"status": 1,
+ "stopped": 1,
+ "log": None}
+ else:
+ raise NotImplementedError("action '{0}' is not supported yet on TRex".format(action))
+
+ # if we arrived here, this means that operation FAILED!
+ return {"status": 0,
+ "log": log}
+
+
+ def traffic_stats(self, port_handle, mode):
+ ALLOWED_MODES = ["aggregate", "streams", "all"]
+ if mode not in ALLOWED_MODES:
+ raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES))
+ # pass this function for now...
+ if mode == "aggregate":
+ # create a new stream with desired attributes, starting by creating packet
+ try:
+ packet = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst,
+ l3_protocol, ip_src_addr, ip_dst_addr, l3_length)
+ # set transmission attributes
+ tx_mode = CTxMode(transmit_mode, rate_pps, **kwargs)
+ # set rx_stats
+ rx_stats = CRxStats() # defaults with disabled
+ # join the generated data into stream
+ stream_obj = CStream()
+ stream_obj_params = {"enabled": True,
+ "self_start": True,
+ "next_stream_id": -1,
+ "isg": 0.0,
+ "mode": tx_mode,
+ "rx_stats": rx_stats,
+ "packet": packet} # vm is excluded from this list since CTRexPktBuilder obj is passed
+ stream_obj.load_data(**stream_obj_params)
+ except Exception as e:
+ # some exception happened during the stream creation
+ return {"status": 0, "log": str(e)}
+ # try adding the stream, until free stream_id is found
+ port_data = self._port_data.get(port_handle)
+ id_candidate = None
+ # TODO: change this to better implementation
+ while True:
+ id_candidate = port_data["stream_id_gen"].next()
+ response = self.trex_client.add_stream(stream_id=id_candidate,
+ stream_obj=stream_obj,
+ port_id=port_handle)
+ res_ok, log = CTRexHltApi.process_response(port_handle, response)
+ if res_ok:
+ # found non-taken stream_id on server
+ # save it for modifying needs
+ port_data["streams"].update({id_candidate: stream_obj})
+ break
+ else:
+ # proceed to another iteration to use another id
+ continue
+ return {"status": 1,
+ "stream_id": id_candidate,
+ "log": None}
+ else:
+ raise NotImplementedError("mode '{0}' is not supported yet on TRex".format(mode))
+
+ def get_aggregate_port_stats(self, port_handle):
+ return self.traffic_stats(port_handle, mode="aggregate")
+
+ def get_stream_stats(self, port_handle):
+ return self.traffic_stats(port_handle, mode="streams")
+
+ # ----- internal functions ----- #
+ def _port_data_init(self, port_list):
+ for port in port_list:
+ self._port_data[port] = {"stream_id_gen": id_count_gen(),
+ "streams": {}}
+
+ @staticmethod
+ def process_response(port_list, response):
+ if isinstance(port_list, list):
+ res_ok, response = response
+ log = CTRexHltApi.join_batch_response(response)
+ else:
+ res_ok = response.success
+ log = str(response)
+ return res_ok, log
+
+ @staticmethod
+ def parse_port_list(port_list):
+ if isinstance(port_list, str):
+ return [int(port)
+ for port in port_list.split()]
+ elif isinstance(port_list, list):
+ return [int(port)
+ for port in port_list]
+ else:
+ return port_list
+
+ @staticmethod
+ def join_batch_response(responses):
+ return "\n".join([str(response)
+ for response in responses])
+
+ @staticmethod
+ def generate_stream(l2_encap, mac_src, mac_dst,
+ l3_protocol, ip_src_addr, ip_dst_addr, l3_length):
+ ALLOWED_L3_PROTOCOL = {"ipv4": dpkt.ethernet.ETH_TYPE_IP,
+ "ipv6": dpkt.ethernet.ETH_TYPE_IP6,
+ "arp": dpkt.ethernet.ETH_TYPE_ARP}
+ ALLOWED_L4_PROTOCOL = {"tcp": dpkt.ip.IP_PROTO_TCP,
+ "udp": dpkt.ip.IP_PROTO_UDP,
+ "icmp": dpkt.ip.IP_PROTO_ICMP,
+ "icmpv6": dpkt.ip.IP_PROTO_ICMP6,
+ "igmp": dpkt.ip.IP_PROTO_IGMP,
+ "rtp": dpkt.ip.IP_PROTO_IRTP,
+ "isis": dpkt.ip.IP_PROTO_ISIS,
+ "ospf": dpkt.ip.IP_PROTO_OSPF}
+
+ pkt_bld = CTRexPktBuilder()
+ if l2_encap == "ethernet_ii":
+ pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet())
+ # set Ethernet layer attributes
+ pkt_bld.set_eth_layer_addr("l2", "src", mac_src)
+ pkt_bld.set_eth_layer_addr("l2", "dst", mac_dst)
+ else:
+ raise NotImplementedError("l2_encap does not support the desired encapsulation '{0}'".format(l2_encap))
+ # set l3 on l2
+ if l3_protocol not in ALLOWED_L3_PROTOCOL:
+ raise ValueError("l3_protocol must be one of the following: {0}".format(ALLOWED_L3_PROTOCOL))
+ pkt_bld.set_layer_attr("l2", "type", ALLOWED_L3_PROTOCOL[l3_protocol])
+
+ # set l3 attributes
+ if l3_protocol == "ipv4":
+ pkt_bld.add_pkt_layer("l3", dpkt.ip.IP())
+ pkt_bld.set_ip_layer_addr("l3", "src", ip_src_addr)
+ pkt_bld.set_ip_layer_addr("l3", "dst", ip_dst_addr)
+ pkt_bld.set_layer_attr("l3", "len", l3_length)
+ else:
+ raise NotImplementedError("l3_protocol '{0}' is not supported by TRex yet.".format(l3_protocol))
+
+ pkt_bld.dump_pkt_to_pcap("stream_test.pcap")
+ return pkt_bld
+
- def config_traffic(self):
- pass
if __name__ == "__main__":
pass
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 334496d1..627c3365 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -10,58 +10,151 @@ from client_utils.jsonrpc_client import JsonRpcClient, BatchMessage
from client_utils.packet_builder import CTRexPktBuilder
import json
from common.trex_stats import *
+from common.trex_streams import *
from collections import namedtuple
+from trex_async_client import CTRexAsyncClient
+
+RpcCmdData = namedtuple('RpcCmdData', ['method', 'params'])
+
+class RpcResponseStatus(namedtuple('RpcResponseStatus', ['success', 'id', 'msg'])):
+ __slots__ = ()
+ def __str__(self):
+ return "{id:^3} - {msg} ({stat})".format(id=self.id,
+ msg=self.msg,
+ stat="success" if self.success else "fail")
+
+# RpcResponseStatus = namedtuple('RpcResponseStatus', ['success', 'id', 'msg'])
class CTRexStatelessClient(object):
"""docstring for CTRexStatelessClient"""
- RpcCmdData = namedtuple('RpcCmdData', ['method', 'params'])
- def __init__(self, username, server="localhost", port=5050, virtual=False):
+ def __init__(self, username, server="localhost", sync_port=5050, async_port = 4500, virtual=False):
super(CTRexStatelessClient, self).__init__()
self.user = username
- self.tx_link = CTRexStatelessClient.CTxLink(server, port, virtual)
+ self.comm_link = CTRexStatelessClient.CCommLink(server, sync_port, virtual)
+ self.verbose = False
self._conn_handler = {}
self._active_ports = set()
self._stats = CTRexStatsManager("port", "stream")
self._system_info = None
+ self._server_version = None
+ self.__err_log = None
+
+ self._async_client = CTRexAsyncClient(async_port)
+
# ----- decorator methods ----- #
+ def acquired(func):
+ def wrapper_f(self, *args, **kwargs):
+ # print func.__name__
+ # print args
+ # print kwargs
+ port_ids = kwargs.get("port_id")
+ if not port_ids:
+ # print "FROM ARGS!"
+ # print args
+ port_ids = args[0]
+ if isinstance(port_ids, int):
+ # make sure port_ids is a list
+ port_ids = [port_ids]
+ bad_ids = set()
+ # print "============="
+ # print port_ids
+ for port_id in port_ids:
+ port_owned = self._conn_handler.get(port_id)
+ if not port_owned:
+ bad_ids.add(port_id)
+ # elif active_and_owned: # stronger condition than just owned, hence gets precedence
+ # if port_owned and port_id in self._active_ports:
+ # continue
+ # else:
+ # bad_ids.add(port_id)
+ else:
+ continue
+ if bad_ids:
+ # Some port IDs are not according to desires status
+ raise ValueError("The requested method ('{0}') cannot be invoked since port IDs {1} are not "
+ "at allowed states".format(func.__name__, list(bad_ids)))
+ else:
+ return func(self, *args, **kwargs)
+ return wrapper_f
+
def force_status(owned=True, active_and_owned=False):
def wrapper(func):
def wrapper_f(self, *args, **kwargs):
+ # print args
+ # print kwargs
port_ids = kwargs.get("port_id")
+ if not port_ids:
+ #print "FROM ARGS!"
+ #print args
+ port_ids = args[0]
if isinstance(port_ids, int):
# make sure port_ids is a list
port_ids = [port_ids]
bad_ids = set()
+ # print "============="
+ # print port_ids
for port_id in port_ids:
- port_owned = self._conn_handler.get(kwargs.get(port_id))
+ port_owned = self._conn_handler.get(port_id)
if owned and not port_owned:
- bad_ids.add(port_ids)
+ bad_ids.add(port_id)
elif active_and_owned: # stronger condition than just owned, hence gets precedence
if port_owned and port_id in self._active_ports:
continue
else:
- bad_ids.add(port_ids)
+ bad_ids.add(port_id)
else:
continue
if bad_ids:
# Some port IDs are not according to desires status
- raise RuntimeError("The requested method ('{0}') cannot be invoked since port IDs {1} are not"
- "at allowed stated".format(func.__name__))
+ raise ValueError("The requested method ('{0}') cannot be invoked since port IDs {1} are not "
+ "at allowed states".format(func.__name__, list(bad_ids)))
else:
- func(self, *args, **kwargs)
+ return func(self, *args, **kwargs)
return wrapper_f
return wrapper
@property
def system_info(self):
if not self._system_info:
- self._system_info = self.get_system_info()
- return self._system_info
+ rc, info = self.get_system_info()
+ if rc:
+ self._system_info = info
+ else:
+ self.__err_log = info
+ return self._system_info if self._system_info else "Unknown"
+
+ @property
+ def server_version(self):
+ if not self._server_version:
+ rc, ver_info = self.get_version()
+ if rc:
+ self._server_version = ver_info
+ else:
+ self.__err_log = ver_info
+ return self._server_version if self._server_version else "Unknown"
+
+ def is_connected(self):
+ return self.comm_link.is_connected
# ----- user-access methods ----- #
+ def connect(self):
+ rc, err = self.comm_link.connect()
+ if not rc:
+ return rc, err
+ return self._init_sync()
+
+ def get_stats_async (self):
+ return self._async_client.get_stats()
+
+ def get_connection_port (self):
+ return self.comm_link.port
+
+ def disconnect(self):
+ return self.comm_link.disconnect()
+
def ping(self):
return self.transmit("ping")
@@ -77,24 +170,45 @@ class CTRexStatelessClient(object):
def get_port_count(self):
return self.system_info.get("port_count")
+ def get_port_ids(self, as_str=False):
+ port_ids = range(self.get_port_count())
+ if as_str:
+ return " ".join(str(p) for p in port_ids)
+ else:
+ return port_ids
+
+ def sync_user(self, sync_streams=False):
+ return self.transmit("sync_user", {"user": self.user, "sync_streams": sync_streams})
+
+ def get_acquired_ports(self):
+ return self._conn_handler.keys()
+
+ def get_active_ports(self):
+ return list(self._active_ports)
+
+ def set_verbose(self, mode):
+ self.comm_link.set_verbose(mode)
+ self.verbose = mode
+
def acquire(self, port_id, force=False):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("acquire", {"port_id": p_id, "user": self.user, "force": force})
+ commands = [RpcCmdData("acquire", {"port_id": p_id, "user": self.user, "force": force})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
- self._process_batch_result(commands, resp_list, self._handle_acquire_response)
+ return self._process_batch_result(commands, resp_list, self._handle_acquire_response)
else:
params = {"port_id": port_id,
"user": self.user,
"force": force}
- command = self.RpcCmdData("acquire", params)
- self._handle_acquire_response(command, self.transmit(command.method, command.params))
- return self._conn_handler.get(port_id)
+ command = RpcCmdData("acquire", params)
+ return self._handle_acquire_response(command,
+ self.transmit(command.method, command.params),
+ self.default_success_test)
@force_status(owned=True)
def release(self, port_id=None):
@@ -103,18 +217,20 @@ class CTRexStatelessClient(object):
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("release", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
+ commands = [RpcCmdData("release", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
- self._process_batch_result(commands, resp_list, self._handle_release_response)
+ return self._process_batch_result(commands, resp_list, self._handle_release_response,
+ success_test=self.ack_success_test)
else:
self._conn_handler.pop(port_id)
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id}
- command = self.RpcCmdData("release", params)
- self._handle_release_response(command, self.transmit(command.method, command.params))
- return
+ command = RpcCmdData("release", params)
+ return self._handle_release_response(command,
+ self.transmit(command.method, command.params),
+ self.ack_success_test)
@force_status(owned=True)
def add_stream(self, stream_id, stream_obj, port_id=None):
@@ -128,6 +244,27 @@ class CTRexStatelessClient(object):
return self.transmit("add_stream", params)
@force_status(owned=True)
+ def add_stream_pack(self, port_id=None, *stream_packs):
+ if not self._is_ports_valid(port_id):
+ raise ValueError("Provided illegal port id input")
+
+ # since almost every run contains more than one transaction with server, handle all as batch mode
+ port_ids = set(port_id) # convert to set to avoid duplications
+ commands = []
+ for stream_pack in stream_packs:
+ commands.extend([RpcCmdData("add_stream", {"port_id": p_id,
+ "handler": self._conn_handler.get(p_id),
+ "stream_id": stream_pack.stream_id,
+ "stream": stream_pack.stream}
+ )
+ for p_id in port_ids]
+ )
+ res_ok, resp_list = self.transmit_batch(commands)
+ if res_ok:
+ return self._process_batch_result(commands, resp_list, self._handle_add_stream_response,
+ success_test=self.ack_success_test)
+
+ @force_status(owned=True)
def remove_stream(self, stream_id, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
@@ -136,7 +273,39 @@ class CTRexStatelessClient(object):
"stream_id": stream_id}
return self.transmit("remove_stream", params)
- @force_status(owned=True, active_and_owned=True)
+ @force_status(owned=True)
+ def remove_all_streams(self, port_id=None):
+ if not self._is_ports_valid(port_id):
+ raise ValueError("Provided illegal port id input")
+ if isinstance(port_id, list) or isinstance(port_id, set):
+ # handle as batch mode
+ port_ids = set(port_id) # convert to set to avoid duplications
+ commands = [RpcCmdData("remove_all_streams", {"port_id": p_id, "handler": self._conn_handler.get(p_id)})
+ for p_id in port_ids]
+ rc, resp_list = self.transmit_batch(commands)
+ if rc:
+ return self._process_batch_result(commands, resp_list, self._handle_remove_streams_response,
+ success_test=self.ack_success_test)
+ else:
+ params = {"port_id": port_id,
+ "handler": self._conn_handler.get(port_id)}
+ command = RpcCmdData("remove_all_streams", params)
+ return self._handle_remove_streams_response(command,
+ self.transmit(command.method, command.params),
+ self.ack_success_test)
+ pass
+
+
+ @force_status(owned=True)#, active_and_owned=True)
+ def get_all_streams(self, port_id, get_pkt = False):
+ if not self._is_ports_valid(port_id):
+ raise ValueError("Provided illegal port id input")
+ params = {"handler": self._conn_handler.get(port_id),
+ "port_id": port_id,
+ "get_pkt": get_pkt}
+ return self.transmit("get_all_streams", params)
+
+ @force_status(owned=True)#, active_and_owned=True)
def get_stream_id_list(self, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
@@ -145,32 +314,38 @@ class CTRexStatelessClient(object):
return self.transmit("get_stream_list", params)
@force_status(owned=True, active_and_owned=True)
- def get_stream(self, stream_id, port_id=None):
+ def get_stream(self, stream_id, port_id, get_pkt = False):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id,
- "stream_id": stream_id}
+ "stream_id": stream_id,
+ "get_pkt": get_pkt}
return self.transmit("get_stream_list", params)
- @force_status(owned=True)
- def start_traffic(self, port_id=None):
+ @acquired
+ def start_traffic(self, multiplier, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("start_traffic", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
+ commands = [RpcCmdData("start_traffic", {"handler": self._conn_handler.get(p_id),
+ "port_id": p_id,
+ "mul": multiplier})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
- self._process_batch_result(commands, resp_list, self._handle_start_traffic_response)
+ return self._process_batch_result(commands, resp_list, self._handle_start_traffic_response,
+ success_test=self.ack_success_test)
else:
params = {"handler": self._conn_handler.get(port_id),
- "port_id": port_id}
- command = self.RpcCmdData("start_traffic", params)
- self._handle_start_traffic_response(command, self.transmit(command.method, command.params))
- return
+ "port_id": port_id,
+ "mul": multiplier}
+ command = RpcCmdData("start_traffic", params)
+ return self._handle_start_traffic_response(command,
+ self.transmit(command.method, command.params),
+ self.ack_success_test)
@force_status(owned=False, active_and_owned=True)
def stop_traffic(self, port_id=None):
@@ -179,22 +354,24 @@ class CTRexStatelessClient(object):
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("stop_traffic", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
+ commands = [RpcCmdData("stop_traffic", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
- self._process_batch_result(commands, resp_list, self._handle_stop_traffic_response)
+ return self._process_batch_result(commands, resp_list, self._handle_stop_traffic_response,
+ success_test=self.ack_success_test)
else:
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id}
- command = self.RpcCmdData("stop_traffic", params)
- self._handle_start_traffic_response(command, self.transmit(command.method, command.params))
- return
+ command = RpcCmdData("stop_traffic", params)
+ return self._handle_start_traffic_response(command,
+ self.transmit(command.method, command.params),
+ self.ack_success_test)
- def get_global_stats(self):
- command = self.RpcCmdData("get_global_stats", {})
- return self._handle_get_global_stats_response(command, self.transmit(command.method, command.params))
- # return self.transmit("get_global_stats")
+# def get_global_stats(self):
+# command = RpcCmdData("get_global_stats", {})
+# return self._handle_get_global_stats_response(command, self.transmit(command.method, command.params))
+# # return self.transmit("get_global_stats")
@force_status(owned=True, active_and_owned=True)
def get_port_stats(self, port_id=None):
@@ -203,7 +380,7 @@ class CTRexStatelessClient(object):
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("get_port_stats", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
+ commands = [RpcCmdData("get_port_stats", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
@@ -211,7 +388,7 @@ class CTRexStatelessClient(object):
else:
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id}
- command = self.RpcCmdData("get_port_stats", params)
+ command = RpcCmdData("get_port_stats", params)
return self._handle_get_port_stats_response(command, self.transmit(command.method, command.params))
@force_status(owned=True, active_and_owned=True)
@@ -221,7 +398,7 @@ class CTRexStatelessClient(object):
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [self.RpcCmdData("get_stream_stats", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
+ commands = [RpcCmdData("get_stream_stats", {"handler": self._conn_handler.get(p_id), "port_id": p_id})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
@@ -229,15 +406,36 @@ class CTRexStatelessClient(object):
else:
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id}
- command = self.RpcCmdData("get_stream_stats", params)
+ command = RpcCmdData("get_stream_stats", params)
return self._handle_get_stream_stats_response(command, self.transmit(command.method, command.params))
# ----- internal methods ----- #
+ def _init_sync(self):
+ # get server version and system info
+ err = False
+ if self.server_version == "Unknown" or self.system_info == "Unknown":
+ self.disconnect()
+ return False, self.__err_log
+ # sync with previous session
+ res_ok, port_info = self.sync_user()
+ if not res_ok:
+ self.disconnect()
+ return False, port_info
+ else:
+ # handle sync data
+ for port in port_info:
+ self._conn_handler[port.get("port_id")] = port.get("handler")
+ if port.get("state") == "transmitting":
+ # port is active
+ self._active_ports.add(port.get("port_id"))
+ return True, ""
+
+
def transmit(self, method_name, params={}):
- return self.tx_link.transmit(method_name, params)
+ return self.comm_link.transmit(method_name, params)
def transmit_batch(self, batch_list):
- return self.tx_link.transmit_batch(batch_list)
+ return self.comm_link.transmit_batch(batch_list)
@staticmethod
def _object_decoder(obj_type, obj_data):
@@ -258,36 +456,86 @@ class CTRexStatelessClient(object):
else:
return False
+ @staticmethod
+ def ack_success_test(result_obj):
+ if result_obj.success and result_obj.data == "ACK":
+ return True
+ else:
+ return False
+
+
# ----- handler internal methods ----- #
- def _handle_acquire_response(self, request, response):
- if response.success:
- self._conn_handler[request.get("port_id")] = response.data
+ def _handle_general_response(self, request, response, msg, success_test=None):
+ port_id = request.params.get("port_id")
+ if not success_test:
+ success_test = self.default_success_test
+ if success_test(response):
+ self._conn_handler[port_id] = response.data
+ return RpcResponseStatus(True, port_id, msg)
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
- def _handle_release_response(self, request, response):
- if response.success:
- del self._conn_handler[request.get("port_id")]
- def _handle_start_traffic_response(self, request, response):
- if response.success:
- self._active_ports.add(request.get("port_id"))
+ def _handle_acquire_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ if success_test(response):
+ self._conn_handler[port_id] = response.data
+ return RpcResponseStatus(True, port_id, "Acquired")
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
- def _handle_stop_traffic_response(self, request, response):
- if response.success:
- self._active_ports.remove(request.get("port_id"))
+ def _handle_add_stream_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ stream_id = request.params.get("stream_id")
+ if success_test(response):
+ return RpcResponseStatus(True, port_id, "Stream {0} added".format(stream_id))
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
+
+ def _handle_remove_streams_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ if success_test(response):
+ return RpcResponseStatus(True, port_id, "Removed")
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
- def _handle_get_global_stats_response(self, request, response):
+ def _handle_release_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ if success_test(response):
+ del self._conn_handler[port_id]
+ return RpcResponseStatus(True, port_id, "Released")
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
+
+ def _handle_start_traffic_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ if success_test(response):
+ self._active_ports.add(port_id)
+ return RpcResponseStatus(True, port_id, "Traffic started")
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
+
+ def _handle_stop_traffic_response(self, request, response, success_test):
+ port_id = request.params.get("port_id")
+ if success_test(response):
+ self._active_ports.remove(port_id)
+ return RpcResponseStatus(True, port_id, "Traffic stopped")
+ else:
+ return RpcResponseStatus(False, port_id, response.data)
+
+ def _handle_get_global_stats_response(self, request, response, success_test):
if response.success:
return CGlobalStats(**response.success)
else:
return False
- def _handle_get_port_stats_response(self, request, response):
+ def _handle_get_port_stats_response(self, request, response, success_test):
if response.success:
return CPortStats(**response.success)
else:
return False
- def _handle_get_stream_stats_response(self, request, response):
+ def _handle_get_stream_stats_response(self, request, response, success_test):
if response.success:
return CStreamStats(**response.success)
else:
@@ -298,32 +546,58 @@ class CTRexStatelessClient(object):
# check each item of the sequence
return all([self._is_ports_valid(port)
for port in port_id])
- elif (isinstance(port_id, int)) and (port_id > 0) and (port_id <= self.get_port_count()):
+ elif (isinstance(port_id, int)) and (port_id >= 0) and (port_id <= self.get_port_count()):
return True
else:
return False
def _process_batch_result(self, req_list, resp_list, handler_func=None, success_test=default_success_test):
+ res_ok = True
+ responses = []
+ if isinstance(success_test, staticmethod):
+ success_test = success_test.__func__
for i, response in enumerate(resp_list):
- # testing each result with success test so that a conclusion report could be deployed in future.
- if success_test(response):
- # run handler method with its params
- handler_func(req_list[i], response)
- else:
- continue # TODO: mark in this case somehow the bad result
+ # run handler method with its params
+ processed_response = handler_func(req_list[i], response, success_test)
+ responses.append(processed_response)
+ if not processed_response.success:
+ res_ok = False
+ # else:
+ # res_ok = False # TODO: mark in this case somehow the bad result
+ # print res_ok
+ # print responses
+ return res_ok, responses
# ------ private classes ------ #
- class CTxLink(object):
+ class CCommLink(object):
"""describes the connectivity of the stateless client method"""
def __init__(self, server="localhost", port=5050, virtual=False):
- super(CTRexStatelessClient.CTxLink, self).__init__()
+ super(CTRexStatelessClient.CCommLink, self).__init__()
self.virtual = virtual
self.server = server
self.port = port
+ self.verbose = False
self.rpc_link = JsonRpcClient(self.server, self.port)
+
+ @property
+ def is_connected(self):
+ if not self.virtual:
+ return self.rpc_link.connected
+ else:
+ return True
+
+ 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()
+
+ def disconnect(self):
if not self.virtual:
- self.rpc_link.connect()
+ return self.rpc_link.disconnect()
def transmit(self, method_name, params={}):
if self.virtual:
@@ -352,144 +626,5 @@ class CTRexStatelessClient(object):
port=self.port)
-class CStream(object):
- """docstring for CStream"""
- DEFAULTS = {"rx_stats": CRxStats,
- "mode": CTxMode,
- "isg": 5.0,
- "next_stream": -1,
- "self_start": True,
- "enabled": True}
-
- def __init__(self, **kwargs):
- super(CStream, self).__init__()
- for k, v in kwargs.items():
- setattr(self, k, v)
- # set default values to unset attributes, according to DEFAULTS dict
- set_keys = set(kwargs.keys())
- keys_to_set = [x
- for x in self.DEFAULTS
- if x not in set_keys]
- for key in keys_to_set:
- default = self.DEFAULTS.get(key)
- if type(default) == type:
- setattr(self, key, default())
- else:
- setattr(self, key, default)
-
- @property
- def packet(self):
- return self._packet
-
- @packet.setter
- def packet(self, packet_obj):
- assert isinstance(packet_obj, CTRexPktBuilder)
- self._packet = packet_obj
-
- @property
- def enabled(self):
- return self._enabled
-
- @enabled.setter
- def enabled(self, bool_value):
- self._enabled = bool(bool_value)
-
- @property
- def self_start(self):
- return self._self_start
-
- @self_start.setter
- def self_start(self, bool_value):
- self._self_start = bool(bool_value)
-
- @property
- def next_stream(self):
- return self._next_stream
-
- @next_stream.setter
- def next_stream(self, value):
- self._next_stream = int(value)
-
- def dump(self):
- pass
- return {"enabled": self.enabled,
- "self_start": self.self_start,
- "isg": self.isg,
- "next_stream": self.next_stream,
- "packet": self.packet.dump_pkt(),
- "mode": self.mode.dump(),
- "vm": self.packet.get_vm_data(),
- "rx_stats": self.rx_stats.dump()}
-
-class CRxStats(object):
-
- def __init__(self, enabled=False, seq_enabled=False, latency_enabled=False):
- self._rx_dict = {"enabled": enabled,
- "seq_enabled": seq_enabled,
- "latency_enabled": latency_enabled}
-
- @property
- def enabled(self):
- return self._rx_dict.get("enabled")
-
- @enabled.setter
- def enabled(self, bool_value):
- self._rx_dict['enabled'] = bool(bool_value)
-
- @property
- def seq_enabled(self):
- return self._rx_dict.get("seq_enabled")
-
- @seq_enabled.setter
- def seq_enabled(self, bool_value):
- self._rx_dict['seq_enabled'] = bool(bool_value)
-
- @property
- def latency_enabled(self):
- return self._rx_dict.get("latency_enabled")
-
- @latency_enabled.setter
- def latency_enabled(self, bool_value):
- self._rx_dict['latency_enabled'] = bool(bool_value)
-
- def dump(self):
- return {k: v
- for k, v in self._rx_dict.items()
- if v
- }
-
-
-class CTxMode(object):
- """docstring for CTxMode"""
- def __init__(self, tx_mode, pps):
- super(CTxMode, self).__init__()
- if tx_mode not in ["continuous", "single_burst", "multi_burst"]:
- raise ValueError("Unknown TX mode ('{0}')has been initialized.".format(tx_mode))
- self._tx_mode = tx_mode
- self._fields = {'pps': float(pps)}
- if tx_mode == "single_burst":
- self._fields['total_pkts'] = 0
- elif tx_mode == "multi_burst":
- self._fields['pkts_per_burst'] = 0
- self._fields['ibg'] = 0.0
- self._fields['count'] = 0
- else:
- pass
-
- def set_tx_mode_attr(self, attr, val):
- if attr in self._fields:
- self._fields[attr] = type(self._fields.get(attr))(val)
- else:
- raise ValueError("The provided attribute ('{0}') is not a legal attribute in selected TX mode ('{1}')".
- format(attr, self._tx_mode))
-
- def dump(self):
- dump = {"type": self._tx_mode}
- dump.update({k: v
- for k, v in self._fields.items()
- })
- return dump
-
-
if __name__ == "__main__":
pass
diff --git a/scripts/automation/trex_control_plane/client_utils/general_utils.py b/scripts/automation/trex_control_plane/client_utils/general_utils.py
index 5488b9dd..69ad14b2 100755
--- a/scripts/automation/trex_control_plane/client_utils/general_utils.py
+++ b/scripts/automation/trex_control_plane/client_utils/general_utils.py
@@ -24,7 +24,7 @@ def user_input():
def get_current_user():
if pwd:
- return pwd.getpwuid( os.geteuid() ).pw_name
+ return pwd.getpwuid(os.geteuid()).pw_name
else:
return getpass.getuser()
@@ -75,6 +75,22 @@ def random_id_gen(length=8):
return_id += random.choice(id_chars)
yield return_id
+def id_count_gen():
+ """
+ A generator for creating an increasing id for objects, starting from 0
+
+ :parameters:
+ None
+
+ :return:
+ an id (unsigned int) with each next() request.
+ """
+ return_id = 0
+ while True:
+ yield return_id
+ return_id += 1
+
+
if __name__ == "__main__":
pass
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 ed14e6f8..58491aba 100755
--- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
@@ -6,6 +6,9 @@ import json
import general_utils
import re
from time import sleep
+from collections import namedtuple
+
+CmdResponse = namedtuple('CmdResponse', ['success', 'data'])
class bcolors:
BLUE = '\033[94m'
@@ -23,12 +26,12 @@ class BatchMessage(object):
self.rpc_client = rpc_client
self.batch_list = []
- def add (self, method_name, params = {}):
+ def add (self, method_name, params={}):
id, msg = self.rpc_client.create_jsonrpc_v2(method_name, params, encode = False)
self.batch_list.append(msg)
- def invoke (self, block = False):
+ def invoke(self, block = False):
if not self.rpc_client.connected:
return False, "Not connected to server"
@@ -36,9 +39,9 @@ class BatchMessage(object):
rc, resp_list = self.rpc_client.send_raw_msg(msg, block = False)
if len(self.batch_list) == 1:
- return True, [(rc, resp_list)]
+ return CmdResponse(True, [CmdResponse(rc, resp_list)])
else:
- return rc, resp_list
+ return CmdResponse(rc, resp_list)
# JSON RPC v2.0 client
@@ -47,7 +50,7 @@ class JsonRpcClient(object):
def __init__ (self, default_server, default_port):
self.verbose = False
self.connected = False
-
+
# default values
self.port = default_port
self.server = default_server
@@ -73,7 +76,7 @@ class JsonRpcClient(object):
# float
pretty_str = re.sub(r'([ ]*:[ ]+)(\-?[1-9][0-9]*\.[0-9]+)',r'\1{0}\2{1}'.format(bcolors.MAGENTA, bcolors.ENDC), pretty_str)
# strings
-
+
pretty_str = re.sub(r'([ ]*:[ ]+)("[^"]*")',r'\1{0}\2{1}'.format(bcolors.RED, bcolors.ENDC), pretty_str)
pretty_str = re.sub(r"('[^']*')", r'{0}\1{1}'.format(bcolors.MAGENTA, bcolors.RED), pretty_str)
except :
@@ -115,7 +118,7 @@ class JsonRpcClient(object):
return self.send_raw_msg(msg, block)
-
+
# low level send of string message
def send_raw_msg (self, msg, block = False):
self.verbose_msg("Sending Request To Server:\n\n" + self.pretty_json(msg) + "\n")
@@ -127,7 +130,7 @@ class JsonRpcClient(object):
self.socket.send(msg, flags = zmq.NOBLOCK)
except zmq.error.ZMQError as e:
self.disconnect()
- return False, "Failed To Get Send Message"
+ return CmdResponse(False, "Failed To Get Send Message")
got_response = False
@@ -145,7 +148,7 @@ class JsonRpcClient(object):
if not got_response:
self.disconnect()
- return False, "Failed To Get Server Response"
+ return CmdResponse(False, "Failed To Get Server Response")
self.verbose_msg("Server Response:\n\n" + self.pretty_json(response) + "\n")
@@ -159,13 +162,13 @@ class JsonRpcClient(object):
for single_response in response_json:
rc, msg = self.process_single_response(single_response)
- rc_list.append( (rc, msg) )
+ rc_list.append( CmdResponse(rc, msg) )
- return True, rc_list
+ return CmdResponse(True, rc_list)
else:
rc, msg = self.process_single_response(response_json)
- return rc, msg
+ return CmdResponse(rc, msg)
def process_single_response (self, response_json):
@@ -182,7 +185,7 @@ class JsonRpcClient(object):
# if no error there should be a result
if ("result" not in response_json):
- return False, "Malfromed Response ({0})".format(str(response))
+ return False, "Malformed Response ({0})".format(str(response))
return True, response_json["result"]
@@ -200,7 +203,7 @@ class JsonRpcClient(object):
else:
return False, "Not connected to server"
- def connect(self, server = None, port = None):
+ def connect(self, server=None, port=None):
if self.connected:
self.disconnect()
@@ -511,3 +514,6 @@ class TrexStatelessClient(JsonRpcClient):
return True, resp_list
# return self.invoke_rpc_method('add_stream', params = params)
+
+if __name__ == "__main__":
+ pass \ No newline at end of file
diff --git a/scripts/automation/trex_control_plane/common/text_opts.py b/scripts/automation/trex_control_plane/common/text_opts.py
new file mode 100755
index 00000000..06c2c056
--- /dev/null
+++ b/scripts/automation/trex_control_plane/common/text_opts.py
@@ -0,0 +1,100 @@
+import json
+import re
+
+TEXT_CODES = {'bold': {'start': '\x1b[1m',
+ 'end': '\x1b[22m'},
+ 'cyan': {'start': '\x1b[36m',
+ 'end': '\x1b[39m'},
+ 'blue': {'start': '\x1b[34m',
+ 'end': '\x1b[39m'},
+ 'red': {'start': '\x1b[31m',
+ 'end': '\x1b[39m'},
+ 'magenta': {'start': '\x1b[35m',
+ 'end': '\x1b[39m'},
+ 'green': {'start': '\x1b[32m',
+ 'end': '\x1b[39m'},
+ 'yellow': {'start': '\x1b[33m',
+ 'end': '\x1b[39m'},
+ 'underline': {'start': '\x1b[4m',
+ 'end': '\x1b[24m'}}
+
+
+def bold(text):
+ return text_attribute(text, 'bold')
+
+
+def cyan(text):
+ return text_attribute(text, 'cyan')
+
+
+def blue(text):
+ return text_attribute(text, 'blue')
+
+
+def red(text):
+ return text_attribute(text, 'red')
+
+
+def magenta(text):
+ return text_attribute(text, 'magenta')
+
+
+def green(text):
+ return text_attribute(text, 'green')
+
+def yellow(text):
+ return text_attribute(text, 'yellow')
+
+def underline(text):
+ return text_attribute(text, 'underline')
+
+
+def text_attribute(text, attribute):
+ return "{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'],
+ txt=text,
+ stop=TEXT_CODES[attribute]['end'])
+
+
+FUNC_DICT = {'blue': blue,
+ 'bold': bold,
+ 'green': green,
+ 'yellow': yellow,
+ 'cyan': cyan,
+ 'magenta': magenta,
+ 'underline': underline,
+ 'red': red}
+
+
+def format_text(text, *args):
+ return_string = text
+ for i in args:
+ func = FUNC_DICT.get(i)
+ if func:
+ return_string = func(return_string)
+ return return_string
+
+# pretty print for JSON
+def pretty_json (json_str, use_colors = True):
+ pretty_str = json.dumps(json.loads(json_str), indent = 4, separators=(',', ': '), sort_keys = True)
+
+ if not use_colors:
+ return pretty_str
+
+ try:
+ # int numbers
+ pretty_str = re.sub(r'([ ]*:[ ]+)(\-?[1-9][0-9]*[^.])',r'\1{0}'.format(blue(r'\2')), pretty_str)
+ # float
+ pretty_str = re.sub(r'([ ]*:[ ]+)(\-?[1-9][0-9]*\.[0-9]+)',r'\1{0}'.format(magenta(r'\2')), pretty_str)
+ # # strings
+ #
+ pretty_str = re.sub(r'([ ]*:[ ]+)("[^"]*")',r'\1{0}'.format(red(r'\2')), pretty_str)
+ pretty_str = re.sub(r"('[^']*')", r'{0}\1{1}'.format(TEXT_CODES['magenta']['start'],
+ TEXT_CODES['red']['start']), pretty_str)
+ except :
+ pass
+
+ return pretty_str
+
+
+if __name__ == "__main__":
+ pass
diff --git a/scripts/automation/trex_control_plane/common/trex_streams.py b/scripts/automation/trex_control_plane/common/trex_streams.py
index 783f2769..bb4c72ca 100755
--- a/scripts/automation/trex_control_plane/common/trex_streams.py
+++ b/scripts/automation/trex_control_plane/common/trex_streams.py
@@ -23,7 +23,7 @@ class CStreamList(object):
if name in self.streams_list:
raise NameError("A stream with this name already exists on this list.")
self.streams_list[name]=stream_obj
- return
+ return name
def remove_stream(self, name):
popped = self.streams_list.pop(name)
@@ -48,6 +48,7 @@ class CStreamList(object):
self.streams_list.clear()
streams_data = load_yaml_to_obj(file_path)
assert isinstance(streams_data, list)
+ new_streams_data = []
for stream in streams_data:
stream_name = stream.get("name")
raw_stream = stream.get("stream")
@@ -58,10 +59,11 @@ class CStreamList(object):
new_stream_data = self.yaml_loader.validate_yaml(raw_stream,
"stream",
multiplier= multiplier)
+ new_streams_data.append(new_stream_data)
new_stream_obj = CStream()
new_stream_obj.load_data(**new_stream_data)
self.append_stream(stream_name, new_stream_obj)
- return new_stream_data
+ return new_streams_data
def compile_streams(self):
# first, assign an id to each stream
@@ -156,7 +158,6 @@ class CStream(object):
"""docstring for CStream"""
FIELDS = ["enabled", "self_start", "next_stream_id", "isg", "mode", "rx_stats", "packet", "vm"]
- # COMPILE_FIELDS = ["enabled", "self_start", "next_stream_id", "isg", "mode", "rx_stats", "packet", "vm"]
def __init__(self):
self.is_loaded = False
@@ -183,6 +184,7 @@ class CStream(object):
if isinstance(kwargs[k], CTRexPktBuilder):
if "vm" not in kwargs:
self.load_packet_obj(kwargs[k])
+ break # vm field check is skipped
else:
raise ValueError("When providing packet object with a CTRexPktBuilder, vm parameter "
"should not be supplied")
@@ -226,8 +228,7 @@ class CStream(object):
return
- def dump(self, compilation=False):
- # fields = CStream.COMPILE_FIELDS if compilation else CStream.FIELDS
+ def dump(self):
if self.is_loaded:
dump = {}
for key in CStream.FIELDS:
@@ -239,10 +240,6 @@ class CStream(object):
else:
raise RuntimeError("CStream object isn't loaded with data. Use 'load_data' method.")
- def dump_compiled(self):
- return self.dump(compilation=True)
-
-
if __name__ == "__main__":
pass
diff --git a/scripts/automation/trex_control_plane/console/parsing_opts.py b/scripts/automation/trex_control_plane/console/parsing_opts.py
new file mode 100755
index 00000000..c94a7461
--- /dev/null
+++ b/scripts/automation/trex_control_plane/console/parsing_opts.py
@@ -0,0 +1,103 @@
+import argparse
+from collections import namedtuple
+import sys
+
+ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options'])
+ArgumentGroup = namedtuple('ArgumentGroup', ['type', 'args', 'options'])
+
+
+# list of available parsing options
+MULTIPLIER = 1
+PORT_LIST = 2
+ALL_PORTS = 3
+PORT_LIST_WITH_ALL = 4
+FILE_PATH = 5
+FILE_FROM_DB = 6
+STREAM_FROM_PATH_OR_FILE = 7
+
+# list of ArgumentGroup types
+MUTEX = 1
+
+
+
+
+OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
+ {'help': "Set multiplier for stream", 'dest': "mult", 'type': float}),
+ PORT_LIST: ArgumentPack(['--port'],
+ {"nargs": '+',
+ # "action": "store_"
+ 'help': "A list of ports on which to apply the command",
+ 'default': []}),
+ ALL_PORTS: ArgumentPack(['-a'],
+ {"action": "store_true",
+ "dest": "all",
+ 'help': "Set this flag to apply the command on all available ports"}),
+
+ FILE_PATH: ArgumentPack(['-f'],
+ {'help': "File path to YAML file that describes a stream pack"}),
+ FILE_FROM_DB: ArgumentPack(['--db'],
+ {'help': "A stream pack which already loaded into console cache."}),
+ # advanced options
+ PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST,
+ ALL_PORTS],
+ {'required': True}),
+ STREAM_FROM_PATH_OR_FILE: ArgumentGroup(MUTEX, [FILE_PATH,
+ FILE_FROM_DB],
+ {'required': True})
+ }
+
+
+class CCmdArgParser(argparse.ArgumentParser):
+
+ def __init__(self, *args, **kwargs):
+ super(CCmdArgParser, self).__init__(*args, **kwargs)
+ pass
+
+ # def error(self, message):
+ # try:
+ # super(CCmdArgParser, self).error(message) # this will trigger system exit!
+ # except SystemExit:
+ # return -1
+ #
+ # # self.print_usage(sys.stderr)
+ # # print ('%s: error: %s\n') % (self.prog, message)
+ # # self.print_help()
+ # return
+
+ def exit(self, status=0, message=None):
+ try:
+ super(CCmdArgParser, self).exit(status, message) # this will trigger system exit!
+ except SystemExit:
+ return -1
+ return
+
+def gen_parser(op_name, description, *args):
+ parser = CCmdArgParser(prog=op_name, conflict_handler='resolve',
+ # add_help=False,
+ description=description)
+ for param in args:
+ try:
+ argument = OPTIONS_DB[param]
+ if isinstance(argument, ArgumentGroup):
+ if argument.type == MUTEX:
+ # handle as mutually exclusive group
+ group = parser.add_mutually_exclusive_group(**argument.options)
+ for sub_argument in argument.args:
+ group.add_argument(*OPTIONS_DB[sub_argument].name_or_flags,
+ **OPTIONS_DB[sub_argument].options)
+ else:
+ # ignore invalid objects
+ continue
+ elif isinstance(argument, ArgumentPack):
+ parser.add_argument(*argument.name_or_flags,
+ **argument.options)
+ else:
+ # ignore invalid objects
+ continue
+ except KeyError as e:
+ cause = e.args[0]
+ raise KeyError("The attribute '{0}' is missing as a field of the {1} option.\n".format(cause, param))
+ return parser
+
+if __name__ == "__main__":
+ pass \ No newline at end of file
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index a9ac040b..a2c738ab 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -17,6 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
+
import cmd
import json
import ast
@@ -28,18 +29,20 @@ import sys
import tty, termios
import trex_root_path
from common.trex_streams import *
-
-
-from client_utils.jsonrpc_client import TrexStatelessClient
+from client.trex_stateless_client import CTRexStatelessClient
+from common.text_opts import *
+from client_utils.general_utils import user_input, get_current_user
+import parsing_opts
import trex_status
from collections import namedtuple
+__version__ = "1.0"
+
LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
-#
-def readch (choices = []):
-
+def readch(choices=[]):
+
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
@@ -55,22 +58,49 @@ def readch (choices = []):
return None
-class YesNoMenu(object):
+class ConfirmMenu(object):
def __init__ (self, caption):
- self.caption = caption
+ self.caption = "{cap} [confirm] : ".format(cap=caption)
- def show (self):
- print "{0}".format(self.caption)
- sys.stdout.write("[Y/y/N/n] : ")
- ch = readch(choices = ['y', 'Y', 'n', 'N'])
- if ch == None:
- return None
-
- print "\n"
- if ch == 'y' or ch == 'Y':
- return True
+ def show(self):
+ sys.stdout.write(self.caption)
+ input = user_input()
+ if input:
+ return False
else:
+ # user hit Enter
+ return True
+
+
+class CStreamsDB(object):
+
+ def __init__(self):
+ self.stream_packs = {}
+
+ def load_streams(self, name, LoadedStreamList_obj):
+ if name in self.stream_packs:
return False
+ else:
+ self.stream_packs[name] = LoadedStreamList_obj
+ return True
+
+ def remove_stream_packs(self, *names):
+ removed_streams = []
+ for name in names:
+ removed = self.stream_packs.pop(name)
+ if removed:
+ removed_streams.append(name)
+ return removed_streams
+
+ def clear(self):
+ self.stream_packs.clear()
+
+ def get_loaded_streams_names(self):
+ return self.stream_packs.keys()
+
+ def get_stream_pack(self, name):
+ return self.stream_packs.get(name)
+
# multi level cmd menu
class CmdMenu(object):
@@ -119,31 +149,33 @@ class AddStreamMenu(CmdMenu):
self.add_menu('Please select ISG', ['d', 'e', 'f'])
# main console object
-class TrexConsole(cmd.Cmd):
+class TRexConsole(cmd.Cmd):
"""Trex Console"""
-
- def __init__(self, rpc_client):
+
+ def __init__(self, stateless_client, verbose):
cmd.Cmd.__init__(self)
- self.rpc_client = rpc_client
+ self.stateless_client = stateless_client
self.do_connect("")
- self.intro = "\n-=TRex Console V1.0=-\n"
- self.intro += "\nType 'help' or '?' for supported actions\n"
+ self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__)
+ self.intro += "\nType 'help' or '?' for supported actions\n"
self.verbose = False
self.postcmd(False, "")
self.user_streams = {}
-
+ self.streams_db = CStreamsDB()
+
# a cool hack - i stole this function and added space
def completenames(self, text, *ignored):
dotext = 'do_'+text
return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)]
+
# set verbose on / off
def do_verbose (self, line):
'''Shows or set verbose mode\n'''
@@ -152,40 +184,41 @@ class TrexConsole(cmd.Cmd):
elif line == "on":
self.verbose = True
- self.rpc_client.set_verbose(True)
- print "\nverbose set to on\n"
+ self.stateless_client.set_verbose(True)
+ print green("\nverbose set to on\n")
elif line == "off":
self.verbose = False
- self.rpc_client.set_verbose(False)
- print "\nverbose set to off\n"
+ self.stateless_client.set_verbose(False)
+ print green("\nverbose set to off\n")
else:
- print "\nplease specify 'on' or 'off'\n"
+ print magenta("\nplease specify 'on' or 'off'\n")
# query the server for registered commands
def do_query_server(self, line):
'''query the RPC server for supported remote commands\n'''
- rc, msg = self.rpc_client.query_rpc_server()
- if not rc:
- print "\n*** " + msg + "\n"
+ res_ok, msg = self.stateless_client.get_supported_cmds()
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
return
-
- print "\nRPC server supports the following commands: \n\n"
+ print "\nRPC server supports the following commands:\n"
for func in msg:
if func:
print func
- print "\n"
+ print ''
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return
def do_ping (self, line):
'''Pings the RPC server\n'''
print "\n-> Pinging RPC server"
- rc, msg = self.rpc_client.ping_rpc_server()
- if rc:
- print "[SUCCESS]\n"
+ res_ok, msg = self.stateless_client.ping()
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
else:
print "\n*** " + msg + "\n"
return
@@ -195,13 +228,21 @@ class TrexConsole(cmd.Cmd):
self.do_acquire(line, True)
+ def complete_force_acquire(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
+
+ def extract_port_ids_from_line(self, line):
+ return {int(x) for x in line.split()}
+
+ def extract_port_ids_from_list(self, port_list):
+ return {int(x) for x in port_list}
+
def parse_ports_from_line (self, line):
port_list = set()
-
if line:
for port_id in line.split(' '):
- if (not port_id.isdigit()) or (int(port_id) < 0) or (int(port_id) >= self.rpc_client.get_port_count()):
- print "Please provide a list of ports seperated by spaces between 0 and {0}".format(self.rpc_client.get_port_count() - 1)
+ if (not port_id.isdigit()) or (int(port_id) < 0) or (int(port_id) >= self.stateless_client.get_port_count()):
+ print "Please provide a list of ports separated by spaces between 0 and {0}".format(self.stateless_client.get_port_count() - 1)
return None
port_list.add(int(port_id))
@@ -209,106 +250,122 @@ class TrexConsole(cmd.Cmd):
port_list = list(port_list)
else:
- port_list = [i for i in xrange(0, self.rpc_client.get_port_count())]
+ port_list = [i for i in xrange(0, self.stateless_client.get_port_count())]
return port_list
- def do_acquire (self, line, force = False):
+
+ def do_acquire(self, line, force=False):
'''Acquire ports\n'''
# make sure that the user wants to acquire all
- if line == "":
- ask = YesNoMenu('Do you want to acquire all ports ? ')
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports")
+ return
+
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to acquire all ports ? ')
rc = ask.show()
if rc == False:
+ print yellow("[ABORTED]\n")
return
-
- port_list = self.parse_ports_from_line(line)
- if not port_list:
- return
-
- print "\nTrying to acquire ports: " + (" ".join(str(x) for x in port_list)) + "\n"
-
- rc, resp_list = self.rpc_client.take_ownership(port_list, force)
-
- if not rc:
- print "\n*** " + resp_list + "\n"
- return
-
- for i, rc in enumerate(resp_list):
- if rc[0]:
- print "Port {0} - Acquired".format(port_list[i])
else:
- print "Port {0} - ".format(port_list[i]) + rc[1]
-
- print "\n"
-
- def do_release (self, line):
- '''Release ports\n'''
-
- if line:
- port_list = self.parse_ports_from_line(line)
+ port_list = self.stateless_client.get_port_ids()
else:
- port_list = self.rpc_client.get_owned_ports()
-
- if not port_list:
- return
-
- rc, resp_list = self.rpc_client.release_ports(port_list)
-
-
- print "\n"
-
- for i, rc in enumerate(resp_list):
- if rc[0]:
- print "Port {0} - Released".format(port_list[i])
+ port_list = self.extract_port_ids_from_line(line)
+
+ # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
+ try:
+ res_ok, log = self.stateless_client.acquire(port_list, force)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+
+ def port_auto_complete(self, text, line, begidx, endidx, acquired=True, active=False):
+ if acquired:
+ if not active:
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_acquired_ports())
+ if x.startswith(text)]
else:
- print "Port {0} - Failed to release port, probably not owned by you or port is under traffic"
-
- print "\n"
-
- def do_get_port_stats (self, line):
- '''Get ports stats\n'''
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_active_ports())
+ if x.startswith(text)]
+ else:
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_port_ids())
+ if x.startswith(text)]
+ ret_list.append("all")
+ return ret_list
- port_list = self.parse_ports_from_line(line)
- if not port_list:
- return
- rc, resp_list = self.rpc_client.get_port_stats(port_list)
+ def complete_acquire(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
- if not rc:
- print "\n*** " + resp_list + "\n"
- return
+ def do_release (self, line):
+ '''Release ports\n'''
- for i, rc in enumerate(resp_list):
- if rc[0]:
- print "\nPort {0} stats:\n{1}\n".format(port_list[i], self.rpc_client.pretty_json(json.dumps(rc[1])))
+ # if line:
+ # port_list = self.parse_ports_from_line(line)
+ # else:
+ # port_list = self.stateless_client.get_owned_ports()
+ args = line.split()
+ if len(args) < 1:
+ print "Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports"
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
else:
- print "\nPort {0} - ".format(i) + rc[1] + "\n"
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
- print "\n"
+ try:
+ res_ok, log = self.stateless_client.release(port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ def complete_release(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx)
def do_connect (self, line):
'''Connects to the server\n'''
if line == "":
- rc, msg = self.rpc_client.connect()
+ res_ok, msg = self.stateless_client.connect()
else:
sp = line.split()
if (len(sp) != 2):
print "\n[usage] connect [server] [port] or without parameters\n"
return
- rc, msg = self.rpc_client.connect(sp[0], sp[1])
+ res_ok, msg = self.stateless_client.connect(sp[0], sp[1])
- if rc:
- print "[SUCCESS]\n"
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
else:
print "\n*** " + msg + "\n"
+ print format_text("[FAILED]\n", 'red', 'bold')
return
- self.supported_rpc = self.rpc_client.get_supported_cmds()
+ self.supported_rpc = self.stateless_client.get_supported_cmds().data
def do_rpc (self, line):
'''Launches a RPC on the server\n'''
@@ -341,22 +398,28 @@ class TrexConsole(cmd.Cmd):
print "Example: rpc test_add {'x': 12, 'y': 17}\n"
return
- rc, msg = self.rpc_client.invoke_rpc_method(method, params)
- if rc:
- print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n"
+ res_ok, msg = self.stateless_client.transmit(method, params)
+ if res_ok:
+ print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n"
else:
print "\n*** " + msg + "\n"
#print "Please try 'reconnect' to reconnect to server"
def complete_rpc (self, text, line, begidx, endidx):
- return [x for x in self.supported_rpc if x.startswith(text)]
+ return [x
+ for x in self.supported_rpc
+ if x.startswith(text)]
def do_status (self, line):
'''Shows a graphical console\n'''
+ if not self.stateless_client.is_connected():
+ print "Not connected to server\n"
+ return
+
self.do_verbose('off')
- trex_status.show_trex_status(self.rpc_client)
+ trex_status.show_trex_status(self.stateless_client)
def do_quit(self, line):
'''Exit the client\n'''
@@ -364,22 +427,22 @@ class TrexConsole(cmd.Cmd):
def do_disconnect (self, line):
'''Disconnect from the server\n'''
- if not self.rpc_client.is_connected():
+ if not self.stateless_client.is_connected():
print "Not connected to server\n"
return
- rc, msg = self.rpc_client.disconnect()
- if rc:
- print "[SUCCESS]\n"
+ res_ok, msg = self.stateless_client.disconnect()
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
else:
print msg + "\n"
def do_whoami (self, line):
'''Prints console user name\n'''
- print "\n" + self.rpc_client.whoami() + "\n"
-
+ print "\n" + self.stateless_client.user + "\n"
+
def postcmd(self, stop, line):
- if self.rpc_client.is_connected():
+ if self.stateless_client.is_connected():
self.prompt = "TRex > "
else:
self.supported_rpc = None
@@ -390,47 +453,47 @@ class TrexConsole(cmd.Cmd):
def default(self, line):
print "'{0}' is an unrecognized command. type 'help' or '?' for a list\n".format(line)
- def do_help (self, line):
- '''Shows This Help Screen\n'''
- if line:
- try:
- func = getattr(self, 'help_' + line)
- except AttributeError:
- try:
- doc = getattr(self, 'do_' + line).__doc__
- if doc:
- self.stdout.write("%s\n"%str(doc))
- return
- except AttributeError:
- pass
- self.stdout.write("%s\n"%str(self.nohelp % (line,)))
- return
- func()
- return
-
- print "\nSupported Console Commands:"
- print "----------------------------\n"
-
- cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
- for cmd in cmds:
- if cmd == "EOF":
- continue
-
- try:
- doc = getattr(self, 'do_' + cmd).__doc__
- if doc:
- help = str(doc)
- else:
- help = "*** Undocumented Function ***\n"
- except AttributeError:
- help = "*** Undocumented Function ***\n"
-
- print "{:<30} {:<30}".format(cmd + " - ", help)
-
- def do_load_stream_list(self, line):
+ # def do_help (self, line):
+ # '''Shows This Help Screen\n'''
+ # if line:
+ # try:
+ # func = getattr(self, 'help_' + line)
+ # except AttributeError:
+ # try:
+ # doc = getattr(self, 'do_' + line).__doc__
+ # if doc:
+ # self.stdout.write("%s\n"%str(doc))
+ # return
+ # except AttributeError:
+ # pass
+ # self.stdout.write("%s\n"%str(self.nohelp % (line,)))
+ # return
+ # func()
+ # return
+ #
+ # print "\nSupported Console Commands:"
+ # print "----------------------------\n"
+ #
+ # cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
+ # for cmd in cmds:
+ # if cmd == "EOF":
+ # continue
+ #
+ # try:
+ # doc = getattr(self, 'do_' + cmd).__doc__
+ # if doc:
+ # help = str(doc)
+ # else:
+ # help = "*** Undocumented Function ***\n"
+ # except AttributeError:
+ # help = "*** Undocumented Function ***\n"
+ #
+ # print "{:<30} {:<30}".format(cmd + " - ", help)
+
+ def do_stream_db_add(self, line):
'''Loads a YAML stream list serialization into user console \n'''
args = line.split()
- if args >= 2:
+ if len(args) >= 2:
name = args[0]
yaml_path = args[1]
try:
@@ -439,23 +502,24 @@ class TrexConsole(cmd.Cmd):
multiplier = 1
stream_list = CStreamList()
loaded_obj = stream_list.load_yaml(yaml_path, multiplier)
- # print self.rpc_client.pretty_json(json.dumps(loaded_obj))
- if name in self.user_streams:
- print "Picked name already exist. Please pick another name."
- else:
- try:
- compiled_streams = stream_list.compile_streams()
- self.user_streams[name] = LoadedStreamList(loaded_obj,
- [StreamPack(v.stream_id, v.stream.dump_compiled())
- for k, v in compiled_streams.items()])
-
- print "Stream '{0}' loaded successfully".format(name)
- except Exception as e:
- raise
+ # print self.stateless_client.pretty_json(json.dumps(loaded_obj))
+ try:
+ compiled_streams = stream_list.compile_streams()
+ res_ok = self.streams_db.load_streams(name, LoadedStreamList(loaded_obj,
+ [StreamPack(v.stream_id, v.stream.dump())
+ for k, v in compiled_streams.items()]))
+ if res_ok:
+ print green("Stream pack '{0}' loaded and added successfully\n".format(name))
+ else:
+ print magenta("Picked name already exist. Please pick another name.\n")
+ except Exception as e:
+ print "adding new stream failed due to the following error:\n", str(e)
+ print format_text("[FAILED]\n", 'red', 'bold')
+
return
else:
- print "please provide load name and YAML path, separated by space.\n" \
- "Optionally, you may provide a third argument to specify multiplier."
+ print magenta("please provide load name and YAML path, separated by space.\n"
+ "Optionally, you may provide a third argument to specify multiplier.\n")
@staticmethod
def tree_autocomplete(text):
@@ -470,92 +534,271 @@ class TrexConsole(cmd.Cmd):
if x.startswith(start_string)]
- def complete_load_stream_list(self, text, line, begidx, endidx):
+ def complete_stream_db_add(self, text, line, begidx, endidx):
arg_num = len(line.split()) - 1
if arg_num == 2:
- return TrexConsole.tree_autocomplete(line.split()[-1])
+ return TRexConsole.tree_autocomplete(line.split()[-1])
else:
return [text]
- def do_show_stream_list(self, line):
+ def do_stream_db_show(self, line):
'''Shows the loaded stream list named [name] \n'''
args = line.split()
if args:
list_name = args[0]
try:
- stream = self.user_streams[list_name]
+ stream = self.streams_db.get_stream_pack(list_name)#user_streams[list_name]
if len(args) >= 2 and args[1] == "full":
- print self.rpc_client.pretty_json(json.dumps(stream.compiled))
+ print pretty_json(json.dumps(stream.compiled))
else:
- print self.rpc_client.pretty_json(json.dumps(stream.loaded))
+ print pretty_json(json.dumps(stream.loaded))
except KeyError as e:
print "Unknown stream list name provided"
else:
- print "\nAvailable stream lists:\n{0}".format(', '.join([x
- for x in self.user_streams.keys()]))
+ print "Available stream packs:\n{0}".format(', '.join(sorted(self.streams_db.get_loaded_streams_names())))
- def complete_show_stream_list(self, text, line, begidx, endidx):
+ def complete_stream_db_show(self, text, line, begidx, endidx):
return [x
- for x in self.user_streams.keys()
+ for x in self.streams_db.get_loaded_streams_names()
if x.startswith(text)]
+ def do_stream_db_remove(self, line):
+ '''Removes a single loaded stream packs from loaded stream pack repository\n'''
+ args = line.split()
+ if args:
+ removed_streams = self.streams_db.remove_stream_packs(*args)
+ if removed_streams:
+ print green("The following stream packs were removed:")
+ print bold(", ".join(sorted(removed_streams)))
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ else:
+ print red("No streams were removed. Make sure to provide valid stream pack names.")
+ else:
+ print magenta("Please provide stream pack name(s), separated with spaces.")
+
+ def do_stream_db_clear(self, line):
+ '''Clears all loaded stream packs from loaded stream pack repository\n'''
+ self.streams_db.clear()
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+
+
+ def complete_stream_db_remove(self, text, line, begidx, endidx):
+ return [x
+ for x in self.streams_db.get_loaded_streams_names()
+ if x.startswith(text)]
+
+
def do_attach(self, line):
+ '''Assign loaded stream pack into specified ports on TRex\n'''
args = line.split()
- if len(args) >= 1:
+ if len(args) >= 2:
+ stream_pack_name = args[0]
+ stream_list = self.streams_db.get_stream_pack(stream_pack_name) #user_streams[args[0]]
+ if not stream_list:
+ print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ if args[1] == "all":
+ ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(' '.join(args[1:]))
+ owned = set(self.stateless_client.get_acquired_ports())
try:
- stream_list = self.user_streams[args[0]]
- port_list = self.parse_ports_from_line(' '.join(args[1:]))
- owned = set(self.rpc_client.get_owned_ports())
if set(port_list).issubset(owned):
- rc, resp_list = self.rpc_client.add_stream(port_list, stream_list.compiled)
- if not rc:
- print "\n*** " + resp_list + "\n"
+ res_ok, log = self.stateless_client.add_stream_pack(port_list, *stream_list.compiled)
+ # res_ok, msg = self.stateless_client.add_stream(port_list, stream_list.compiled)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return
else:
- print "Not all desired ports are aquired.\n" \
+ print "Not all desired ports are acquired.\n" \
"Acquired ports are: {acq}\n" \
"Requested ports: {req}\n" \
"Missing ports: {miss}".format(acq=list(owned),
req=port_list,
miss=list(set(port_list).difference(owned)))
- except KeyError as e:
- cause = e.args[0]
- print "Provided stream list name '{0}' doesn't exists.".format(cause)
+ print format_text("[FAILED]\n", 'red', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ else:
+ print magenta("Please provide list name and ports to attach to, "
+ "or specify 'all' to attach all owned ports.\n")
+
+ def complete_attach(self, text, line, begidx, endidx):
+ arg_num = len(line.split()) - 1
+ if arg_num == 1:
+ # return optional streams packs
+ if line.endswith(" "):
+ return self.port_auto_complete(text, line, begidx, endidx)
+ return [x
+ for x in self.streams_db.get_loaded_streams_names()
+ if x.startswith(text)]
+ elif arg_num >= 2:
+ # return optional ports to attach to
+ return self.port_auto_complete(text, line, begidx, endidx)
else:
- print "Please provide list name and ports to attach to, or leave empty to attach to all ports."
+ return [text]
+ def prompt_response(self, response_obj):
+ resp_list = response_obj if isinstance(response_obj, list) else [response_obj]
+ def format_return_status(return_status):
+ if return_status:
+ return green("OK")
+ else:
+ return red("FAIL")
+ for response in resp_list:
+ response_str = "{id:^3} - {msg} ({stat})".format(id=response.id,
+ msg=response.msg,
+ stat=format_return_status(response.success))
+ print response_str
+ return
+ def do_remove_all_streams(self, line):
+ '''Acquire ports\n'''
+ # make sure that the user wants to acquire all
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, "
+ "or specify 'all' to remove from all acquired ports")
+ return
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to remove all stream packs from all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+
+ # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
+ try:
+ res_ok, log = self.stateless_client.remove_all_streams(port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ def complete_remove_all_streams(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx)
+ def do_start_traffic(self, line):
+ '''Start pre-submitted traffic in specified ports on TRex\n'''
+ # make sure that the user wants to acquire all
+ # parser = parsing_opts.gen_parser("start_traffic", self.do_start_traffic.__doc__,
+ # parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.MULTIPLIER)
+ # opts = parser.parse_args(line.split())
+ #
+ # print opts
+ # return
+ # # return
+ # # if not opts.port_list:
+ # # print magenta("Please provide a list of ports separated by spaces, "
+ # # "or specify 'all' to start traffic on all acquired ports")
+ # # return
+ #
+ # if "all" in opts.port_list:
+ # ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
+ # rc = ask.show()
+ # if rc == False:
+ # print yellow("[ABORTED]\n")
+ # return
+ # else:
+ # port_list = self.stateless_client.get_acquired_ports()
+ # else:
+ # try:
+ # port_list = self.extract_port_ids_from_list(opts.port_list)
+ # except ValueError as e:
+ # print magenta(e)
+ # return
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, "
+ "or specify 'all' to start traffic on all acquired ports")
+ return
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+ try:
+ res_ok, log = self.stateless_client.start_traffic(1.0, port_id=port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ def complete_start_traffic(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx)
+ def help_start_traffic(self):
+ self.do_start_traffic("-h")
- # adds a very simple stream
- def do_add_simple_stream (self, line):
- if line == "":
- add_stream = AddStreamMenu()
- add_stream.show()
+ def do_stop_traffic(self, line):
+ '''Stop active traffic in specified ports on TRex\n'''
+ # make sure that the user wants to acquire all
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, "
+ "or specify 'all' to stop traffic on all acquired ports")
return
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_active_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
- params = line.split()
- port_id = int(params[0])
- stream_id = int(params[1])
+ try:
+ res_ok, log = self.stateless_client.stop_traffic(port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
- packet = [0xFF,0xFF,0xFF]
- rc, msg = self.rpc_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet)
- if rc:
- print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n"
- else:
- print "\n*** " + msg + "\n"
+ def complete_stop_traffic(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, active=True)
# aliasing
do_exit = do_EOF = do_q = do_quit
-def setParserOptions ():
+def setParserOptions():
parser = argparse.ArgumentParser(prog="trex_console.py")
parser.add_argument("-s", "--server", help = "TRex Server [default is localhost]",
@@ -566,22 +809,30 @@ def setParserOptions ():
default = 5050,
type = int)
- parser.add_argument("-u", "--user", help = "User Name [default is random generated]\n",
- default = 'user_' + ''.join(random.choice(string.digits) for _ in range(5)),
+ parser.add_argument("-z", "--pub", help = "TRex Async Publisher Port [default is 4500]\n",
+ default = 4500,
+ type = int)
+
+ parser.add_argument("-u", "--user", help = "User Name [default is currently logged in user]\n",
+ default = get_current_user(),
type = str)
+ parser.add_argument("--verbose", dest="verbose",
+ action="store_true", help="Switch ON verbose option. Default is: OFF.",
+ default = False)
+
return parser
-def main ():
+def main():
parser = setParserOptions()
- options = parser.parse_args(sys.argv[1:])
+ options = parser.parse_args()
- # RPC client
- rpc_client = TrexStatelessClient(options.server, options.port, options.user)
+ # Stateless client connection
+ stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub)
# console
try:
- console = TrexConsole(rpc_client)
+ console = TRexConsole(stateless_client, options.verbose)
console.cmdloop()
except KeyboardInterrupt as e:
print "\n\n*** Caught Ctrl + C... Exiting...\n\n"
diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py
index 2c5a648f..2b97d7d3 100644
--- a/scripts/automation/trex_control_plane/console/trex_status.py
+++ b/scripts/automation/trex_control_plane/console/trex_status.py
@@ -11,22 +11,27 @@ import datetime
g_curses_active = False
+################### utils #################
+
# simple percetange show
def percentage (a, total):
x = int ((float(a) / total) * 100)
return str(x) + "%"
-# simple float to human readable
-def float_to_human_readable (size, suffix = "bps"):
- for unit in ['','K','M','G']:
- if abs(size) < 1024.0:
- return "%3.1f %s%s" % (size, unit, suffix)
- size /= 1024.0
- return "NaN"
+################### panels #################
# panel object
class TrexStatusPanel(object):
- def __init__ (self, h, l, y, x, headline):
+ def __init__ (self, h, l, y, x, headline, status_obj):
+
+ self.status_obj = status_obj
+
+ self.log = status_obj.log
+ self.stateless_client = status_obj.stateless_client
+
+ self.stats = status_obj.stats
+ self.general_stats = status_obj.general_stats
+
self.h = h
self.l = l
self.y = y
@@ -53,64 +58,26 @@ class TrexStatusPanel(object):
return self.win
-# total stats (ports + global)
-class Stats():
- def __init__ (self, rpc_client, port_list, interval = 100):
-
- self.rpc_client = rpc_client
-
- self.port_list = port_list
- self.port_stats = {}
-
- self.interval = interval
- self.delay_count = 0
-
- def get_port_stats (self, port_id):
- if self.port_stats.get(port_id):
- return self.port_stats[port_id]
- else:
- return None
-
- def query_sync (self):
- self.delay_count += 1
- if self.delay_count < self.interval:
- return
-
- self.delay_count = 0
-
- # query global stats
-
- # query port stats
-
- rc, resp_list = self.rpc_client.get_port_stats(self.port_list)
- if not rc:
- return
-
- for i, rc in enumerate(resp_list):
- if rc[0]:
- self.port_stats[self.port_list[i]] = rc[1]
-
-
# various kinds of panels
# Server Info Panel
class ServerInfoPanel(TrexStatusPanel):
def __init__ (self, h, l, y, x, status_obj):
- super(ServerInfoPanel, self).__init__(h, l, y ,x ,"Server Info:")
-
- self.status_obj = status_obj
+ super(ServerInfoPanel, self).__init__(h, l, y ,x ,"Server Info:", status_obj)
def draw (self):
- if self.status_obj.server_version == None:
+ if not self.status_obj.server_version :
+ return
+
+ if not self.status_obj.server_sys_info:
return
- self.clear()
- connection_details = self.status_obj.rpc_client.get_connection_details()
+ self.clear()
- self.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.status_obj.server_sys_info["hostname"] + ":" + str(connection_details['port'])))
+ self.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.status_obj.server_sys_info["hostname"] + ":" + str(self.stateless_client.get_connection_port())))
self.getwin().addstr(4, 2, "{:<30} {:30}".format("Version:", self.status_obj.server_version["version"]))
self.getwin().addstr(5, 2, "{:<30} {:30}".format("Build:",
self.status_obj.server_version["build_date"] + " @ " +
@@ -123,7 +90,7 @@ class ServerInfoPanel(TrexStatusPanel):
self.getwin().addstr(9, 2, "{:<30} {:<30}".format("Ports Count:", self.status_obj.server_sys_info["port_count"]))
- ports_owned = " ".join(str(x) for x in self.status_obj.rpc_client.get_owned_ports())
+ ports_owned = " ".join(str(x) for x in self.status_obj.owned_ports_list)
if not ports_owned:
ports_owned = "None"
@@ -134,92 +101,123 @@ class ServerInfoPanel(TrexStatusPanel):
class GeneralInfoPanel(TrexStatusPanel):
def __init__ (self, h, l, y, x, status_obj):
- super(GeneralInfoPanel, self).__init__(h, l, y ,x ,"General Info:")
-
- self.status_obj = status_obj
+ super(GeneralInfoPanel, self).__init__(h, l, y ,x ,"General Info:", status_obj)
def draw (self):
- pass
+ self.clear()
+
+ if not self.general_stats.is_online():
+ self.getwin().addstr(3, 2, "No Published Data From TRex Server")
+ return
+
+ self.getwin().addstr(3, 2, "{:<30} {:0.2f} %".format("CPU util.:", self.general_stats.get("m_cpu_util")))
+
+ self.getwin().addstr(6, 2, "{:<30} {:} / {:}".format("Total Tx. rate:",
+ self.general_stats.get("m_tx_bps", format = True, suffix = "bps"),
+ self.general_stats.get("m_tx_pps", format = True, suffix = "pps")))
+
+
+ self.getwin().addstr(8, 2, "{:<30} {:} / {:}".format("Total Tx:",
+ self.general_stats.get_rel("m_total_tx_bytes", format = True, suffix = "B"),
+ self.general_stats.get_rel("m_total_tx_pkts", format = True, suffix = "pkts")))
+
+ self.getwin().addstr(11, 2, "{:<30} {:} / {:}".format("Total Rx. rate:",
+ self.general_stats.get("m_rx_bps", format = True, suffix = "bps"),
+ self.general_stats.get("m_rx_pps", format = True, suffix = "pps")))
+
+
+ self.getwin().addstr(13, 2, "{:<30} {:} / {:}".format("Total Rx:",
+ self.general_stats.get_rel("m_total_rx_bytes", format = True, suffix = "B"),
+ self.general_stats.get_rel("m_total_rx_pkts", format = True, suffix = "pkts")))
# all ports stats
class PortsStatsPanel(TrexStatusPanel):
def __init__ (self, h, l, y, x, status_obj):
- super(PortsStatsPanel, self).__init__(h, l, y ,x ,"Trex Ports:")
+ super(PortsStatsPanel, self).__init__(h, l, y ,x ,"Trex Ports:", status_obj)
- self.status_obj = status_obj
def draw (self):
self.clear()
- owned_ports = self.status_obj.rpc_client.get_owned_ports()
+ owned_ports = self.status_obj.owned_ports_list
if not owned_ports:
self.getwin().addstr(3, 2, "No Owned Ports - Please Acquire One Or More Ports")
return
# table header
- self.getwin().addstr(3, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
- "Port ID", "Tx [pps]", "Tx [bps]", "Tx [bytes]", "Rx [pps]", "Rx [bps]", "Rx [bytes]"))
+ self.getwin().addstr(3, 2, "{:^15} {:^30} {:^30} {:^30}".format(
+ "Port ID", "Tx Rate [bps/pps]", "Rx Rate [bps/pps]", "Total Bytes [tx/rx]"))
+
- # port loop
- self.status_obj.stats.query_sync()
for i, port_index in enumerate(owned_ports):
port_stats = self.status_obj.stats.get_port_stats(port_index)
if port_stats:
- self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,.2f} {:^15,.2f} {:^15,} {:^15,.2f} {:^15,.2f} {:^15,}".format(
+ self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^30} {:^30} {:^30}".format(
"{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]),
- port_stats["tx_pps"],
- port_stats["tx_bps"],
- port_stats["total_tx_bytes"],
- port_stats["rx_pps"],
- port_stats["rx_bps"],
- port_stats["total_rx_bytes"]))
-
+ "{0} / {1}".format(port_stats.get("m_total_tx_bps", format = True, suffix = "bps"),
+ port_stats.get("m_total_tx_pps", format = True, suffix = "pps")),
+
+ "{0} / {1}".format(port_stats.get("m_total_rx_bps", format = True, suffix = "bps"),
+ port_stats.get("m_total_rx_pps", format = True, suffix = "pps")),
+ "{0} / {1}".format(port_stats.get_rel("obytes", format = True, suffix = "B"),
+ port_stats.get_rel("ibytes", format = True, suffix = "B"))))
+
else:
- self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
+ self.getwin().addstr(5 + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format(
"{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]),
"N/A",
"N/A",
"N/A",
- "N/A",
- "N/A",
"N/A"))
+
+ # old format
+# if port_stats:
+# self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
+# "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]),
+# port_stats.get("m_total_tx_pps", format = True, suffix = "pps"),
+# port_stats.get("m_total_tx_bps", format = True, suffix = "bps"),
+# port_stats.get_rel("obytes", format = True, suffix = "B"),
+# port_stats.get("m_total_rx_pps", format = True, suffix = "pps"),
+# port_stats.get("m_total_rx_bps", format = True, suffix = "bps"),
+# port_stats.get_rel("ibytes", format = True, suffix = "B")))
+#
+# else:
+# self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
+# "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]),
+# "N/A",
+# "N/A",
+# "N/A",
+# "N/A",
+# "N/A",
+# "N/A"))
+
# control panel
class ControlPanel(TrexStatusPanel):
def __init__ (self, h, l, y, x, status_obj):
- super(ControlPanel, self).__init__(h, l, y, x, "")
+ super(ControlPanel, self).__init__(h, l, y, x, "", status_obj)
- self.status_obj = status_obj
def draw (self):
self.clear()
self.getwin().addstr(1, 2, "'g' - general, '0-{0}' - specific port, 'f' - freeze, 'c' - clear stats, 'p' - ping server, 'q' - quit"
- .format(self.status_obj.rpc_client.get_port_count() - 1))
+ .format(self.status_obj.stateless_client.get_port_count() - 1))
- index = 3
-
- cut = len(self.status_obj.log) - 4
- if cut < 0:
- cut = 0
-
- for l in self.status_obj.log[cut:]:
- self.getwin().addstr(index, 2, l)
- index += 1
+ self.log.draw(self.getwin(), 2, 3)
# specific ports panels
class SinglePortPanel(TrexStatusPanel):
def __init__ (self, h, l, y, x, status_obj, port_id):
- super(SinglePortPanel, self).__init__(h, l, y, x, "Port {0}".format(port_id))
+ super(SinglePortPanel, self).__init__(h, l, y, x, "Port {0}".format(port_id), status_obj)
- self.status_obj = status_obj
self.port_id = port_id
def draw (self):
@@ -227,7 +225,7 @@ class SinglePortPanel(TrexStatusPanel):
self.clear()
- if not self.port_id in self.status_obj.rpc_client.get_owned_ports():
+ if not self.port_id in self.status_obj.owned_ports_list:
self.getwin().addstr(y, 2, "Port {0} is not owned by you, please acquire the port for more info".format(self.port_id))
return
@@ -241,16 +239,19 @@ class SinglePortPanel(TrexStatusPanel):
y += 2
# streams
- if 'streams' in self.status_obj.snapshot[self.port_id]:
- for stream_id, stream in self.status_obj.snapshot[self.port_id]['streams'].iteritems():
+
+ if 'streams' in self.status_obj.owned_ports[str(self.port_id)]:
+ stream_info = self.status_obj.owned_ports[str(self.port_id)]['streams']
+
+ for stream_id, stream in sorted(stream_info.iteritems(), key=operator.itemgetter(0)):
self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
stream_id,
- ("True" if stream['stream']['enabled'] else "False"),
- stream['stream']['mode']['type'],
- ("True" if stream['stream']['self_start'] else "False"),
- stream['stream']['isg'],
- (stream['stream']['next_stream_id'] if stream['stream']['next_stream_id'] != -1 else "None"),
- ("{0} instr.".format(len(stream['stream']['vm'])) if stream['stream']['vm'] else "None")))
+ ("True" if stream['enabled'] else "False"),
+ stream['mode']['type'],
+ ("True" if stream['self_start'] else "False"),
+ stream['isg'],
+ (stream['next_stream_id'] if stream['next_stream_id'] != -1 else "None"),
+ ("{0} instr.".format(len(stream['vm'])) if stream['vm'] else "None")))
y += 1
@@ -260,128 +261,180 @@ class SinglePortPanel(TrexStatusPanel):
self.getwin().addstr(y, 2, "Traffic:", curses.A_UNDERLINE)
y += 2
- self.status_obj.stats.query_sync()
- port_stats = self.status_obj.stats.get_port_stats(self.port_id)
- # table header
- self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
- "Port ID", "Tx [pps]", "Tx [bps]", "Tx [bytes]", "Rx [pps]", "Rx [bps]", "Rx [bytes]"))
+ # table header
+ self.getwin().addstr(y, 2, "{:^15} {:^30} {:^30} {:^30}".format(
+ "Port ID", "Tx Rate [bps/pps]", "Rx Rate [bps/pps]", "Total Bytes [tx/rx]"))
+
y += 2
- if port_stats:
- self.getwin().addstr(y, 2, "{:^15} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,}".format(
- "{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]),
- port_stats["tx_pps"],
- port_stats["tx_bps"],
- port_stats["total_tx_bytes"],
- port_stats["rx_pps"],
- port_stats["rx_bps"],
- port_stats["total_rx_bytes"]))
+ port_stats = self.status_obj.stats.get_port_stats(self.port_id)
+ if port_stats:
+ self.getwin().addstr(y, 2, "{:^15} {:^30} {:^30} {:^30}".format(
+ "{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]),
+ "{0} / {1}".format(port_stats.get("m_total_tx_bps", format = True, suffix = "bps"),
+ port_stats.get("m_total_tx_pps", format = True, suffix = "pps")),
+
+ "{0} / {1}".format(port_stats.get("m_total_rx_bps", format = True, suffix = "bps"),
+ port_stats.get("m_total_rx_pps", format = True, suffix = "pps")),
+ "{0} / {1}".format(port_stats.get_rel("obytes", format = True, suffix = "B"),
+ port_stats.get_rel("ibytes", format = True, suffix = "B"))))
+
else:
- self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format(
+ self.getwin().addstr(y + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format(
"{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]),
"N/A",
"N/A",
"N/A",
- "N/A",
- "N/A",
"N/A"))
- y += 2
-# status object
-class TrexStatus():
- def __init__ (self, stdscr, rpc_client):
- self.stdscr = stdscr
+################### main objects #################
+
+# status log
+class TrexStatusLog():
+ def __init__ (self):
self.log = []
- self.rpc_client = rpc_client
- self.snapshot = self.rpc_client.snapshot()
+ def add_event (self, msg):
+ self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg))
- # fetch server info
- self.get_server_info()
+ def draw (self, window, x, y, max_lines = 4):
+ index = y
+
+ cut = len(self.log) - max_lines
+ if cut < 0:
+ cut = 0
+
+ for msg in self.log[cut:]:
+ window.addstr(index, x, msg)
+ index += 1
+
+# status commands
+class TrexStatusCommands():
+ def __init__ (self, status_object):
- # create stats objects
- self.stats = Stats(rpc_client, self.rpc_client.get_owned_ports())
+ self.status_object = status_object
+
+ self.stateless_client = status_object.stateless_client
+ self.log = self.status_object.log
- # register actions
self.actions = {}
- self.actions[ord('q')] = self.action_quit
- self.actions[ord('p')] = self.action_ping
- self.actions[ord('f')] = self.action_freeze
+ self.actions[ord('q')] = self._quit
+ self.actions[ord('p')] = self._ping
+ self.actions[ord('f')] = self._freeze
- self.actions[ord('g')] = self.action_show_ports_stats
+ self.actions[ord('g')] = self._show_ports_stats
- for port_id in xrange(0, self.rpc_client.get_port_count()):
- self.actions[ord('0') + port_id] = self.action_show_port_generator(port_id)
+ # register all the available ports shortcuts
+ for port_id in xrange(0, self.stateless_client.get_port_count()):
+ self.actions[ord('0') + port_id] = self._show_port_generator(port_id)
+
+
+ # handle a key pressed
+ def handle (self, ch):
+ if ch in self.actions:
+ return self.actions[ch]()
+ else:
+ self.log.add_event("Unknown key pressed, please see legend")
+ return True
+
+ # show all ports
+ def _show_ports_stats (self):
+ self.log.add_event("Switching to all ports view")
+ self.status_object.stats_panel = self.status_object.ports_stats_panel
-
- # all ports stats
- def action_show_ports_stats (self):
- self.add_log_event("Switching to all ports view")
- self.stats_panel = self.ports_stats_panel
-
return True
- # function generator for different ports requests
- def action_show_port_generator (self, port_id):
- def action_show_port():
- self.add_log_event("Switching panel to port {0}".format(port_id))
- self.stats_panel = self.ports_panels[port_id]
+
+ # function generator for different ports requests
+ def _show_port_generator (self, port_id):
+ def _show_port():
+ self.log.add_event("Switching panel to port {0}".format(port_id))
+ self.status_object.stats_panel = self.status_object.ports_panels[port_id]
return True
- return action_show_port
+ return _show_port
- def action_freeze (self):
- self.update_active = not self.update_active
- self.add_log_event("Update continued" if self.update_active else "Update stopped")
+ def _freeze (self):
+ self.status_object.update_active = not self.status_object.update_active
+ self.log.add_event("Update continued" if self.status_object.update_active else "Update stopped")
return True
- def action_quit(self):
+ def _quit(self):
return False
- def action_ping (self):
- self.add_log_event("Pinging RPC server")
+ def _ping (self):
+ self.log.add_event("Pinging RPC server")
- rc, msg = self.rpc_client.ping_rpc_server()
+ rc, msg = self.stateless_client.ping()
if rc:
- self.add_log_event("Server replied: '{0}'".format(msg))
+ self.log.add_event("Server replied: '{0}'".format(msg))
else:
- self.add_log_event("Failed to get reply")
+ self.log.add_event("Failed to get reply")
return True
- def get_server_info (self):
+# status object
+#
+#
+#
+class TrexStatus():
+ def __init__ (self, stdscr, stateless_client):
+ self.stdscr = stdscr
- self.server_version = self.rpc_client.get_rpc_server_version()
- self.server_sys_info = self.rpc_client.get_system_info()
+ self.stateless_client = stateless_client
+ self.log = TrexStatusLog()
+ self.cmds = TrexStatusCommands(self)
- def add_log_event (self, msg):
- self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg))
+ self.stats = stateless_client.get_stats_async()
+ self.general_stats = stateless_client.get_stats_async().get_general_stats()
- # control panel
- def update_control (self):
- self.control_panel.clear()
+ # fetch server info
+ rc, self.server_sys_info = self.stateless_client.get_system_info()
+ if not rc:
+ return
- self.control_panel.getwin().addstr(1, 2, "'g' - general, '0-{0}' - specific port, 'f' - freeze, 'c' - clear stats, 'p' - ping server, 'q' - quit"
- .format(self.rpc_client.get_port_count() - 1))
+ rc, self.server_version = self.stateless_client.get_version()
+ if not rc:
+ return
- index = 3
+ # list of owned ports
+ self.owned_ports_list = self.stateless_client.get_acquired_ports()
+
+ # data per port
+ self.owned_ports = {}
- cut = len(self.log) - 4
- if cut < 0:
- cut = 0
+ for port_id in self.owned_ports_list:
+ self.owned_ports[str(port_id)] = {}
+ self.owned_ports[str(port_id)]['streams'] = {}
- for l in self.log[cut:]:
- self.control_panel.getwin().addstr(index, 2, l)
- index += 1
+ rc, stream_list = self.stateless_client.get_all_streams(port_id)
+ if not rc:
+ raise Exception("unable to get streams")
+ self.owned_ports[str(port_id)] = stream_list
+
+
+ try:
+ curses.curs_set(0)
+ except:
+ pass
+
+ curses.use_default_colors()
+ self.stdscr.nodelay(1)
+ curses.nonl()
+ curses.noecho()
+
+ self.generate_layout()
+
+
def generate_layout (self):
self.max_y = self.stdscr.getmaxyx()[0]
self.max_x = self.stdscr.getmaxyx()[1]
@@ -394,7 +447,7 @@ class TrexStatus():
self.ports_stats_panel = PortsStatsPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self)
self.ports_panels = {}
- for i in xrange(0, self.rpc_client.get_port_count()):
+ for i in xrange(0, self.stateless_client.get_port_count()):
self.ports_panels[i] = SinglePortPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self, i)
# at start time we point to the main one
@@ -411,28 +464,27 @@ class TrexStatus():
# no key , continue
if ch == curses.ERR:
return True
-
- # check for registered function
- if ch in self.actions:
- return self.actions[ch]()
- else:
- self.add_log_event("Unknown key pressed, please see legend")
-
- return True
+
+ return self.cmds.handle(ch)
# main run entry point
def run (self):
- try:
- curses.curs_set(0)
- except:
- pass
- curses.use_default_colors()
- self.stdscr.nodelay(1)
- curses.nonl()
- curses.noecho()
+ # list of owned ports
+ self.owned_ports_list = self.stateless_client.get_acquired_ports()
- self.generate_layout()
+ # data per port
+ self.owned_ports = {}
+
+ for port_id in self.owned_ports_list:
+ self.owned_ports[str(port_id)] = {}
+ self.owned_ports[str(port_id)]['streams'] = {}
+
+ rc, stream_list = self.stateless_client.get_all_streams(port_id)
+ if not rc:
+ raise Exception("unable to get streams")
+
+ self.owned_ports[str(port_id)] = stream_list
self.update_active = True
while (True):
@@ -454,14 +506,21 @@ class TrexStatus():
sleep(0.01)
-def show_trex_status_internal (stdscr, rpc_client):
- trex_status = TrexStatus(stdscr, rpc_client)
+# global container
+trex_status = None
+
+def show_trex_status_internal (stdscr, stateless_client):
+ global trex_status
+
+ if trex_status == None:
+ trex_status = TrexStatus(stdscr, stateless_client)
+
trex_status.run()
-def show_trex_status (rpc_client):
+def show_trex_status (stateless_client):
try:
- curses.wrapper(show_trex_status_internal, rpc_client)
+ curses.wrapper(show_trex_status_internal, stateless_client)
except KeyboardInterrupt:
curses.endwin()
diff --git a/scripts/automation/trex_control_plane/examples/stateless_example.py b/scripts/automation/trex_control_plane/examples/stateless_example.py
new file mode 100755
index 00000000..bb0fe983
--- /dev/null
+++ b/scripts/automation/trex_control_plane/examples/stateless_example.py
@@ -0,0 +1,30 @@
+#!/router/bin/python
+
+import trex_root_path
+from client.trex_hltapi import CTRexHltApi
+
+if __name__ == "__main__":
+ port_list = [1,2]
+ try:
+ hlt_client = CTRexHltApi()
+ con = hlt_client.connect("localhost", port_list, "danklei", break_locks=True, reset=True)#, port=6666)
+ print con
+
+ res = hlt_client.traffic_config("create", 1)#, ip_src_addr="2000.2.2")
+ print res
+ res = hlt_client.traffic_config("create", 2)#, ip_src_addr="2000.2.2")
+ print res
+
+ res = hlt_client.traffic_control("run", [1, 2])#, ip_src_addr="2000.2.2")
+ print res
+
+ res = hlt_client.traffic_control("stop", [1, 2])#, ip_src_addr="2000.2.2")
+ print res
+
+
+
+ except Exception as e:
+ raise
+ finally:
+ res = hlt_client.cleanup_session(port_list)
+ print res \ No newline at end of file
diff --git a/scripts/cap2/many_client_example.yaml b/scripts/cap2/many_client_example.yaml
new file mode 100644
index 00000000..7908a5a4
--- /dev/null
+++ b/scripts/cap2/many_client_example.yaml
@@ -0,0 +1,42 @@
+- duration : 1.0
+ generator :
+ distribution : "random"
+ clients_start : "20.0.0.1"
+ clients_end : "20.10.85.255"
+ servers_start : "90.0.0.1"
+ servers_end : "90.0.255.255"
+ clients_per_gb : 201
+ min_clients : 101
+ dual_port_mask : "1.0.0.0"
+ tcp_aging : 0
+ udp_aging : 0
+ generator_clients :
+ - name : "c1"
+ distribution : "random"
+ ip_start : "21.0.0.1"
+ ip_end : "21.10.255.255"
+ - name : "c2"
+ distribution : "random"
+ ip_start : "36.0.0.1"
+ ip_end : "36.0.1.254"
+ generator_servers :
+ - name : "s1"
+ distribution : "random"
+ ip_start : "22.0.0.1"
+ ip_end : "22.1.255.255"
+ track_ports : false
+ - name : "s2"
+ distribution : "random"
+ ip_start : "38.0.0.1"
+ ip_end : "38.0.3.255"
+ track_ports : false
+ mac : [0x0,0x0,0x0,0x1,0x0,0x00]
+ cap_info :
+ - name: cap2/http_get.pcap
+ client_pool: "c1"
+ server_pool: "s1"
+ cps : 1.0
+ ipg : 100
+ rtt : 10000
+ w : 1
+
diff --git a/scripts/exp/dns-0-ex.erf b/scripts/exp/dns-0-ex.erf
index 5ffffcb3..fdb19009 100755
--- a/scripts/exp/dns-0-ex.erf
+++ b/scripts/exp/dns-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns-0.erf b/scripts/exp/dns-0.erf
index d8d601b7..fdb19009 100644
--- a/scripts/exp/dns-0.erf
+++ b/scripts/exp/dns-0.erf
Binary files differ
diff --git a/scripts/exp/dns_e-0-ex.erf b/scripts/exp/dns_e-0-ex.erf
index 7ebfd69a..e0de09fc 100755
--- a/scripts/exp/dns_e-0-ex.erf
+++ b/scripts/exp/dns_e-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns_e-0.erf b/scripts/exp/dns_e-0.erf
index 7ebfd69a..e0de09fc 100644
--- a/scripts/exp/dns_e-0.erf
+++ b/scripts/exp/dns_e-0.erf
Binary files differ
diff --git a/scripts/exp/dns_flip-0-ex.erf b/scripts/exp/dns_flip-0-ex.erf
index f6074ad7..774f0fdf 100755
--- a/scripts/exp/dns_flip-0-ex.erf
+++ b/scripts/exp/dns_flip-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns_flip-0.erf b/scripts/exp/dns_flip-0.erf
index f6074ad7..774f0fdf 100644
--- a/scripts/exp/dns_flip-0.erf
+++ b/scripts/exp/dns_flip-0.erf
Binary files differ
diff --git a/scripts/exp/dns_ipv6-0-ex.erf b/scripts/exp/dns_ipv6-0-ex.erf
index c47a6496..e0d33efc 100755
--- a/scripts/exp/dns_ipv6-0-ex.erf
+++ b/scripts/exp/dns_ipv6-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns_ipv6-0.erf b/scripts/exp/dns_ipv6-0.erf
index 53dee235..e0d33efc 100644
--- a/scripts/exp/dns_ipv6-0.erf
+++ b/scripts/exp/dns_ipv6-0.erf
Binary files differ
diff --git a/scripts/exp/dns_one_server-0-ex.erf b/scripts/exp/dns_one_server-0-ex.erf
index 0d3d447b..15323016 100755
--- a/scripts/exp/dns_one_server-0-ex.erf
+++ b/scripts/exp/dns_one_server-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns_one_server-0.erf b/scripts/exp/dns_one_server-0.erf
index ef76a69b..15323016 100644
--- a/scripts/exp/dns_one_server-0.erf
+++ b/scripts/exp/dns_one_server-0.erf
Binary files differ
diff --git a/scripts/exp/dns_p-0-ex.erf b/scripts/exp/dns_p-0-ex.erf
index ec313584..7d93c1d3 100755
--- a/scripts/exp/dns_p-0-ex.erf
+++ b/scripts/exp/dns_p-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dns_p-0.erf b/scripts/exp/dns_p-0.erf
index ec313584..7d93c1d3 100644
--- a/scripts/exp/dns_p-0.erf
+++ b/scripts/exp/dns_p-0.erf
Binary files differ
diff --git a/scripts/exp/dyn_pyld1-0-ex.erf b/scripts/exp/dyn_pyld1-0-ex.erf
index 7d2089db..6a0028dc 100755
--- a/scripts/exp/dyn_pyld1-0-ex.erf
+++ b/scripts/exp/dyn_pyld1-0-ex.erf
Binary files differ
diff --git a/scripts/exp/dyn_pyld1-0.erf b/scripts/exp/dyn_pyld1-0.erf
index 175a810c..6a0028dc 100644
--- a/scripts/exp/dyn_pyld1-0.erf
+++ b/scripts/exp/dyn_pyld1-0.erf
Binary files differ
diff --git a/scripts/exp/imix-0-ex.erf b/scripts/exp/imix-0-ex.erf
index 233e6b31..07fb2ace 100755
--- a/scripts/exp/imix-0-ex.erf
+++ b/scripts/exp/imix-0-ex.erf
Binary files differ
diff --git a/scripts/exp/imix-0.erf b/scripts/exp/imix-0.erf
index c41a3006..07fb2ace 100644
--- a/scripts/exp/imix-0.erf
+++ b/scripts/exp/imix-0.erf
Binary files differ
diff --git a/scripts/exp/imix_v6-0-ex.erf b/scripts/exp/imix_v6-0-ex.erf
index 56412091..c5f247d1 100755
--- a/scripts/exp/imix_v6-0-ex.erf
+++ b/scripts/exp/imix_v6-0-ex.erf
Binary files differ
diff --git a/scripts/exp/imix_v6-0.erf b/scripts/exp/imix_v6-0.erf
index a85ed2b9..c5f247d1 100644
--- a/scripts/exp/imix_v6-0.erf
+++ b/scripts/exp/imix_v6-0.erf
Binary files differ
diff --git a/scripts/exp/limit_single_pkt-0-ex.erf b/scripts/exp/limit_single_pkt-0-ex.erf
index 3f7f0ff2..adc6fd46 100755
--- a/scripts/exp/limit_single_pkt-0-ex.erf
+++ b/scripts/exp/limit_single_pkt-0-ex.erf
Binary files differ
diff --git a/scripts/exp/limit_single_pkt-0.erf b/scripts/exp/limit_single_pkt-0.erf
index 548d2e3f..adc6fd46 100644
--- a/scripts/exp/limit_single_pkt-0.erf
+++ b/scripts/exp/limit_single_pkt-0.erf
Binary files differ
diff --git a/scripts/exp/sfr2-0-ex.erf b/scripts/exp/sfr2-0-ex.erf
index 5e2b791f..e5dfc4c3 100755
--- a/scripts/exp/sfr2-0-ex.erf
+++ b/scripts/exp/sfr2-0-ex.erf
Binary files differ
diff --git a/scripts/exp/sfr2-0.erf b/scripts/exp/sfr2-0.erf
index bf5ff3ef..e5dfc4c3 100644
--- a/scripts/exp/sfr2-0.erf
+++ b/scripts/exp/sfr2-0.erf
Binary files differ
diff --git a/src/bp_gtest.cpp b/src/bp_gtest.cpp
index a529d637..03ab74bd 100755
--- a/src/bp_gtest.cpp
+++ b/src/bp_gtest.cpp
@@ -66,7 +66,7 @@ int test_priorty_queue(void){
int i;
for (i=0; i<10; i++) {
node = new CGenNode();
- printf(" +%x \n",node);
+ printf(" +%p \n",node);
node->m_flow_id = 10-i;
node->m_pkt_info = (CFlowPktInfo *)(uintptr_t)i;
node->m_time = (double)i+0.1;
@@ -74,7 +74,7 @@ int test_priorty_queue(void){
}
while (!p_queue.empty()) {
node = p_queue.top();
- printf(" -->%x \n",node);
+ printf(" -->%p \n",node);
//node->Dump(stdout);
p_queue.pop();
//delete node;
@@ -159,7 +159,7 @@ public:
bool init(void){
- uint16 * ports;
+ uint16 * ports = NULL;
CTupleBase tuple;
CErfIF erf_vif;
@@ -205,7 +205,7 @@ public:
}
}
- lpt->generate_erf(buf,CGlobalInfo::m_options.preview);
+ lpt->start_generate_stateful(buf,CGlobalInfo::m_options.preview);
lpt->m_node_gen.DumpHist(stdout);
cmp.d_sec = m_time_diff;
@@ -663,6 +663,7 @@ TEST_F(basic, latency1) {
po->preview.setFileWrite(true);
uint8_t mac[]={0,0,0,1,0,0};
+ (void)mac;
CErfIF erf_vif;
erf_vif.set_review_mode(&CGlobalInfo::m_options.preview);
@@ -714,6 +715,7 @@ TEST_F(basic, latency2) {
uint8_t mac[]={0,0,0,1,0,0};
+ (void)mac;
mac[0]=0;
mac[1]=0;
@@ -728,14 +730,13 @@ TEST_F(basic, latency2) {
int i;
for (i=0; i<100; i++) {
- uint8_t *p;
rte_mbuf_t * m=l.generate_pkt(0);
- p=rte_pktmbuf_mtod(m, uint8_t*);
+ rte_pktmbuf_mtod(m, uint8_t*);
//utl_DumpBuffer(stdout,p,l.get_pkt_size(),0);
port0.update_packet(m);
- p=rte_pktmbuf_mtod(m, uint8_t*);
+ rte_pktmbuf_mtod(m, uint8_t*);
//utl_DumpBuffer(stdout,p,l.get_pkt_size(),0);
//printf("offset is : %d \n",l.get_payload_offset());
@@ -763,6 +764,7 @@ TEST_F(basic, latency3) {
uint8_t mac[]={0,0,0,1,0,0};
+ (void)mac;
mac[0]=0;
@@ -850,6 +852,7 @@ public:
TEST_F(basic, latency4) {
uint8_t mac[]={0,0,0,1,0,0};
+ (void)mac;
mac[0]=0;
mac[1]=0;
@@ -2031,6 +2034,10 @@ public:
virtual int send_node(CGenNode * node);
+ virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){
+ return (0);
+ }
+
/**
* flush all pending packets into the stream
@@ -2105,7 +2112,7 @@ public:
int i;
for (i=0; i<m_threads; i++) {
lpt=fl.m_threads_info[i];
- lpt->generate_erf("t1",CGlobalInfo::m_options.preview);
+ lpt->start_generate_stateful("t1",CGlobalInfo::m_options.preview);
}
fl.Delete();
return (true);
@@ -2121,7 +2128,7 @@ class CRxCheck1 : public CRxCheckCallbackBase {
public:
virtual void handle_packet(rte_mbuf_t * m){
- char *mp=rte_pktmbuf_mtod(m, char*);
+ rte_pktmbuf_mtod(m, char*);
CRx_check_header * rx_p;
rte_mbuf_t * m2 = m->next;
rx_p=(CRx_check_header *)rte_pktmbuf_mtod(m2, char*);
@@ -2755,7 +2762,7 @@ TEST_F(gt_ring, ring1) {
TEST_F(gt_ring, ring2) {
CMessagingManager ringmg;
- ringmg.Create(8);
+ ringmg.Create(8, "test");
int i;
for (i=0; i<8; i++) {
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index c3581c55..0c0cbb75 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -25,6 +25,7 @@ limitations under the License.
#include "msg_manager.h"
#include <common/basic_utils.h>
+#include <trex_stream_node.h>
#undef VALG
@@ -71,11 +72,11 @@ void CGlobalMemory::Dump(FILE *fd){
c_size=c_size*2;
}
- fprintf(fd," %-40s : %lu \n",names[i].c_str(),m_mbuf[i]);
+ fprintf(fd," %-40s : %lu \n",names[i].c_str(),(ulong)m_mbuf[i]);
}
c_total += (m_mbuf[MBUF_DP_FLOWS] * sizeof(CGenNode));
- fprintf(fd," %-40s : %lu \n","get_each_core_dp_flows",get_each_core_dp_flows());
+ fprintf(fd," %-40s : %lu \n","get_each_core_dp_flows",(ulong)get_each_core_dp_flows());
fprintf(fd," %-40s : %s \n","Total memory",double_to_human_str(c_total,"bytes",KBYE_1024).c_str() );
}
@@ -239,7 +240,7 @@ bool CPlatformSocketInfoConfig::init(){
}
if ( m_thread_phy_to_virtual[phy_thread] ){
- printf("ERROR physical thread %d defined twice %d \n",phy_thread);
+ printf("ERROR physical thread %d defined twice\n",phy_thread);
exit(1);
}
m_thread_phy_to_virtual[phy_thread]=virt_thread;
@@ -268,7 +269,7 @@ bool CPlatformSocketInfoConfig::init(){
void CPlatformSocketInfoConfig::dump(FILE *fd){
- fprintf(fd," core_mask %x \n",get_cores_mask());
+ fprintf(fd," core_mask %llx \n",(unsigned long long)get_cores_mask());
fprintf(fd," sockets :");
int i;
for (i=0; i<MAX_SOCKETS_SUPPORTED; i++) {
@@ -279,7 +280,7 @@ void CPlatformSocketInfoConfig::dump(FILE *fd){
fprintf(fd," \n");
fprintf(fd," active sockets : %d \n",max_num_active_sockets());
- fprintf(fd," ports_sockets : \n",max_num_active_sockets());
+ fprintf(fd," ports_sockets : %d \n",max_num_active_sockets());
for (i=0; i<(MAX_LATENCY_PORTS); i++) {
fprintf(fd,"%d,",port_to_socket(i));
@@ -820,7 +821,6 @@ void CPacketIndication::UpdatePacketPadding(){
void CPacketIndication::RefreshPointers(){
char *pobase=getBasePtr();
- CPacketIndication * obj=this;
m_ether = (EthernetHeader *) (pobase + m_ether_offset);
l3.m_ipv4 = (IPHeader *) (pobase + m_ip_offset);
@@ -1671,7 +1671,6 @@ char * CFlowPktInfo::push_ipv4_option_offline(uint8_t bytes){
void CFlowPktInfo::mask_as_learn(){
- char *p;
CNatOption *lpNat;
if ( m_pkt_indication.is_ipv6() ){
lpNat=(CNatOption *)push_ipv6_option_offline(CNatOption::noOPTION_LEN);
@@ -2265,7 +2264,7 @@ void CCCapFileMemoryUsage::dump(FILE *fd){
int c_total=0;
for (i=0; i<CCCapFileMemoryUsage::MASK_SIZE; i++) {
- fprintf(fd," size_%-7d : %lu \n",c_size,m_buf[i]);
+ fprintf(fd," size_%-7d : %lu \n",c_size, (ulong)m_buf[i]);
c_total +=m_buf[i]*c_size;
c_size = c_size*2;
}
@@ -2440,7 +2439,6 @@ void operator >> (const YAML::Node& node, CFlowYamlInfo & fi) {
if ( node.FindValue("dyn_pyload") ){
- int i;
const YAML::Node& dyn_pyload = node["dyn_pyload"];
for(unsigned i=0;i<dyn_pyload.size();i++) {
CFlowYamlDpPkt fd;
@@ -2839,8 +2837,20 @@ void CFlowStats::DumpHeader(FILE *fd){
void CFlowStats::Dump(FILE *fd){
//"name","cps","f-pkts","f-bytes","Mb/sec","MB/sec","c-flows","PPS","total-Mbytes-duration","errors","flows"
fprintf(fd," %02d, %-40s ,%4.2f,%4.2f, %5.0f , %7.0f ,%7.2f ,%7.2f , %7.2f , %10.0f , %5.0f , %7.0f , %llu , %llu \n",
- m_id,m_name.c_str(),m_cps,get_normal_cps(),
- m_pkt,m_bytes,duration_sec,m_mb_sec,m_mB_sec,m_c_flows,m_pps,m_total_Mbytes,m_errors,m_flows);
+ m_id,
+ m_name.c_str(),
+ m_cps,
+ get_normal_cps(),
+ m_pkt,
+ m_bytes,
+ duration_sec,
+ m_mb_sec,
+ m_mB_sec,
+ m_c_flows,
+ m_pps,
+ m_total_Mbytes,
+ (unsigned long long)m_errors,
+ (unsigned long long)m_flows);
}
bool CFlowGeneratorRecPerThread::Create(CTupleGeneratorSmart * global_gen,
@@ -3045,21 +3055,20 @@ void CGenNode::DumpHeader(FILE *fd){
}
void CGenNode::Dump(FILE *fd){
- fprintf(fd,"%.6f,%llx,%p,%llu,%d,%d,%d,%d,%d,%d,%x,%x,%d\n",m_time,m_flow_id,m_pkt_info,
- m_pkt_info->m_pkt_indication.m_packet->pkt_cnt,
- m_pkt_info->m_pkt_indication.m_packet->pkt_len,
- m_pkt_info->m_pkt_indication.m_desc.getId(),
- (m_pkt_info->m_pkt_indication.m_desc.IsInitSide()?1:0),
- m_pkt_info->m_pkt_indication.m_desc.IsLastPkt(),
+ fprintf(fd,"%.6f,%llx,%p,%llu,%d,%d,%d,%d,%d,%d,%x,%x,%d\n",
+ m_time,
+ (unsigned long long)m_flow_id,
+ m_pkt_info,
+ (unsigned long long)m_pkt_info->m_pkt_indication.m_packet->pkt_cnt,
+ m_pkt_info->m_pkt_indication.m_packet->pkt_len,
+ m_pkt_info->m_pkt_indication.m_desc.getId(),
+ (m_pkt_info->m_pkt_indication.m_desc.IsInitSide()?1:0),
+ m_pkt_info->m_pkt_indication.m_desc.IsLastPkt(),
m_type,
m_thread_id,
m_src_ip,
m_dest_ip,
- m_src_port
-
-
-
- );
+ m_src_port);
}
@@ -3114,14 +3123,10 @@ int CNodeGenerator::close_file(CFlowGenListPerThread * thread){
return (0);
}
-int CNodeGenerator::flush_one_node_to_file(CGenNode * node){
- BP_ASSERT(m_v_if);
- return (m_v_if->send_node(node));
-}
int CNodeGenerator::update_stats(CGenNode * node){
if ( m_preview_mode.getVMode() >2 ){
- fprintf(stdout," %llu ,",m_cnt);
+ fprintf(stdout," %llu ,", (unsigned long long)m_cnt);
node->Dump(stdout);
m_cnt++;
}
@@ -3204,6 +3209,10 @@ bool CFlowGenListPerThread::Create(uint32_t thread_id,
assert(m_ring_from_rx);
assert(m_ring_to_rx);
+
+ /* create the info required for stateless DP core */
+ m_stateless_dp_info.create(thread_id, this);
+
return (true);
}
@@ -3351,6 +3360,7 @@ void CFlowGenListPerThread::Delete(){
m_node_gen.Delete();
Clean();
m_cpu_cp_u.Delete();
+
}
@@ -3397,15 +3407,24 @@ int CNodeGenerator::flush_file(dsec_t max_time,
bool done=false;
thread->m_cpu_dp_u.start_work();
- while (!m_p_queue.empty()) {
+
+ /**
+ * if a positive value was given to max time
+ * schedule an exit node
+ */
+ if ( (max_time > 0) && (!always) ) {
+ CGenNode *exit_node = thread->create_node();
+
+ exit_node->m_type = CGenNode::EXIT_SCHED;
+ exit_node->m_time = max_time;
+ add_node(exit_node);
+ }
+
+ while (true) {
+
node = m_p_queue.top();
- n_time = node->m_time+ offset;
+ n_time = node->m_time + offset;
- if (( (n_time) > max_time ) &&
- (always==false) ) {
- /* nothing to do */
- break;
- }
events++;
/*#ifdef VALG
if (events > 1 ) {
@@ -3416,7 +3435,6 @@ int CNodeGenerator::flush_file(dsec_t max_time,
if ( likely ( m_is_realtime ) ){
dsec_t dt ;
thread->m_cpu_dp_u.commit();
- bool once=false;
while ( true ) {
dt = now_sec() - n_time ;
@@ -3425,12 +3443,6 @@ int CNodeGenerator::flush_file(dsec_t max_time,
break;
}
- if (!once) {
- /* check the msg queue once */
- thread->check_msgs();
- once=true;
- }
-
rte_pause();
}
thread->m_cpu_dp_u.start_work();
@@ -3449,55 +3461,72 @@ int CNodeGenerator::flush_file(dsec_t max_time,
flush_time=now_sec();
}
}
+
#ifndef RTE_DPDK
- thread->check_msgs();
+ thread->check_msgs();
#endif
uint8_t type=node->m_type;
- if ( likely( type == CGenNode::FLOW_PKT ) ) {
- /* PKT */
- if ( !(node->is_repeat_flow()) || (always==false)) {
- flush_one_node_to_file(node);
- #ifdef _DEBUG
- update_stats(node);
- #endif
- }
- m_p_queue.pop();
- if ( node->is_last_in_flow() ) {
- if ((node->is_repeat_flow()) && (always==false)) {
- /* Flow is repeated, reschedule it */
- thread->reschedule_flow( node);
- }else{
- /* Flow will not be repeated, so free node */
- thread->free_last_flow_node( node);
- }
- }else{
- node->update_next_pkt_in_flow();
- m_p_queue.push(node);
- }
+ if ( type == CGenNode::STATELESS_PKT ) {
+ m_p_queue.pop();
+ CGenNodeStateless *node_sl = (CGenNodeStateless *)node;
+
+ /* if the stream has been deactivated - end */
+ if (unlikely(!node_sl->is_active())) {
+ thread->free_node(node);
+ } else {
+ node_sl->handle(thread);
+ }
+
}else{
- if ((type == CGenNode::FLOW_FIF)) {
- /* callback to our method */
+ if ( likely( type == CGenNode::FLOW_PKT ) ) {
+ /* PKT */
+ if ( !(node->is_repeat_flow()) || (always==false)) {
+ flush_one_node_to_file(node);
+ #ifdef _DEBUG
+ update_stats(node);
+ #endif
+ }
m_p_queue.pop();
- if ( always == false) {
- thread->m_cur_time_sec = node->m_time ;
-
- if ( thread->generate_flows_roundrobin(&done) <0){
- break;
+ if ( node->is_last_in_flow() ) {
+ if ((node->is_repeat_flow()) && (always==false)) {
+ /* Flow is repeated, reschedule it */
+ thread->reschedule_flow( node);
+ }else{
+ /* Flow will not be repeated, so free node */
+ thread->free_last_flow_node( node);
}
- if (!done) {
- node->m_time +=d_time;
- m_p_queue.push(node);
+ }else{
+ node->update_next_pkt_in_flow();
+ m_p_queue.push(node);
+ }
+ }else{
+ if ((type == CGenNode::FLOW_FIF)) {
+ /* callback to our method */
+ m_p_queue.pop();
+ if ( always == false) {
+ thread->m_cur_time_sec = node->m_time ;
+
+ if ( thread->generate_flows_roundrobin(&done) <0){
+ break;
+ }
+ if (!done) {
+ node->m_time +=d_time;
+ m_p_queue.push(node);
+ }else{
+ thread->free_node(node);
+ }
}else{
thread->free_node(node);
}
+
}else{
- thread->free_node(node);
+ bool exit_sccheduler = handle_slow_messages(type,node,thread,always);
+ if (exit_sccheduler) {
+ break;
+ }
}
-
- }else{
- handle_slow_messages(type,node,thread,always);
}
}
}
@@ -3512,17 +3541,21 @@ int CNodeGenerator::flush_file(dsec_t max_time,
return (0);
}
-void CNodeGenerator::handle_slow_messages(uint8_t type,
- CGenNode * node,
- CFlowGenListPerThread * thread,
- bool always){
+bool
+CNodeGenerator::handle_slow_messages(uint8_t type,
+ CGenNode * node,
+ CFlowGenListPerThread * thread,
+ bool always){
+
+ /* should we continue after */
+ bool exit_scheduler = false;
if (unlikely (type == CGenNode::FLOW_DEFER_PORT_RELEASE) ) {
m_p_queue.pop();
thread->handler_defer_job(node);
thread->free_node(node);
- }else{
- if (type == CGenNode::FLOW_PKT_NAT) {
+
+ } else if (type == CGenNode::FLOW_PKT_NAT) {
/*repeat and NAT is not supported */
if ( node->is_nat_first_state() ){
node->set_nat_wait_state();
@@ -3536,7 +3569,7 @@ void CNodeGenerator::handle_slow_messages(uint8_t type,
m_p_queue.pop();
/* time out, need to free the flow and remove the association , we didn't get convertion yet*/
thread->terminate_nat_flows(node);
- return;
+ return (exit_scheduler);
}else{
flush_one_node_to_file(node);
@@ -3556,24 +3589,39 @@ void CNodeGenerator::handle_slow_messages(uint8_t type,
m_p_queue.push(node);
}
- }else{
- if ( type == CGenNode::FLOW_SYNC ){
- thread->check_msgs(); /* check messages */
- m_v_if->flush_tx_queue(); /* flush pkt each timeout */
- m_p_queue.pop();
- if ( always == false) {
- node->m_time += SYNC_TIME_OUT;
- m_p_queue.push(node);
- }else{
- thread->free_node(node);
- }
+ } else if ( type == CGenNode::FLOW_SYNC ) {
- }else{
- printf(" ERROR type is not valid %d \n",type);
- assert(0);
+ /* flow sync message is a sync point for time */
+ thread->m_cur_time_sec = node->m_time;
+
+ /* first pop the node */
+ m_p_queue.pop();
+
+ thread->check_msgs(); /* check messages */
+ m_v_if->flush_tx_queue(); /* flush pkt each timeout */
+
+ /* on always (clean queue path) and queue empty - exit */
+ if ( always && (m_p_queue.empty()) ) {
+ thread->free_node(node);
+ exit_scheduler = true;
+ } else {
+ /* schedule for next maintenace */
+ node->m_time += SYNC_TIME_OUT;
+ m_p_queue.push(node);
}
+
+
+ } else if ( type == CGenNode::EXIT_SCHED ) {
+ m_p_queue.pop();
+ thread->free_node(node);
+ exit_scheduler = true;
+
+ } else {
+ printf(" ERROR type is not valid %d \n",type);
+ assert(0);
}
- }
+
+ return exit_scheduler;
}
@@ -3809,11 +3857,15 @@ void CFlowGenListPerThread::handel_nat_msg(CGenNodeNatInfo * msg){
}
}
+void CFlowGenListPerThread::check_msgs(void) {
+
+ /* inlined for performance */
+ m_stateless_dp_info.periodic_check_for_cp_messages();
-void CFlowGenListPerThread::check_msgs(void){
- if ( likely ( m_ring_from_rx->isEmpty() ) ){
+ if ( likely ( m_ring_from_rx->isEmpty() ) ) {
return;
}
+
#ifdef NAT_TRACE_
printf(" %.03f got message from RX \n",now_sec());
#endif
@@ -3833,9 +3885,11 @@ void CFlowGenListPerThread::check_msgs(void){
case CGenNodeMsgBase::NAT_FIRST:
handel_nat_msg((CGenNodeNatInfo * )msg);
break;
+
case CGenNodeMsgBase::LATENCY_PKT:
handel_latecy_pkt_msg((CGenNodeLatencyPktInfo *) msg);
break;
+
default:
printf("ERROR pkt-thread message type is not valid %d \n",msg_type);
assert(0);
@@ -3845,8 +3899,49 @@ void CFlowGenListPerThread::check_msgs(void){
}
}
+void delay(int msec);
+
-void CFlowGenListPerThread::generate_erf(std::string erf_file_name,
+const uint8_t test_udp_pkt[]={
+ 0x00,0x00,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x00,0x00,
+ 0x08,0x00,
+
+ 0x45,0x00,0x00,0x81,
+ 0xaf,0x7e,0x00,0x00,
+ 0x12,0x11,0xd9,0x23,
+ 0x01,0x01,0x01,0x01,
+ 0x3d,0xad,0x72,0x1b,
+
+ 0x11,0x11,
+ 0x11,0x11,
+
+ 0x00,0x6d,
+ 0x00,0x00,
+
+ 0x64,0x31,0x3a,0x61,
+ 0x64,0x32,0x3a,0x69,0x64,
+ 0x32,0x30,0x3a,0xd0,0x0e,
+ 0xa1,0x4b,0x7b,0xbd,0xbd,
+ 0x16,0xc6,0xdb,0xc4,0xbb,0x43,
+ 0xf9,0x4b,0x51,0x68,0x33,0x72,
+ 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f,
+ 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3,
+ 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f,
+ 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39,
+ 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31,
+ 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d,
+ 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d,
+ 0xe7
+};
+
+void CFlowGenListPerThread::start_stateless_daemon(){
+ m_cur_time_sec = 0;
+ m_stateless_dp_info.start();
+}
+
+
+void CFlowGenListPerThread::start_generate_stateful(std::string erf_file_name,
CPreviewMode & preview){
/* now we are ready to generate*/
if ( m_cap_gen.size()==0 ){
@@ -3963,6 +4058,7 @@ int CFlowGenList::load_from_mac_file(std::string file_name) {
exit(-1);
}
+ return (0);
}
@@ -4435,9 +4531,12 @@ void CTupleTemplateGenerator::Generate(){
#endif
+static uint32_t get_rand_32(uint32_t MinimumRange,
+ uint32_t MaximumRange) __attribute__ ((unused));
+
+static uint32_t get_rand_32(uint32_t MinimumRange,
+ uint32_t MaximumRange) {
-static uint32_t get_rand_32(uint32_t MinimumRange ,
- uint32_t MaximumRange ){
enum {RANDS_NUM = 2 , RAND_MAX_BITS = 0xf , UNSIGNED_INT_BITS = 0x20 , TWO_BITS_MASK = 0x3};
const double TWO_POWER_32_BITS = 0x10000000 * (double)0x10;
@@ -4670,7 +4769,6 @@ void CCPortLatency::reset(){
static uint8_t nat_is_port_can_send(uint8_t port_id){
- uint8_t offset= ((port_id>>1)<<1);
uint8_t client_index = (port_id %2);
return (client_index ==0 ?1:0);
}
@@ -4792,7 +4890,7 @@ void CCPortLatency::dump_counters_json(std::string & json ){
}
void CCPortLatency::DumpCounters(FILE *fd){
- #define DP_A1(f) if (f) fprintf(fd," %-40s : %llu \n",#f,f)
+ #define DP_A1(f) if (f) fprintf(fd," %-40s : %llu \n",#f, (unsigned long long)f)
fprintf(fd," counter \n");
fprintf(fd," -----------\n");
@@ -4811,7 +4909,7 @@ void CCPortLatency::DumpCounters(FILE *fd){
fprintf(fd," -----------\n");
m_hist.Dump(fd);
- fprintf(fd," %-40s : %llu \n","jitter",get_jitter_usec());
+ fprintf(fd," %-40s : %lu \n","jitter", (ulong)get_jitter_usec());
}
bool CCPortLatency::dump_packet(rte_mbuf_t * m){
@@ -4835,6 +4933,9 @@ bool CCPortLatency::dump_packet(rte_mbuf_t * m){
if ( unlikely( CGlobalInfo::m_options.preview.get_vlan_mode_enable() ) ){
vlan_offset=4;
}
+
+ (void)vlan_offset;
+
// utl_DumpBuffer(stdout,p,pkt_size,0);
return (0);
@@ -4870,9 +4971,7 @@ bool CCPortLatency::check_packet(rte_mbuf_t * m,CRx_check_header * & rx_p){
uint16_t vlan_offset=parser.m_vlan_offset;
uint8_t *p=rte_pktmbuf_mtod(m, uint8_t*);
- rx_p=(CRx_check_header *)0;
- bool managed_by_ip_options=false;
- bool is_rx_check=true;
+ rx_p = (CRx_check_header *)0;
if ( !parser.IsLatencyPkt() ){
@@ -4989,7 +5088,7 @@ void CLatencyManager::Delete(){
static uint8_t swap_port(uint8_t port_id){
uint8_t offset= ((port_id>>1)<<1);
uint8_t client_index = (port_id %2);
- return (offset+client_index^1);
+ return (offset + (client_index ^ 1));
}
@@ -5112,8 +5211,6 @@ void CLatencyManager::run_rx_queue_msgs(uint8_t thread_id,
CGenNodeMsgBase * msg=(CGenNodeMsgBase *)node;
- CGenNodeLatencyPktInfo * msg1=(CGenNodeLatencyPktInfo *)msg;
-
uint8_t msg_type = msg->m_msg_type;
switch (msg_type ) {
case CGenNodeMsgBase::LATENCY_PKT:
@@ -5236,7 +5333,7 @@ void CLatencyManager::start(int iter){
}
if ( iter>0 ){
if ( ( cnt>iter) ){
- printf("stop due iter %d %d \n",iter);
+ printf("stop due iter %d\n",iter);
break;
}
}
@@ -5405,8 +5502,8 @@ void CLatencyManager::DumpRxCheckVerification(FILE *fd,
fprintf(fd," rx_checker is disabled \n");
return;
}
- fprintf(fd," rx_check Tx : %u \n",total_tx_rx_check);
- fprintf(fd," rx_check Rx : %u \n",m_rx_check_manager.getTotalRx() );
+ fprintf(fd," rx_check Tx : %llu \n", (unsigned long long)total_tx_rx_check);
+ fprintf(fd," rx_check Rx : %llu \n", (unsigned long long)m_rx_check_manager.getTotalRx() );
fprintf(fd," rx_check verification :" );
if (m_rx_check_manager.getTotalRx() == total_tx_rx_check) {
fprintf(fd," OK \n" );
@@ -6659,7 +6756,6 @@ bool CSimplePacketParser::Parse(){
EthernetHeader *m_ether = (EthernetHeader *)p;
IPHeader * ipv4=0;
IPv6Header * ipv6=0;
- uint16_t pkt_size=rte_pktmbuf_pkt_len(m);
m_vlan_offset=0;
m_option_offset=0;
diff --git a/src/bp_sim.h b/src/bp_sim.h
index b7cfb20b..36595581 100755
--- a/src/bp_sim.h
+++ b/src/bp_sim.h
@@ -57,6 +57,8 @@ limitations under the License.
#include <arpa/inet.h>
#include "platform_cfg.h"
+#include <trex_stateless_dp_core.h>
+
#undef NAT_TRACE_
@@ -360,6 +362,25 @@ public:
*/
virtual int flush_tx_queue(void)=0;
+
+ /**
+ * update the source and destination mac-addr of a given mbuf by global database
+ *
+ * @param dir
+ * @param m
+ *
+ * @return
+ */
+ virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m)=0;
+
+ /**
+ * translate a port_id to the correct dir on the core
+ *
+ */
+ virtual pkt_dir_t port_id_to_dir(uint8_t port_id) {
+ return (CS_INVALID);
+ }
+
public:
@@ -721,6 +742,7 @@ public:
m_run_mode = RUN_MODE_INVALID;
}
+
CPreviewMode preview;
float m_factor;
float m_duration;
@@ -741,9 +763,10 @@ public:
uint16_t m_run_flags;
uint8_t m_mac_splitter;
uint8_t m_pad;
-
trex_run_mode_e m_run_mode;
+
+
std::string cfg_file;
std::string mac_file;
std::string platform_cfg_file;
@@ -778,6 +801,10 @@ public:
return ( m_latency_rate == 0 ?true:false);
}
+ bool is_stateless(){
+ return (m_run_mode == RUN_MODE_INTERACTIVE ?true:false);
+ }
+
bool is_latency_enabled(){
return ( !is_latency_disabled() );
}
@@ -867,6 +894,8 @@ public:
/* number of main active sockets. socket #0 is always used */
virtual socket_id_t max_num_active_sockets()=0;
+ virtual ~CPlatformSocketInfoBase() {}
+
public:
/* which socket to allocate memory to each port */
virtual socket_id_t port_to_socket(port_id_t port)=0;
@@ -1181,12 +1210,15 @@ public:
public:
static CRteMemPool m_mem_pool[MAX_SOCKETS_SUPPORTED];
- static uint32_t m_nodes_pool_size;
- static CParserOption m_options;
- static CGlobalMemory m_memory_cfg;
- static CPlatformSocketInfo m_socket;
+ static uint32_t m_nodes_pool_size;
+ static CParserOption m_options;
+ static CGlobalMemory m_memory_cfg;
+ static CPlatformSocketInfo m_socket;
};
+static inline int get_is_stateless(){
+ return (CGlobalInfo::m_options.is_stateless() );
+}
static inline int get_is_rx_check_mode(){
return (CGlobalInfo::m_options.preview.get_is_rx_check_enable() ?1:0);
@@ -1307,8 +1339,8 @@ public:
-#define DP(f) if (f) printf(" %-40s: %llu \n",#f,f)
-#define DP_name(n,f) if (f) printf(" %-40s: %llu \n",n,f)
+#define DP(f) if (f) printf(" %-40s: %llu \n",#f,(unsigned long long)f)
+#define DP_name(n,f) if (f) printf(" %-40s: %llu \n",n,(unsigned long long)f)
#define DP_S(f,f_s) if (f) printf(" %-40s: %s \n",#f,f_s.c_str())
@@ -1333,15 +1365,18 @@ class CCapFileFlowInfo ;
/* this is a simple struct, do not add constructor and destractor here!
we are optimizing the allocation dealocation !!!
*/
-struct CGenNode {
+
+struct CGenNodeBase {
public:
enum {
- FLOW_PKT=0,
- FLOW_FIF=1,
- FLOW_DEFER_PORT_RELEASE=2,
- FLOW_PKT_NAT=3,
- FLOW_SYNC=4 /* called evey 1 msec */
+ FLOW_PKT =0,
+ FLOW_FIF =1,
+ FLOW_DEFER_PORT_RELEASE =2,
+ FLOW_PKT_NAT =3,
+ FLOW_SYNC =4, /* called evey 1 msec */
+ STATELESS_PKT =5,
+ EXIT_SCHED =6
};
@@ -1349,7 +1384,7 @@ public:
enum {
NODE_FLAGS_DIR =1,
NODE_FLAGS_MBUF_CACHE =2,
- NODE_FLAGS_SAMPLE_RX_CHECK =4,
+ NODE_FLAGS_SAMPLE_RX_CHECK =4,
NODE_FLAGS_LEARN_MODE =8, /* bits 3,4 MASK 0x18 wait for second direction packet */
NODE_FLAGS_LEARN_MSG_PROCESSED =0x10, /* got NAT msg */
@@ -1360,19 +1395,49 @@ public:
NODE_FLAGS_INIT_START_FROM_SERVER_SIDE_SERVER_ADDR = 0x100 /* init packet start from server side with server addr */
};
+
public:
- /* C1 */
+ /*********************************************/
+ /* C1 must */
uint8_t m_type;
uint8_t m_thread_id; /* zero base */
uint8_t m_socket_id;
- uint8_t m_pad2;
+ uint8_t m_pad2;
uint16_t m_src_port;
uint16_t m_flags; /* BIT 0 - DIR ,
BIT 1 - mbug_cache
BIT 2 - SAMPLE DUPLICATE */
- double m_time;
+ double m_time; /* can't change this header - size 16 bytes*/
+
+public:
+ bool operator <(const CGenNodeBase * rsh ) const {
+ return (m_time<rsh->m_time);
+ }
+ bool operator ==(const CGenNodeBase * rsh ) const {
+ return (m_time==rsh->m_time);
+ }
+ bool operator >(const CGenNodeBase * rsh ) const {
+ return (m_time>rsh->m_time);
+ }
+
+public:
+ void set_socket_id(socket_id_t socket){
+ m_socket_id=socket;
+ }
+
+ socket_id_t get_socket_id(){
+ return ( m_socket_id );
+ }
+
+
+};
+
+
+struct CGenNode : public CGenNodeBase {
+
+public:
uint32_t m_src_ip; /* client ip */
uint32_t m_dest_ip; /* server ip */
@@ -1402,25 +1467,8 @@ public:
uint32_t m_end_of_cache_line[6];
public:
- bool operator <(const CGenNode * rsh ) const {
- return (m_time<rsh->m_time);
- }
- bool operator ==(const CGenNode * rsh ) const {
- return (m_time==rsh->m_time);
- }
- bool operator >(const CGenNode * rsh ) const {
- return (m_time>rsh->m_time);
- }
-public:
void Dump(FILE *fd);
- void set_socket_id(socket_id_t socket){
- m_socket_id=socket;
- }
-
- socket_id_t get_socket_id(){
- return ( m_socket_id );
- }
static void DumpHeader(FILE *fd);
@@ -1603,6 +1651,7 @@ public:
} __rte_cache_aligned;
+
#if __x86_64__
/* size of 64 bytes */
#define DEFER_CLIENTS_NUM (16)
@@ -1647,19 +1696,29 @@ public:
need to clean this up and derive this objects from base object but require too much refactoring right now
hhaim
*/
+
+#define COMPARE_NODE_OBJECT(NODE_NAME) if ( sizeof(NODE_NAME) != sizeof(CGenNode) ) { \
+ printf("ERROR sizeof(%s) %lu != sizeof(CGenNode) %lu must be the same size \n",#NODE_NAME,sizeof(NODE_NAME),sizeof(CGenNode)); \
+ assert(0); \
+ }\
+ if ( (int)offsetof(struct NODE_NAME,m_type)!=offsetof(struct CGenNodeBase,m_type) ){\
+ printf("ERROR offsetof(struct %s,m_type)!=offsetof(struct CGenNodeBase,m_type) \n",#NODE_NAME);\
+ assert(0);\
+ }\
+ if ( (int)offsetof(struct CGenNodeDeferPort,m_time)!=offsetof(struct CGenNodeBase,m_time) ){\
+ printf("ERROR offsetof(struct %s,m_time)!=offsetof(struct CGenNodeBase,m_time) \n",#NODE_NAME);\
+ assert(0);\
+ }
+
+#define COMPARE_NODE_OBJECT_SIZE(NODE_NAME) if ( sizeof(NODE_NAME) != sizeof(CGenNode) ) { \
+ printf("ERROR sizeof(%s) %lu != sizeof(CGenNode) %lu must be the same size \n",#NODE_NAME,sizeof(NODE_NAME),sizeof(CGenNode)); \
+ assert(0); \
+ }
+
+
+
inline int check_objects_sizes(void){
- if ( sizeof(CGenNodeDeferPort) != sizeof(CGenNode) ) {
- printf("ERROR sizeof(CGenNodeDeferPort) %lu != sizeof(CGenNode) %lu must be the same size \n",sizeof(CGenNodeDeferPort),sizeof(CGenNode));
- assert(0);
- }
- if ( (int)offsetof(struct CGenNodeDeferPort,m_type)!=offsetof(struct CGenNode,m_type) ){
- printf("ERROR offsetof(struct CGenNodeDeferPort,m_type)!=offsetof(struct CGenNode,m_type) \n");
- assert(0);
- }
- if ( (int)offsetof(struct CGenNodeDeferPort,m_time)!=offsetof(struct CGenNode,m_time) ){
- printf("ERROR offsetof(struct CGenNodeDeferPort,m_time)!=offsetof(struct CGenNode,m_time) \n");
- assert(0);
- }
+ COMPARE_NODE_OBJECT(CGenNodeDeferPort);
return (0);
}
@@ -1718,6 +1777,11 @@ public:
virtual int write_pkt(CCapPktRaw *pkt_raw);
virtual int close_file(void);
+ virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){
+ return (0);
+ }
+
+
/**
* send one packet
@@ -1779,6 +1843,10 @@ public:
return (0);
}
+ virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){
+ return (0);
+ }
+
virtual int send_node(CGenNode * node);
@@ -1799,6 +1867,7 @@ public:
CFlowGenListPerThread * Parent(){
return (m_parent);
}
+
public:
void add_node(CGenNode * mynode);
void remove_all(CFlowGenListPerThread * thread);
@@ -1830,11 +1899,14 @@ public:
private:
- int flush_one_node_to_file(CGenNode * node);
+ inline int flush_one_node_to_file(CGenNode * node){
+ return (m_v_if->send_node(node));
+ }
int update_stats(CGenNode * node);
- FORCE_NO_INLINE void handle_slow_messages(uint8_t type,
- CGenNode * node,
- CFlowGenListPerThread * thread,
+
+ FORCE_NO_INLINE bool handle_slow_messages(uint8_t type,
+ CGenNode * node,
+ CFlowGenListPerThread * thread,
bool always);
@@ -2310,6 +2382,7 @@ public:
return (uint32_t)((uintptr_t)( ((char *)l3.m_ipv4)-getBasePtr()) );
}else{
BP_ASSERT(0);
+ return (0);
}
}
@@ -3325,13 +3398,21 @@ public :
inline CGenNode * create_node(void);
+ inline CGenNodeStateless * create_node_sl(void){
+ return ((CGenNodeStateless*)create_node() );
+ }
+
+
inline void free_node(CGenNode *p);
inline void free_last_flow_node(CGenNode *p);
public:
void Clean();
- void generate_erf(std::string erf_file_name,CPreviewMode &preview);
+ void start_generate_stateful(std::string erf_file_name,CPreviewMode &preview);
+ void start_stateless_daemon();
+
+
void Dump(FILE *fd);
void DumpCsv(FILE *fd);
void DumpStats(FILE *fd);
@@ -3344,6 +3425,7 @@ public:
private:
void check_msgs(void);
+
void handel_nat_msg(CGenNodeNatInfo * msg);
void handel_latecy_pkt_msg(CGenNodeLatencyPktInfo * msg);
@@ -3421,7 +3503,12 @@ private:
CNodeRing * m_ring_to_rx; /* ring dp -> latency thread */
flow_id_node_t m_flow_id_to_node_lookup;
-};
+
+ TrexStatelessDpCore m_stateless_dp_info;
+
+private:
+ uint8_t m_cacheline_pad[RTE_CACHE_LINE_SIZE][19]; // improve prefech
+} __rte_cache_aligned ;
inline CGenNode * CFlowGenListPerThread::create_node(void){
CGenNode * res;
diff --git a/src/common/Network/Packet/IPHeader.cpp b/src/common/Network/Packet/IPHeader.cpp
index 3b90a1aa..c3363603 100755
--- a/src/common/Network/Packet/IPHeader.cpp
+++ b/src/common/Network/Packet/IPHeader.cpp
@@ -52,7 +52,7 @@ void IPHeader::dump(FILE *fd)
{
fprintf(fd, "\nIPHeader");
fprintf(fd, "\nSource 0x%.8lX, Destination 0x%.8lX, Protocol 0x%.1X",
- getSourceIp(), getDestIp(), getProtocol());
+ (ulong)getSourceIp(), (ulong)getDestIp(), (uint)getProtocol());
fprintf(fd, "\nTTL : %d, Id : 0x%.2X, Ver %d, Header Length %d, Total Length %d",
getTimeToLive(), getId(), getVersion(), getHeaderLength(), getTotalLength());
if(isFragmented())
diff --git a/src/common/Network/Packet/TCPHeader.cpp b/src/common/Network/Packet/TCPHeader.cpp
index bf28db2e..1826cef8 100755
--- a/src/common/Network/Packet/TCPHeader.cpp
+++ b/src/common/Network/Packet/TCPHeader.cpp
@@ -25,7 +25,7 @@ void TCPHeader::dump(FILE *fd)
fprintf(fd, "\nSourcePort 0x%.4X, DestPort 0x%.4X",
getSourcePort(), getDestPort());
fprintf(fd, "\nSeqNum 0x%.8lX, AckNum 0x%.8lX, Window %d",
- getSeqNumber(), getAckNumber(), getWindowSize());
+ (ulong)getSeqNumber(), (ulong)getAckNumber(), getWindowSize());
fprintf(fd, "\nHeader Length : %d, Checksum : 0x%.4X",
getHeaderLength(), getChecksum());
fprintf(fd, "\nFlags : SYN - %d, FIN - %d, ACK - %d, URG - %d, RST - %d, PSH - %d",
diff --git a/src/common/c_common.h b/src/common/c_common.h
index d8320aaa..3e43644f 100755
--- a/src/common/c_common.h
+++ b/src/common/c_common.h
@@ -46,7 +46,7 @@ typedef void* c_pvoid;
#ifdef _DEBUG
#define BP_ASSERT(a) assert(a)
#else
- #define BP_ASSERT(a)
+ #define BP_ASSERT(a) (void (a))
#endif
#endif
diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp
index 250d5342..6b8e3eff 100644
--- a/src/gtest/rpc_test.cpp
+++ b/src/gtest/rpc_test.cpp
@@ -30,6 +30,8 @@ limitations under the License.
using namespace std;
+uint16_t gtest_get_mock_server_port();
+
class RpcTest : public testing::Test {
protected:
@@ -44,7 +46,12 @@ protected:
m_context = zmq_ctx_new ();
m_socket = zmq_socket (m_context, ZMQ_REQ);
- zmq_connect (m_socket, "tcp://localhost:5050");
+
+ std::stringstream ss;
+ ss << "tcp://localhost:";
+ ss << gtest_get_mock_server_port();
+
+ zmq_connect (m_socket, ss.str().c_str());
}
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 0341516c..2bab4dff 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -82,7 +82,7 @@ private:
void CTRexDpStreamModeSingleBurst::dump(FILE *fd){
fprintf (fd," pps : %f \n",m_pps);
- fprintf (fd," total_packets : %llu \n",m_total_packets);
+ fprintf (fd," total_packets : %llu \n", (unsigned long long)m_total_packets);
}
@@ -130,9 +130,9 @@ private:
void CTRexDpStreamModeMultiBurst::dump(FILE *fd){
fprintf (fd," pps : %f \n",m_pps);
- fprintf (fd," total_packets : %llu \n",m_pkts_per_burst);
+ fprintf (fd," total_packets : %llu \n", (unsigned long long)m_pkts_per_burst);
fprintf (fd," ibg : %f \n",m_ibg);
- fprintf (fd," num_of_bursts : %llu \n",m_number_of_bursts);
+ fprintf (fd," num_of_bursts : %lu \n", (ulong)m_number_of_bursts);
}
diff --git a/src/gtest/tuple_gen_test.cpp b/src/gtest/tuple_gen_test.cpp
index 8a774e38..f3b9fa1e 100755
--- a/src/gtest/tuple_gen_test.cpp
+++ b/src/gtest/tuple_gen_test.cpp
@@ -161,7 +161,6 @@ TEST(tuple_gen,clientPoolL) {
0,0);
CTupleBase result;
uint32_t result_src;
- uint32_t result_dest;
uint16_t result_port;
for(int i=0;i<10;i++) {
@@ -186,7 +185,6 @@ TEST(tuple_gen,clientPool) {
0,0);
CTupleBase result;
uint32_t result_src;
- uint32_t result_dest;
uint16_t result_port;
for(int i=0;i<10;i++) {
@@ -436,7 +434,6 @@ TEST(tuple_gen,template1) {
template_1.GenerateTuple(result);
uint32_t result_src = result.getClient();
uint32_t result_dest = result.getServer();
- uint16_t result_port = result.getClientPort();
//printf(" %x %x %x \n",result_src,result_dest,result_port);
EXPECT_EQ(result_src, (uint32_t)(0x10000001+i));
EXPECT_EQ(result_dest, (uint32_t)(((0x12121212)) ));
@@ -489,9 +486,6 @@ TEST(tuple_gen,no_free) {
int i;
for (i=0; i<65557; i++) {
template_1.GenerateTuple(result);
- uint32_t result_src = result.getClient();
- uint32_t result_dest = result.getServer();
- uint16_t result_port = result.getClientPort();
}
// should have error
EXPECT_TRUE((gen.getErrorAllocationCounter()>0)?true:false);
@@ -514,8 +508,6 @@ TEST(tuple_gen,try_to_free) {
int i;
for (i=0; i<65557; i++) {
template_1.GenerateTuple(result);
- uint32_t result_src = result.getClient();
- uint32_t result_dest = result.getServer();
uint16_t result_port = result.getClientPort();
gen.FreePort(0,result.getClientId(),result_port);
}
diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h
new file mode 100644
index 00000000..5890a965
--- /dev/null
+++ b/src/internal_api/trex_platform_api.h
@@ -0,0 +1,134 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+
+#ifndef __TREX_PLATFORM_API_H__
+#define __TREX_PLATFORM_API_H__
+
+#include <stdint.h>
+#include <vector>
+
+/**
+ * Global stats
+ *
+ * @author imarom (06-Oct-15)
+ */
+class TrexPlatformGlobalStats {
+public:
+ TrexPlatformGlobalStats() {
+ m_stats = {0};
+ }
+
+ struct {
+ double m_cpu_util;
+
+ double m_tx_bps;
+ double m_rx_bps;
+
+ double m_tx_pps;
+ double m_rx_pps;
+
+ uint64_t m_total_tx_pkts;
+ uint64_t m_total_rx_pkts;
+
+ uint64_t m_total_tx_bytes;
+ uint64_t m_total_rx_bytes;
+
+ uint64_t m_tx_rx_errors;
+ } m_stats;
+};
+
+/**
+ * Per Interface stats
+ *
+ * @author imarom (26-Oct-15)
+ */
+class TrexPlatformInterfaceStats {
+
+public:
+ TrexPlatformInterfaceStats() {
+ m_stats = {0};
+ }
+
+public:
+
+ struct {
+
+ double m_tx_bps;
+ double m_rx_bps;
+
+ double m_tx_pps;
+ double m_rx_pps;
+
+ uint64_t m_total_tx_pkts;
+ uint64_t m_total_rx_pkts;
+
+ uint64_t m_total_tx_bytes;
+ uint64_t m_total_rx_bytes;
+
+ uint64_t m_tx_rx_errors;
+ } m_stats;
+};
+
+
+/**
+ * low level API interface
+ * can be implemented by DPDK or mock
+ *
+ * @author imarom (25-Oct-15)
+ */
+
+class TrexPlatformApi {
+public:
+ virtual void port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list) const = 0;
+ virtual void get_global_stats(TrexPlatformGlobalStats &stats) const = 0;
+ virtual void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const = 0;
+ virtual uint8_t get_dp_core_count() const = 0;
+ virtual ~TrexPlatformApi() {}
+};
+
+
+/**
+ * DPDK implementation of the platform API
+ *
+ * @author imarom (26-Oct-15)
+ */
+class TrexDpdkPlatformApi : public TrexPlatformApi {
+public:
+ void port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list) const;
+ void get_global_stats(TrexPlatformGlobalStats &stats) const;
+ void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const;
+ uint8_t get_dp_core_count() const;
+};
+
+/**
+ * MOCK implementation of the platform API
+ *
+ * @author imarom (26-Oct-15)
+ */
+class TrexMockPlatformApi : public TrexPlatformApi {
+public:
+ void port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list) const {}
+ void get_global_stats(TrexPlatformGlobalStats &stats) const;
+ void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const;
+ uint8_t get_dp_core_count() const;
+};
+
+#endif /* __TREX_PLATFORM_API_H__ */
diff --git a/src/main.cpp b/src/main.cpp
index 96789cdd..df9d8b40 100755
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -185,25 +185,6 @@ int curent_time(){
#include <pthread.h>
-void delay(int msec){
-
- if (msec == 0)
- {//user that requested that probebly wanted the minimal delay
- //but because of scaling problem he have got 0 so we will give the min delay
- //printf("\n\n\nERROR-Task delay ticks == 0 found in task %s task id = %d\n\n\n\n",
- // SANB_TaskName(SANB_TaskIdSelf()), SANB_TaskIdSelf());
- msec =1;
-
- }
-
- struct timespec time1, remain; // 2 sec max delay
- time1.tv_sec=msec/1000;
- time1.tv_nsec=(msec - (time1.tv_sec*1000))*1000000;
-
- nanosleep(&time1,&remain);
-}
-
-
struct per_thread_t {
pthread_t tid;
};
@@ -233,11 +214,12 @@ void * thread_task(void *info){
char buf[100];
sprintf(buf,"my%d.erf",obj->thread_id);
- volatile int i;
- lpt->generate_erf(buf,*obj->preview_info);
+ lpt->start_generate_stateful(buf,*obj->preview_info);
lpt->m_node_gen.DumpHist(stdout);
printf("end thread %d \n",obj->thread_id);
}
+
+ return (NULL);
}
@@ -325,7 +307,7 @@ void test_load_list_of_cap_files(CParserOption * op){
lpt=fl.m_threads_info[i];
char buf[100];
sprintf(buf,"my%d.erf",i);
- lpt->generate_erf(buf,op->preview);
+ lpt->start_generate_stateful(buf,op->preview);
lpt->m_node_gen.DumpHist(stdout);
}
//sprintf(buf,"my%d.erf",7);
@@ -353,7 +335,7 @@ int load_list_of_cap_files(CParserOption * op){
lpt->set_vif(&erf_vif);
if ( (op->preview.getVMode() >1) || op->preview.getFileWrite() ) {
- lpt->generate_erf(op->out_file,op->preview);
+ lpt->start_generate_stateful(op->out_file,op->preview);
}
lpt->m_node_gen.DumpHist(stdout);
@@ -424,8 +406,6 @@ void update_tcp_seq_num(CCapFileFlowInfo * obj,
int i;
for (i=pkt_id+1; i<s; i++) {
- uint32_t seq;
- uint32_t ack;
pkt=obj->GetPacket(i);
tcp=pkt->m_pkt_indication.l4.m_tcp;
@@ -509,7 +489,7 @@ int manipolate_capfile() {
CCapFileFlowInfo flow_info;
flow_info.Create();
- int res=flow_info.load_cap_file("avl/delay_10_rtsp_0.pcap",0,0);
+ flow_info.load_cap_file("avl/delay_10_rtsp_0.pcap",0,0);
change_pkt_len(&flow_info,4-1 ,6);
change_pkt_len(&flow_info,5-1 ,6);
@@ -534,7 +514,7 @@ int manipolate_capfile_sip() {
CCapFileFlowInfo flow_info;
flow_info.Create();
- int res=flow_info.load_cap_file("avl/delay_10_sip_0.pcap",0,0);
+ flow_info.load_cap_file("avl/delay_10_sip_0.pcap",0,0);
change_pkt_len(&flow_info,1-1 ,6+6);
change_pkt_len(&flow_info,2-1 ,6+6);
@@ -551,8 +531,8 @@ int manipolate_capfile_sip1() {
CCapFileFlowInfo flow_info;
flow_info.Create();
- int res=flow_info.load_cap_file("avl/delay_sip_0.pcap",0,0);
- CFlowPktInfo * pkt=flow_info.GetPacket(1);
+ flow_info.load_cap_file("avl/delay_sip_0.pcap",0,0);
+ flow_info.GetPacket(1);
change_pkt_len(&flow_info,1-1 ,6+6+10);
@@ -588,7 +568,7 @@ public:
void CMergeCapFileRec::Dump(FILE *fd,int _id){
- double time;
+ double time = 0.0;
bool stop=GetCurPacket(time);
fprintf (fd," id:%2d stop : %d index:%4d %3.4f \n",_id,stop?1:0,m_index,time);
}
@@ -639,6 +619,8 @@ bool CMergeCapFileRec::Create(std::string cap_file,
m_limit_number_of_packets =0;
m_start_time = pkt->m_packet->get_time() ;
m_offset = offset;
+
+ return (true);
}
@@ -682,12 +664,12 @@ bool CMergeCapFile::run_merge(std::string to_cap_file){
int min_index=0;
double min_time;
- fprintf(stdout," --------------\n",cnt);
+ fprintf(stdout," --------------\n");
fprintf(stdout," pkt : %d \n",cnt);
for (i=0; i<MERGE_CAP_FILES; i++) {
m[i].Dump(stdout,i);
}
- fprintf(stdout," --------------\n",cnt);
+ fprintf(stdout," --------------\n");
bool valid = false;
for (i=0; i<MERGE_CAP_FILES; i++) {
@@ -721,6 +703,8 @@ bool CMergeCapFile::run_merge(std::string to_cap_file){
};
m_results.save_to_erf(to_cap_file,1);
+
+ return (true);
}
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp
index a0af9fdf..c4ecb97d 100755
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -55,7 +55,10 @@ limitations under the License.
#include <common/arg/SimpleGlob.h>
#include <common/arg/SimpleOpt.h>
#include <common/basic_utils.h>
+
#include <stateless/cp/trex_stateless.h>
+#include <stateless/dp/trex_stream_node.h>
+
#include <../linux_dpdk/version.h>
extern "C" {
@@ -73,6 +76,7 @@ extern "C" {
#include "msg_manager.h"
#include "platform_cfg.h"
+#include <internal_api/trex_platform_api.h>
#define RX_CHECK_MIX_SAMPLE_RATE 8
#define RX_CHECK_MIX_SAMPLE_RATE_1G 2
@@ -104,8 +108,6 @@ extern "C" int vmxnet3_xmit_set_callback(rte_mbuf_convert_to_one_seg_t cb);
#define RTE_TEST_TX_DESC_DEFAULT 512
#define RTE_TEST_RX_DESC_DROP 0
-
-
static inline int get_vm_one_queue_enable(){
return (CGlobalInfo::m_options.preview.get_vm_one_queue_enable() ?1:0);
}
@@ -686,12 +688,13 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
CSimpleOpt args(argc, argv, parser_options);
bool latency_was_set=false;
+ (void)latency_was_set;
+
int a=0;
int node_dump=0;
po->preview.setFileWrite(true);
po->preview.setRealTime(true);
- int res1;
uint32_t tmp_data;
po->m_run_mode = CParserOption::RUN_MODE_INVALID;
@@ -928,40 +931,30 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
}
}
- return 0;
-}
-
-
-int main_test(int argc , char * argv[]);
-
-
-
-
-void delay(int msec){
-
- if (msec == 0)
- {//user that requested that probebly wanted the minimal delay
- //but because of scaling problem he have got 0 so we will give the min delay
- //printf("\n\n\nERROR-Task delay ticks == 0 found in task %s task id = %d\n\n\n\n",
- // SANB_TaskName(SANB_TaskIdSelf()), SANB_TaskIdSelf());
- msec =1;
+ if ( get_is_stateless() ) {
+ if ( po->preview.get_is_rx_check_enable() ) {
+ parse_err("Rx check is not supported with interactive mode ");
+ }
- }
+ if ( (! po->is_latency_disabled()) || (po->preview.getOnlyLatency()) ){
+ parse_err("Latecny check is not supported with interactive mode ");
+ }
- struct timespec time1, remain; // 2 sec max delay
- time1.tv_sec=msec/1000;
- time1.tv_nsec=(msec - (time1.tv_sec*1000))*1000000;
+ if ( po->preview.getSingleCore() ){
+ parse_err("single core is not supported with interactive mode ");
+ }
- nanosleep(&time1,&remain);
+ }
+ return 0;
}
-
-static const char * default_argv[] = {"xx","-c", "0x7", "-n","2","-b","0000:0b:01.01"};
-static int argv_num = 7;
-
+int main_test(int argc , char * argv[]);
+//static const char * default_argv[] = {"xx","-c", "0x7", "-n","2","-b","0000:0b:01.01"};
+//static int argv_num = 7;
+
#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
@@ -1145,8 +1138,8 @@ void CPhyEthIFStats::Clear(){
void CPhyEthIFStats::DumpAll(FILE *fd){
- #define DP_A4(f) printf(" %-40s : %llu \n",#f,f)
- #define DP_A(f) if (f) printf(" %-40s : %llu \n",#f,f)
+ #define DP_A4(f) printf(" %-40s : %llu \n",#f, (unsigned long long)f)
+ #define DP_A(f) if (f) printf(" %-40s : %llu \n",#f, (unsigned long long)f)
DP_A4(opackets);
DP_A4(obytes);
DP_A4(ipackets);
@@ -1185,7 +1178,7 @@ public:
m_port_id = portid;
m_last_rx_rate = 0.0;
m_last_tx_rate = 0.0;
- m_last_pps=0.0;
+ m_last_tx_pps = 0.0;
return (true);
}
void Delete();
@@ -1261,8 +1254,12 @@ public:
return (m_last_rx_rate);
}
- float get_last_pps_rate(){
- return (m_last_pps);
+ float get_last_tx_pps_rate(){
+ return (m_last_tx_pps);
+ }
+
+ float get_last_rx_pps_rate(){
+ return (m_last_rx_pps);
}
CPhyEthIFStats & get_stats(){
@@ -1315,12 +1312,14 @@ private:
CBwMeasure m_bw_tx;
CBwMeasure m_bw_rx;
CPPSMeasure m_pps_tx;
+ CPPSMeasure m_pps_rx;
CPhyEthIFStats m_stats;
- float m_last_rx_rate;
float m_last_tx_rate;
- float m_last_pps;
+ float m_last_rx_rate;
+ float m_last_tx_pps;
+ float m_last_rx_pps;
public:
struct rte_eth_dev_info m_dev_info;
};
@@ -1615,10 +1614,6 @@ void CPhyEthIF::macaddr_get(struct ether_addr *mac_addr){
void CPhyEthIF::get_stats_1g(CPhyEthIFStats *stats){
- int i;
- uint64_t t=0;
-
-
stats->ipackets += pci_reg_read(E1000_GPRC) ;
stats->ibytes += (pci_reg_read(E1000_GORCL) );
@@ -1656,7 +1651,8 @@ void CPhyEthIF::get_stats_1g(CPhyEthIFStats *stats){
m_last_tx_rate = m_bw_tx.add(stats->obytes);
m_last_rx_rate = m_bw_rx.add(stats->ibytes);
- m_last_pps = m_pps_tx.add(stats->opackets);
+ m_last_tx_pps = m_pps_tx.add(stats->opackets);
+ m_last_rx_pps = m_pps_rx.add(stats->ipackets);
}
@@ -1666,14 +1662,15 @@ void CPhyEthIF::get_stats(CPhyEthIFStats *stats){
m_last_tx_rate = m_bw_tx.add(stats->obytes);
m_last_rx_rate = m_bw_rx.add(stats->ibytes);
- m_last_pps = m_pps_tx.add(stats->opackets);
+ m_last_tx_pps = m_pps_tx.add(stats->opackets);
+ m_last_rx_pps = m_pps_rx.add(stats->ipackets);
}
void dump_hw_state(FILE *fd,struct ixgbe_hw_stats *hs ){
- #define DP_A1(f) if (hs->f) fprintf(fd," %-40s : %llu \n",#f,hs->f)
- #define DP_A2(f,m) for (i=0;i<m; i++) { if (hs->f[i]) fprintf(fd," %-40s[%d] : %llu \n",#f,i,hs->f[i]); }
+ #define DP_A1(f) if (hs->f) fprintf(fd," %-40s : %llu \n",#f, (unsigned long long)hs->f)
+ #define DP_A2(f,m) for (i=0;i<m; i++) { if (hs->f[i]) fprintf(fd," %-40s[%d] : %llu \n",#f,i, (unsigned long long)hs->f[i]); }
int i;
//for (i=0;i<8; i++) { if (hs->mpc[i]) fprintf(fd," %-40s[%d] : %llu \n","mpc",i,hs->mpc[i]); }
@@ -1855,6 +1852,9 @@ public:
bool process_rx_pkt(pkt_dir_t dir,rte_mbuf_t * m);
+ virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m);
+
+ virtual pkt_dir_t port_id_to_dir(uint8_t port_id);
public:
void GetCoreCounters(CVirtualIFPerSideStats *stats);
@@ -1867,7 +1867,11 @@ public:
return ( CGlobalInfo::m_socket.port_to_socket( m_ports[0].m_port->get_port_id() ) );
}
-private:
+ const CCorePerPort * get_ports() {
+ return m_ports;
+ }
+
+protected:
int send_burst(CCorePerPort * lp_port,
uint16_t len,
@@ -1878,13 +1882,21 @@ private:
-private:
+protected:
uint8_t m_core_id;
uint16_t m_mbuf_cache;
CCorePerPort m_ports[CS_NUM]; /* each core has 2 tx queues 1. client side and server side */
CNodeRing * m_ring_to_rx;
+
+} __rte_cache_aligned; ;
+
+class CCoreEthIFStateless : public CCoreEthIF {
+public:
+ virtual int send_node(CGenNode * node);
};
+
+
bool CCoreEthIF::Create(uint8_t core_id,
uint16_t tx_client_queue_id,
CPhyEthIF * tx_client_port,
@@ -1985,6 +1997,7 @@ void CCoreEthIF::flush_rx_queue(void){
}
}
+
int CCoreEthIF::flush_tx_queue(void){
/* flush both sides */
pkt_dir_t dir ;
@@ -2084,6 +2097,8 @@ int CCoreEthIF::send_burst(CCorePerPort * lp_port,
rte_pktmbuf_free(m);
}
}
+
+ return (0);
}
@@ -2104,6 +2119,8 @@ int CCoreEthIF::send_pkt(CCorePerPort * lp_port,
len = 0;
}
lp_port->m_len = len;
+
+ return (0);
}
@@ -2140,6 +2157,23 @@ void CCoreEthIF::update_mac_addr(CGenNode * node,uint8_t *p){
}
+
+int CCoreEthIFStateless::send_node(CGenNode * no){
+ CGenNodeStateless * node_sl=(CGenNodeStateless *) no;
+
+ /* check that we have mbuf */
+ rte_mbuf_t * m=node_sl->get_cache_mbuf();
+ assert( m );
+ pkt_dir_t dir=(pkt_dir_t)node_sl->get_mbuf_cache_dir();
+ CCorePerPort * lp_port=&m_ports[dir];
+ CVirtualIFPerSideStats * lp_stats = &m_stats[dir];
+ rte_pktmbuf_refcnt_update(m,1);
+ send_pkt(lp_port,m,lp_stats);
+ return (0);
+};
+
+
+
int CCoreEthIF::send_node(CGenNode * node){
if ( unlikely( node->get_cache_mbuf() !=NULL ) ) {
@@ -2233,6 +2267,29 @@ int CCoreEthIF::send_node(CGenNode * node){
}
+int CCoreEthIF::update_mac_addr_from_global_cfg(pkt_dir_t dir,
+ rte_mbuf_t *m){
+ assert(m);
+ assert(dir<2);
+ CCorePerPort * lp_port=&m_ports[dir];
+ uint8_t *p=rte_pktmbuf_mtod(m, uint8_t*);
+ uint8_t p_id=lp_port->m_port->get_port_id();
+
+ memcpy(p,CGlobalInfo::m_options.get_dst_src_mac_addr(p_id),12);
+ return (0);
+}
+
+pkt_dir_t
+CCoreEthIF::port_id_to_dir(uint8_t port_id) {
+
+ for (pkt_dir_t dir = 0; dir < CS_NUM; dir++) {
+ if (m_ports[dir].m_port->get_port_id() == port_id) {
+ return dir;
+ }
+ }
+
+ return (CS_INVALID);
+}
class CLatencyHWPort : public CPortLatencyHWBase {
public:
@@ -2420,6 +2477,10 @@ public:
uint64_t oerrors;
float m_total_tx_bps;
+ float m_total_tx_pps;
+
+ float m_total_rx_bps;
+ float m_total_rx_pps;
};
class CGlobalStats {
@@ -2456,6 +2517,7 @@ public:
float m_tx_bps;
float m_rx_bps;
float m_tx_pps;
+ float m_rx_pps;
float m_tx_cps;
float m_tx_expected_cps;
float m_tx_expected_pps;
@@ -2488,7 +2550,7 @@ std::string CGlobalStats::get_field(std::string name,float &f){
std::string CGlobalStats::get_field(std::string name,uint64_t &f){
char buff[200];
- sprintf(buff,"\"%s\":%llu,",name.c_str(),f);
+ sprintf(buff,"\"%s\":%llu,",name.c_str(), (unsigned long long)f);
return (std::string(buff));
}
@@ -2500,7 +2562,7 @@ std::string CGlobalStats::get_field_port(int port,std::string name,float &f){
std::string CGlobalStats::get_field_port(int port,std::string name,uint64_t &f){
char buff[200];
- sprintf(buff,"\"%s-%d\":%llu,",name.c_str(),port,f);
+ sprintf(buff,"\"%s-%d\":%llu,",name.c_str(),port, (unsigned long long)f);
return (std::string(buff));
}
@@ -2516,6 +2578,7 @@ void CGlobalStats::dump_json(std::string & json){
json+=GET_FIELD(m_tx_bps);
json+=GET_FIELD(m_rx_bps);
json+=GET_FIELD(m_tx_pps);
+ json+=GET_FIELD(m_rx_pps);
json+=GET_FIELD(m_tx_cps);
json+=GET_FIELD(m_tx_expected_cps);
json+=GET_FIELD(m_tx_expected_pps);
@@ -2550,6 +2613,9 @@ void CGlobalStats::dump_json(std::string & json){
json+=GET_FIELD_PORT(i,ierrors) ;
json+=GET_FIELD_PORT(i,oerrors) ;
json+=GET_FIELD_PORT(i,m_total_tx_bps);
+ json+=GET_FIELD_PORT(i,m_total_tx_pps);
+ json+=GET_FIELD_PORT(i,m_total_rx_bps);
+ json+=GET_FIELD_PORT(i,m_total_rx_pps);
}
json+=m_template.dump_as_json("template");
json+="\"unknown\":0}}" ;
@@ -2569,7 +2635,7 @@ void CGlobalStats::DumpAllPorts(FILE *fd){
fprintf (fd," Platform_factor : %2.1f \n",m_platform_factor);
fprintf (fd," Total-Tx : %s ",double_to_human_str(m_tx_bps,"bps",KBYE_1000).c_str());
if ( CGlobalInfo::is_learn_mode() ) {
- fprintf (fd," Nat_time_out : %8llu \n",m_total_nat_time_out);
+ fprintf (fd," Nat_time_out : %8llu \n", (unsigned long long)m_total_nat_time_out);
}else{
fprintf (fd,"\n");
}
@@ -2577,49 +2643,52 @@ void CGlobalStats::DumpAllPorts(FILE *fd){
fprintf (fd," Total-Rx : %s ",double_to_human_str(m_rx_bps,"bps",KBYE_1000).c_str());
if ( CGlobalInfo::is_learn_mode() ) {
- fprintf (fd," Nat_no_fid : %8llu \n",m_total_nat_no_fid);
+ fprintf (fd," Nat_no_fid : %8llu \n", (unsigned long long)m_total_nat_no_fid);
}else{
fprintf (fd,"\n");
}
fprintf (fd," Total-PPS : %s ",double_to_human_str(m_tx_pps,"pps",KBYE_1000).c_str());
if ( CGlobalInfo::is_learn_mode() ) {
- fprintf (fd," Total_nat_active: %8llu \n",m_total_nat_active);
+ fprintf (fd," Total_nat_active: %8llu \n", (unsigned long long)m_total_nat_active);
}else{
fprintf (fd,"\n");
}
fprintf (fd," Total-CPS : %s ",double_to_human_str(m_tx_cps,"cps",KBYE_1000).c_str());
if ( CGlobalInfo::is_learn_mode() ) {
- fprintf (fd," Total_nat_open : %8llu \n",m_total_nat_open);
+ fprintf (fd," Total_nat_open : %8llu \n", (unsigned long long)m_total_nat_open);
}else{
fprintf (fd,"\n");
}
fprintf (fd,"\n");
fprintf (fd," Expected-PPS : %s ",double_to_human_str(m_tx_expected_pps,"pps",KBYE_1000).c_str());
if ( CGlobalInfo::is_learn_verify_mode() ) {
- fprintf (fd," Nat_learn_errors: %8llu \n",m_total_nat_learn_error);
+ fprintf (fd," Nat_learn_errors: %8llu \n", (unsigned long long)m_total_nat_learn_error);
}else{
fprintf (fd,"\n");
}
fprintf (fd," Expected-CPS : %s \n",double_to_human_str(m_tx_expected_cps,"cps",KBYE_1000).c_str());
fprintf (fd," Expected-BPS : %s \n",double_to_human_str(m_tx_expected_bps,"bps",KBYE_1000).c_str());
fprintf (fd,"\n");
- fprintf (fd," Active-flows : %8llu Clients : %8llu Socket-util : %3.4f %% \n",(uint64_t)m_active_flows,m_total_clients,m_socket_util);
+ fprintf (fd," Active-flows : %8llu Clients : %8llu Socket-util : %3.4f %% \n",
+ (unsigned long long)m_active_flows,
+ (unsigned long long)m_total_clients,
+ m_socket_util);
fprintf (fd," Open-flows : %8llu Servers : %8llu Socket : %8llu Socket/Clients : %.1f \n",
- (uint64_t)m_open_flows,
- m_total_servers,
- m_active_sockets,
+ (unsigned long long)m_open_flows,
+ (unsigned long long)m_total_servers,
+ (unsigned long long)m_active_sockets,
(float)m_active_sockets/(float)m_total_clients);
if (m_total_alloc_error) {
- fprintf (fd," Total_alloc_err : %llu \n",(uint64_t)m_total_alloc_error);
+ fprintf (fd," Total_alloc_err : %llu \n", (unsigned long long)m_total_alloc_error);
}
if ( m_total_queue_full ){
- fprintf (fd," Total_queue_full : %llu \n",(uint64_t)m_total_queue_full);
+ fprintf (fd," Total_queue_full : %llu \n", (unsigned long long)m_total_queue_full);
}
if (m_total_queue_drop) {
- fprintf (fd," Total_queue_drop : %llu \n",(uint64_t)m_total_queue_drop);
+ fprintf (fd," Total_queue_drop : %llu \n", (unsigned long long)m_total_queue_drop);
}
//m_template.Dump(fd);
@@ -2643,8 +2712,8 @@ void CGlobalStats::Dump(FILE *fd,DumpFormat mode){
CPerPortStats * lp=&m_port[i];
fprintf(fd,"port : %d \n",(int)i);
fprintf(fd,"------------\n");
- #define GS_DP_A4(f) fprintf(fd," %-40s : %llu \n",#f,lp->f)
- #define GS_DP_A(f) if (lp->f) fprintf(fd," %-40s : %llu \n",#f,lp->f)
+ #define GS_DP_A4(f) fprintf(fd," %-40s : %llu \n",#f, (unsigned long long)lp->f)
+ #define GS_DP_A(f) if (lp->f) fprintf(fd," %-40s : %llu \n",#f, (unsigned long long)lp->f)
GS_DP_A4(opackets);
GS_DP_A4(obytes);
GS_DP_A4(ipackets);
@@ -2719,10 +2788,10 @@ void CGlobalStats::Dump(FILE *fd,DumpFormat mode){
-struct CGlobalPortCfg {
+struct CGlobalTRex {
public:
- CGlobalPortCfg (){
+ CGlobalTRex (){
m_max_ports=4;
m_max_cores=1;
m_cores_to_dual_ports=0;
@@ -2732,10 +2801,11 @@ public:
m_expected_pps=0.0;
m_expected_cps=0.0;
m_expected_bps=0.0;
+ m_trex_stateless = NULL;
}
public:
- bool Create(bool is_stateless);
+ bool Create();
void Delete();
int ixgbe_prob_init();
@@ -2754,6 +2824,8 @@ public:
public:
int start_send_master();
+ int start_master_stateless();
+
int run_in_core(virtual_thread_id_t virt_core_id);
int stop_core(virtual_thread_id_t virt_core_id);
@@ -2800,7 +2872,6 @@ public:
- int test_send1();
int rcv_send(int port,int queue_id);
int rcv_send_all(int queue_id);
@@ -2866,7 +2937,9 @@ public:
CPhyEthIF m_ports[BP_MAX_PORTS];
- CCoreEthIF m_cores_vif[BP_MAX_CORES]; /* counted from 1 , 2,3 core zero is reserve*/
+ CCoreEthIF m_cores_vif_sf[BP_MAX_CORES]; /* counted from 1 , 2,3 core zero is reserve - stateful */
+ CCoreEthIFStateless m_cores_vif_sl[BP_MAX_CORES]; /* counted from 1 , 2,3 core zero is reserve - stateless*/
+ CCoreEthIF * m_cores_vif[BP_MAX_CORES];
CParserOption m_po ;
@@ -2889,54 +2962,14 @@ private:
CLatencyPktInfo m_latency_pkt;
CZMqPublisher m_zmq_publisher;
-};
-
-
-int CGlobalPortCfg::test_send1(){
-
- CParserOption po ;
- CFlowGenList fl;
-
- po.cfg_file = "cap2/dns.yaml";
- //po.cfg_file = "cap2/sfr3.yaml";
- //po.cfg_file = "cap2/sfr4.yaml";
- //po.cfg_file = "cap2/sfr.yaml";
-
- po.preview.setVMode(3);
- po.preview.setFileWrite(true);
-
- fl.Create();
-
- fl.load_from_yaml(po.cfg_file,1);
- //fl.DumpPktSize();
-
- fl.generate_p_thread_info(1);
- CFlowGenListPerThread * lpt;
-
- int i;
- for (i=0; i<1; i++) {
- lpt = fl.m_threads_info[i];
- //CNullIF * erf_vif = new CNullIF();
- CVirtualIF * erf_vif = &m_cores_vif[0];
- lpt->set_vif(erf_vif);
- lpt->generate_erf("hey",po.preview);
- lpt->m_node_gen.DumpHist(stdout);
- lpt->DumpStats(stdout);
- }
+public:
+ TrexStateless *m_trex_stateless;
+};
- m_cores_vif[0].flush_tx_queue();
- delay(1000);
- //fprintf(stdout," drop : %llu \n",m_test_drop);
- m_cores_vif[0].DumpCoreStats(stdout);
- m_cores_vif[0].DumpIfStats(stdout);
- fl.Delete();
-}
-
-
-int CGlobalPortCfg::rcv_send(int port,int queue_id){
+int CGlobalTRex::rcv_send(int port,int queue_id){
CPhyEthIF * lp=&m_ports[port];
rte_mbuf_t * rx_pkts[32];
@@ -2955,7 +2988,7 @@ int CGlobalPortCfg::rcv_send(int port,int queue_id){
return (0);
}
-int CGlobalPortCfg::rcv_send_all(int queue_id){
+int CGlobalTRex::rcv_send_all(int queue_id){
int i;
for (i=0; i<m_max_ports; i++) {
rcv_send(i,queue_id);
@@ -2966,16 +2999,16 @@ int CGlobalPortCfg::rcv_send_all(int queue_id){
-int CGlobalPortCfg::test_send(){
+int CGlobalTRex::test_send(){
int i;
- CPhyEthIF * lp=&m_ports[0];
-
//set_promisc_all(true);
//create_sctp_pkt();
create_udp_pkt();
CRx_check_header rx_check_header;
+ (void)rx_check_header;
+
rx_check_header.m_time_stamp=0x1234567;
rx_check_header.m_option_type=RX_CHECK_V4_OPT_TYPE;
rx_check_header.m_option_len=RX_CHECK_V4_OPT_LEN;
@@ -3049,7 +3082,7 @@ int CGlobalPortCfg::test_send(){
}*/
#endif
- fprintf(stdout," drop : %llu \n",m_test_drop);
+ fprintf(stdout," drop : %llu \n", (unsigned long long)m_test_drop);
return (0);
}
@@ -3118,7 +3151,7 @@ const uint8_t sctp_pkt1[]={
-int CGlobalPortCfg::create_pkt(uint8_t *pkt,int pkt_size){
+int CGlobalTRex::create_pkt(uint8_t *pkt,int pkt_size){
rte_mempool_t * mp= CGlobalInfo::m_mem_pool[0].m_big_mbuf_pool ;
rte_mbuf_t * m=rte_pktmbuf_alloc(mp);
@@ -3138,17 +3171,17 @@ int CGlobalPortCfg::create_pkt(uint8_t *pkt,int pkt_size){
return (0);
}
-int CGlobalPortCfg::create_udp_pkt(){
+int CGlobalTRex::create_udp_pkt(){
return (create_pkt((uint8_t*)udp_pkt,sizeof(udp_pkt)));
}
-int CGlobalPortCfg::create_sctp_pkt(){
+int CGlobalTRex::create_sctp_pkt(){
return (create_pkt((uint8_t*)sctp_pkt1,sizeof(sctp_pkt1)));
}
/* test by sending 10 packets ...*/
-int CGlobalPortCfg::test_send_pkts(uint16_t queue_id,
+int CGlobalTRex::test_send_pkts(uint16_t queue_id,
int pkt,
int port){
@@ -3174,26 +3207,30 @@ int CGlobalPortCfg::test_send_pkts(uint16_t queue_id,
-int CGlobalPortCfg::set_promisc_all(bool enable){
+int CGlobalTRex::set_promisc_all(bool enable){
int i;
for (i=0; i<m_max_ports; i++) {
CPhyEthIF * _if=&m_ports[i];
_if->set_promiscuous(enable);
}
+
+ return (0);
}
-int CGlobalPortCfg::reset_counters(){
+int CGlobalTRex::reset_counters(){
int i;
for (i=0; i<m_max_ports; i++) {
CPhyEthIF * _if=&m_ports[i];
_if->stats_clear();
}
+
+ return (0);
}
-bool CGlobalPortCfg::is_all_links_are_up(bool dump){
+bool CGlobalTRex::is_all_links_are_up(bool dump){
bool all_link_are=true;
int i;
for (i=0; i<m_max_ports; i++) {
@@ -3212,7 +3249,7 @@ bool CGlobalPortCfg::is_all_links_are_up(bool dump){
-int CGlobalPortCfg::ixgbe_rx_queue_flush(){
+int CGlobalTRex::ixgbe_rx_queue_flush(){
int i;
for (i=0; i<m_max_ports; i++) {
CPhyEthIF * _if=&m_ports[i];
@@ -3222,7 +3259,7 @@ int CGlobalPortCfg::ixgbe_rx_queue_flush(){
}
-int CGlobalPortCfg::ixgbe_configure_mg(void){
+int CGlobalTRex::ixgbe_configure_mg(void){
int i;
CLatencyManagerCfg mg_cfg;
mg_cfg.m_max_ports = m_max_ports;
@@ -3262,10 +3299,12 @@ int CGlobalPortCfg::ixgbe_configure_mg(void){
m_mg.Create(&mg_cfg);
m_mg.set_mask(CGlobalInfo::m_options.m_latency_mask);
+
+ return (0);
}
-int CGlobalPortCfg::ixgbe_start(void){
+int CGlobalTRex::ixgbe_start(void){
int i;
for (i=0; i<m_max_ports; i++) {
@@ -3384,11 +3423,15 @@ int CGlobalPortCfg::ixgbe_start(void){
*/
int port_offset=0;
- int queue_offset=0;
for (i=0; i<get_cores_tx(); i++) {
int j=(i+1);
int queue_id=((j-1)/get_base_num_cores() ); /* for the first min core queue 0 , then queue 1 etc */
- m_cores_vif[j].Create(j,
+ if ( get_is_stateless() ){
+ m_cores_vif[j]=&m_cores_vif_sl[j];
+ }else{
+ m_cores_vif[j]=&m_cores_vif_sf[j];
+ }
+ m_cores_vif[j]->Create(j,
queue_id,
&m_ports[port_offset], /* 0,2*/
queue_id,
@@ -3403,28 +3446,39 @@ int CGlobalPortCfg::ixgbe_start(void){
fprintf(stdout," -------------------------------\n");
CCoreEthIF::DumpIfCfgHeader(stdout);
for (i=0; i<get_cores_tx(); i++) {
- m_cores_vif[i+1].DumpIfCfg(stdout);
+ m_cores_vif[i+1]->DumpIfCfg(stdout);
}
fprintf(stdout," -------------------------------\n");
+
+ return (0);
}
-bool CGlobalPortCfg::Create(bool is_stateless){
+bool CGlobalTRex::Create(){
+ CFlowsYamlInfo pre_yaml_info;
- /* hack - need to refactor */
- if (!is_stateless) {
- if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port,
- !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){
- return (false);
- }
+ if (get_is_stateless()) {
+
+ TrexStatelessCfg cfg;
+
+ TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, global_platform_cfg_info.m_zmq_rpc_port);
+
+ cfg.m_port_count = CGlobalInfo::m_options.m_expected_portd;
+ cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
+ cfg.m_rpc_async_cfg = NULL;
+ cfg.m_rpc_server_verbose = false;
+ cfg.m_platform_api = new TrexDpdkPlatformApi();
+
+ m_trex_stateless = new TrexStateless(cfg);
+
+ } else {
+ pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
}
- /* We load the YAML twice,
- this is the first time. to update global flags */
- CFlowsYamlInfo pre_yaml_info;
- if (!is_stateless) {
- pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
- }
+ if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port,
+ !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){
+ return (false);
+ }
if ( pre_yaml_info.m_vlan_info.m_enable ){
CGlobalInfo::m_options.preview.set_vlan_mode_enable(true);
@@ -3434,16 +3488,17 @@ bool CGlobalPortCfg::Create(bool is_stateless){
ixgbe_prob_init();
cores_prob_init();
queues_prob_init();
- /* allocate rings */
- assert( CMsgIns::Ins()->Create(get_cores_tx()) );
- if ( sizeof(CGenNodeNatInfo) != sizeof(CGenNode) ) {
- printf("ERROR sizeof(CGenNodeNatInfo) %d != sizeof(CGenNode) %d must be the same size \n",sizeof(CGenNodeNatInfo),sizeof(CGenNode));
- assert(0);
- }
+ /* allocate rings */
+ assert( CMsgIns::Ins()->Create(get_cores_tx()) );
+
+ if ( sizeof(CGenNodeNatInfo) != sizeof(CGenNode) ) {
+ printf("ERROR sizeof(CGenNodeNatInfo) %lu != sizeof(CGenNode) %lu must be the same size \n",sizeof(CGenNodeNatInfo),sizeof(CGenNode));
+ assert(0);
+ }
if ( sizeof(CGenNodeLatencyPktInfo) != sizeof(CGenNode) ) {
- printf("ERROR sizeof(CGenNodeLatencyPktInfo) %d != sizeof(CGenNode) %d must be the same size \n",sizeof(CGenNodeLatencyPktInfo),sizeof(CGenNode));
+ printf("ERROR sizeof(CGenNodeLatencyPktInfo) %lu != sizeof(CGenNode) %lu must be the same size \n",sizeof(CGenNodeLatencyPktInfo),sizeof(CGenNode));
assert(0);
}
@@ -3463,16 +3518,13 @@ bool CGlobalPortCfg::Create(bool is_stateless){
return (true);
}
-void CGlobalPortCfg::Delete(){
+void CGlobalTRex::Delete(){
m_zmq_publisher.Delete();
}
-int CGlobalPortCfg::ixgbe_prob_init(void){
-
- uint8_t nb_ports;
-
+int CGlobalTRex::ixgbe_prob_init(void){
m_max_ports = rte_eth_dev_count();
if (m_max_ports == 0)
@@ -3561,13 +3613,13 @@ int CGlobalPortCfg::ixgbe_prob_init(void){
return (0);
}
-int CGlobalPortCfg::cores_prob_init(){
+int CGlobalTRex::cores_prob_init(){
m_max_cores = rte_lcore_count();
assert(m_max_cores>0);
return (0);
}
-int CGlobalPortCfg::queues_prob_init(){
+int CGlobalTRex::queues_prob_init(){
if (m_max_cores < 2) {
rte_exit(EXIT_FAILURE, "number of cores should be at least 3 \n");
@@ -3608,7 +3660,7 @@ int CGlobalPortCfg::queues_prob_init(){
}
-void CGlobalPortCfg::dump_config(FILE *fd){
+void CGlobalTRex::dump_config(FILE *fd){
fprintf(fd," number of ports : %u \n",m_max_ports);
fprintf(fd," max cores for 2 ports : %u \n",m_cores_to_dual_ports);
fprintf(fd," max queue per port : %u \n",m_max_queues_per_port);
@@ -3616,7 +3668,7 @@ void CGlobalPortCfg::dump_config(FILE *fd){
-void CGlobalPortCfg::dump_post_test_stats(FILE *fd){
+void CGlobalTRex::dump_post_test_stats(FILE *fd){
uint64_t pkt_out=0;
uint64_t pkt_out_bytes=0;
uint64_t pkt_in_bytes=0;
@@ -3627,7 +3679,7 @@ void CGlobalPortCfg::dump_post_test_stats(FILE *fd){
int i;
for (i=0; i<get_cores_tx(); i++) {
- CCoreEthIF * erf_vif = &m_cores_vif[i+1];
+ CCoreEthIF * erf_vif = m_cores_vif[i+1];
CVirtualIFPerSideStats stats;
erf_vif->GetCoreCounters(&stats);
sw_pkt_out += stats.m_tx_pkt;
@@ -3652,17 +3704,17 @@ void CGlobalPortCfg::dump_post_test_stats(FILE *fd){
fprintf (fd," summary stats \n");
fprintf (fd," -------------- \n");
- fprintf (fd," Total-pkt-drop : %d pkts \n",(int64_t)(pkt_out-pkt_in));
- fprintf (fd," Total-tx-bytes : %llu bytes \n",pkt_out_bytes);
- fprintf (fd," Total-tx-sw-bytes : %llu bytes \n",sw_pkt_out_bytes);
- fprintf (fd," Total-rx-bytes : %llu byte \n",pkt_in_bytes);
+ fprintf (fd," Total-pkt-drop : %llu pkts \n",(unsigned long long)(pkt_out-pkt_in));
+ fprintf (fd," Total-tx-bytes : %llu bytes \n", (unsigned long long)pkt_out_bytes);
+ fprintf (fd," Total-tx-sw-bytes : %llu bytes \n", (unsigned long long)sw_pkt_out_bytes);
+ fprintf (fd," Total-rx-bytes : %llu byte \n", (unsigned long long)pkt_in_bytes);
fprintf (fd," \n");
- fprintf (fd," Total-tx-pkt : %llu pkts \n",pkt_out);
- fprintf (fd," Total-rx-pkt : %llu pkts \n",pkt_in);
- fprintf (fd," Total-sw-tx-pkt : %llu pkts \n",sw_pkt_out);
- fprintf (fd," Total-sw-err : %llu pkts \n",sw_pkt_out_err);
+ fprintf (fd," Total-tx-pkt : %llu pkts \n", (unsigned long long)pkt_out);
+ fprintf (fd," Total-rx-pkt : %llu pkts \n", (unsigned long long)pkt_in);
+ fprintf (fd," Total-sw-tx-pkt : %llu pkts \n", (unsigned long long)sw_pkt_out);
+ fprintf (fd," Total-sw-err : %llu pkts \n", (unsigned long long)sw_pkt_out_err);
if ( !CGlobalInfo::m_options.is_latency_disabled() ){
@@ -3675,7 +3727,7 @@ void CGlobalPortCfg::dump_post_test_stats(FILE *fd){
}
-void CGlobalPortCfg::update_stats(){
+void CGlobalTRex::update_stats(){
int i;
for (i=0; i<m_max_ports; i++) {
@@ -3696,12 +3748,13 @@ void CGlobalPortCfg::update_stats(){
}
-void CGlobalPortCfg::get_stats(CGlobalStats & stats){
+void CGlobalTRex::get_stats(CGlobalStats & stats){
int i;
float total_tx=0.0;
float total_rx=0.0;
- float total_pps=0.0;
+ float total_tx_pps=0.0;
+ float total_rx_pps=0.0;
stats.m_total_tx_pkts = 0;
stats.m_total_rx_pkts = 0;
@@ -3729,6 +3782,9 @@ void CGlobalPortCfg::get_stats(CGlobalStats & stats){
stp->ierrors = st.ierrors;
stp->oerrors = st.oerrors;
stp->m_total_tx_bps = _if->get_last_tx_rate()*_1Mb_DOUBLE;
+ stp->m_total_tx_pps = _if->get_last_tx_pps_rate();
+ stp->m_total_rx_bps = _if->get_last_rx_rate()*_1Mb_DOUBLE;
+ stp->m_total_rx_pps = _if->get_last_rx_pps_rate();
stats.m_total_tx_pkts += st.opackets;
stats.m_total_rx_pkts += st.ipackets;
@@ -3737,7 +3793,8 @@ void CGlobalPortCfg::get_stats(CGlobalStats & stats){
total_tx +=_if->get_last_tx_rate();
total_rx +=_if->get_last_rx_rate();
- total_pps +=_if->get_last_pps_rate();
+ total_tx_pps +=_if->get_last_tx_pps_rate();
+ total_rx_pps +=_if->get_last_rx_pps_rate();
}
@@ -3798,7 +3855,13 @@ void CGlobalPortCfg::get_stats(CGlobalStats & stats){
stats.m_total_clients = total_clients;
stats.m_total_servers = total_servers;
stats.m_active_sockets = active_sockets;
- stats.m_socket_util =100.0*(double)active_sockets/(double)total_sockets;
+
+ if (total_sockets != 0) {
+ stats.m_socket_util =100.0*(double)active_sockets/(double)total_sockets;
+ } else {
+ stats.m_socket_util = 0;
+ }
+
float drop_rate=total_tx-total_rx;
@@ -3814,7 +3877,8 @@ void CGlobalPortCfg::get_stats(CGlobalStats & stats){
stats.m_tx_bps = total_tx*pf*_1Mb_DOUBLE;
stats.m_rx_bps = total_rx*pf*_1Mb_DOUBLE;
- stats.m_tx_pps = total_pps*pf;
+ stats.m_tx_pps = total_tx_pps*pf;
+ stats.m_rx_pps = total_rx_pps*pf;
stats.m_tx_cps = m_last_total_cps*pf;
stats.m_tx_expected_cps = m_expected_cps*pf;
@@ -3822,7 +3886,7 @@ void CGlobalPortCfg::get_stats(CGlobalStats & stats){
stats.m_tx_expected_bps = m_expected_bps*pf;
}
-bool CGlobalPortCfg::sanity_check(){
+bool CGlobalTRex::sanity_check(){
CFlowGenListPerThread * lpt;
uint32_t errors=0;
@@ -3842,7 +3906,7 @@ bool CGlobalPortCfg::sanity_check(){
/* dump the template info */
-void CGlobalPortCfg::dump_template_info(std::string & json){
+void CGlobalTRex::dump_template_info(std::string & json){
CFlowGenListPerThread * lpt = m_fl.m_threads_info[0];
CFlowsYamlInfo * yaml_info=&lpt->m_yaml_info;
@@ -3857,7 +3921,7 @@ void CGlobalPortCfg::dump_template_info(std::string & json){
json+="]}" ;
}
-void CGlobalPortCfg::dump_stats(FILE *fd,std::string & json,
+void CGlobalTRex::dump_stats(FILE *fd,std::string & json,
CGlobalStats::DumpFormat format){
CGlobalStats stats;
update_stats();
@@ -3897,11 +3961,15 @@ void CGlobalPortCfg::dump_stats(FILE *fd,std::string & json,
}
-int CGlobalPortCfg::run_in_master(){
+int CGlobalTRex::run_in_master(){
std::string json;
bool was_stopped=false;
+ if ( get_is_stateless() ) {
+ m_trex_stateless->launch_control_plane();
+ }
+
while ( true ) {
if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ){
@@ -3953,10 +4021,10 @@ int CGlobalPortCfg::run_in_master(){
m_fl.m_threads_info[0]->m_node_gen.dump_json(json);
m_zmq_publisher.publish_json(json);
- dump_template_info(json);
- m_zmq_publisher.publish_json(json);
-
-
+ if ( !get_is_stateless() ){
+ dump_template_info(json);
+ m_zmq_publisher.publish_json(json);
+ }
if ( !CGlobalInfo::m_options.is_latency_disabled() ){
m_mg.update();
@@ -4009,6 +4077,10 @@ int CGlobalPortCfg::run_in_master(){
}
+ /* stateless info */
+ m_trex_stateless->generate_publish_snapshot(json);
+ m_zmq_publisher.publish_json(json);
+
delay(500);
if ( is_all_cores_finished() ) {
@@ -4027,7 +4099,7 @@ int CGlobalPortCfg::run_in_master(){
-int CGlobalPortCfg::run_in_laterncy_core(void){
+int CGlobalTRex::run_in_laterncy_core(void){
if ( !CGlobalInfo::m_options.is_latency_disabled() ){
m_mg.start(0);
}
@@ -4035,12 +4107,12 @@ int CGlobalPortCfg::run_in_laterncy_core(void){
}
-int CGlobalPortCfg::stop_core(virtual_thread_id_t virt_core_id){
+int CGlobalTRex::stop_core(virtual_thread_id_t virt_core_id){
m_signal[virt_core_id]=1;
return (0);
}
-int CGlobalPortCfg::run_in_core(virtual_thread_id_t virt_core_id){
+int CGlobalTRex::run_in_core(virtual_thread_id_t virt_core_id){
CPreviewMode *lp=&CGlobalInfo::m_options.preview;
if ( lp->getSingleCore() &&
@@ -4051,19 +4123,23 @@ int CGlobalPortCfg::run_in_core(virtual_thread_id_t virt_core_id){
return (0);
}
+
assert(m_fl_was_init);
CFlowGenListPerThread * lpt;
lpt = m_fl.m_threads_info[virt_core_id-1];
- lpt->generate_erf(CGlobalInfo::m_options.out_file,*lp);
- //lpt->m_node_gen.DumpHist(stdout);
- //lpt->DumpStats(stdout);
+
+ if (get_is_stateless()) {
+ lpt->start_stateless_daemon();
+ }else{
+ lpt->start_generate_stateful(CGlobalInfo::m_options.out_file,*lp);
+ }
m_signal[virt_core_id]=1;
return (0);
}
-int CGlobalPortCfg::stop_master(){
+int CGlobalTRex::stop_master(){
delay(1000);
std::string json;
@@ -4084,7 +4160,7 @@ int CGlobalPortCfg::stop_master(){
int i;
for (i=0; i<get_cores_tx(); i++) {
lpt = m_fl.m_threads_info[i];
- CCoreEthIF * erf_vif = &m_cores_vif[i+1];
+ CCoreEthIF * erf_vif = m_cores_vif[i+1];
erf_vif->DumpCoreStats(stdout);
erf_vif->DumpIfStats(stdout);
@@ -4115,9 +4191,10 @@ int CGlobalPortCfg::stop_master(){
dump_post_test_stats(stdout);
m_fl.Delete();
+ return (0);
}
-bool CGlobalPortCfg::is_all_cores_finished(){
+bool CGlobalTRex::is_all_cores_finished(){
int i;
for (i=0; i<get_cores_tx(); i++) {
if ( m_signal[i+1]==0){
@@ -4128,8 +4205,34 @@ bool CGlobalPortCfg::is_all_cores_finished(){
}
+int CGlobalTRex::start_master_stateless(){
+ int i;
+ for (i=0; i<BP_MAX_CORES; i++) {
+ m_signal[i]=0;
+ }
+ m_fl.Create();
+ m_expected_pps = 0;
+ m_expected_cps = 0;
+ m_expected_bps = 0;
+
+ m_fl.generate_p_thread_info(get_cores_tx());
+ CFlowGenListPerThread * lpt;
+
+ for (i=0; i<get_cores_tx(); i++) {
+ lpt = m_fl.m_threads_info[i];
+ CVirtualIF * erf_vif = m_cores_vif[i+1];
+ lpt->set_vif(erf_vif);
+ lpt->m_node_gen.m_socket_id =m_cores_vif[i+1]->get_socket_id();
+ }
+ m_fl_was_init=true;
+
+ return (0);
+}
+
-int CGlobalPortCfg::start_send_master(){
+
+
+int CGlobalTRex::start_send_master(){
int i;
for (i=0; i<BP_MAX_CORES; i++) {
m_signal[i]=0;
@@ -4174,20 +4277,26 @@ int CGlobalPortCfg::start_send_master(){
for (i=0; i<get_cores_tx(); i++) {
lpt = m_fl.m_threads_info[i];
//CNullIF * erf_vif = new CNullIF();
- CVirtualIF * erf_vif = &m_cores_vif[i+1];
+ CVirtualIF * erf_vif = m_cores_vif[i+1];
lpt->set_vif(erf_vif);
/* socket id */
- lpt->m_node_gen.m_socket_id =m_cores_vif[i+1].get_socket_id();
+ lpt->m_node_gen.m_socket_id =m_cores_vif[i+1]->get_socket_id();
}
m_fl_was_init=true;
+ return (0);
}
////////////////////////////////////////////
-static CGlobalPortCfg ports_cfg;
+static CGlobalTRex g_trex;
+
+
+TrexStateless * get_stateless_obj() {
+ return g_trex.m_trex_stateless;
+}
static int latency_one_lcore(__attribute__((unused)) void *dummy)
{
@@ -4196,34 +4305,22 @@ static int latency_one_lcore(__attribute__((unused)) void *dummy)
if ( lpsock->thread_phy_is_latency( phy_id ) ){
- ports_cfg.run_in_laterncy_core();
+ g_trex.run_in_laterncy_core();
}else{
if ( lpsock->thread_phy_is_master( phy_id ) ) {
- ports_cfg.run_in_master();
+ g_trex.run_in_master();
delay(1);
}else{
delay((uint32_t)(1000.0*CGlobalInfo::m_options.m_duration));
/* this core has stopped */
- ports_cfg.m_signal[ lpsock->thread_phy_to_virt( phy_id ) ]=1;
+ g_trex.m_signal[ lpsock->thread_phy_to_virt( phy_id ) ]=1;
}
}
return 0;
}
-static int stateless_entry(__attribute__((unused)) void *dummy) {
- CPlatformSocketInfo * lpsock=&CGlobalInfo::m_socket;
- physical_thread_id_t phy_id = rte_lcore_id();
-
- if (lpsock->thread_phy_is_master( phy_id )) {
- TrexStateless::get_instance().launch_control_plane();
- } else {
- TrexStateless::get_instance().launch_on_dp_core(phy_id);
- }
-
- return (0);
-}
static int slave_one_lcore(__attribute__((unused)) void *dummy)
{
@@ -4232,13 +4329,13 @@ static int slave_one_lcore(__attribute__((unused)) void *dummy)
if ( lpsock->thread_phy_is_latency( phy_id ) ){
- ports_cfg.run_in_laterncy_core();
+ g_trex.run_in_laterncy_core();
}else{
if ( lpsock->thread_phy_is_master( phy_id ) ) {
- ports_cfg.run_in_master();
+ g_trex.run_in_master();
delay(1);
}else{
- ports_cfg.run_in_core( lpsock->thread_phy_to_virt( phy_id ) );
+ g_trex.run_in_core( lpsock->thread_phy_to_virt( phy_id ) );
}
}
return 0;
@@ -4329,7 +4426,6 @@ int update_global_info_from_platform_file(){
int update_dpdk_args(void){
- uint32_t cores_number;
CPlatformSocketInfo * lpsock=&CGlobalInfo::m_socket;
CParserOption * lpop= &CGlobalInfo::m_options;
@@ -4346,7 +4442,7 @@ int update_dpdk_args(void){
}
- sprintf(global_cores_str,"0x%x",lpsock->get_cores_mask());
+ sprintf(global_cores_str,"0x%llx",(unsigned long long)lpsock->get_cores_mask());
/* set the DPDK options */
global_dpdk_args_num =7;
@@ -4397,6 +4493,7 @@ int update_dpdk_args(void){
printf(" %s \n",global_dpdk_args[i]);
}
}
+ return (0);
}
@@ -4418,7 +4515,7 @@ int sim_load_list_of_cap_files(CParserOption * op){
lpt->set_vif(&erf_vif);
if ( (op->preview.getVMode() >1) || op->preview.getFileWrite() ) {
- lpt->generate_erf(op->out_file,op->preview);
+ lpt->start_generate_stateful(op->out_file,op->preview);
}
lpt->m_node_gen.DumpHist(stdout);
@@ -4430,42 +4527,6 @@ int sim_load_list_of_cap_files(CParserOption * op){
}
-
-
-static int
-launch_stateless_trex() {
- CPlatformSocketInfo *lpsock=&CGlobalInfo::m_socket;
- CParserOption *lpop= &CGlobalInfo::m_options;
- CPlatformYamlInfo *cg=&global_platform_cfg_info;
-
- TrexStatelessCfg cfg;
-
- TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
- TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
-
- cfg.m_dp_core_count = lpop->preview.getCores();
- cfg.m_port_count = lpop->m_expected_portd;
- cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
- cfg.m_rpc_async_cfg = &rpc_async_cfg;
- cfg.m_rpc_server_verbose = true;
-
- TrexStateless::configure(cfg);
-
- printf("\nStarting T-Rex Stateless\n");
- printf("Starting RPC Server...\n\n");
-
- rte_eal_mp_remote_launch(stateless_entry, NULL, CALL_MASTER);
-
- unsigned lcore_id;
- RTE_LCORE_FOREACH_SLAVE(lcore_id) {
- if (rte_eal_wait_lcore(lcore_id) < 0)
- return -1;
- }
- return (0);
-}
-
-
-
int main_test(int argc , char * argv[]){
utl_termio_init();
@@ -4525,78 +4586,62 @@ int main_test(int argc , char * argv[]){
return ( sim_load_list_of_cap_files(&CGlobalInfo::m_options) );
}
- bool is_stateless = (CGlobalInfo::m_options.m_run_mode == CParserOption::RUN_MODE_INTERACTIVE);
-
- if ( !ports_cfg.Create(is_stateless) ){
+ if ( !g_trex.Create() ){
exit(1);
}
- /* patch here */
- if (is_stateless) {
- return launch_stateless_trex();
- }
-
-
if (po->preview.get_is_rx_check_enable() && (po->m_rx_check_sampe< get_min_sample_rate()) ) {
po->m_rx_check_sampe = get_min_sample_rate();
printf("Warning rx check sample rate should be lower than %d setting it to %d\n",get_min_sample_rate(),get_min_sample_rate());
}
/* set dump mode */
- ports_cfg.m_io_modes.set_mode((CTrexGlobalIoMode::CliDumpMode)CGlobalInfo::m_options.m_io_mode);
+ g_trex.m_io_modes.set_mode((CTrexGlobalIoMode::CliDumpMode)CGlobalInfo::m_options.m_io_mode);
if ( !CGlobalInfo::m_options.is_latency_disabled()
&& (CGlobalInfo::m_options.m_latency_prev>0) ){
uint32_t pkts = CGlobalInfo::m_options.m_latency_prev*
CGlobalInfo::m_options.m_latency_rate;
printf("Start prev latency check - hack for Keren for %d sec \n",CGlobalInfo::m_options.m_latency_prev);
- ports_cfg.m_mg.start(pkts);
+ g_trex.m_mg.start(pkts);
printf("Delay now you can call command \n");
delay(CGlobalInfo::m_options.m_latency_prev* 1000);
printf("Finish wating \n");
- ports_cfg.m_mg.reset();
- ports_cfg.reset_counters();
+ g_trex.m_mg.reset();
+ g_trex.reset_counters();
}
- ports_cfg.start_send_master();
+ if ( get_is_stateless() ) {
+ g_trex.start_master_stateless();
- // TBD remove
- //ports_cfg.test_latency();
- /* test seding */
- //while (1) {
- //}
+ }else{
+ g_trex.start_send_master();
+ }
/* TBD_FDIR */
#if 0
printf(" test_send \n");
- ports_cfg.test_send();
+ g_trex.test_send();
while (1) {
delay(10000);
}
#endif
-
-
-
- //ports_cfg.test_latency();
- //return (0);
-
-
if ( CGlobalInfo::m_options.preview.getOnlyLatency() ){
rte_eal_mp_remote_launch(latency_one_lcore, NULL, CALL_MASTER);
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
if (rte_eal_wait_lcore(lcore_id) < 0)
return -1;
}
- ports_cfg.stop_master();
+ g_trex.stop_master();
return (0);
}
if ( CGlobalInfo::m_options.preview.getSingleCore() ) {
- ports_cfg.run_in_core(1);
- ports_cfg.stop_master();
+ g_trex.run_in_core(1);
+ g_trex.stop_master();
return (0);
}
@@ -4606,8 +4651,8 @@ int main_test(int argc , char * argv[]){
return -1;
}
- ports_cfg.stop_master();
- ports_cfg.Delete();
+ g_trex.stop_master();
+ g_trex.Delete();
utl_termio_reset();
return (0);
@@ -4732,14 +4777,13 @@ int CTRexExtendedDriverBase1G::configure_rx_filter_rules(CPhyEthIF * _if){
/* enable all rules */
_if->pci_reg_write(E1000_WUFC, (mask<<16) | (1<<14) );
+
+ return (0);
}
void CTRexExtendedDriverBase1G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){
- int i;
- uint64_t t=0;
-
stats->ipackets += _if->pci_reg_read(E1000_GPRC) ;
stats->ibytes += (_if->pci_reg_read(E1000_GORCL) );
@@ -4869,6 +4913,7 @@ int CTRexExtendedDriverBase10G::configure_rx_filter_rules(CPhyEthIF * _if){
rte_exit(EXIT_FAILURE, " ERROR rte_eth_dev_fdir_add_perfect_filter : %d\n",res);
}
}
+ return (0);
}
int CTRexExtendedDriverBase10G::configure_drop_queue(CPhyEthIF * _if){
@@ -4991,6 +5036,8 @@ int CTRexExtendedDriverBase40G::configure_rx_filter_rules(CPhyEthIF * _if){
add_rules(_if,RTE_ETH_FLOW_TYPE_UDPV6,ttl);
add_rules(_if,RTE_ETH_FLOW_TYPE_TCPV6,ttl);
}
+
+ return (0);
}
@@ -5146,3 +5193,54 @@ struct rte_mbuf * rte_mbuf_convert_to_one_seg(struct rte_mbuf *m){
}
+/***********************************************************
+ * platfrom API object
+ * TODO: REMOVE THIS TO A SEPERATE FILE
+ *
+ **********************************************************/
+void
+TrexDpdkPlatformApi::get_global_stats(TrexPlatformGlobalStats &stats) const {
+ CGlobalStats trex_stats;
+ g_trex.get_stats(trex_stats);
+
+ stats.m_stats.m_cpu_util = trex_stats.m_cpu_util;
+
+ stats.m_stats.m_tx_bps = trex_stats.m_tx_bps;
+ stats.m_stats.m_tx_pps = trex_stats.m_tx_pps;
+ stats.m_stats.m_total_tx_pkts = trex_stats.m_total_tx_pkts;
+ stats.m_stats.m_total_tx_bytes = trex_stats.m_total_tx_bytes;
+
+ stats.m_stats.m_rx_bps = trex_stats.m_rx_bps;
+ stats.m_stats.m_rx_pps = /*trex_stats.m_rx_pps*/ 0; /* missing */
+ stats.m_stats.m_total_rx_pkts = trex_stats.m_total_rx_pkts;
+ stats.m_stats.m_total_rx_bytes = trex_stats.m_total_rx_bytes;
+}
+
+void
+TrexDpdkPlatformApi::get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const {
+
+}
+
+uint8_t
+TrexDpdkPlatformApi::get_dp_core_count() const {
+ return CGlobalInfo::m_options.preview.getCores();
+}
+
+
+void
+TrexDpdkPlatformApi::port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list) const {
+
+ cores_id_list.clear();
+
+ /* iterate over all DP cores */
+ for (uint8_t core_id = 0; core_id < g_trex.get_cores_tx(); core_id++) {
+
+ /* iterate over all the directions*/
+ for (uint8_t dir = 0 ; dir < CS_NUM; dir++) {
+ if (g_trex.m_cores_vif[core_id + 1]->get_ports()[dir].m_port->get_port_id() == port_id) {
+ cores_id_list.push_back(std::make_pair(core_id, dir));
+ }
+ }
+ }
+}
+
diff --git a/src/mock/trex_platform_api_mock.cpp b/src/mock/trex_platform_api_mock.cpp
new file mode 100644
index 00000000..54f71e10
--- /dev/null
+++ b/src/mock/trex_platform_api_mock.cpp
@@ -0,0 +1,49 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+
+#include <internal_api/trex_platform_api.h>
+
+void
+TrexMockPlatformApi::get_global_stats(TrexPlatformGlobalStats &stats) const {
+
+ stats.m_stats.m_cpu_util = 0;
+
+ stats.m_stats.m_tx_bps = 0;
+ stats.m_stats.m_tx_pps = 0;
+ stats.m_stats.m_total_tx_pkts = 0;
+ stats.m_stats.m_total_tx_bytes = 0;
+
+ stats.m_stats.m_rx_bps = 0;
+ stats.m_stats.m_rx_pps = 0;
+ stats.m_stats.m_total_rx_pkts = 0;
+ stats.m_stats.m_total_rx_bytes = 0;
+}
+
+void
+TrexMockPlatformApi::get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const {
+
+}
+
+uint8_t
+TrexMockPlatformApi::get_dp_core_count() const {
+ return (1);
+}
+
diff --git a/src/mock/trex_rpc_server_mock.cpp b/src/mock/trex_rpc_server_mock.cpp
index de43f92f..0bdf6cf1 100644
--- a/src/mock/trex_rpc_server_mock.cpp
+++ b/src/mock/trex_rpc_server_mock.cpp
@@ -21,12 +21,71 @@ limitations under the License.
#include <trex_rpc_server_api.h>
#include <trex_stateless.h>
+#include <trex_stateless_dp_core.h>
+
+#include <msg_manager.h>
#include <iostream>
+#include <sstream>
#include <unistd.h>
+#include <string.h>
+#include <zmq.h>
+#include <bp_sim.h>
using namespace std;
+static TrexStateless *g_trex_stateless;
+static uint16_t g_rpc_port;
+
+static bool
+verify_tcp_port_is_free(uint16_t port) {
+ void *m_context = zmq_ctx_new();
+ void *m_socket = zmq_socket (m_context, ZMQ_REP);
+ std::stringstream ss;
+ ss << "tcp://*:";
+ ss << port;
+
+ int rc = zmq_bind (m_socket, ss.str().c_str());
+
+ zmq_close(m_socket);
+ zmq_term(m_context);
+
+ return (rc == 0);
+}
+
+static uint16_t
+find_free_tcp_port(uint16_t start_port = 5050) {
+ void *m_context = zmq_ctx_new();
+ void *m_socket = zmq_socket (m_context, ZMQ_REP);
+
+ uint16_t port = start_port;
+ while (true) {
+ std::stringstream ss;
+ ss << "tcp://*:";
+ ss << port;
+
+ int rc = zmq_bind (m_socket, ss.str().c_str());
+ if (rc == 0) {
+ break;
+ }
+
+ port++;
+ }
+
+ zmq_close(m_socket);
+ zmq_term(m_context);
+
+ return port;
+}
+
+TrexStateless * get_stateless_obj() {
+ return g_trex_stateless;
+}
+
+uint16_t gtest_get_mock_server_port() {
+ return g_rpc_port;
+}
+
/**
* on simulation this is not rebuild every version
* (improved stub)
@@ -42,44 +101,87 @@ extern "C" const char * get_build_time(void){
int gtest_main(int argc, char **argv);
-int main(int argc, char *argv[]) {
+static bool parse_uint16(const string arg, uint16_t &port) {
+ stringstream ss(arg);
+
+ bool x = (ss >> port);
+
+ return (x);
+}
+
+static void
+run_dummy_core() {
+ //TODO: connect this to the scheduler
+
+ //CFlowGenList fl;
+ //fl.Create();
+ //CFlowGenListPerThread *lp = new CFlowGenListPerThread();
+ //lp->Create(0, 0, NULL, 0);
+ //TrexStatelessDpCore dummy_core(0, lp);
+ //lp->start_stateless_daemon();
+}
+int main(int argc, char *argv[]) {
bool is_gtest = false;
+ time_init();
+ CGlobalInfo::m_socket.Create(0);
+
+ CGlobalInfo::init_pools(1000);
+ assert( CMsgIns::Ins()->Create(1));
+
+ std::thread *m_thread = new std::thread(run_dummy_core);
+ (void)m_thread;
+
// gtest ?
if (argc > 1) {
- if (string(argv[1]) != "--ut") {
- cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n";
+ string arg = string(argv[1]);
+
+ if (arg == "--ut") {
+ g_rpc_port = find_free_tcp_port();
+ is_gtest = true;
+ } else if (parse_uint16(arg, g_rpc_port)) {
+ bool rc = verify_tcp_port_is_free(g_rpc_port);
+ if (!rc) {
+ cout << "port " << g_rpc_port << " is not available to use\n";
+ exit(-1);
+ }
+ } else {
+
+ cout << "\n[Usage] " << argv[0] << ": " << " [--ut] or [port number < 65535]\n\n";
exit(-1);
}
- is_gtest = true;
+
+ } else {
+ g_rpc_port = find_free_tcp_port();
}
/* configure the stateless object with 4 ports */
TrexStatelessCfg cfg;
- TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
- TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
+ TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, g_rpc_port);
+ //TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
cfg.m_port_count = 4;
- cfg.m_dp_core_count = 2;
cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
- cfg.m_rpc_async_cfg = &rpc_async_cfg;
+ cfg.m_rpc_async_cfg = NULL;
cfg.m_rpc_server_verbose = (is_gtest ? false : true);
+ cfg.m_platform_api = new TrexMockPlatformApi();
- TrexStateless::configure(cfg);
+ g_trex_stateless = new TrexStateless(cfg);
- TrexStateless::get_instance().launch_control_plane();
+ g_trex_stateless->launch_control_plane();
/* gtest handling */
if (is_gtest) {
int rc = gtest_main(argc, argv);
- TrexStateless::destroy();
+ delete g_trex_stateless;
+ g_trex_stateless = NULL;
return rc;
}
cout << "\n-= Starting RPC Server Mock =-\n\n";
- cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n";
+ cout << "Listening on tcp://localhost:" << g_rpc_port << " [ZMQ]\n\n";
cout << "Server Started\n\n";
@@ -87,6 +189,7 @@ int main(int argc, char *argv[]) {
sleep(1);
}
- TrexStateless::destroy();
+ delete g_trex_stateless;
+ g_trex_stateless = NULL;
}
diff --git a/src/msg_manager.cpp b/src/msg_manager.cpp
index 4db96583..9f41d08c 100755
--- a/src/msg_manager.cpp
+++ b/src/msg_manager.cpp
@@ -26,7 +26,7 @@ limitations under the License.
/*TBD: need to fix socket_id for NUMA */
-bool CMessagingManager::Create(uint8_t num_dp_threads){
+bool CMessagingManager::Create(uint8_t num_dp_threads,std::string a_name){
m_num_dp_threads=num_dp_threads;
assert(m_dp_to_cp==0);
assert(m_cp_to_dp==0);
@@ -38,11 +38,11 @@ bool CMessagingManager::Create(uint8_t num_dp_threads){
char name[100];
lp=getRingCpToDp(i);
- sprintf(name,"cp_to_dp_%d",i);
+ sprintf(name,"%s_to_%d",(char *)a_name.c_str(),i);
assert(lp->Create(std::string(name),1024,0)==true);
lp=getRingDpToCp(i);
- sprintf(name,"dp_to_cp_%d",i);
+ sprintf(name,"%s_from_%d",(char *)a_name.c_str(),i);
assert(lp->Create(std::string(name),1024,0)==true);
}
@@ -89,7 +89,12 @@ CMsgIns * CMsgIns::Ins(void){
}
bool CMsgIns::Create(uint8_t num_threads){
- return ( m_rx_dp.Create(num_threads) );
+
+ bool res = m_cp_dp.Create(num_threads,"cp_dp");
+ if (!res) {
+ return (res);
+ }
+ return (m_rx_dp.Create(num_threads,"rx_dp"));
}
diff --git a/src/msg_manager.h b/src/msg_manager.h
index b25660bb..8958f826 100755
--- a/src/msg_manager.h
+++ b/src/msg_manager.h
@@ -23,12 +23,20 @@ limitations under the License.
#include "CRing.h"
+#include <string>
/* messages from CP->DP Ids */
-#define NAT_MSG (7)
-#define LATENCY_PKT_SEND_MSG (8)
+struct CGenNodeMsgBase {
+ enum {
+ NAT_FIRST = 7,
+ LATENCY_PKT = 8,
+ } msg_types;
+
+public:
+ uint8_t m_msg_type; /* msg type */
+};
/*
@@ -71,7 +79,7 @@ public:
m_dp_to_cp=0;
m_num_dp_threads=0;
}
- bool Create(uint8_t num_dp_threads);
+ bool Create(uint8_t num_dp_threads,std::string name);
void Delete();
CNodeRing * getRingCpToDp(uint8_t thread_id);
CNodeRing * getRingDpToCp(uint8_t thread_id);
@@ -94,12 +102,18 @@ public:
CMessagingManager * getRxDp(){
return (&m_rx_dp);
}
+ CMessagingManager * getCpDp(){
+ return (&m_cp_dp);
+ }
+
uint8_t get_num_threads(){
return (m_rx_dp.get_num_threads());
}
private:
CMessagingManager m_rx_dp;
+ CMessagingManager m_cp_dp;
+
private:
/* one instance */
diff --git a/src/nat_check.cpp b/src/nat_check.cpp
index 676c1292..170d2de6 100755
--- a/src/nat_check.cpp
+++ b/src/nat_check.cpp
@@ -171,8 +171,8 @@ void CNatRxManager::handle_packet_ipv4(CNatOption * option,
}
-#define MYDP(f) if (f) fprintf(fd," %-40s: %llu \n",#f,f)
-#define MYDP_A(f) fprintf(fd," %-40s: %llu \n",#f,f)
+#define MYDP(f) if (f) fprintf(fd," %-40s: %llu \n",#f,(unsigned long long)f)
+#define MYDP_A(f) fprintf(fd," %-40s: %llu \n",#f, (unsigned long long)f)
diff --git a/src/nat_check.h b/src/nat_check.h
index b67c523c..a500ddaf 100755
--- a/src/nat_check.h
+++ b/src/nat_check.h
@@ -59,16 +59,6 @@ struct CNatFlowInfo {
this struct should be in the same size of CGenNode beacuse allocator is global .
*/
-struct CGenNodeMsgBase {
- enum {
- NAT_FIRST = NAT_MSG,
- LATENCY_PKT = LATENCY_PKT_SEND_MSG
- } msg_types;
-
-public:
- uint8_t m_msg_type; /* msg type */
-};
-
struct CGenNodeNatInfo : public CGenNodeMsgBase {
uint8_t m_pad;
diff --git a/src/os_time.h b/src/os_time.h
index 153ee3e3..0e732abf 100755
--- a/src/os_time.h
+++ b/src/os_time.h
@@ -22,6 +22,7 @@ limitations under the License.
*/
#include <stdint.h>
+#include <time.h>
typedef uint64_t hr_time_t; // time in high res tick
typedef uint32_t hr_time_32_t; // time in high res tick
@@ -129,6 +130,25 @@ static inline dsec_t now_sec(void){
}
+static inline
+void delay(int msec){
+
+ if (msec == 0)
+ {//user that requested that probebly wanted the minimal delay
+ //but because of scaling problem he have got 0 so we will give the min delay
+ //printf("\n\n\nERROR-Task delay ticks == 0 found in task %s task id = %d\n\n\n\n",
+ // SANB_TaskName(SANB_TaskIdSelf()), SANB_TaskIdSelf());
+ msec =1;
+
+ }
+
+ struct timespec time1, remain; // 2 sec max delay
+ time1.tv_sec=msec/1000;
+ time1.tv_nsec=(msec - (time1.tv_sec*1000))*1000000;
+
+ nanosleep(&time1,&remain);
+}
+
#endif
diff --git a/src/pal/linux/mbuf.h b/src/pal/linux/mbuf.h
index 693b095a..35a442bf 100755
--- a/src/pal/linux/mbuf.h
+++ b/src/pal/linux/mbuf.h
@@ -185,8 +185,9 @@ static inline void utl_rte_pktmbuf_add_last(rte_mbuf_t *m,rte_mbuf_t *m_last){
#define __rte_cache_aligned
-#define CACHE_LINE_SIZE 64
+#define CACHE_LINE_SIZE 64
+#define RTE_CACHE_LINE_SIZE 64
#define SOCKET_ID_ANY 0
#endif
diff --git a/src/platform_cfg.cpp b/src/platform_cfg.cpp
index f0911611..df04cd89 100755
--- a/src/platform_cfg.cpp
+++ b/src/platform_cfg.cpp
@@ -127,7 +127,7 @@ void CPlatformMemoryYamlInfo::Dump(FILE *fd){
int i=0;
for (i=0; i<MBUF_SIZE; i++) {
- fprintf(fd," %-40s : %lu \n",names[i].c_str(),m_mbuf[i]);
+ fprintf(fd," %-40s : %lu \n",names[i].c_str(), (ulong)m_mbuf[i]);
}
}
@@ -300,6 +300,10 @@ void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
plat_info.m_telnet_exist=true;
}
+ if ( node.FindValue("zmq_rpc_port") ){
+ node["zmq_rpc_port"] >> plat_info.m_zmq_rpc_port;
+ }
+
if ( node.FindValue("port_bandwidth_gb") ){
node["port_bandwidth_gb"] >> plat_info.m_port_bandwidth_gb;
}
@@ -375,7 +379,7 @@ void CPlatformYamlInfo::Dump(FILE *fd){
}else{
fprintf(fd," port limit : not configured \n");
}
- fprintf(fd," port_bandwidth_gb : %lu \n",m_port_bandwidth_gb);
+ fprintf(fd," port_bandwidth_gb : %lu \n", (ulong)m_port_bandwidth_gb);
if ( m_if_mask_exist && m_if_mask.size() ) {
fprintf(fd," if_mask : ");
@@ -383,7 +387,7 @@ void CPlatformYamlInfo::Dump(FILE *fd){
for (i=0; i<(int)m_if_mask.size(); i++) {
fprintf(fd," %s,",m_if_mask[i].c_str());
}
- fprintf(fd,"\n",m_if_mask[i].c_str());
+ fprintf(fd,"\n");
}else{
fprintf(fd," if_mask : None \n");
diff --git a/src/platform_cfg.h b/src/platform_cfg.h
index 2f335471..b4b03b10 100755
--- a/src/platform_cfg.h
+++ b/src/platform_cfg.h
@@ -184,6 +184,7 @@ public:
m_telnet_exist=false;
m_telnet_port=4502 ;
+ m_zmq_rpc_port = 5050;
m_mac_info_exist=false;
m_port_bandwidth_gb = 10;
@@ -209,15 +210,17 @@ public:
std::string m_limit_memory;
uint32_t m_thread_per_dual_if;
- uint32_t m_port_bandwidth_gb;
+ uint32_t m_port_bandwidth_gb;
- bool m_enable_zmq_pub_exist;
- bool m_enable_zmq_pub;
- uint16_t m_zmq_pub_port;
+ bool m_enable_zmq_pub_exist;
+ bool m_enable_zmq_pub;
+ uint16_t m_zmq_pub_port;
- bool m_telnet_exist;
- uint16_t m_telnet_port;
+ bool m_telnet_exist;
+ uint16_t m_telnet_port;
+
+ uint16_t m_zmq_rpc_port;
bool m_mac_info_exist;
std::vector <CMacYamlInfo> m_mac_info;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index ae87d749..b40e996f 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -145,7 +145,7 @@ trex_rpc_cmd_rc_e
TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
string hostname;
- TrexStateless & instance = TrexStateless::get_instance();
+ TrexStateless * main = get_stateless_obj();
Json::Value &section = result["result"];
@@ -155,21 +155,21 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
section["uptime"] = TrexRpcServer::get_server_uptime();
/* FIXME: core count */
- section["dp_core_count"] = instance.get_dp_core_count();
+ section["dp_core_count"] = main->get_dp_core_count();
section["core_type"] = get_cpu_model();
/* ports */
- section["port_count"] = instance.get_port_count();
+ section["port_count"] = main->get_port_count();
section["ports"] = Json::arrayValue;
- for (int i = 0; i < instance.get_port_count(); i++) {
+ for (int i = 0; i < main->get_port_count(); i++) {
string driver;
string speed;
- TrexStatelessPort *port = instance.get_port_by_id(i);
+ TrexStatelessPort *port = main->get_port_by_id(i);
port->get_properties(driver, speed);
section["ports"][i]["index"] = i;
@@ -201,7 +201,7 @@ TrexRpcCmdGetOwner::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_port(params, result);
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
section["owner"] = port->get_owner();
return (TREX_RPC_CMD_OK);
@@ -220,7 +220,7 @@ TrexRpcCmdAcquire::_run(const Json::Value &params, Json::Value &result) {
bool force = parse_bool(params, "force", result);
/* if not free and not you and not force - fail */
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
if ( (!port->is_free_to_aquire()) && (port->get_owner() != new_owner) && (!force)) {
generate_execute_err(result, "port is already taken by '" + port->get_owner() + "'");
@@ -242,7 +242,7 @@ TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_port(params, result);
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
if (port->get_state() == TrexStatelessPort::PORT_STATE_TRANSMITTING) {
generate_execute_err(result, "cannot release a port during transmission");
@@ -264,7 +264,7 @@ TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_port(params, result);
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
if (port->get_state() == TrexStatelessPort::PORT_STATE_DOWN) {
generate_execute_err(result, "cannot get stats - port is down");
@@ -277,3 +277,42 @@ TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
return (TREX_RPC_CMD_OK);
}
+/**
+ * request the server a sync about a specific user
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdSyncUser::_run(const Json::Value &params, Json::Value &result) {
+
+ const string &user = parse_string(params, "user", result);
+ bool sync_streams = parse_bool(params, "sync_streams", result);
+
+ result["result"] = Json::arrayValue;
+
+ for (auto port : get_stateless_obj()->get_port_list()) {
+ if (port->get_owner() == user) {
+
+ Json::Value owned_port;
+
+ owned_port["port_id"] = port->get_port_id();
+ owned_port["handler"] = port->get_owner_handler();
+ owned_port["state"] = port->get_state_as_string();
+
+ /* if sync streams was asked - sync all the streams */
+ if (sync_streams) {
+ owned_port["streams"] = Json::arrayValue;
+
+ std::vector <TrexStream *> streams;
+ port->get_stream_table()->get_object_list(streams);
+
+ for (auto stream : streams) {
+ owned_port["streams"].append(stream->get_stream_json());
+ }
+ }
+
+ result["result"].append(owned_port);
+ }
+ }
+
+ return (TREX_RPC_CMD_OK);
+}
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index 20107411..4fa0956d 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -114,7 +114,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
/* make sure this is a valid stream to add */
validate_stream(stream, result);
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(stream->m_port_id);
port->get_stream_table()->add_stream(stream);
result["result"] = "ACK";
@@ -127,7 +127,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
TrexStream *
TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t port_id, uint32_t stream_id, Json::Value &result) {
- TrexStream *stream;
+ TrexStream *stream = NULL;
const Json::Value &mode = parse_object(section, "mode", result);
std::string type = parse_string(mode, "type", result);
@@ -200,9 +200,9 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
std::string min_value_str = parse_string(inst, "min_value", result);
std::string max_value_str = parse_string(inst, "max_value", result);
- uint64_t init_value;
- uint64_t min_value;
- uint64_t max_value;
+ uint64_t init_value = 0;
+ uint64_t min_value = 0;
+ uint64_t max_value = 0;
try {
init_value = str2num(init_value_str);
@@ -282,15 +282,15 @@ TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &resu
}
/* port id should be between 0 and count - 1 */
- if (stream->m_port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (stream->m_port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
delete stream;
generate_execute_err(result, ss.str());
}
/* add the stream to the port's stream table */
- TrexStatelessPort * port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id);
+ TrexStatelessPort * port = get_stateless_obj()->get_port_by_id(stream->m_port_id);
/* does such a stream exists ? */
if (port->get_stream_table()->get_stream_by_id(stream->m_stream_id)) {
@@ -312,13 +312,13 @@ TrexRpcCmdRemoveStream::_run(const Json::Value &params, Json::Value &result) {
uint32_t stream_id = parse_int(params, "stream_id", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id);
if (!stream) {
@@ -344,13 +344,13 @@ trex_rpc_cmd_rc_e
TrexRpcCmdRemoveAllStreams::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
port->get_stream_table()->remove_and_delete_all_streams();
result["result"] = "ACK";
@@ -369,15 +369,15 @@ TrexRpcCmdGetStreamList::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
- port->get_stream_table()->get_stream_list(stream_list);
+ port->get_stream_table()->get_id_list(stream_list);
Json::Value json_list = Json::arrayValue;
@@ -397,17 +397,17 @@ TrexRpcCmdGetStreamList::_run(const Json::Value &params, Json::Value &result) {
**************************/
trex_rpc_cmd_rc_e
TrexRpcCmdGetStream::_run(const Json::Value &params, Json::Value &result) {
- uint8_t port_id = parse_byte(params, "port_id", result);
-
+ uint8_t port_id = parse_byte(params, "port_id", result);
+ bool get_pkt = parse_bool(params, "get_pkt", result);
uint32_t stream_id = parse_int(params, "stream_id", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id);
@@ -418,7 +418,12 @@ TrexRpcCmdGetStream::_run(const Json::Value &params, Json::Value &result) {
}
/* return the stored stream json (instead of decoding it all over again) */
- result["result"]["stream"] = stream->get_stream_json();
+ Json::Value j = stream->get_stream_json();
+ if (!get_pkt) {
+ j.removeMember("packet");
+ }
+
+ result["result"]["stream"] = j;
return (TREX_RPC_CMD_OK);
@@ -432,16 +437,17 @@ trex_rpc_cmd_rc_e
TrexRpcCmdStartTraffic::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
+ double mul = parse_double(params, "mul", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
- TrexStatelessPort::rc_e rc = port->start_traffic();
+ TrexStatelessPort::rc_e rc = port->start_traffic(mul);
if (rc == TrexStatelessPort::RC_OK) {
result["result"] = "ACK";
@@ -462,7 +468,7 @@ TrexRpcCmdStartTraffic::_run(const Json::Value &params, Json::Value &result) {
generate_execute_err(result, ss.str());
}
- return (TREX_RPC_CMD_OK);
+ return (TREX_RPC_CMD_OK);
}
/***************************
@@ -473,13 +479,13 @@ trex_rpc_cmd_rc_e
TrexRpcCmdStopTraffic::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
port->stop_traffic();
result["result"] = "ACK";
@@ -487,3 +493,43 @@ TrexRpcCmdStopTraffic::_run(const Json::Value &params, Json::Value &result) {
return (TREX_RPC_CMD_OK);
}
+/***************************
+ * get all streams
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetAllStreams::_run(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_byte(params, "port_id", result);
+ bool get_pkt = parse_bool(params, "get_pkt", result);
+
+ if (port_id >= get_stateless_obj()->get_port_count()) {
+ std::stringstream ss;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
+ generate_execute_err(result, ss.str());
+ }
+
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
+
+ std::vector <TrexStream *> streams;
+ port->get_stream_table()->get_object_list(streams);
+
+ Json::Value streams_json = Json::objectValue;
+ for (auto stream : streams) {
+
+ Json::Value j = stream->get_stream_json();
+
+ /* should we include the packet as well ? */
+ if (!get_pkt) {
+ j.removeMember("packet");
+ }
+
+ std::stringstream ss;
+ ss << stream->m_stream_id;
+
+ streams_json[ss.str()] = j;
+ }
+
+ result["result"]["streams"] = streams_json;
+
+ return (TREX_RPC_CMD_OK);
+}
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index 5926a8d8..a604d9a1 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -99,11 +99,16 @@ void parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream,
TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetAllStreams, "get_all_streams", 2, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 3, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1, true);
+
+
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 2, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdSyncUser, "sync_user", 2, false);
+
#endif /* __TREX_RPC_CMD_H__ */
diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp
index f4d21f2f..46fe499b 100644
--- a/src/rpc-server/trex_rpc_async_server.cpp
+++ b/src/rpc-server/trex_rpc_async_server.cpp
@@ -79,7 +79,7 @@ TrexRpcServerAsync::_rpc_thread_cb() {
}
/* trigger a full update for stats */
- TrexStateless::get_instance().update_stats();
+ //get_stateless_obj()->update_stats();
/* done with the lock */
if (m_lock) {
@@ -87,7 +87,7 @@ TrexRpcServerAsync::_rpc_thread_cb() {
}
/* encode them to JSON */
- TrexStateless::get_instance().encode_stats(snapshot);
+ get_stateless_obj()->encode_stats(snapshot);
/* write to string and publish */
std::string snapshot_str = writer.write(snapshot);
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index 920a8d30..af0db3f4 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -61,7 +61,7 @@ TrexRpcCommand::verify_ownership(const Json::Value &params, Json::Value &result)
std::string handler = parse_string(params, "handler", result);
uint8_t port_id = parse_port(params, result);
- TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
if (!port->verify_owner_handler(handler)) {
generate_execute_err(result, "invalid handler provided. please pass the handler given when calling 'acquire' or take ownership");
@@ -78,9 +78,9 @@ TrexRpcCommand::parse_port(const Json::Value &params, Json::Value &result) {
void
TrexRpcCommand::validate_port_id(uint8_t port_id, Json::Value &result) {
- if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ if (port_id >= get_stateless_obj()->get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)get_stateless_obj()->get_port_count() - 1;
generate_execute_err(result, ss.str());
}
}
diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index c1c546f3..e3bd7848 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -42,12 +42,15 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
register_command(new TrexRpcCmdRelease());
register_command(new TrexRpcCmdGetPortStats());
+ register_command(new TrexRpcCmdSyncUser());
+
/* stream commands */
register_command(new TrexRpcCmdAddStream());
register_command(new TrexRpcCmdRemoveStream());
register_command(new TrexRpcCmdRemoveAllStreams());
register_command(new TrexRpcCmdGetStreamList());
register_command(new TrexRpcCmdGetStream());
+ register_command(new TrexRpcCmdGetAllStreams());
register_command(new TrexRpcCmdStartTraffic());
register_command(new TrexRpcCmdStopTraffic());
}
diff --git a/src/rx_check.cpp b/src/rx_check.cpp
index 3a67ca23..59b42e1a 100755
--- a/src/rx_check.cpp
+++ b/src/rx_check.cpp
@@ -45,8 +45,8 @@ void CRxCheckFlowTableStats::Clear(){
}
-#define MYDP(f) if (f) fprintf(fd," %-40s: %llu \n",#f,f)
-#define MYDP_A(f) fprintf(fd," %-40s: %llu \n",#f,f)
+#define MYDP(f) if (f) fprintf(fd," %-40s: %llu \n",#f,(unsigned long long)f)
+#define MYDP_A(f) fprintf(fd," %-40s: %llu \n",#f,(unsigned long long)f)
#define MYDP_J(f) json+=add_json(#f,f);
#define MYDP_J_LAST(f) json+=add_json(#f,f,true);
@@ -146,7 +146,7 @@ void CRxCheckFlowTableMap::dump_all(FILE *fd){
rx_check_flow_map_iter_t it;
for (it= m_map.begin(); it != m_map.end(); ++it) {
CRxCheckFlow *lp = it->second;
- printf ("flow_id: %d \n",lp->m_flow_id);
+ printf ("flow_id: %llu \n",(unsigned long long)lp->m_flow_id);
}
}
@@ -208,7 +208,7 @@ std::string CPerTxthreadTemplateInfo::dump_as_json(std::string name){
int i;
for (i=0;i<MAX_TEMPLATES_STATS;i++){
char buff[200];
- sprintf(buff,"%llu",m_template_info[i]);
+ sprintf(buff,"%llu", (unsigned long long)m_template_info[i]);
json+=std::string(buff);
if ( i < MAX_TEMPLATES_STATS-1) {
json+=std::string(",");
@@ -231,7 +231,7 @@ void CPerTxthreadTemplateInfo::Dump(FILE *fd){
int i;
for (i=0; i<MAX_TEMPLATES_STATS; i++) {
if (m_template_info[i]) {
- fprintf (fd," template id: %llu %llu \n",i,m_template_info[i]);
+ fprintf (fd," template id: %d %llu \n",i, (unsigned long long)m_template_info[i]);
}
}
}
@@ -484,7 +484,7 @@ void RxCheckManager::DumpTemplate(FILE *fd,bool verbose){
if (cnt==0){
fprintf(fd,"\n");
}
- fprintf(fd,"[id:%2d val:%8d,rx:%8d], ",i,lp->get_error_counter(),lp->get_rx_counter());
+ fprintf(fd,"[id:%2d val:%8llu,rx:%8llu], ",i, (unsigned long long)lp->get_error_counter(), (unsigned long long)lp->get_rx_counter());
cnt++;
if (cnt>5) {
cnt=0;
@@ -500,7 +500,11 @@ void RxCheckManager::DumpTemplateFull(FILE *fd){
int i;
for (i=0; i<MAX_TEMPLATES_STATS;i++ ) {
CPerTemplateInfo * lp=get_template(i);
- fprintf(fd," template_id_%2d , errors:%8d, jitter: %lu rx : %lu \n",i,lp->get_error_counter(),lp->get_jitter_usec(),lp->get_rx_counter() );
+ fprintf(fd," template_id_%2d , errors:%8llu, jitter: %llu rx : %llu \n",
+ i,
+ (unsigned long long)lp->get_error_counter(),
+ (unsigned long long)lp->get_jitter_usec(),
+ (unsigned long long)lp->get_rx_counter() );
}
}
@@ -514,7 +518,11 @@ void RxCheckManager::DumpShort(FILE *fd){
DumpTemplate(fd,false);
fprintf(fd,"\n");
fprintf(fd,"---\n");
- fprintf(fd," active flows: %8d, fif: %8d, drop: %8d, errors: %8d \n",m_stats.m_active,m_stats.m_fif,m_stats.m_err_drop,m_stats.get_total_err());
+ fprintf(fd," active flows: %8llu, fif: %8llu, drop: %8llu, errors: %8llu \n",
+ (unsigned long long)m_stats.m_active,
+ (unsigned long long)m_stats.m_fif,
+ (unsigned long long)m_stats.m_err_drop,
+ (unsigned long long)m_stats.get_total_err());
fprintf(fd,"------------------------------------------------------------------------------------------------------------\n");
}
diff --git a/src/rx_check.h b/src/rx_check.h
index 6f9763a2..07f5684c 100755
--- a/src/rx_check.h
+++ b/src/rx_check.h
@@ -30,9 +30,10 @@ limitations under the License.
typedef enum {
- CLIENT_SIDE=0,
- SERVER_SIDE=1,
- CS_NUM=2
+ CLIENT_SIDE = 0,
+ SERVER_SIDE = 1,
+ CS_NUM = 2,
+ CS_INVALID = 255
} pkt_dir_enum_t;
typedef uint8_t pkt_dir_t ;
diff --git a/src/rx_check_header.cpp b/src/rx_check_header.cpp
index 8ee580db..5934ee15 100755
--- a/src/rx_check_header.cpp
+++ b/src/rx_check_header.cpp
@@ -42,11 +42,11 @@ void CRx_check_header::dump(FILE *fd){
void CNatOption::dump(FILE *fd){
- fprintf(fd," op : %lx \n",get_option_type());
- fprintf(fd," ol : %lx \n",get_option_len());
- fprintf(fd," thread_id : %lx \n",get_thread_id());
- fprintf(fd," magic : %lx \n",get_magic());
- fprintf(fd," fid : %lx \n",get_fid());
+ fprintf(fd," op : %x \n",get_option_type());
+ fprintf(fd," ol : %x \n",get_option_len());
+ fprintf(fd," thread_id : %x \n",get_thread_id());
+ fprintf(fd," magic : %x \n",get_magic());
+ fprintf(fd," fid : %x \n",get_fid());
utl_DumpBuffer(stdout,(void *)&u.m_data[0],8,0);
}
diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp
index 72762e26..e0e95450 100644
--- a/src/stateless/cp/trex_stateless.cpp
+++ b/src/stateless/cp/trex_stateless.cpp
@@ -31,55 +31,58 @@ using namespace std;
* Trex stateless object
*
**********************************************************/
-TrexStateless::TrexStateless() {
- m_is_configured = false;
-}
-
/**
- * configure the singleton stateless object
*
*/
-void TrexStateless::configure(const TrexStatelessCfg &cfg) {
-
- TrexStateless& instance = get_instance_internal();
-
- /* check status */
- if (instance.m_is_configured) {
- throw TrexException("re-configuration of stateless object is not allowed");
- }
+TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) {
/* create RPC servers */
/* set both servers to mutex each other */
- instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &instance.m_global_cp_lock);
- instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose);
+ m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &m_global_cp_lock);
+ m_rpc_server->set_verbose(cfg.m_rpc_server_verbose);
/* configure ports */
+ m_port_count = cfg.m_port_count;
- instance.m_port_count = cfg.m_port_count;
-
- for (int i = 0; i < instance.m_port_count; i++) {
- instance.m_ports.push_back(new TrexStatelessPort(i));
+ for (int i = 0; i < m_port_count; i++) {
+ m_ports.push_back(new TrexStatelessPort(i));
}
- /* cores */
- instance.m_dp_core_count = cfg.m_dp_core_count;
- for (int i = 0; i < instance.m_dp_core_count; i++) {
- instance.m_dp_cores.push_back(new TrexStatelessDpCore(i));
+ m_platform_api = cfg.m_platform_api;
+}
+
+/**
+ * release all memory
+ *
+ * @author imarom (08-Oct-15)
+ */
+TrexStateless::~TrexStateless() {
+
+ /* release memory for ports */
+ for (auto port : m_ports) {
+ delete port;
}
+ m_ports.clear();
+
+ /* stops the RPC server */
+ m_rpc_server->stop();
+ delete m_rpc_server;
+
+ m_rpc_server = NULL;
- /* done */
- instance.m_is_configured = true;
+ delete m_platform_api;
+ m_platform_api = NULL;
}
+
/**
* starts the control plane side
*
*/
void
TrexStateless::launch_control_plane() {
- //std::cout << "\n on control/master core \n";
/* pin this process to the current running CPU
any new thread will be called on the same CPU
@@ -94,39 +97,6 @@ TrexStateless::launch_control_plane() {
m_rpc_server->start();
}
-void
-TrexStateless::launch_on_dp_core(uint8_t core_id) {
- m_dp_cores[core_id - 1]->run();
-}
-
-/**
- * destroy the singleton and release all memory
- *
- * @author imarom (08-Oct-15)
- */
-void
-TrexStateless::destroy() {
- TrexStateless& instance = get_instance_internal();
-
- if (!instance.m_is_configured) {
- return;
- }
-
- /* release memory for ports */
- for (auto port : instance.m_ports) {
- delete port;
- }
- instance.m_ports.clear();
-
- /* stops the RPC server */
- instance.m_rpc_server->stop();
- delete instance.m_rpc_server;
-
- instance.m_rpc_server = NULL;
-
- /* done */
- instance.m_is_configured = false;
-}
/**
* fetch a port by ID
@@ -148,57 +118,32 @@ TrexStateless::get_port_count() {
uint8_t
TrexStateless::get_dp_core_count() {
- return m_dp_core_count;
-}
-
-void
-TrexStateless::update_stats() {
-
- /* update CPU util.
- TODO
- */
- m_stats.m_stats.m_cpu_util = 0;
-
- /* for every port update and accumulate */
- for (uint8_t i = 0; i < m_port_count; i++) {
- m_ports[i]->update_stats();
-
- const TrexPortStats & port_stats = m_ports[i]->get_stats();
-
- m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps;
- m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps;
-
- m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps;
- m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps;
-
- m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts;
- m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts;
-
- m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes;
- m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes;
-
- m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors;
- }
+ return m_platform_api->get_dp_core_count();
}
void
TrexStateless::encode_stats(Json::Value &global) {
- global["cpu_util"] = m_stats.m_stats.m_cpu_util;
+ const TrexPlatformApi *api = get_stateless_obj()->get_platform_api();
+
+ TrexPlatformGlobalStats stats;
+ api->get_global_stats(stats);
- global["tx_bps"] = m_stats.m_stats.m_tx_bps;
- global["rx_bps"] = m_stats.m_stats.m_rx_bps;
+ global["cpu_util"] = stats.m_stats.m_cpu_util;
- global["tx_pps"] = m_stats.m_stats.m_tx_pps;
- global["rx_pps"] = m_stats.m_stats.m_rx_pps;
+ global["tx_bps"] = stats.m_stats.m_tx_bps;
+ global["rx_bps"] = stats.m_stats.m_rx_bps;
- global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts);
- global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts);
+ global["tx_pps"] = stats.m_stats.m_tx_pps;
+ global["rx_pps"] = stats.m_stats.m_rx_pps;
- global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes);
- global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes);
+ global["total_tx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_tx_pkts);
+ global["total_rx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_rx_pkts);
- global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors);
+ global["total_tx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_tx_bytes);
+ global["total_rx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_rx_bytes);
+
+ global["tx_rx_errors"] = Json::Value::UInt64(stats.m_stats.m_tx_rx_errors);
for (uint8_t i = 0; i < m_port_count; i++) {
std::stringstream ss;
@@ -210,3 +155,20 @@ TrexStateless::encode_stats(Json::Value &global) {
}
}
+/**
+ * generate a snapshot for publish (async publish)
+ *
+ */
+void
+TrexStateless::generate_publish_snapshot(std::string &snapshot) {
+ Json::FastWriter writer;
+ Json::Value root;
+
+ root["name"] = "trex-stateless-info";
+ root["type"] = 0;
+
+ /* stateless specific info goes here */
+ root["data"] = Json::nullValue;
+
+ snapshot = writer.write(root);
+}
diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h
index 649b25dd..57c6ef1d 100644
--- a/src/stateless/cp/trex_stateless.h
+++ b/src/stateless/cp/trex_stateless.h
@@ -29,9 +29,10 @@ limitations under the License.
#include <trex_stream.h>
#include <trex_stateless_port.h>
-#include <trex_stateless_dp_core.h>
#include <trex_rpc_server_api.h>
+#include <internal_api/trex_platform_api.h>
+
/**
* generic exception for errors
* TODO: move this to a better place
@@ -88,17 +89,17 @@ public:
/* default values */
TrexStatelessCfg() {
m_port_count = 0;
- m_dp_core_count = 0;
m_rpc_req_resp_cfg = NULL;
m_rpc_async_cfg = NULL;
- m_rpc_server_verbose = false;
+ m_rpc_server_verbose = false;
+ m_platform_api = NULL;
}
const TrexRpcServerConfig *m_rpc_req_resp_cfg;
const TrexRpcServerConfig *m_rpc_async_cfg;
+ const TrexPlatformApi *m_platform_api;
bool m_rpc_server_verbose;
uint8_t m_port_count;
- uint8_t m_dp_core_count;
};
/**
@@ -113,27 +114,8 @@ public:
* reconfiguration is not allowed
* an exception will be thrown
*/
- static void configure(const TrexStatelessCfg &cfg);
-
- /**
- * destroy the instance
- *
- */
- static void destroy();
-
- /**
- * singleton public get instance
- *
- */
- static TrexStateless& get_instance() {
- TrexStateless& instance = get_instance_internal();
-
- if (!instance.m_is_configured) {
- throw TrexException("object is not configured");
- }
-
- return instance;
- }
+ TrexStateless(const TrexStatelessCfg &cfg);
+ ~TrexStateless();
/**
* starts the control plane side
@@ -152,12 +134,6 @@ public:
uint8_t get_dp_core_count();
- /**
- * update all the stats (deep update)
- * (include all the ports and global stats)
- *
- */
- void update_stats();
/**
* fetch all the stats
@@ -165,22 +141,25 @@ public:
*/
void encode_stats(Json::Value &global);
+ /**
+ * generate a snapshot for publish
+ */
+ void generate_publish_snapshot(std::string &snapshot);
-protected:
- TrexStateless();
+ const TrexPlatformApi * get_platform_api() {
+ return (m_platform_api);
+ }
- static TrexStateless& get_instance_internal () {
- static TrexStateless instance;
- return instance;
+ const std::vector <TrexStatelessPort *> get_port_list() {
+ return m_ports;
}
- /* c++ 2011 style singleton */
+protected:
+
+ /* no copy or assignment */
TrexStateless(TrexStateless const&) = delete;
void operator=(TrexStateless const&) = delete;
- /* status */
- bool m_is_configured;
-
/* RPC server array */
TrexRpcServer *m_rpc_server;
@@ -188,15 +167,20 @@ protected:
std::vector <TrexStatelessPort *> m_ports;
uint8_t m_port_count;
- /* cores */
- std::vector <TrexStatelessDpCore *> m_dp_cores;
- uint8_t m_dp_core_count;
-
- /* stats */
- TrexStatelessStats m_stats;
+ /* platform API */
+ const TrexPlatformApi *m_platform_api;
std::mutex m_global_cp_lock;
};
+/**
+ * an anchor function
+ *
+ * @author imarom (25-Oct-15)
+ *
+ * @return TrexStateless&
+ */
+TrexStateless * get_stateless_obj();
+
#endif /* __TREX_STATELESS_H__ */
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index a31847a5..cb6fcc0e 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -18,20 +18,34 @@ 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.
*/
+
#include <trex_stateless.h>
#include <trex_stateless_port.h>
+#include <trex_stateless_messaging.h>
+#include <trex_streams_compiler.h>
+
#include <string>
#ifndef TREX_RPC_MOCK_SERVER
+
// DPDK c++ issue
-#define UINT8_MAX 255
-#define UINT16_MAX 0xFFFF
+#ifndef UINT8_MAX
+ #define UINT8_MAX 255
+#endif
+
+#ifndef UINT16_MAX
+ #define UINT16_MAX 0xFFFF
+#endif
+
// DPDK c++ issue
#endif
#include <rte_ethdev.h>
#include <os_time.h>
+void
+port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list);
+
using namespace std;
/***************************
@@ -49,7 +63,7 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
*
*/
TrexStatelessPort::rc_e
-TrexStatelessPort::start_traffic(void) {
+TrexStatelessPort::start_traffic(double mul) {
if (m_port_state != PORT_STATE_UP_IDLE) {
return (RC_ERR_BAD_STATE_FOR_OP);
@@ -59,19 +73,46 @@ TrexStatelessPort::start_traffic(void) {
return (RC_ERR_NO_STREAMS);
}
+ /* fetch all the streams from the table */
+ vector<TrexStream *> streams;
+ get_stream_table()->get_object_list(streams);
+
+ /* compiler it */
+ TrexStreamsCompiler compiler;
+ TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, mul);
+
+ bool rc = compiler.compile(streams, *compiled_obj);
+ if (!rc) {
+ return (RC_ERR_FAILED_TO_COMPILE_STREAMS);
+ }
+
+ /* generate a message to all the relevant DP cores to start transmitting */
+ TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj);
+
+ send_message_to_dp(start_msg);
+
+ /* move the state to transmiting */
m_port_state = PORT_STATE_TRANSMITTING;
- /* real code goes here */
return (RC_OK);
}
-void
+TrexStatelessPort::rc_e
TrexStatelessPort::stop_traffic(void) {
/* real code goes here */
- if (m_port_state == PORT_STATE_TRANSMITTING) {
- m_port_state = PORT_STATE_UP_IDLE;
+ if (m_port_state != PORT_STATE_TRANSMITTING) {
+ return (RC_ERR_BAD_STATE_FOR_OP);
}
+
+ /* generate a message to all the relevant DP cores to start transmitting */
+ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id);
+
+ send_message_to_dp(stop_msg);
+
+ m_port_state = PORT_STATE_UP_IDLE;
+
+ return (RC_OK);
}
/**
@@ -130,99 +171,42 @@ TrexStatelessPort::generate_handler() {
return (ss.str());
}
-/**
- * update stats for the port
- *
- */
-void
-TrexStatelessPort::update_stats() {
- struct rte_eth_stats stats;
- rte_eth_stats_get(m_port_id, &stats);
-
- /* copy straight values */
- m_stats.m_stats.m_total_tx_bytes = stats.obytes;
- m_stats.m_stats.m_total_rx_bytes = stats.ibytes;
-
- m_stats.m_stats.m_total_tx_pkts = stats.opackets;
- m_stats.m_stats.m_total_rx_pkts = stats.ipackets;
-
- /* calculate stats */
- m_stats.m_stats.m_tx_bps = m_stats.m_bw_tx_bps.add(stats.obytes);
- m_stats.m_stats.m_rx_bps = m_stats.m_bw_rx_bps.add(stats.ibytes);
-
- m_stats.m_stats.m_tx_pps = m_stats.m_bw_tx_pps.add(stats.opackets);
- m_stats.m_stats.m_rx_pps = m_stats.m_bw_rx_pps.add(stats.ipackets);
-
-}
-
-const TrexPortStats &
-TrexStatelessPort::get_stats() {
- return m_stats;
-}
void
TrexStatelessPort::encode_stats(Json::Value &port) {
- port["tx_bps"] = m_stats.m_stats.m_tx_bps;
- port["rx_bps"] = m_stats.m_stats.m_rx_bps;
+ const TrexPlatformApi *api = get_stateless_obj()->get_platform_api();
- port["tx_pps"] = m_stats.m_stats.m_tx_pps;
- port["rx_pps"] = m_stats.m_stats.m_rx_pps;
+ TrexPlatformInterfaceStats stats;
+ api->get_interface_stats(m_port_id, stats);
- port["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts);
- port["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts);
+ port["tx_bps"] = stats.m_stats.m_tx_bps;
+ port["rx_bps"] = stats.m_stats.m_rx_bps;
- port["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes);
- port["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes);
-
- port["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors);
-}
+ port["tx_pps"] = stats.m_stats.m_tx_pps;
+ port["rx_pps"] = stats.m_stats.m_rx_pps;
+ port["total_tx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_tx_pkts);
+ port["total_rx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_rx_pkts);
-
-/***************************
- * BW measurement
- *
- **************************/
-/* TODO: move this to a common place */
-BWMeasure::BWMeasure() {
- reset();
+ port["total_tx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_tx_bytes);
+ port["total_rx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_rx_bytes);
+
+ port["tx_rx_errors"] = Json::Value::UInt64(stats.m_stats.m_tx_rx_errors);
}
-void BWMeasure::reset(void) {
- m_start=false;
- m_last_time_msec=0;
- m_last_bytes=0;
- m_last_result=0.0;
-};
-
-double BWMeasure::calc_MBsec(uint32_t dtime_msec,
- uint64_t dbytes){
- double rate=0.000008*( ( (double)dbytes*(double)os_get_time_freq())/((double)dtime_msec) );
- return(rate);
-}
+void
+TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) {
-double BWMeasure::add(uint64_t size) {
- if ( false == m_start ) {
- m_start=true;
- m_last_time_msec = os_get_time_msec() ;
- m_last_bytes=size;
- return(0.0);
- }
+ std::vector<std::pair<uint8_t, uint8_t>> cores_id_list;
- uint32_t ctime=os_get_time_msec();
- if ((ctime - m_last_time_msec) <os_get_time_freq() ) {
- return(m_last_result);
- }
+ get_stateless_obj()->get_platform_api()->port_id_to_cores(m_port_id, cores_id_list);
- uint32_t dtime_msec = ctime-m_last_time_msec;
- uint64_t dbytes = size - m_last_bytes;
+ for (auto core_pair : cores_id_list) {
- m_last_time_msec = ctime;
- m_last_bytes = size;
+ /* send the message to the core */
+ CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_pair.first);
+ ring->Enqueue((CGenNode *)msg->clone());
+ }
- m_last_result= 0.5*calc_MBsec(dtime_msec,dbytes) +0.5*(m_last_result);
- return( m_last_result );
}
-
-
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index 428d5aee..09183768 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -23,70 +23,7 @@ limitations under the License.
#include <trex_stream.h>
-/**
- * bandwidth measurement class
- *
- */
-class BWMeasure {
-public:
- BWMeasure();
- void reset(void);
- double add(uint64_t size);
-
-private:
- double calc_MBsec(uint32_t dtime_msec,
- uint64_t dbytes);
-
-public:
- bool m_start;
- uint32_t m_last_time_msec;
- uint64_t m_last_bytes;
- double m_last_result;
-};
-
-/**
- * TRex stateless port stats
- *
- * @author imarom (24-Sep-15)
- */
-class TrexPortStats {
-
-public:
- TrexPortStats() {
- m_stats = {0};
-
- m_bw_tx_bps.reset();
- m_bw_rx_bps.reset();
-
- m_bw_tx_pps.reset();
- m_bw_rx_pps.reset();
- }
-
-public:
-
- BWMeasure m_bw_tx_bps;
- BWMeasure m_bw_rx_bps;
-
- BWMeasure m_bw_tx_pps;
- BWMeasure m_bw_rx_pps;
-
- struct {
-
- double m_tx_bps;
- double m_rx_bps;
-
- double m_tx_pps;
- double m_rx_pps;
-
- uint64_t m_total_tx_pkts;
- uint64_t m_total_rx_pkts;
-
- uint64_t m_total_tx_bytes;
- uint64_t m_total_rx_bytes;
-
- uint64_t m_tx_rx_errors;
- } m_stats;
-};
+class TrexStatelessCpToDpMsgBase;
/**
* describes a stateless port
@@ -121,13 +58,13 @@ public:
* start traffic
*
*/
- rc_e start_traffic(void);
+ rc_e start_traffic(double mul);
/**
* stop traffic
*
*/
- void stop_traffic(void);
+ rc_e stop_traffic(void);
/**
* access the stream table
@@ -203,28 +140,25 @@ public:
}
/**
- * update the values of the stats
- *
- */
- void update_stats();
-
- const TrexPortStats & get_stats();
-
- /**
* encode stats as JSON
*/
void encode_stats(Json::Value &port);
+ uint8_t get_port_id() {
+ return m_port_id;
+ }
+
private:
std::string generate_handler();
+ void send_message_to_dp(TrexStatelessCpToDpMsgBase *msg);
+
TrexStreamTable m_stream_table;
uint8_t m_port_id;
port_state_e m_port_state;
std::string m_owner;
std::string m_owner_handler;
- TrexPortStats m_stats;
};
#endif /* __TREX_STATELESS_PORT_H__ */
diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp
index 182036f1..ba306137 100644
--- a/src/stateless/cp/trex_stream.cpp
+++ b/src/stateless/cp/trex_stream.cpp
@@ -20,6 +20,7 @@ limitations under the License.
*/
#include <trex_stream.h>
#include <cstddef>
+#include <string.h>
/**************************************
* stream
@@ -103,14 +104,24 @@ TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) {
}
}
-void TrexStreamTable::get_stream_list(std::vector<uint32_t> &stream_list) {
- stream_list.clear();
+void TrexStreamTable::get_id_list(std::vector<uint32_t> &id_list) {
+ id_list.clear();
for (auto stream : m_stream_table) {
- stream_list.push_back(stream.first);
+ id_list.push_back(stream.first);
}
}
+void TrexStreamTable::get_object_list(std::vector<TrexStream *> &object_list) {
+ object_list.clear();
+
+ for (auto stream : m_stream_table) {
+ object_list.push_back(stream.second);
+ }
+
+}
+
int TrexStreamTable::size() {
return m_stream_table.size();
}
+
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index f5bc96ef..c8a15240 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -37,10 +37,6 @@ class TrexRpcCmdAddStream;
*
*/
class TrexStream {
- /* provide the RPC parser a way to access private fields */
- friend class TrexRpcCmdAddStream;
- friend class TrexRpcCmdGetStream;
- friend class TrexStreamTable;
public:
TrexStream(uint8_t port_id, uint32_t stream_id);
@@ -56,7 +52,7 @@ public:
/* access the stream json */
const Json::Value & get_stream_json();
-protected:
+public:
/* basic */
uint8_t m_port_id;
uint32_t m_stream_id;
@@ -189,7 +185,13 @@ public:
*
* @param stream_list
*/
- void get_stream_list(std::vector<uint32_t> &stream_list);
+ void get_id_list(std::vector<uint32_t> &id_list);
+
+ /**
+ * populate a list with all the stream objects
+ *
+ */
+ void get_object_list(std::vector<TrexStream *> &object_list);
/**
* get the table size
@@ -197,6 +199,9 @@ public:
*/
int size();
+ std::unordered_map<int, TrexStream *>::iterator begin() {return m_stream_table.begin();}
+ std::unordered_map<int, TrexStream *>::iterator end() {return m_stream_table.end();}
+
private:
/**
* holds all the stream in a hash table by stream id
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
new file mode 100644
index 00000000..06c0119a
--- /dev/null
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -0,0 +1,106 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+
+#include <string.h>
+#include <trex_streams_compiler.h>
+#include <trex_stream.h>
+
+/**************************************
+ * stream compiled object
+ *************************************/
+TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) {
+}
+
+TrexStreamsCompiledObj::~TrexStreamsCompiledObj() {
+ for (auto &obj : m_objs) {
+ delete obj.m_pkt;
+ }
+ m_objs.clear();
+}
+
+void
+TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len) {
+ obj_st obj;
+
+ obj.m_isg_usec = isg_usec;
+ obj.m_port_id = m_port_id;
+ obj.m_pps = pps * m_mul;
+ obj.m_pkt_len = pkt_len;
+
+ obj.m_pkt = new uint8_t[pkt_len];
+ memcpy(obj.m_pkt, pkt, pkt_len);
+
+ m_objs.push_back(obj);
+}
+
+TrexStreamsCompiledObj *
+TrexStreamsCompiledObj::clone() {
+
+ TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id, m_mul);
+
+ /**
+ * clone each element
+ */
+ for (auto obj : m_objs) {
+ new_compiled_obj->add_compiled_stream(obj.m_isg_usec,
+ obj.m_pps,
+ obj.m_pkt,
+ obj.m_pkt_len);
+ }
+
+ return new_compiled_obj;
+}
+
+/**************************************
+ * stream compiler
+ *************************************/
+bool
+TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams, TrexStreamsCompiledObj &obj) {
+ /* for now we do something trivial, */
+ for (auto stream : streams) {
+
+ /* skip non-enabled streams */
+ if (!stream->m_enabled) {
+ continue;
+ }
+
+ /* for now skip also non self started streams */
+ if (!stream->m_self_start) {
+ continue;
+ }
+
+ /* for now support only continous ... */
+ TrexStreamContinuous *cont_stream = dynamic_cast<TrexStreamContinuous *>(stream);
+ if (!cont_stream) {
+ continue;
+ }
+
+ /* add it */
+ obj.add_compiled_stream(cont_stream->m_isg_usec,
+ cont_stream->get_pps(),
+ cont_stream->m_pkt.binary,
+ cont_stream->m_pkt.len);
+ }
+
+ return true;
+}
+
+
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
new file mode 100644
index 00000000..404fdd21
--- /dev/null
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -0,0 +1,79 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+#ifndef __TREX_STREAMS_COMPILER_H__
+#define __TREX_STREAMS_COMPILER_H__
+
+#include <stdint.h>
+#include <vector>
+
+class TrexStreamsCompiler;
+class TrexStream;
+
+/**
+ * compiled object for a table of streams
+ *
+ * @author imarom (28-Oct-15)
+ */
+class TrexStreamsCompiledObj {
+ friend class TrexStreamsCompiler;
+public:
+
+ TrexStreamsCompiledObj(uint8_t port_id, double m_mul);
+ ~TrexStreamsCompiledObj();
+
+ struct obj_st {
+ double m_isg_usec;
+ double m_pps;
+ uint8_t *m_pkt;
+ uint16_t m_pkt_len;
+ uint8_t m_port_id;
+ };
+
+ const std::vector<obj_st> & get_objects() {
+ return m_objs;
+ }
+
+ /**
+ * clone the compiled object
+ *
+ */
+ TrexStreamsCompiledObj * clone();
+
+private:
+ void add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len);
+ std::vector<obj_st> m_objs;
+
+ uint8_t m_port_id;
+ double m_mul;
+};
+
+class TrexStreamsCompiler {
+public:
+ /**
+ * compiles a vector of streams to an object passable to the DP
+ *
+ * @author imarom (28-Oct-15)
+ *
+ */
+ bool compile(const std::vector<TrexStream *> &streams, TrexStreamsCompiledObj &obj);
+};
+
+#endif /* __TREX_STREAMS_COMPILER_H__ */
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index 3755b82c..b2bd0152 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -18,118 +18,186 @@ 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.
*/
-
#include <trex_stateless_dp_core.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <trex_stateless.h>
+#include <trex_stateless_messaging.h>
+#include <trex_streams_compiler.h>
+#include <trex_stream_node.h>
#include <bp_sim.h>
-#ifndef TREX_RPC_MOCK_SERVER
+static inline double
+usec_to_sec(double usec) {
+ return (usec / (1000 * 1000));
+}
+
-// DPDK c++ issue
-#define UINT8_MAX 255
-#define UINT16_MAX 0xFFFF
-// DPDK c++ issue
-#endif
+void
+TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) {
+ m_thread_id = thread_id;
+ m_core = core;
-#include <rte_ethdev.h>
-#include "mbuf.h"
+ CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp();
+
+ m_ring_from_cp = cp_dp->getRingCpToDp(thread_id);
+ m_ring_to_cp = cp_dp->getRingDpToCp(thread_id);
+
+ m_state = STATE_IDLE;
+}
/**
- * TEST
+ * in idle state loop, the processor most of the time sleeps
+ * and periodically checks for messages
*
+ * @author imarom (01-Nov-15)
*/
-static const uint8_t udp_pkt[]={
- 0x00,0x00,0x00,0x01,0x00,0x00,
- 0x00,0x00,0x00,0x01,0x00,0x00,
- 0x08,0x00,
-
- 0x45,0x00,0x00,0x81,
- 0xaf,0x7e,0x00,0x00,
- 0x12,0x11,0xd9,0x23,
- 0x01,0x01,0x01,0x01,
- 0x3d,0xad,0x72,0x1b,
-
- 0x11,0x11,
- 0x11,0x11,
-
- 0x00,0x6d,
- 0x00,0x00,
-
- 0x64,0x31,0x3a,0x61,
- 0x64,0x32,0x3a,0x69,0x64,
- 0x32,0x30,0x3a,0xd0,0x0e,
- 0xa1,0x4b,0x7b,0xbd,0xbd,
- 0x16,0xc6,0xdb,0xc4,0xbb,0x43,
- 0xf9,0x4b,0x51,0x68,0x33,0x72,
- 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f,
- 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3,
- 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f,
- 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39,
- 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31,
- 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d,
- 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d,
- 0xe7
-};
-
-static int
-test_inject_pkt(uint8_t *pkt, uint32_t pkt_size) {
-
- #ifndef TREX_RPC_MOCK_SERVER
- rte_mempool_t * mp= CGlobalInfo::m_mem_pool[0].m_big_mbuf_pool ;
- #else
- rte_mempool_t * mp = NULL;
- #endif
-
- rte_mbuf_t *m = rte_pktmbuf_alloc(mp);
- if ( unlikely(m==0) ) {
- printf("ERROR no packets \n");
- return (-1);
+void
+TrexStatelessDpCore::idle_state_loop() {
+
+ while (m_state == STATE_IDLE) {
+ periodic_check_for_cp_messages();
+ delay(200);
}
+}
+
+/**
+ * scehduler runs when traffic exists
+ * it will return when no more transmitting is done on this
+ * core
+ *
+ * @author imarom (01-Nov-15)
+ */
+void
+TrexStatelessDpCore::start_scheduler() {
+ /* creates a maintenace job using the scheduler */
+ CGenNode * node_sync = m_core->create_node() ;
+ node_sync->m_type = CGenNode::FLOW_SYNC;
+ node_sync->m_time = m_core->m_cur_time_sec + SYNC_TIME_OUT;
+ m_core->m_node_gen.add_node(node_sync);
+
+ double old_offset = 0.0;
+ m_core->m_node_gen.flush_file(-1, 0.0, false, m_core, old_offset);
+ m_core->m_node_gen.close_file(m_core);
+}
+
+void
+TrexStatelessDpCore::start() {
+
+ while (true) {
+ idle_state_loop();
+
+ start_scheduler();
+ }
+}
+
+void
+TrexStatelessDpCore::add_cont_stream(uint8_t port_id,
+ double isg_usec,
+ double pps,
+ const uint8_t *pkt,
+ uint16_t pkt_len) {
+
+ CGenNodeStateless *node = m_core->create_node_sl();
+
+ /* add periodic */
+ node->m_type = CGenNode::STATELESS_PKT;
+
+ node->m_time = m_core->m_cur_time_sec + usec_to_sec(isg_usec);
+
+ pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(port_id);
+ node->m_flags = 0;
+
+ /* set socket id */
+ node->set_socket_id(m_core->m_node_gen.m_socket_id);
+
+ /* build a mbuf from a packet */
+ uint16_t pkt_size = pkt_len;
+ const uint8_t *stream_pkt = pkt;
+
+ /* stateless specific fields */
+ node->m_next_time_offset = 1.0 / pps;
+ node->m_is_stream_active = 1;
+ node->m_port_id = port_id;
+
+ /* allocate const mbuf */
+ rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size);
+ assert(m);
+
char *p = rte_pktmbuf_append(m, pkt_size);
assert(p);
- /* set pkt data */
- memcpy(p,pkt,pkt_size);
+ /* copy the packet */
+ memcpy(p,stream_pkt,pkt_size);
- rte_mbuf_t *tx_pkts[32];
- tx_pkts[0] = m;
- uint8_t nb_pkts = 1;
- uint16_t ret = rte_eth_tx_burst(0, 0, tx_pkts, nb_pkts);
- (void)ret;
- rte_pktmbuf_free(m);
+ /* set dir 0 or 1 client or server */
+ node->set_mbuf_cache_dir(dir);
- return (0);
-}
+ /* TBD repace the mac if req we should add flag */
+ m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, m);
+
+ /* set the packet as a readonly */
+ node->set_cache_mbuf(m);
+
+ /* keep track */
+ m_active_nodes.push_back(node);
+
+ /* schedule */
+ m_core->m_node_gen.add_node((CGenNode *)node);
+
+ m_state = TrexStatelessDpCore::STATE_TRANSMITTING;
-static int
-test_inject_udp_pkt(){
- return (test_inject_pkt((uint8_t*)udp_pkt,sizeof(udp_pkt)));
}
void
-TrexStatelessDpCore::test_inject_dummy_pkt() {
- test_inject_udp_pkt();
+TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) {
+ for (auto single_stream : obj->get_objects()) {
+ add_cont_stream(single_stream.m_port_id,
+ single_stream.m_isg_usec,
+ single_stream.m_pps,
+ single_stream.m_pkt,
+ single_stream.m_pkt_len);
+ }
}
-/***************************
- * DP core
- *
- **************************/
-TrexStatelessDpCore::TrexStatelessDpCore(uint8_t core_id) : m_core_id(core_id) {
+void
+TrexStatelessDpCore::stop_traffic(uint8_t port_id) {
+ /* we cannot remove nodes not from the top of the queue so
+ for every active node - make sure next time
+ the scheduler invokes it, it will be free */
+ for (auto node : m_active_nodes) {
+ if (node->m_port_id == port_id) {
+ node->m_is_stream_active = 0;
+ }
+ }
+
+ /* remove all the non active nodes */
+ auto pred = std::remove_if(m_active_nodes.begin(),
+ m_active_nodes.end(),
+ [](CGenNodeStateless *node) { return (!node->m_is_stream_active); });
+
+ m_active_nodes.erase(pred, m_active_nodes.end());
+
+ if (m_active_nodes.size() == 0) {
+ m_state = STATE_IDLE;
+ /* stop the scheduler */
+
+ CGenNode *node = m_core->create_node() ;
+
+ node->m_type = CGenNode::EXIT_SCHED;
+
+ /* make sure it will be scheduled after the current node */
+ node->m_time = m_core->m_cur_time_sec + 0.0001;
+
+ m_core->m_node_gen.add_node(node);
+ }
+
}
/**
- * main function for DP core
+ * handle a message from CP to DP
*
*/
-void
-TrexStatelessDpCore::run() {
- printf("\nOn DP core %d\n", m_core_id);
- while (true) {
- test_inject_dummy_pkt();
- rte_pause();
- }
+void
+TrexStatelessDpCore::handle_cp_msg(TrexStatelessCpToDpMsgBase *msg) {
+ msg->handle(this);
+ delete msg;
}
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
index 4b09b752..f4dbad08 100644
--- a/src/stateless/dp/trex_stateless_dp_core.h
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -21,23 +21,128 @@ limitations under the License.
#ifndef __TREX_STATELESS_DP_CORE_H__
#define __TREX_STATELESS_DP_CORE_H__
-#include <stdint.h>
+#include <vector>
+
+#include <msg_manager.h>
+#include <pal_utl.h>
+
+class TrexStatelessCpToDpMsgBase;
+class TrexStatelessDpStart;
+class CFlowGenListPerThread;
+class CGenNodeStateless;
+class TrexStreamsCompiledObj;
-/**
- * stateless DP core object
- *
- */
class TrexStatelessDpCore {
+
public:
- TrexStatelessDpCore(uint8_t core_id);
+ /* states */
+ enum state_e {
+ STATE_IDLE,
+ STATE_TRANSMITTING
+ };
+
+ TrexStatelessDpCore() {
+ m_thread_id = 0;
+ m_core = NULL;
+ }
+
+ /**
+ * "static constructor"
+ *
+ * @param thread_id
+ * @param core
+ */
+ void create(uint8_t thread_id, CFlowGenListPerThread *core);
+
+ /**
+ * launch the stateless DP core code
+ *
+ */
+ void start();
+
+ /**
+ * dummy traffic creator
+ *
+ * @author imarom (27-Oct-15)
+ *
+ * @param pkt
+ * @param pkt_len
+ */
+ void start_traffic(TrexStreamsCompiledObj *obj);
+
+ /**
+ * stop all traffic for this core
+ *
+ */
+ void stop_traffic(uint8_t port_id);
+
+ /**
+ * check for and handle messages from CP
+ *
+ * @author imarom (27-Oct-15)
+ */
+ void periodic_check_for_cp_messages() {
+ // doing this inline for performance reasons
+
+ /* fast path */
+ if ( likely ( m_ring_from_cp->isEmpty() ) ) {
+ return;
+ }
- /* starts the DP core run */
- void run();
+ while ( true ) {
+ CGenNode * node = NULL;
+ if (m_ring_from_cp->Dequeue(node) != 0) {
+ break;
+ }
+ assert(node);
+
+ TrexStatelessCpToDpMsgBase * msg = (TrexStatelessCpToDpMsgBase *)node;
+ handle_cp_msg(msg);
+ }
+
+ }
private:
- void test_inject_dummy_pkt();
- uint8_t m_core_id;
+ /**
+ * in idle state loop, the processor most of the time sleeps
+ * and periodically checks for messages
+ *
+ */
+ void idle_state_loop();
+
+ /**
+ * real job is done when scheduler is launched
+ *
+ */
+ void start_scheduler();
+
+ /**
+ * handles a CP to DP message
+ *
+ * @author imarom (27-Oct-15)
+ *
+ * @param msg
+ */
+ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg);
+
+ void add_cont_stream(uint8_t dir,
+ double isg,
+ double pps,
+ const uint8_t *pkt,
+ uint16_t pkt_len);
+
+ uint8_t m_thread_id;
+ state_e m_state;
+ CNodeRing *m_ring_from_cp;
+ CNodeRing *m_ring_to_cp;
+
+ /* holds the current active nodes */
+ std::vector<CGenNodeStateless *> m_active_nodes;
+
+ /* pointer to the main object */
+ CFlowGenListPerThread *m_core;
};
#endif /* __TREX_STATELESS_DP_CORE_H__ */
+
diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h
new file mode 100644
index 00000000..92b428ab
--- /dev/null
+++ b/src/stateless/dp/trex_stream_node.h
@@ -0,0 +1,105 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+#ifndef __TREX_STREAM_NODE_H__
+#define __TREX_STREAM_NODE_H__
+
+#include <bp_sim.h>
+
+class TrexStatelessDpCore;
+
+/* this is a event for stateless */
+struct CGenNodeStateless : public CGenNodeBase {
+friend class TrexStatelessDpCore;
+
+private:
+ void * m_cache_mbuf;
+
+ double m_next_time_offset;
+ uint8_t m_is_stream_active;
+ uint8_t m_port_id;
+
+ /* pad to match the size of CGenNode */
+ uint8_t m_pad_end[87];
+
+
+public:
+
+ inline bool is_active() {
+ return m_is_stream_active;
+ }
+
+
+ /**
+ * main function to handle an event of a packet tx
+ *
+ */
+ inline void handle(CFlowGenListPerThread *thread) {
+
+ thread->m_node_gen.m_v_if->send_node( (CGenNode *)this);
+
+ /* in case of continues */
+ m_time += m_next_time_offset;
+
+ /* insert a new event */
+ thread->m_node_gen.m_p_queue.push( (CGenNode *)this);
+ }
+
+ void set_socket_id(socket_id_t socket){
+ m_socket_id=socket;
+ }
+
+ socket_id_t get_socket_id(){
+ return ( m_socket_id );
+ }
+
+ inline void set_mbuf_cache_dir(pkt_dir_t dir){
+ if (dir) {
+ m_flags |=NODE_FLAGS_DIR;
+ }else{
+ m_flags &=~NODE_FLAGS_DIR;
+ }
+ }
+
+ inline pkt_dir_t get_mbuf_cache_dir(){
+ return ((pkt_dir_t)( m_flags &1));
+ }
+
+
+
+ inline void set_cache_mbuf(rte_mbuf_t * m){
+ m_cache_mbuf=(void *)m;
+ m_flags |= NODE_FLAGS_MBUF_CACHE;
+ }
+
+ inline rte_mbuf_t * get_cache_mbuf(){
+ if ( m_flags &NODE_FLAGS_MBUF_CACHE ) {
+ return ((rte_mbuf_t *)m_cache_mbuf);
+ }else{
+ return ((rte_mbuf_t *)0);
+ }
+ }
+
+
+} __rte_cache_aligned;
+
+static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)");
+
+#endif /* __TREX_STREAM_NODE_H__ */
diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp
new file mode 100644
index 00000000..032559bc
--- /dev/null
+++ b/src/stateless/messaging/trex_stateless_messaging.cpp
@@ -0,0 +1,78 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+#include <trex_stateless_messaging.h>
+#include <trex_stateless_dp_core.h>
+#include <trex_streams_compiler.h>
+#include <string.h>
+
+/*************************
+ start traffic message
+ ************************/
+TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj) : m_obj(obj) {
+}
+
+
+/**
+ * clone for DP start message
+ *
+ */
+TrexStatelessCpToDpMsgBase *
+TrexStatelessDpStart::clone() {
+
+ TrexStreamsCompiledObj *new_obj = m_obj->clone();
+
+ TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(new_obj);
+
+ return new_msg;
+}
+
+TrexStatelessDpStart::~TrexStatelessDpStart() {
+ if (m_obj) {
+ delete m_obj;
+ }
+}
+
+bool
+TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) {
+
+ dp_core->start_traffic(m_obj);
+ return true;
+}
+
+/*************************
+ stop traffic message
+ ************************/
+bool
+TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) {
+ dp_core->stop_traffic(m_port_id);
+ return true;
+}
+
+/**
+ * clone for DP stop message
+ *
+ */
+TrexStatelessCpToDpMsgBase *
+TrexStatelessDpStop::clone() {
+ TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStop(m_port_id);
+
+ return new_msg;
+}
diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h
new file mode 100644
index 00000000..7978b7f9
--- /dev/null
+++ b/src/stateless/messaging/trex_stateless_messaging.h
@@ -0,0 +1,101 @@
+/*
+ Itay Marom
+ Cisco Systems, Inc.
+*/
+
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+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.
+*/
+#ifndef __TREX_STATELESS_MESSAGING_H__
+#define __TREX_STATELESS_MESSAGING_H__
+
+#include <msg_manager.h>
+
+class TrexStatelessDpCore;
+class TrexStreamsCompiledObj;
+
+/**
+ * defines the base class for CP to DP messages
+ *
+ * @author imarom (27-Oct-15)
+ */
+class TrexStatelessCpToDpMsgBase {
+public:
+
+ TrexStatelessCpToDpMsgBase() {
+ }
+
+ virtual ~TrexStatelessCpToDpMsgBase() {
+ }
+
+ /**
+ * virtual function to handle a message
+ *
+ */
+ virtual bool handle(TrexStatelessDpCore *dp_core) = 0;
+
+
+ /**
+ * clone the current message
+ *
+ */
+ virtual TrexStatelessCpToDpMsgBase * clone() = 0;
+
+ /* no copy constructor */
+ TrexStatelessCpToDpMsgBase(TrexStatelessCpToDpMsgBase &) = delete;
+
+};
+
+/**
+ * a message to start traffic
+ *
+ * @author imarom (27-Oct-15)
+ */
+class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase {
+public:
+
+ TrexStatelessDpStart(TrexStreamsCompiledObj *obj);
+
+ ~TrexStatelessDpStart();
+
+ virtual bool handle(TrexStatelessDpCore *dp_core);
+
+ virtual TrexStatelessCpToDpMsgBase * clone();
+
+private:
+ TrexStreamsCompiledObj *m_obj;
+};
+
+/**
+ * a message to stop traffic
+ *
+ * @author imarom (27-Oct-15)
+ */
+class TrexStatelessDpStop : public TrexStatelessCpToDpMsgBase {
+public:
+
+ TrexStatelessDpStop(uint8_t port_id) : m_port_id(port_id) {
+ }
+
+ virtual bool handle(TrexStatelessDpCore *dp_core);
+
+ virtual TrexStatelessCpToDpMsgBase * clone();
+
+private:
+ uint8_t m_port_id;
+};
+
+
+#endif /* __TREX_STATELESS_MESSAGING_H__ */
diff --git a/src/stub/trex_stateless_stub.cpp b/src/stub/trex_stateless_stub.cpp
new file mode 100644
index 00000000..199356d8
--- /dev/null
+++ b/src/stub/trex_stateless_stub.cpp
@@ -0,0 +1,23 @@
+
+#include <trex_stateless_dp_core.h>
+
+class CFlowGenListPerThread;
+class TrexStatelessCpToDpMsgBase;
+
+void
+TrexStatelessDpCore::create(unsigned char, CFlowGenListPerThread*) {
+ m_thread_id = 0;
+ m_core = NULL;
+
+ m_state = STATE_IDLE;
+
+ CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp();
+
+ m_ring_from_cp = cp_dp->getRingCpToDp(0);
+ m_ring_to_cp = cp_dp->getRingDpToCp(0);
+}
+
+void TrexStatelessDpCore::start(){}
+
+void TrexStatelessDpCore::handle_cp_msg(TrexStatelessCpToDpMsgBase*) {}
+
diff --git a/src/time_histogram.cpp b/src/time_histogram.cpp
index f1b47e59..96796bfc 100755
--- a/src/time_histogram.cpp
+++ b/src/time_histogram.cpp
@@ -182,10 +182,10 @@ void CTimeHistogram::DumpWinMax(FILE *fd){
}
void CTimeHistogram::Dump(FILE *fd){
- fprintf (fd," min_delta : %lu usec \n",get_usec(m_min_delta));
+ fprintf (fd," min_delta : %lu usec \n", (ulong)get_usec(m_min_delta));
fprintf (fd," cnt : %lu \n",m_cnt);
fprintf (fd," high_cnt : %lu \n",m_high_cnt);
- fprintf (fd," max_d_time : %lu usec\n",get_usec(m_max_dt));
+ fprintf (fd," max_d_time : %lu usec\n", (ulong)get_usec(m_max_dt));
//fprintf (fd," average : %.0f usec\n", get_total_average());
fprintf (fd," sliding_average : %.0f usec\n", get_average_latency());
fprintf (fd," precent : %.1f %%\n",(100.0*(double)m_high_cnt/(double)m_cnt));
@@ -198,7 +198,7 @@ void CTimeHistogram::Dump(FILE *fd){
for (j=0; j<HISTOGRAM_SIZE_LOG; j++) {
for (i=0; i<HISTOGRAM_SIZE; i++) {
if (m_hcnt[j][i] >0 ) {
- fprintf (fd," h[%lu] : %lu \n",(base*(i+1)),m_hcnt[j][i]);
+ fprintf (fd," h[%u] : %llu \n",(base*(i+1)),(unsigned long long)m_hcnt[j][i]);
}
}
base=base*10;
diff --git a/src/tuple_gen.h b/src/tuple_gen.h
index 29adbd69..d34e27bc 100755
--- a/src/tuple_gen.h
+++ b/src/tuple_gen.h
@@ -553,6 +553,9 @@ public:
class CServerPoolBase {
public:
+
+ virtual ~CServerPoolBase() {}
+
virtual void GenerateTuple(CTupleBase& tuple) = 0;
virtual uint16_t GenerateOnePort(uint32_t idx) = 0;
virtual void Delete() = 0;
diff --git a/src/utl_json.cpp b/src/utl_json.cpp
index 990346f5..fb55be0a 100755
--- a/src/utl_json.cpp
+++ b/src/utl_json.cpp
@@ -25,7 +25,7 @@ limitations under the License.
std::string add_json(std::string name, uint32_t counter,bool last){
char buff[200];
- sprintf(buff,"\"%s\":%lu",name.c_str(),counter);
+ sprintf(buff,"\"%s\":%lu",name.c_str(), (ulong)counter);
std::string s= std::string(buff);
if (!last) {
s+=",";
@@ -35,7 +35,7 @@ std::string add_json(std::string name, uint32_t counter,bool last){
std::string add_json(std::string name, uint64_t counter,bool last){
char buff[200];
- sprintf(buff,"\"%s\":%llu",name.c_str(),counter);
+ sprintf(buff,"\"%s\":%llu",name.c_str(), (unsigned long long)counter);
std::string s= std::string(buff);
if (!last) {
s+=",";
diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 5f3ca735..828817e4 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -104,6 +104,8 @@ bool utl_yaml_read_uint16(const YAML::Node& node,
val = (uint16_t)val_tmp;
res=true;
}
+
+ return (res);
}
bool utl_yaml_read_bool(const YAML::Node& node,