summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Klein <danklei@cisco.com>2015-10-20 05:39:14 +0300
committerDan Klein <danklei@cisco.com>2015-10-20 05:39:14 +0300
commitcf753587ffb7b89cff1863c74ca334b8c41fd0c0 (patch)
treef9d8bd9e67cb93306e93041f11f5e4124a6e151a
parentd09df99769f67819c64a7a025dbdcd39811c7b44 (diff)
parent51ad078182d17b42a36c239c3c21381eeb3eec85 (diff)
Merge branch 'master' into master-demo +
working demo of loading a YAML, and attaching it to server
-rwxr-xr-xCONTRIBUTORS2
-rwxr-xr-xVERSION2
-rwxr-xr-xlinux/ws_main.py17
-rwxr-xr-xlinux_dpdk/ws_main.py16
-rwxr-xr-xscripts/automation/trex_control_plane/client_utils/jsonrpc_client.py3
-rwxr-xr-xscripts/automation/trex_control_plane/common/trex_streams.py5
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py112
-rwxr-xr-x[-rw-r--r--]scripts/automation/trex_control_plane/console/trex_root_path.py0
-rw-r--r--scripts/automation/trex_control_plane/console/trex_status.py2
-rwxr-xr-xscripts/cfg/cfg_example1.yaml9
-rwxr-xr-xsrc/bp_sim.cpp186
-rwxr-xr-xsrc/bp_sim.h39
-rw-r--r--src/gtest/rpc_test.cpp9
-rwxr-xr-xsrc/gtest/tuple_gen_test.cpp4
-rw-r--r--src/mac_mapping.h60
-rwxr-xr-xsrc/main_dpdk.cpp164
-rw-r--r--src/mock/rte_ethdev.h44
-rw-r--r--src/mock/trex_rpc_server_mock.cpp (renamed from src/rpc-server/trex_rpc_server_mock.cpp)44
-rwxr-xr-xsrc/platform_cfg.cpp151
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp17
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp11
-rw-r--r--src/rpc-server/trex_rpc_async_server.cpp109
-rw-r--r--src/rpc-server/trex_rpc_async_server.h54
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp3
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.cpp12
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.h2
-rw-r--r--src/rpc-server/trex_rpc_server.cpp16
-rw-r--r--src/rpc-server/trex_rpc_server_api.h11
-rw-r--r--src/stateless/cp/trex_stateless.cpp212
-rw-r--r--src/stateless/cp/trex_stateless.h202
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp228
-rw-r--r--src/stateless/cp/trex_stateless_port.h (renamed from src/stateless/trex_stateless_api.h)158
-rw-r--r--src/stateless/cp/trex_stream.cpp (renamed from src/stateless/trex_stream.cpp)2
-rw-r--r--src/stateless/cp/trex_stream.h (renamed from src/stateless/trex_stream_api.h)6
-rw-r--r--src/stateless/cp/trex_stream_vm.cpp (renamed from src/stateless/trex_stream_vm.cpp)0
-rw-r--r--src/stateless/cp/trex_stream_vm.h (renamed from src/stateless/trex_stream_vm.h)0
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp135
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h43
-rw-r--r--src/stateless/trex_stateless.cpp171
-rwxr-xr-xsrc/tuple_gen.cpp49
-rwxr-xr-xsrc/tuple_gen.h308
-rwxr-xr-xsrc/utl_yaml.cpp18
42 files changed, 1876 insertions, 760 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 57d19820..3cda10ac 100755
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,4 +1,4 @@
-Hanoh haim
+Hanoch haim hhaim@cisco.com
Dave Johnson
Wenxian Li
Dan Klein
diff --git a/VERSION b/VERSION
index 6781e9e3..8ce21723 100755
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-v1.77
+v1.78
diff --git a/linux/ws_main.py b/linux/ws_main.py
index 8ad3e5ba..eac46ac7 100755
--- a/linux/ws_main.py
+++ b/linux/ws_main.py
@@ -142,15 +142,18 @@ net_src = SrcGroup(dir='src/common/Network/Packet',
# stateless code
stateless_src = SrcGroup(dir='src/stateless/',
- src_list=['trex_stream.cpp',
- 'trex_stream_vm.cpp',
- 'trex_stateless.cpp',
+ src_list=['cp/trex_stream.cpp',
+ 'cp/trex_stream_vm.cpp',
+ 'cp/trex_stateless.cpp',
+ 'cp/trex_stateless_port.cpp',
+ 'dp/trex_stateless_dp_core.cpp'
])
# RPC code
rpc_server_src = SrcGroup(dir='src/rpc-server/',
src_list=[
'trex_rpc_server.cpp',
'trex_rpc_req_resp_server.cpp',
+ 'trex_rpc_async_server.cpp',
'trex_rpc_jsonrpc_v2_parser.cpp',
'trex_rpc_cmds_table.cpp',
'trex_rpc_cmd.cpp',
@@ -162,10 +165,12 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/',
])
# RPC mock server (test)
-rpc_server_mock_src = SrcGroup(dir='src/rpc-server/',
+rpc_server_mock_src = SrcGroup(dir='src/mock/',
src_list=[
'trex_rpc_server_mock.cpp',
'../gtest/rpc_test.cpp',
+ '../pal/linux/mbuf.cpp',
+ '../os_time.cpp',
])
# JSON package
@@ -233,8 +238,10 @@ cxxflags_base =['-DWIN_UCODE_SIM',
includes_path =''' ../src/pal/linux/
../src/
+ ../src/mock/
../src/rpc-server/
- ../src/stateless/
+ ../src/stateless/cp/
+ ../src/stateless/dp/
../external_libs/json/
../external_libs/zmq/include/
../external_libs/yaml-cpp/include/
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py
index 6aad508a..61a9d4f3 100755
--- a/linux_dpdk/ws_main.py
+++ b/linux_dpdk/ws_main.py
@@ -141,6 +141,7 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/',
src_list=[
'trex_rpc_server.cpp',
'trex_rpc_req_resp_server.cpp',
+ 'trex_rpc_async_server.cpp',
'trex_rpc_jsonrpc_v2_parser.cpp',
'trex_rpc_cmds_table.cpp',
'trex_rpc_cmd.cpp',
@@ -148,8 +149,17 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/',
'commands/trex_rpc_cmd_test.cpp',
'commands/trex_rpc_cmd_general.cpp',
'commands/trex_rpc_cmd_stream.cpp',
+
])
+# stateless code
+stateless_src = SrcGroup(dir='src/stateless/',
+ src_list=['cp/trex_stream.cpp',
+ 'cp/trex_stream_vm.cpp',
+ 'cp/trex_stateless.cpp',
+ 'cp/trex_stateless_port.cpp',
+ 'dp/trex_stateless_dp_core.cpp'
+ ])
# JSON package
json_src = SrcGroup(dir='external_libs/json',
src_list=[
@@ -346,6 +356,9 @@ bp =SrcGroups([
cmn_src ,
net_src ,
yaml_src,
+ rpc_server_src,
+ json_src,
+ stateless_src,
version_src
]);
@@ -400,7 +413,8 @@ includes_path =''' ../src/pal/linux_dpdk/
../src/
../src/rpc-server/
- ../src/stateless/
+ ../src/stateless/cp/
+ ../src/stateless/dp/
../external_libs/yaml-cpp/include/
../external_libs/zmq/include/
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 b2d83cff..ed14e6f8 100755
--- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
@@ -505,7 +505,8 @@ class TrexStatelessClient(JsonRpcClient):
for i, rc in enumerate(resp_list):
if rc[0]:
- self.port_handlers[port_id_array[i]] = rc[1]
+ print "Stream {0} - {1}".format(i, rc[1])
+ # self.port_handlers[port_id_array[i]] = rc[1]
return True, resp_list
diff --git a/scripts/automation/trex_control_plane/common/trex_streams.py b/scripts/automation/trex_control_plane/common/trex_streams.py
index 674a6bcc..1aeb46b0 100755
--- a/scripts/automation/trex_control_plane/common/trex_streams.py
+++ b/scripts/automation/trex_control_plane/common/trex_streams.py
@@ -105,9 +105,8 @@ class CRxStats(object):
if self.enabled:
dump = {"enabled": True}
dump.update({k: getattr(self, k)
- for k in CRxStats.FIELDS
- if getattr(self, k) or k == "stream_id"
- })
+ for k in CRxStats.FIELDS}
+ )
return dump
else:
return {"enabled": False}
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index 945bb177..688f80f3 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -8,15 +8,100 @@ import random
import string
import sys
+import tty, termios
import trex_root_path
from common.trex_streams import *
+
from client_utils.jsonrpc_client import TrexStatelessClient
import trex_status
from collections import namedtuple
LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
+#
+
+def readch (choices = []):
+
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ while True:
+ ch = sys.stdin.read(1)
+ if (ord(ch) == 3) or (ord(ch) == 4):
+ return None
+ if ch in choices:
+ return ch
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+
+ return None
+
+class YesNoMenu(object):
+ def __init__ (self, caption):
+ self.caption = 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
+ else:
+ return False
+
+# multi level cmd menu
+class CmdMenu(object):
+ def __init__ (self):
+ self.menus = []
+
+
+ def add_menu (self, caption, options):
+ menu = {}
+ menu['caption'] = caption
+ menu['options'] = options
+ self.menus.append(menu)
+
+ def show (self):
+ cur_level = 0
+ print "\n"
+
+ selected_path = []
+ for menu in self.menus:
+ # show all the options
+ print "{0}\n".format(menu['caption'])
+ for i, option in enumerate(menu['options']):
+ print "{0}. {1}".format(i + 1, option)
+
+ #print "\nPlease select an option: "
+
+ choices = range(0, len(menu['options']))
+ choices = [ chr(x + 48) for x in choices]
+
+ print ""
+ ch = readch(choices)
+ print ""
+
+ if ch == None:
+ return None
+
+ selected_path.append(int(ch) - 1)
+
+ return selected_path
+
+
+class AddStreamMenu(CmdMenu):
+ def __init__ (self):
+ super(AddStreamMenu, self).__init__()
+ self.add_menu('Please select type of stream', ['a', 'b', 'c'])
+ self.add_menu('Please select ISG', ['d', 'e', 'f'])
+
+# main console object
class TrexConsole(cmd.Cmd):
"""Trex Console"""
@@ -114,6 +199,13 @@ class TrexConsole(cmd.Cmd):
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 ? ')
+ rc = ask.show()
+ if rc == False:
+ return
+
port_list = self.parse_ports_from_line(line)
if not port_list:
return
@@ -399,12 +491,24 @@ class TrexConsole(cmd.Cmd):
- # do
- #def do_snapshot (self, line):
- #for key, value in self.rpc_client.snapshot()[1]['streams'].iteritems():
- #print str(key) + " " + str(value)
+ # adds a very simple stream
+ def do_add_simple_stream (self, line):
+ if line == "":
+ add_stream = AddStreamMenu()
+ add_stream.show()
+ return
+ params = line.split()
+ port_id = int(params[0])
+ stream_id = int(params[1])
+
+ 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"
# aliasing
do_exit = do_EOF = do_q = do_quit
diff --git a/scripts/automation/trex_control_plane/console/trex_root_path.py b/scripts/automation/trex_control_plane/console/trex_root_path.py
index de4ec03b..de4ec03b 100644..100755
--- a/scripts/automation/trex_control_plane/console/trex_root_path.py
+++ b/scripts/automation/trex_control_plane/console/trex_root_path.py
diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py
index b881f9f5..2c5a648f 100644
--- a/scripts/automation/trex_control_plane/console/trex_status.py
+++ b/scripts/automation/trex_control_plane/console/trex_status.py
@@ -170,7 +170,7 @@ class PortsStatsPanel(TrexStatusPanel):
port_stats = self.status_obj.stats.get_port_stats(port_index)
if port_stats:
- self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,}".format(
+ self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,.2f} {:^15,.2f} {:^15,} {:^15,.2f} {:^15,.2f} {:^15,}".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"],
diff --git a/scripts/cfg/cfg_example1.yaml b/scripts/cfg/cfg_example1.yaml
index bfd7fd88..224fb15e 100755
--- a/scripts/cfg/cfg_example1.yaml
+++ b/scripts/cfg/cfg_example1.yaml
@@ -6,8 +6,15 @@
enable_zmq_pub : true # enable publisher for stats data
zmq_pub_port : 4507
telnet_port : 4508 # the telnet port in case it is enable ( with intercative mode )
+ platform :
+ master_thread_id : 12
+ latency_thread_id : 13
+ dual_if :
+ - socket : 1
+ threads : [8,9,10,11]
+
port_info : # set eh mac addr
- - dest_mac : [0x1,0x0,0x0,0x1,0x0,0x00] # port 0
+ - dest_mac : [1,0x0,0x0,0x1,0x0,0x00] # port 0
src_mac : [0x2,0x0,0x0,0x2,0x0,0x00]
- dest_mac : [0x3,0x0,0x0,0x3,0x0,0x00] # port 1
src_mac : [0x4,0x0,0x0,0x4,0x0,0x00]
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index 7cbeb09d..c3581c55 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -2350,21 +2350,13 @@ void operator >> (const YAML::Node& node, CFlowYamlDpPkt & fi) {
void operator >> (const YAML::Node& node, CVlanYamlInfo & fi) {
uint32_t tmp;
- try {
- node["enable"] >> tmp ;
- fi.m_enable=tmp;
- }catch ( const std::exception& e ) {
-
- }
-
- try {
- node["vlan0"] >> tmp;
- fi.m_vlan_per_port[0] = tmp;
- node["vlan1"] >> tmp;
- fi.m_vlan_per_port[1] = tmp;
- }catch ( const std::exception& e ) {
- // there is a default
-
+ if ( node.FindValue("enable") ){
+ node["enable"] >> tmp ;
+ fi.m_enable=tmp;
+ node["vlan0"] >> tmp;
+ fi.m_vlan_per_port[0] = tmp;
+ node["vlan1"] >> tmp;
+ fi.m_vlan_per_port[1] = tmp;
}
}
@@ -2372,15 +2364,15 @@ void operator >> (const YAML::Node& node, CVlanYamlInfo & fi) {
void operator >> (const YAML::Node& node, CFlowYamlInfo & fi) {
node["name"] >> fi.m_name;
-
- try {
+
+ if ( node.FindValue("client_pool") ){
node["client_pool"] >> fi.m_client_pool_name;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_client_pool_name = "default";
}
- try {
+ if ( node.FindValue("server_pool") ){
node["server_pool"] >> fi.m_server_pool_name;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_server_pool_name = "default";
}
@@ -2393,37 +2385,38 @@ void operator >> (const YAML::Node& node, CFlowYamlInfo & fi) {
fi.m_rtt_sec = t/1000000.0;
node["w"] >> fi.m_w;
- try {
+ if ( node.FindValue("cap_ipg") ){
node["cap_ipg"] >> fi.m_cap_mode;
fi.m_cap_mode_was_set =true;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_cap_mode_was_set =false;
}
- try {
+ if ( node.FindValue("wlength") ){
node["wlength"] >> fi.m_wlength;
fi.m_wlength_set=true;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_wlength_set=false;
fi.m_wlength =500;
}
- try {
+ if ( node.FindValue("limit") ){
node["limit"] >> fi.m_limit;
fi.m_limit_was_set = true;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_limit_was_set = false;
fi.m_limit = 0;
}
- try {
+ if ( node.FindValue("plugin_id") ){
uint32_t plugin_val;
node["plugin_id"] >> plugin_val;
fi.m_plugin_id=plugin_val;
- } catch ( const std::exception& e ) {
+ }else{
fi.m_plugin_id=0;
}
+
fi.m_one_app_server_was_set = false;
fi.m_one_app_server = false;
if ( utl_yaml_read_ip_addr(node,
@@ -2446,30 +2439,26 @@ void operator >> (const YAML::Node& node, CFlowYamlInfo & fi) {
}
- try {
- int i;
- const YAML::Node& dyn_pyload = node["dyn_pyload"];
- for(unsigned i=0;i<dyn_pyload.size();i++) {
- CFlowYamlDpPkt fd;
- dyn_pyload[i] >> fd;
- if ( fi.m_dpPkt == 0 ){
- fi.m_dpPkt = new CFlowYamlDynamicPyloadPlugin();
- if (fi.m_plugin_id == 0) {
- fi.m_plugin_id = mpDYN_PYLOAD;
- }else{
- fprintf(stderr," plugin should be zero with dynamic pyload program");
- exit(-1);
- }
- }
-
- fd.Dump(stdout);
-
- fi.m_dpPkt->Add(fd);
- printf(" here ");
- }
- } catch ( const std::exception& e ) {
- fi.m_dpPkt=0;
- }
+ 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;
+ dyn_pyload[i] >> fd;
+ if ( fi.m_dpPkt == 0 ){
+ fi.m_dpPkt = new CFlowYamlDynamicPyloadPlugin();
+ if (fi.m_plugin_id == 0) {
+ fi.m_plugin_id = mpDYN_PYLOAD;
+ }else{
+ fprintf(stderr," plugin should be zero with dynamic pyload program");
+ exit(-1);
+ }
+ }
+ fi.m_dpPkt->Add(fd);
+ }
+ }else{
+ fi.m_dpPkt=0;
+ }
}
@@ -2478,13 +2467,12 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
node["duration"] >> flows_info.m_duration_sec;
- try {
- node["generator"] >> flows_info.m_tuple_gen;
- flows_info.m_tuple_gen_was_set =true;
- } catch ( const std::exception& e ) {
- flows_info.m_tuple_gen_was_set =false;
+ if ( node.FindValue("generator") ) {
+ node["generator"] >> flows_info.m_tuple_gen;
+ flows_info.m_tuple_gen_was_set =true;
+ }else{
+ flows_info.m_tuple_gen_was_set =false;
}
-
// m_ipv6_set will be true if and only if both src_ipv6
// and dst_ipv6 are provided. These are used to set
@@ -2500,7 +2488,8 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
// formed by providing src_ipv6,dst_ipv6 and specifying
// {0,0,0,0,0,0xffff}
flows_info.m_ipv6_set=true;
- try {
+
+ if ( node.FindValue("src_ipv6") ) {
const YAML::Node& src_ipv6_info = node["src_ipv6"];
if (src_ipv6_info.size() == 6 ){
for(unsigned i=0;i<src_ipv6_info.size();i++) {
@@ -2509,14 +2498,13 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
node[i] >> fi;
flows_info.m_src_ipv6.push_back(fi);
}
- }else{
- flows_info.m_ipv6_set=false;
}
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_ipv6_set=false;
}
- try {
+
+ if ( node.FindValue("dst_ipv6") ) {
const YAML::Node& dst_ipv6_info = node["dst_ipv6"];
if (dst_ipv6_info.size() == 6 ){
for(unsigned i=0;i<dst_ipv6_info.size();i++) {
@@ -2525,67 +2513,65 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
node[i] >> fi;
flows_info.m_dst_ipv6.push_back(fi);
}
- }else{
- flows_info.m_ipv6_set=false;
}
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_ipv6_set=false;
}
- try {
+ if ( node.FindValue("cap_ipg") ) {
node["cap_ipg"] >> flows_info.m_cap_mode;
flows_info.m_cap_mode_set=true;
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_cap_mode=false;
flows_info.m_cap_mode_set=false;
}
- double t;
- try {
+ double t=0.0;
+
+ if ( node.FindValue("cap_ipg_min") ) {
node["cap_ipg_min"] >> t ;
flows_info.m_cap_ipg_min = t/1000000.0;
flows_info.m_cap_ipg_min_set=true;
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_cap_ipg_min_set=false;
flows_info.m_cap_ipg_min = 20;
}
- try {
+ if ( node.FindValue("cap_override_ipg") ) {
node["cap_override_ipg"] >> t;
flows_info.m_cap_overide_ipg = t/1000000.0;
flows_info.m_cap_overide_ipg_set = true;
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_cap_overide_ipg_set = false;
flows_info.m_cap_overide_ipg = 0;
}
- try {
+ if (node.FindValue("wlength")) {
node["wlength"] >> flows_info.m_wlength;
flows_info.m_wlength_set=true;
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_wlength_set=false;
flows_info.m_wlength =100;
}
- try {
+ if (node.FindValue("one_app_server")) {
node["one_app_server"] >> flows_info.m_one_app_server;
flows_info.m_one_app_server_was_set=true;
- } catch ( const std::exception& e ) {
+ }else{
flows_info.m_one_app_server =false;
flows_info.m_one_app_server_was_set=false;
}
- try {
- node["vlan"] >> flows_info.m_vlan_info;
- } catch ( const std::exception& e ) {
- }
- try {
- node["mac_override_by_ip"] >> flows_info.m_mac_replace_by_ip;
- } catch ( const std::exception& e ) {
- flows_info.m_mac_replace_by_ip =false;
+ if (node.FindValue("vlan")) {
+ node["vlan"] >> flows_info.m_vlan_info;
}
+ if (node.FindValue("mac_override_by_ip")) {
+ node["mac_override_by_ip"] >> flows_info.m_mac_replace_by_ip;
+ }else{
+ flows_info.m_mac_replace_by_ip =false;
+ }
const YAML::Node& mac_info = node["mac"];
for(unsigned i=0;i<mac_info.size();i++) {
@@ -2593,7 +2579,7 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
const YAML::Node & node =mac_info;
node[i] >> fi;
flows_info.m_mac_base.push_back(fi);
- }
+ }
const YAML::Node& cap_info = node["cap_info"];
for(unsigned i=0;i<cap_info.size();i++) {
@@ -3177,7 +3163,7 @@ bool CFlowGenListPerThread::Create(uint32_t thread_id,
/* split the clients to threads */
CTupleGenYamlInfo * tuple_gen = &m_flow_list->m_yaml_info.m_tuple_gen;
- m_smart_gen.Create(0,m_thread_id,m_flow_list->is_mac_info_configured);
+ m_smart_gen.Create(0,m_thread_id,m_flow_list->get_is_mac_conf());
/* split the clients to threads using the mask */
CIpPortion portion;
@@ -3191,7 +3177,7 @@ bool CFlowGenListPerThread::Create(uint32_t thread_id,
portion.m_ip_end,
get_longest_flow(i,true),
get_total_kcps(i,true)*1000,
- m_flow_list,
+ &m_flow_list->m_mac_info,
tuple_gen->m_client_pool[i].m_tcp_aging_sec,
tuple_gen->m_client_pool[i].m_udp_aging_sec
);
@@ -3962,7 +3948,7 @@ int CFlowGenList::load_from_mac_file(std::string file_name) {
printf(" ERROR no mac_file is set, file %s does not exist \n",file_name.c_str());
exit(-1);
}
- is_mac_info_configured = true;
+ m_mac_info.set_configured(true);
try {
std::ifstream fin((char *)file_name.c_str());
@@ -3970,7 +3956,7 @@ int CFlowGenList::load_from_mac_file(std::string file_name) {
YAML::Node doc;
parser.GetNextDocument(doc);
- doc[0] >> m_mac_info;
+ doc[0] >> m_mac_info.get_mac_info();
} catch ( const std::exception& e ) {
std::cout << e.what() << "\n";
m_mac_info.clear();
@@ -3982,7 +3968,6 @@ int CFlowGenList::load_from_mac_file(std::string file_name) {
int CFlowGenList::load_from_yaml(std::string file_name,
uint32_t num_threads){
- is_mac_info_configured = false;
uint8_t idx;
m_yaml_info.load_from_yaml_file(file_name);
if (m_yaml_info.verify_correctness(num_threads) ==false){
@@ -6643,25 +6628,6 @@ void CFlowYamlDynamicPyloadPlugin::Dump(FILE *fd){
}
}
-bool is_mac_info_conf(CFlowGenList *fl_list) {
- if (fl_list) {
- return fl_list->is_mac_info_configured;
- }
- return false;
-}
-
-mac_addr_align_t * get_mac_addr_by_ip(CFlowGenList *fl_list,
- uint32_t ip) {
- if (fl_list &&
- fl_list->is_mac_info_configured &&
- fl_list->m_mac_info.count(ip)>0) {
- return &fl_list->m_mac_info[ip];
- }
- return NULL;
-}
-
-
-
uint16_t CSimplePacketParser::getPktSize(){
uint16_t ip_len=0;
if (m_ipv4) {
diff --git a/src/bp_sim.h b/src/bp_sim.h
index 29b9a724..b7cfb20b 100755
--- a/src/bp_sim.h
+++ b/src/bp_sim.h
@@ -221,7 +221,9 @@ private:
memset(m_pyload_mbuf_ptr+len+m_new_pkt_size,0xa,(-m_new_pkt_size));
}
+ return (0);
}
+
public:
int16_t m_new_pkt_size; /* New packet size after transform by plugin */
CFlowPktInfo * m_pkt_info;
@@ -302,7 +304,7 @@ public:
void CVirtualIFPerSideStats::Dump(FILE *fd){
- #define DP_B(f) if (f) printf(" %-40s : %llu \n",#f,f)
+ #define DP_B(f) if (f) printf(" %-40s : %lu \n",#f,f)
DP_B(m_tx_pkt);
DP_B(m_tx_rx_check_pkt);
DP_B(m_tx_bytes);
@@ -688,6 +690,15 @@ public:
RUN_FLAGS_RXCHECK_CONST_TS =1,
};
+ /**
+ * different running modes for Trex
+ */
+ enum trex_run_mode_e {
+ RUN_MODE_INVALID,
+ RUN_MODE_BATCH,
+ RUN_MODE_INTERACTIVE
+ };
+
public:
CParserOption(){
m_factor=1.0;
@@ -707,6 +718,7 @@ public:
m_run_flags=0;
prefix="";
m_mac_splitter=0;
+ m_run_mode = RUN_MODE_INVALID;
}
CPreviewMode preview;
@@ -730,13 +742,14 @@ public:
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;
+ std::string cfg_file;
+ std::string mac_file;
+ std::string platform_cfg_file;
- std::string out_file;
- std::string prefix;
+ std::string out_file;
+ std::string prefix;
CMacAddrCfg m_mac_addr[MAX_LATENCY_PORTS];
@@ -1429,7 +1442,7 @@ public:
inline bool is_eligible_from_server_side(){
- return ( (m_src_ip&1==1)?true:false);
+ return ( ( (m_src_ip&1) == 1)?true:false);
}
@@ -1636,7 +1649,7 @@ public:
*/
inline int check_objects_sizes(void){
if ( sizeof(CGenNodeDeferPort) != sizeof(CGenNode) ) {
- printf("ERROR sizeof(CGenNodeDeferPort) %d != sizeof(CGenNode) %d must be the same size \n",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) ){
@@ -2576,6 +2589,8 @@ inline void CFlowPktInfo::update_pkt_info2(char *p,
EthernetHeader * et =
(EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset());
+ (void)et;
+
if ( unlikely (m_pkt_indication.is_ipv6())) {
IPv6Header *ipv6= (IPv6Header *)ipv4;
@@ -2658,6 +2673,8 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
EthernetHeader * et =
(EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset());
+ (void)et;
+
uint16_t src_port = node->m_src_port;
pkt_dir_t ip_dir = node->cur_pkt_ip_addr_dir();
@@ -2858,6 +2875,7 @@ inline rte_mbuf_t * CFlowPktInfo::do_generate_new_mbuf_ex_vm(CGenNode * node,
/* need to update the mbuf size here .., this is not must but needed for accuracy */
uint16_t buf_adjust = len - vm.m_new_pkt_size;
int rc = rte_pktmbuf_trim(m, buf_adjust);
+ (void)rc;
/* update IP length , and TCP checksum , we can accelerate this using hardware ! */
uint16_t pkt_adjust = vm.m_new_pkt_size - m_packet->pkt_len;
@@ -3430,6 +3448,7 @@ inline void CFlowGenListPerThread::free_last_flow_node(CGenNode *p){
free_node( p);
}
+
class CFlowGenList {
public:
@@ -3457,12 +3476,12 @@ public:
double get_total_tx_bps();
uint32_t get_total_repeat_flows();
double get_delta_flow_is_sec();
+ bool get_is_mac_conf() { return m_mac_info.is_configured();}
public:
std::vector<CFlowGeneratorRec *> m_cap_gen; /* global info */
CFlowsYamlInfo m_yaml_info; /* global yaml*/
std::vector<CFlowGenListPerThread *> m_threads_info;
- bool is_mac_info_configured;
- std::map<uint32_t, mac_addr_align_t> m_mac_info; /* global mac info loaded form mac_file*/
+ CFlowGenListMac m_mac_info;
};
diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp
index 38d34320..250d5342 100644
--- a/src/gtest/rpc_test.cpp
+++ b/src/gtest/rpc_test.cpp
@@ -42,11 +42,6 @@ protected:
m_verbose = false;
- TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
-
- m_rpc = new TrexRpcServer(cfg);
- m_rpc->start();
-
m_context = zmq_ctx_new ();
m_socket = zmq_socket (m_context, ZMQ_REQ);
zmq_connect (m_socket, "tcp://localhost:5050");
@@ -54,9 +49,6 @@ protected:
}
virtual void TearDown() {
- m_rpc->stop();
-
- delete m_rpc;
zmq_close(m_socket);
zmq_term(m_context);
}
@@ -657,3 +649,4 @@ TEST_F(RpcTestOwned, start_stop_traffic) {
send_request(request, response);
EXPECT_EQ(response["result"], "ACK");
}
+
diff --git a/src/gtest/tuple_gen_test.cpp b/src/gtest/tuple_gen_test.cpp
index 8791b67d..8a774e38 100755
--- a/src/gtest/tuple_gen_test.cpp
+++ b/src/gtest/tuple_gen_test.cpp
@@ -334,7 +334,8 @@ TEST(tuple_gen,GenerateTupleMac) {
CClientPool gen;
gen.Create(cdSEQ_DIST,
- 0x10000001, 0x1000000f, 64000,2, &fl,true,0,0);
+ 0x10000001, 0x1000000f, 64000,2, &fl.m_mac_info,true,0,0);
+
CTupleBase result;
uint32_t result_src;
uint16_t result_port;
@@ -348,6 +349,7 @@ TEST(tuple_gen,GenerateTupleMac) {
result_mac = result.getClientMac();
EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%2));
EXPECT_EQ(result_port, 1024+i/2);
+ printf("i:%d,mac:%d\n",i,result_mac->mac[3]);
if (i%2==0)
EXPECT_EQ(result_mac->mac[3], 5);
else
diff --git a/src/mac_mapping.h b/src/mac_mapping.h
new file mode 100644
index 00000000..84151e8c
--- /dev/null
+++ b/src/mac_mapping.h
@@ -0,0 +1,60 @@
+#ifndef MAC_MAPPING_H_
+#define MAC_MAPPING_H_
+
+#define INUSED 0
+#define UNUSED 1
+typedef struct mac_addr_align_ {
+public:
+ uint8_t mac[6];
+ uint8_t inused;
+ uint8_t pad;
+} mac_addr_align_t;
+
+typedef struct mac_mapping_ {
+ mac_addr_align_t mac;
+ uint32_t ip;
+} mac_mapping_t;
+
+class CFlowGenListMac {
+public:
+ CFlowGenListMac() {
+ set_configured(false);
+ }
+
+ std::map<uint32_t, mac_addr_align_t> &
+ get_mac_info () {
+ return m_mac_info;
+ }
+
+ bool is_configured() {
+ return is_mac_info_configured;
+ }
+
+ void set_configured(bool is_conf) {
+ is_mac_info_configured = is_conf;
+ }
+
+ void clear() {
+ set_configured(false);
+ m_mac_info.clear();
+ }
+
+ uint32_t is_mac_exist(uint32_t ip) {
+ if (is_configured()) {
+ return m_mac_info.count(ip);
+ } else {
+ return 0;
+ }
+ }
+ mac_addr_align_t* get_mac_addr_by_ip(uint32_t ip) {
+ if (is_mac_exist(ip)!=0) {
+ return &(m_mac_info[ip]);
+ }
+ return NULL;
+ }
+private:
+ bool is_mac_info_configured;
+ std::map<uint32_t, mac_addr_align_t> m_mac_info; /* global mac info loaded form mac_file*/
+};
+
+#endif //MAC_MAPPING_H_
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp
index 820fb3fa..a0af9fdf 100755
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -55,6 +55,7 @@ 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 <../linux_dpdk/version.h>
extern "C" {
@@ -426,7 +427,8 @@ static char global_loglevel_str[20];
// cores =0==1,1*2,2,3,4,5,6
// An enum for all the option types
enum { OPT_HELP,
- OPT_CFG,
+ OPT_MODE_BATCH,
+ OPT_MODE_INTERACTIVE,
OPT_NODE_DUMP,
OPT_UT,
OPT_FILE_OUT,
@@ -478,15 +480,16 @@ enum { OPT_HELP,
*/
static CSimpleOpt::SOption parser_options[] =
{
- { OPT_HELP, "-?", SO_NONE },
- { OPT_HELP, "-h", SO_NONE },
- { OPT_HELP, "--help", SO_NONE },
- { OPT_UT, "--ut", SO_NONE },
- { OPT_CFG, "-f", SO_REQ_SEP},
- { OPT_PLAT_CFG_FILE,"--cfg", SO_REQ_SEP},
- { OPT_REAL_TIME , "-r", SO_NONE },
- { OPT_SINGLE_CORE , "-s", SO_NONE },
- { OPT_FILE_OUT , "-o" , SO_REQ_SEP},
+ { OPT_HELP, "-?", SO_NONE },
+ { OPT_HELP, "-h", SO_NONE },
+ { OPT_HELP, "--help", SO_NONE },
+ { OPT_UT, "--ut", SO_NONE },
+ { OPT_MODE_BATCH, "-f", SO_REQ_SEP},
+ { OPT_MODE_INTERACTIVE, "-i", SO_NONE },
+ { OPT_PLAT_CFG_FILE, "--cfg", SO_REQ_SEP},
+ { OPT_REAL_TIME , "-r", SO_NONE },
+ { OPT_SINGLE_CORE, "-s", SO_NONE },
+ { OPT_FILE_OUT, "-o" , SO_REQ_SEP},
{ OPT_FLIP_CLIENT_SERVER,"--flip",SO_NONE },
{ OPT_FLOW_FLIP_CLIENT_SERVER,"-p",SO_NONE },
{ OPT_FLOW_FLIP_CLIENT_SERVER_SIDE,"-e",SO_NONE },
@@ -533,13 +536,18 @@ static CSimpleOpt::SOption parser_options[] =
static int usage(){
- printf(" Usage: t-rex-64 [OPTION] -f cfg.yaml -c cores \n");
+ printf(" Usage: t-rex-64 [MODE] [OPTION] -f cfg.yaml -c cores \n");
printf(" \n");
printf(" \n");
- printf(" options \n");
+
+ printf(" mode \n\n");
printf(" -f [file] : YAML file with template configuration \n");
+ printf(" -i : launch TRex in interactive mode (RPC server)\n");
printf(" \n\n");
- printf(" --mac [file] : YAML file with <client ip, mac addr> configuration \n");
+
+ printf(" options \n\n");
+
+ printf(" --mac [file] : YAML file with <client ip, mac addr> configuration \n");
printf(" \n\n");
printf(" -r : realtime enable \n");
printf(" \n\n");
@@ -612,7 +620,8 @@ static int usage(){
printf(" --mac-spread : Spread the destination mac-order by this factor. e.g 2 will generate the traffic to 2 devices DEST-MAC ,DEST-MAC+1 \n");
printf(" maximum is up to 128 devices \n");
- printf(" simulation mode : \n");
+
+ printf("\n simulation mode : \n");
printf(" Using this mode you can generate the traffic into a pcap file and learn how trex works \n");
printf(" With this version you must be SUDO to use this mode ( I know this is not normal ) \n");
printf(" you can use the Linux CEL version of t-rex to do it without super user \n");
@@ -653,6 +662,7 @@ static int usage(){
printf(" Open Source Components / Libraries \n");
printf(" DPDK (BSD) \n");
printf(" YAML-CPP (BSD) \n");
+ printf(" JSONCPP (MIT) \n");
printf(" \n");
printf(" Open Source Binaries \n");
printf(" ZMQ (LGPL v3plus) \n");
@@ -667,6 +677,11 @@ static int usage(){
int gtest_main(int argc, char **argv) ;
+static void parse_err(const std::string &msg) {
+ std::cout << "\nArgument Parsing Error: \n\n" << "*** "<< msg << "\n\n";
+ exit(-1);
+}
+
static int parse_options(int argc, char *argv[], CParserOption* po, bool first_time ) {
CSimpleOpt args(argc, argv, parser_options);
@@ -679,36 +694,55 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
int res1;
uint32_t tmp_data;
+ po->m_run_mode = CParserOption::RUN_MODE_INVALID;
while ( args.Next() ){
if (args.LastError() == SO_SUCCESS) {
switch (args.OptionId()) {
+
case OPT_UT :
- printf(" Supported only in simulation \n");
- res1=0;
- exit(res1);
+ parse_err("Supported only in simulation");
break;
+
case OPT_HELP:
usage();
return -1;
- case OPT_CFG:
+
+ case OPT_MODE_BATCH:
+ if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) {
+ parse_err("Please specify single run mode");
+ }
+ po->m_run_mode = CParserOption::RUN_MODE_BATCH;
po->cfg_file = args.OptionArg();
break;
+
+ case OPT_MODE_INTERACTIVE:
+ if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) {
+ parse_err("Please specify single run mode");
+ }
+ po->m_run_mode = CParserOption::RUN_MODE_INTERACTIVE;
+ break;
+
case OPT_NO_KEYBOARD_INPUT :
po->preview.set_no_keyboard(true);
break;
+
case OPT_MAC_FILE :
po->mac_file = args.OptionArg();
break;
+
case OPT_PLAT_CFG_FILE :
po->platform_cfg_file = args.OptionArg();
break;
+
case OPT_SINGLE_CORE :
po->preview.setSingleCore(true);
break;
+
case OPT_IPV6:
po->preview.set_ipv6_mode_enable(true);
break;
+
case OPT_VLAN:
po->preview.set_vlan_mode_enable(true);
break;
@@ -726,6 +760,7 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
printf(" warning -r is deprecated, real time is not needed any more , it is the default \n");
po->preview.setRealTime(true);
break;
+
case OPT_NO_FLOW_CONTROL:
po->preview.set_disable_flow_control_setting(true);
break;
@@ -832,21 +867,20 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
} // End of while
- if ((po->cfg_file =="") ) {
- printf("Invalid combination of parameters you must add -f with configuration file \n");
- return -1;
+ if ((po->m_run_mode == CParserOption::RUN_MODE_INVALID) ) {
+ parse_err("Please provide single run mode (e.g. batch or interactive)");
}
if ( po->m_mac_splitter > 128 ){
- printf("maximum mac spreading is 128 you set it to %d \n",po->m_mac_splitter);
- return -1;
+ std::stringstream ss;
+ ss << "maximum mac spreading is 128 you set it to: " << po->m_mac_splitter;
+ parse_err(ss.str());
}
if ( po->preview.get_learn_mode_enable() ){
if ( po->preview.get_ipv6_mode_enable() ){
- printf("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n");
- printf("if you think it is important,open a defect \n");
- return -1;
+ parse_err("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n" \
+ "if you think it is important,open a defect \n");
}
if ( po->is_latency_disabled() ){
/* set latency thread */
@@ -2701,7 +2735,7 @@ public:
}
public:
- bool Create();
+ bool Create(bool is_stateless);
void Delete();
int ixgbe_prob_init();
@@ -3375,18 +3409,22 @@ int CGlobalPortCfg::ixgbe_start(void){
}
-bool CGlobalPortCfg::Create(){
-
- if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port,
- !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){
- return (false);
- }
+bool CGlobalPortCfg::Create(bool is_stateless){
+ /* 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);
+ }
+ }
/* We load the YAML twice,
this is the first time. to update global flags */
CFlowsYamlInfo pre_yaml_info;
- pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
+ if (!is_stateless) {
+ pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
+ }
if ( pre_yaml_info.m_vlan_info.m_enable ){
CGlobalInfo::m_options.preview.set_vlan_mode_enable(true);
@@ -3863,6 +3901,7 @@ int CGlobalPortCfg::run_in_master(){
std::string json;
bool was_stopped=false;
+
while ( true ) {
if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ){
@@ -3976,6 +4015,7 @@ int CGlobalPortCfg::run_in_master(){
break;
}
}
+
m_mg.stop();
delay(1000);
if ( was_stopped ){
@@ -4100,9 +4140,9 @@ int CGlobalPortCfg::start_send_master(){
if (CGlobalInfo::m_options.mac_file != "") {
CGlobalInfo::m_options.preview.set_mac_ip_mapping_enable(true);
m_fl.load_from_mac_file(CGlobalInfo::m_options.mac_file);
- m_fl.is_mac_info_configured = true;
+ m_fl.m_mac_info.set_configured(true);
} else {
- m_fl.is_mac_info_configured = false;
+ m_fl.m_mac_info.set_configured(false);
}
m_expected_pps = m_fl.get_total_pps();
@@ -4172,7 +4212,18 @@ static int latency_one_lcore(__attribute__((unused)) void *dummy)
}
+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)
{
@@ -4381,7 +4432,37 @@ 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);
+}
@@ -4436,7 +4517,6 @@ int main_test(int argc , char * argv[]){
rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
}
-
time_init();
/* check if we are in simulation mode */
@@ -4445,11 +4525,18 @@ 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() ){
+ if ( !ports_cfg.Create(is_stateless) ){
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());
@@ -4518,6 +4605,7 @@ int main_test(int argc , char * argv[]){
if (rte_eal_wait_lcore(lcore_id) < 0)
return -1;
}
+
ports_cfg.stop_master();
ports_cfg.Delete();
utl_termio_reset();
diff --git a/src/mock/rte_ethdev.h b/src/mock/rte_ethdev.h
new file mode 100644
index 00000000..046d8366
--- /dev/null
+++ b/src/mock/rte_ethdev.h
@@ -0,0 +1,44 @@
+/*
+ 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 __MOCK_FILE_RTE_ETHDEV_H__
+#define __MOCK_FILE_RTE_ETHDEV_H__
+
+#include <string.h>
+
+struct rte_eth_stats {
+ uint64_t obytes;
+ uint64_t ibytes;
+ uint64_t opackets;
+ uint64_t ipackets;
+};
+
+static inline void
+rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats) {
+ memset(stats, 0, sizeof(rte_eth_stats));
+}
+
+static inline uint16_t
+rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts) {
+ return (0);
+}
+
+#endif /* __MOCK_FILE_RTE_ETHDEV_H__ */
diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/mock/trex_rpc_server_mock.cpp
index 835e28b8..de43f92f 100644
--- a/src/rpc-server/trex_rpc_server_mock.cpp
+++ b/src/mock/trex_rpc_server_mock.cpp
@@ -20,7 +20,7 @@ limitations under the License.
*/
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
#include <iostream>
#include <unistd.h>
@@ -44,29 +44,42 @@ int gtest_main(int argc, char **argv);
int main(int argc, char *argv[]) {
- /* configure the stateless object with 4 ports */
- TrexStateless::configure(4);
+ bool is_gtest = false;
- // gtest ?
+ // gtest ?
if (argc > 1) {
if (string(argv[1]) != "--ut") {
cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n";
exit(-1);
}
- return gtest_main(argc, argv);
+ is_gtest = true;
}
- cout << "\n-= Starting RPC Server Mock =-\n\n";
- cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n";
+ /* configure the stateless object with 4 ports */
+ TrexStatelessCfg cfg;
- TrexRpcServerConfig rpc_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
- TrexRpcServer rpc(rpc_cfg);
+ TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
+ TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
- /* init the RPC server */
- rpc.start();
+ 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_server_verbose = (is_gtest ? false : true);
- cout << "Setting Server To Full Verbose\n\n";
- rpc.set_verbose(true);
+ TrexStateless::configure(cfg);
+
+ TrexStateless::get_instance().launch_control_plane();
+
+ /* gtest handling */
+ if (is_gtest) {
+ int rc = gtest_main(argc, argv);
+ TrexStateless::destroy();
+ return rc;
+ }
+
+ cout << "\n-= Starting RPC Server Mock =-\n\n";
+ cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n";
cout << "Server Started\n\n";
@@ -74,7 +87,6 @@ int main(int argc, char *argv[]) {
sleep(1);
}
- rpc.stop();
-
-
+ TrexStateless::destroy();
}
+
diff --git a/src/platform_cfg.cpp b/src/platform_cfg.cpp
index a226a9ac..f0911611 100755
--- a/src/platform_cfg.cpp
+++ b/src/platform_cfg.cpp
@@ -189,107 +189,70 @@ void operator >> (const YAML::Node& node, CMacYamlInfo & mac_info) {
}
void operator >> (const YAML::Node& node, CPlatformMemoryYamlInfo & plat_info) {
- try {
- node["mbuf_64"] >> plat_info.m_mbuf[MBUF_64];
- } catch ( const std::exception& e ) {
- }
- try {
- node["mbuf_128"] >> plat_info.m_mbuf[MBUF_128];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_64") ){
+ node["mbuf_64"] >> plat_info.m_mbuf[MBUF_64];
}
- try {
- node["mbuf_256"] >> plat_info.m_mbuf[MBUF_256];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_128") ){
+ node["mbuf_128"] >> plat_info.m_mbuf[MBUF_128];
}
- try {
- node["mbuf_512"] >> plat_info.m_mbuf[MBUF_512];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_256") ){
+ node["mbuf_256"] >> plat_info.m_mbuf[MBUF_256];
}
- try {
- node["mbuf_1024"] >> plat_info.m_mbuf[MBUF_1024];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_512") ){
+ node["mbuf_512"] >> plat_info.m_mbuf[MBUF_512];
}
- try {
- node["mbuf_2048"] >> plat_info.m_mbuf[MBUF_2048];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_1024") ){
+ node["mbuf_1024"] >> plat_info.m_mbuf[MBUF_1024];
}
- try {
- node["traffic_mbuf_64"] >> plat_info.m_mbuf[TRAFFIC_MBUF_64];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("mbuf_2048") ){
+ node["mbuf_2048"] >> plat_info.m_mbuf[MBUF_2048];
}
- try {
- node["traffic_mbuf_128"] >> plat_info.m_mbuf[TRAFFIC_MBUF_128];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_64") ){
+ node["traffic_mbuf_64"] >> plat_info.m_mbuf[TRAFFIC_MBUF_64];
}
- try {
- node["traffic_mbuf_256"] >> plat_info.m_mbuf[TRAFFIC_MBUF_256];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_128") ){
+ node["traffic_mbuf_128"] >> plat_info.m_mbuf[TRAFFIC_MBUF_128];
}
- try {
- node["traffic_mbuf_512"] >> plat_info.m_mbuf[TRAFFIC_MBUF_512];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_256") ){
+ node["traffic_mbuf_256"] >> plat_info.m_mbuf[TRAFFIC_MBUF_256];
}
- try {
- node["traffic_mbuf_1024"] >> plat_info.m_mbuf[TRAFFIC_MBUF_1024];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_512") ){
+ node["traffic_mbuf_512"] >> plat_info.m_mbuf[TRAFFIC_MBUF_512];
}
- try {
- node["traffic_mbuf_2048"] >> plat_info.m_mbuf[TRAFFIC_MBUF_2048];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_1024") ){
+ node["traffic_mbuf_1024"] >> plat_info.m_mbuf[TRAFFIC_MBUF_1024];
}
- try {
- node["dp_flows"] >> plat_info.m_mbuf[MBUF_DP_FLOWS];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("traffic_mbuf_2048") ){
+ node["traffic_mbuf_2048"] >> plat_info.m_mbuf[TRAFFIC_MBUF_2048];
}
- try {
- node["global_flows"] >> plat_info.m_mbuf[MBUF_GLOBAL_FLOWS];
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("dp_flows") ){
+ node["dp_flows"] >> plat_info.m_mbuf[MBUF_DP_FLOWS];
}
-}
-
-void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
- try {
- node["port_limit"] >> plat_info.m_port_limit;
- plat_info.m_port_limit_exist=true;
- } catch ( const std::exception& e ) {
- plat_info.m_port_limit=0xffffffff;
+ if ( node.FindValue("global_flows") ){
+ node["global_flows"] >> plat_info.m_mbuf[MBUF_GLOBAL_FLOWS];
}
+}
- try {
- const YAML::Node& interface_mask = node["interface_mask"];
- for(unsigned i=0;i<interface_mask.size();i++) {
- std::string fi;
- const YAML::Node & node = interface_mask;
- node[i] >> fi;
- plat_info.m_if_mask.push_back(fi);
- }
- plat_info.m_if_mask_exist=true;
- } catch ( const std::exception& e ) {
-
- }
+void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
- try {
- node["enable_zmq_pub"] >> plat_info.m_enable_zmq_pub;
- node["zmq_pub_port"] >> plat_info.m_zmq_pub_port;
- plat_info.m_enable_zmq_pub_exist = true;
- } catch ( const std::exception& e ) {
- plat_info.m_enable_zmq_pub_exist = false;
+ if (node.FindValue("interface_mask")) {
+ printf("WARNING interface_mask in not used any more !\n");
}
/* must have interfaces */
@@ -301,31 +264,44 @@ void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
plat_info.m_if_list.push_back(fi);
}
- try {
- node["prefix"] >> plat_info.m_prefix;
- } catch ( const std::exception& e ) {
+
+ if ( node.FindValue("port_limit") ){
+ node["port_limit"] >> plat_info.m_port_limit;
+ plat_info.m_port_limit_exist=true;
}
- try {
- node["limit_memory"] >> plat_info.m_limit_memory;
- } catch ( const std::exception& e ) {
+
+
+ plat_info.m_enable_zmq_pub_exist = true;
+
+ if ( node.FindValue("enable_zmq_pub") ){
+ node["enable_zmq_pub"] >> plat_info.m_enable_zmq_pub;
+ plat_info.m_enable_zmq_pub_exist = true;
}
- try {
- node["c"] >> plat_info.m_thread_per_dual_if;
- } catch ( const std::exception& e ) {
+
+ if ( node.FindValue("zmq_pub_port") ){
+ node["zmq_pub_port"] >> plat_info.m_zmq_pub_port;
+ plat_info.m_enable_zmq_pub_exist = true;
+ }
+
+ if ( node.FindValue("prefix") ){
+ node["prefix"] >> plat_info.m_prefix;
}
+ if ( node.FindValue("limit_memory") ){
+ node["limit_memory"] >> plat_info.m_limit_memory;
+ }
+ if ( node.FindValue("c") ){
+ node["c"] >> plat_info.m_thread_per_dual_if;
+ }
- try {
- node["telnet_port"] >> plat_info.m_telnet_port;
- plat_info.m_telnet_exist=true;
- } catch ( const std::exception& e ) {
- plat_info.m_telnet_port=4501;
+ if ( node.FindValue("telnet_port") ){
+ node["telnet_port"] >> plat_info.m_telnet_port;
+ plat_info.m_telnet_exist=true;
}
- try {
- node["port_bandwidth_gb"] >> plat_info.m_port_bandwidth_gb;
- } catch ( const std::exception& e ) {
+ if ( node.FindValue("port_bandwidth_gb") ){
+ node["port_bandwidth_gb"] >> plat_info.m_port_bandwidth_gb;
}
if ( node.FindValue("memory") ){
@@ -337,7 +313,7 @@ void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
plat_info.m_platform.m_is_exists=true;
}
- try {
+ if ( node.FindValue("port_info") ) {
const YAML::Node& mac_info = node["port_info"];
for(unsigned i=0;i<mac_info.size();i++) {
CMacYamlInfo fi;
@@ -346,7 +322,6 @@ void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
plat_info.m_mac_info.push_back(fi);
}
plat_info.m_mac_info_exist = true;
- }catch ( const std::exception& e ) {
}
}
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index 0c9f2c49..ae87d749 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -21,7 +21,8 @@ limitations under the License.
#include "trex_rpc_cmds.h"
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
#include <trex_rpc_cmds_table.h>
#include <fstream>
@@ -154,7 +155,7 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
section["uptime"] = TrexRpcServer::get_server_uptime();
/* FIXME: core count */
- section["dp_core_count"] = 1;
+ section["dp_core_count"] = instance.get_dp_core_count();
section["core_type"] = get_cpu_model();
/* ports */
@@ -271,17 +272,7 @@ TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
result["result"]["status"] = port->get_state_as_string();
- result["result"]["tx_bps"] = Json::Value::UInt64(port->get_port_stats().tx_bps);
- result["result"]["tx_pps"] = Json::Value::UInt64(port->get_port_stats().tx_pps);
- result["result"]["total_tx_pkts"] = Json::Value::UInt64(port->get_port_stats().total_tx_pkts);
- result["result"]["total_tx_bytes"] = Json::Value::UInt64(port->get_port_stats().total_tx_bytes);
-
- result["result"]["rx_bps"] = Json::Value::UInt64(port->get_port_stats().rx_bps);
- result["result"]["rx_pps"] = Json::Value::UInt64(port->get_port_stats().rx_pps);
- result["result"]["total_rx_pkts"] = Json::Value::UInt64(port->get_port_stats().total_rx_pkts);
- result["result"]["total_rx_bytes"] = Json::Value::UInt64(port->get_port_stats().total_rx_bytes);
-
- result["result"]["tx_rx_error"] = Json::Value::UInt64(port->get_port_stats().tx_rx_errors);
+ port->encode_stats(result["result"]);
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 1450e1a9..20107411 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -1,5 +1,5 @@
/*
- Itay Marom
+ Itay Marom, Dan Klein
Cisco Systems, Inc.
*/
@@ -20,8 +20,9 @@ limitations under the License.
*/
#include "trex_rpc_cmds.h"
#include <trex_rpc_server_api.h>
-#include <trex_stream_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stream.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
#include <iostream>
@@ -107,7 +108,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
if (stream->m_rx_check.m_enable) {
stream->m_rx_check.m_stream_id = parse_int(rx, "stream_id", result);
stream->m_rx_check.m_seq_enabled = parse_bool(rx, "seq_enabled", result);
- stream->m_rx_check.m_latency = parse_bool(rx, "latency", result);
+ stream->m_rx_check.m_latency = parse_bool(rx, "latency_enabled", result);
}
/* make sure this is a valid stream to add */
@@ -232,7 +233,7 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
void
TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result) {
- std::string flow_var_name = parse_string(inst, "flow_var_name", result);
+ std::string flow_var_name = parse_string(inst, "name", result);
uint16_t pkt_offset = parse_uint16(inst, "pkt_offset", result);
int add_value = parse_int(inst, "add_value", result);
bool is_big_endian = parse_bool(inst, "is_big_endian", result);
diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp
new file mode 100644
index 00000000..f4d21f2f
--- /dev/null
+++ b/src/rpc-server/trex_rpc_async_server.cpp
@@ -0,0 +1,109 @@
+/*
+ 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.
+*/
+
+/* required for sleep_for c++ 2011
+ https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/608145
+*/
+#define _GLIBCXX_USE_NANOSLEEP
+
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
+#include <trex_rpc_async_server.h>
+#include <zmq.h>
+#include <json/json.h>
+#include <string>
+#include <iostream>
+
+/**
+ * ZMQ based publisher server
+ *
+ */
+TrexRpcServerAsync::TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "publisher", lock) {
+ /* ZMQ is not thread safe - this should be outside */
+ m_context = zmq_ctx_new();
+}
+
+/**
+ * publisher thread
+ *
+ */
+void
+TrexRpcServerAsync::_rpc_thread_cb() {
+ std::stringstream ss;
+
+ /* create a socket based on the configuration */
+ m_socket = zmq_socket (m_context, ZMQ_PUB);
+
+ switch (m_cfg.get_protocol()) {
+ case TrexRpcServerConfig::RPC_PROT_TCP:
+ ss << "tcp://*:";
+ break;
+ default:
+ throw TrexRpcException("unknown protocol for RPC");
+ }
+
+ ss << m_cfg.get_port();
+
+ /* bind the scoket */
+ int rc = zmq_bind (m_socket, ss.str().c_str());
+ if (rc != 0) {
+ throw TrexRpcException("Unable to start ZMQ server at: " + ss.str());
+ }
+
+ /* while the server is running - publish results */
+ while (m_is_running) {
+ Json::Value snapshot;
+ Json::FastWriter writer;
+
+ /* if lock was provided - take it */
+ if (m_lock) {
+ m_lock->lock();
+ }
+
+ /* trigger a full update for stats */
+ TrexStateless::get_instance().update_stats();
+
+ /* done with the lock */
+ if (m_lock) {
+ m_lock->unlock();
+ }
+
+ /* encode them to JSON */
+ TrexStateless::get_instance().encode_stats(snapshot);
+
+ /* write to string and publish */
+ std::string snapshot_str = writer.write(snapshot);
+
+ zmq_send(m_socket, snapshot_str.c_str(), snapshot_str.size(), 0);
+ //std::cout << "sending " << snapshot_str << "\n";
+
+ /* relax for some time */
+ std::this_thread::sleep_for (std::chrono::milliseconds(1000));
+ }
+
+ /* must be closed from the same thread */
+ zmq_close(m_socket);
+}
+
+void
+TrexRpcServerAsync::_stop_rpc_thread() {
+ zmq_term(m_context);
+}
diff --git a/src/rpc-server/trex_rpc_async_server.h b/src/rpc-server/trex_rpc_async_server.h
new file mode 100644
index 00000000..02d1490e
--- /dev/null
+++ b/src/rpc-server/trex_rpc_async_server.h
@@ -0,0 +1,54 @@
+/*
+ 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_RPC_ASYNC_SERVER_H__
+#define __TREX_RPC_ASYNC_SERVER_H__
+
+#include <trex_rpc_server_api.h>
+#include <trex_stateless_port.h>
+
+/**
+ * async RPC server
+ *
+ * @author imarom (11-Aug-15)
+ */
+class TrexRpcServerAsync : public TrexRpcServerInterface {
+public:
+
+ TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL);
+
+protected:
+ void _rpc_thread_cb();
+ void _stop_rpc_thread();
+
+private:
+
+ void handle_server_error(const std::string &specific_err);
+
+ static const int RPC_MAX_MSG_SIZE = (20 * 1024);
+ void *m_context;
+ void *m_socket;
+ uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE];
+};
+
+
+#endif /* __TREX_RPC_ASYNC_SERVER_H__ */
+
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index 6c355e70..920a8d30 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -20,7 +20,8 @@ limitations under the License.
*/
#include <trex_rpc_cmd_api.h>
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
trex_rpc_cmd_rc_e
TrexRpcCommand::run(const Json::Value &params, Json::Value &result) {
diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp
index 3d52686c..9147f75d 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.cpp
+++ b/src/rpc-server/trex_rpc_req_resp_server.cpp
@@ -34,7 +34,7 @@ limitations under the License.
* ZMQ based request-response server
*
*/
-TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg, "req resp") {
+TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "req resp", lock) {
/* ZMQ is not thread safe - this should be outside */
m_context = zmq_ctx_new();
}
@@ -127,6 +127,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
int index = 0;
+ /* if lock was provided, take it */
+ if (m_lock) {
+ m_lock->lock();
+ }
+
/* for every command parsed - launch it */
for (auto command : commands) {
Json::Value single_response;
@@ -138,6 +143,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
}
+ /* done with the lock */
+ if (m_lock) {
+ m_lock->unlock();
+ }
+
/* write the JSON to string and sever on ZMQ */
std::string response_str;
diff --git a/src/rpc-server/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h
index 7c1d66d1..1f638adf 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.h
+++ b/src/rpc-server/trex_rpc_req_resp_server.h
@@ -32,7 +32,7 @@ limitations under the License.
class TrexRpcServerReqRes : public TrexRpcServerInterface {
public:
- TrexRpcServerReqRes(const TrexRpcServerConfig &cfg);
+ TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL);
protected:
void _rpc_thread_cb();
diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp
index 6b8c200d..a14e6f97 100644
--- a/src/rpc-server/trex_rpc_server.cpp
+++ b/src/rpc-server/trex_rpc_server.cpp
@@ -21,6 +21,7 @@ limitations under the License.
#include <trex_rpc_server_api.h>
#include <trex_rpc_req_resp_server.h>
+#include <trex_rpc_async_server.h>
#include <trex_rpc_jsonrpc_v2_parser.h>
#include <unistd.h>
#include <zmq.h>
@@ -29,7 +30,7 @@ limitations under the License.
/************** RPC server interface ***************/
-TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name) : m_cfg(cfg), m_name(name) {
+TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *lock) : m_cfg(cfg), m_name(name), m_lock(lock) {
m_is_running = false;
m_is_verbose = false;
}
@@ -112,10 +113,19 @@ get_current_date_time() {
const std::string TrexRpcServer::s_server_uptime = get_current_date_time();
-TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) {
+TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg,
+ const TrexRpcServerConfig *async_cfg,
+ std::mutex *lock) {
/* add the request response server */
- m_servers.push_back(new TrexRpcServerReqRes(req_resp_cfg));
+ if (req_resp_cfg) {
+ m_servers.push_back(new TrexRpcServerReqRes(*req_resp_cfg, lock));
+ }
+
+ /* add async publisher */
+ if (async_cfg) {
+ m_servers.push_back(new TrexRpcServerAsync(*async_cfg, lock));
+ }
}
TrexRpcServer::~TrexRpcServer() {
diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h
index 06bbe10c..ff876ac4 100644
--- a/src/rpc-server/trex_rpc_server_api.h
+++ b/src/rpc-server/trex_rpc_server_api.h
@@ -24,6 +24,7 @@ limitations under the License.
#include <stdint.h>
#include <vector>
+#include <mutex>
#include <thread>
#include <string>
#include <stdexcept>
@@ -68,7 +69,7 @@ private:
class TrexRpcServerInterface {
public:
- TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name);
+ TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *m_lock = NULL);
virtual ~TrexRpcServerInterface();
/**
@@ -127,6 +128,7 @@ protected:
bool m_is_verbose;
std::thread *m_thread;
std::string m_name;
+ std::mutex *m_lock;
};
/**
@@ -139,8 +141,11 @@ protected:
class TrexRpcServer {
public:
- /* currently only request response server config is required */
- TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg);
+ /* creates the collection of servers using configurations */
+ TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg,
+ const TrexRpcServerConfig *async_cfg,
+ std::mutex *m_lock = NULL);
+
~TrexRpcServer();
/**
diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp
new file mode 100644
index 00000000..72762e26
--- /dev/null
+++ b/src/stateless/cp/trex_stateless.cpp
@@ -0,0 +1,212 @@
+/*
+ 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.h>
+#include <trex_stateless_port.h>
+
+#include <sched.h>
+#include <iostream>
+#include <unistd.h>
+
+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");
+ }
+
+ /* 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);
+
+ /* configure ports */
+
+ 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));
+ }
+
+ /* 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));
+ }
+
+ /* done */
+ instance.m_is_configured = true;
+}
+
+/**
+ * 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
+ (control plane restriction)
+ */
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
+ CPU_SET(sched_getcpu(), &mask);
+ sched_setaffinity(0, sizeof(mask), &mask);
+
+ /* start RPC server */
+ 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
+ *
+ */
+TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) {
+ if (port_id >= m_port_count) {
+ throw TrexException("index out of range");
+ }
+
+ return m_ports[port_id];
+
+}
+
+uint8_t
+TrexStateless::get_port_count() {
+ return m_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;
+ }
+}
+
+void
+TrexStateless::encode_stats(Json::Value &global) {
+
+ global["cpu_util"] = m_stats.m_stats.m_cpu_util;
+
+ global["tx_bps"] = m_stats.m_stats.m_tx_bps;
+ global["rx_bps"] = m_stats.m_stats.m_rx_bps;
+
+ global["tx_pps"] = m_stats.m_stats.m_tx_pps;
+ global["rx_pps"] = m_stats.m_stats.m_rx_pps;
+
+ 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["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["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors);
+
+ for (uint8_t i = 0; i < m_port_count; i++) {
+ std::stringstream ss;
+
+ ss << "port " << i;
+ Json::Value &port_section = global[ss.str()];
+
+ m_ports[i]->encode_stats(port_section);
+ }
+}
+
diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h
new file mode 100644
index 00000000..649b25dd
--- /dev/null
+++ b/src/stateless/cp/trex_stateless.h
@@ -0,0 +1,202 @@
+/*
+ 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_H__
+#define __TREX_STATELESS_H__
+
+#include <stdint.h>
+#include <string>
+#include <stdexcept>
+
+#include <mutex>
+
+#include <trex_stream.h>
+#include <trex_stateless_port.h>
+#include <trex_stateless_dp_core.h>
+#include <trex_rpc_server_api.h>
+
+/**
+ * generic exception for errors
+ * TODO: move this to a better place
+ */
+class TrexException : public std::runtime_error
+{
+public:
+ TrexException() : std::runtime_error("") {
+
+ }
+ TrexException(const std::string &what) : std::runtime_error(what) {
+ }
+};
+
+class TrexStatelessPort;
+
+/**
+ * unified stats
+ *
+ * @author imarom (06-Oct-15)
+ */
+class TrexStatelessStats {
+public:
+ TrexStatelessStats() {
+ 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;
+};
+
+/**
+ * config object for stateless object
+ *
+ * @author imarom (08-Oct-15)
+ */
+class TrexStatelessCfg {
+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;
+ }
+
+ const TrexRpcServerConfig *m_rpc_req_resp_cfg;
+ const TrexRpcServerConfig *m_rpc_async_cfg;
+ bool m_rpc_server_verbose;
+ uint8_t m_port_count;
+ uint8_t m_dp_core_count;
+};
+
+/**
+ * defines the T-Rex stateless operation mode
+ *
+ */
+class TrexStateless {
+public:
+
+ /**
+ * configure the stateless object singelton
+ * 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;
+ }
+
+ /**
+ * starts the control plane side
+ *
+ */
+ void launch_control_plane();
+
+ /**
+ * launch on a single DP core
+ *
+ */
+ void launch_on_dp_core(uint8_t core_id);
+
+ TrexStatelessPort * get_port_by_id(uint8_t port_id);
+ uint8_t get_port_count();
+
+ 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
+ *
+ */
+ void encode_stats(Json::Value &global);
+
+
+protected:
+ TrexStateless();
+
+ static TrexStateless& get_instance_internal () {
+ static TrexStateless instance;
+ return instance;
+ }
+
+ /* c++ 2011 style singleton */
+ TrexStateless(TrexStateless const&) = delete;
+ void operator=(TrexStateless const&) = delete;
+
+ /* status */
+ bool m_is_configured;
+
+ /* RPC server array */
+ TrexRpcServer *m_rpc_server;
+
+ /* ports */
+ 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;
+
+ std::mutex m_global_cp_lock;
+};
+
+#endif /* __TREX_STATELESS_H__ */
+
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
new file mode 100644
index 00000000..a31847a5
--- /dev/null
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -0,0 +1,228 @@
+/*
+ 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.h>
+#include <trex_stateless_port.h>
+#include <string>
+
+#ifndef TREX_RPC_MOCK_SERVER
+// DPDK c++ issue
+#define UINT8_MAX 255
+#define UINT16_MAX 0xFFFF
+// DPDK c++ issue
+#endif
+
+#include <rte_ethdev.h>
+#include <os_time.h>
+
+using namespace std;
+
+/***************************
+ * trex stateless port
+ *
+ **************************/
+TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
+ m_port_state = PORT_STATE_UP_IDLE;
+ clear_owner();
+}
+
+
+/**
+ * starts the traffic on the port
+ *
+ */
+TrexStatelessPort::rc_e
+TrexStatelessPort::start_traffic(void) {
+
+ if (m_port_state != PORT_STATE_UP_IDLE) {
+ return (RC_ERR_BAD_STATE_FOR_OP);
+ }
+
+ if (get_stream_table()->size() == 0) {
+ return (RC_ERR_NO_STREAMS);
+ }
+
+ m_port_state = PORT_STATE_TRANSMITTING;
+
+ /* real code goes here */
+ return (RC_OK);
+}
+
+void
+TrexStatelessPort::stop_traffic(void) {
+
+ /* real code goes here */
+ if (m_port_state == PORT_STATE_TRANSMITTING) {
+ m_port_state = PORT_STATE_UP_IDLE;
+ }
+}
+
+/**
+* access the stream table
+*
+*/
+TrexStreamTable * TrexStatelessPort::get_stream_table() {
+ return &m_stream_table;
+}
+
+
+std::string
+TrexStatelessPort::get_state_as_string() {
+
+ switch (get_state()) {
+ case PORT_STATE_DOWN:
+ return "down";
+
+ case PORT_STATE_UP_IDLE:
+ return "idle";
+
+ case PORT_STATE_TRANSMITTING:
+ return "transmitting";
+ }
+
+ return "unknown";
+}
+
+void
+TrexStatelessPort::get_properties(string &driver, string &speed) {
+
+ /* take this from DPDK */
+ driver = "e1000";
+ speed = "1 Gbps";
+}
+
+
+/**
+ * generate a random connection handler
+ *
+ */
+std::string
+TrexStatelessPort::generate_handler() {
+ std::stringstream ss;
+
+ static const char alphanum[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+
+ /* generate 8 bytes of random handler */
+ for (int i = 0; i < 8; ++i) {
+ ss << alphanum[rand() % (sizeof(alphanum) - 1)];
+ }
+
+ 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;
+
+ port["tx_pps"] = m_stats.m_stats.m_tx_pps;
+ port["rx_pps"] = m_stats.m_stats.m_rx_pps;
+
+ 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["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);
+}
+
+
+
+/***************************
+ * BW measurement
+ *
+ **************************/
+/* TODO: move this to a common place */
+BWMeasure::BWMeasure() {
+ reset();
+}
+
+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);
+}
+
+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);
+ }
+
+ uint32_t ctime=os_get_time_msec();
+ if ((ctime - m_last_time_msec) <os_get_time_freq() ) {
+ return(m_last_result);
+ }
+
+ uint32_t dtime_msec = ctime-m_last_time_msec;
+ uint64_t dbytes = size - m_last_bytes;
+
+ m_last_time_msec = ctime;
+ m_last_bytes = size;
+
+ m_last_result= 0.5*calc_MBsec(dtime_msec,dbytes) +0.5*(m_last_result);
+ return( m_last_result );
+}
+
+
diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/cp/trex_stateless_port.h
index 7a9080aa..428d5aee 100644
--- a/src/stateless/trex_stateless_api.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -18,27 +18,74 @@ 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_API_H__
-#define __TREX_STATELESS_API_H__
+#ifndef __TREX_STATELESS_PORT_H__
+#define __TREX_STATELESS_PORT_H__
-#include <stdint.h>
-#include <string>
-#include <stdexcept>
+#include <trex_stream.h>
-#include <trex_stream_api.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;
+};
/**
- * generic exception for errors
- * TODO: move this to a better place
+ * TRex stateless port stats
+ *
+ * @author imarom (24-Sep-15)
*/
-class TrexException : public std::runtime_error
-{
+class TrexPortStats {
+
public:
- TrexException() : std::runtime_error("") {
+ TrexPortStats() {
+ m_stats = {0};
+ m_bw_tx_bps.reset();
+ m_bw_rx_bps.reset();
+
+ m_bw_tx_pps.reset();
+ m_bw_rx_pps.reset();
}
- TrexException(const std::string &what) : std::runtime_error(what) {
- }
+
+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;
};
/**
@@ -49,20 +96,6 @@ public:
class TrexStatelessPort {
public:
- struct TrexPortStats {
- uint64_t tx_pps;
- uint64_t tx_bps;
- uint64_t total_tx_pkts;
- uint64_t total_tx_bytes;
-
- uint64_t rx_pps;
- uint64_t rx_bps;
- uint64_t total_rx_pkts;
- uint64_t total_rx_bytes;
-
- uint64_t tx_rx_errors;
- };
-
/**
* port state
*/
@@ -169,15 +202,18 @@ public:
}
- const TrexPortStats & get_port_stats(void) {
- /* scrabble */
- m_stats.tx_bps += 1 + rand() % 100;
- m_stats.tx_pps += 1 + rand() % 10;
- m_stats.total_tx_bytes += 1 + rand() % 10;
- m_stats.total_tx_pkts += 1 + rand() % 5;
+ /**
+ * update the values of the stats
+ *
+ */
+ void update_stats();
+
+ const TrexPortStats & get_stats();
- return m_stats;
- }
+ /**
+ * encode stats as JSON
+ */
+ void encode_stats(Json::Value &port);
private:
@@ -191,54 +227,4 @@ private:
TrexPortStats m_stats;
};
-/**
- * defines the T-Rex stateless operation mode
- *
- */
-class TrexStateless {
-public:
-
- /**
- * configure the stateless object singelton
- * reconfiguration is not allowed
- * an exception will be thrown
- */
- static void configure(uint8_t port_count);
-
- /**
- * 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;
- }
-
- TrexStatelessPort *get_port_by_id(uint8_t port_id);
- uint8_t get_port_count();
-
-protected:
- TrexStateless();
- ~TrexStateless();
-
- static TrexStateless& get_instance_internal () {
- static TrexStateless instance;
- return instance;
- }
-
- /* c++ 2011 style singleton */
- TrexStateless(TrexStateless const&) = delete;
- void operator=(TrexStateless const&) = delete;
-
- bool m_is_configured;
- TrexStatelessPort **m_ports;
- uint8_t m_port_count;
-};
-
-#endif /* __TREX_STATELESS_API_H__ */
-
+#endif /* __TREX_STATELESS_PORT_H__ */
diff --git a/src/stateless/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp
index 8bf04748..182036f1 100644
--- a/src/stateless/trex_stream.cpp
+++ b/src/stateless/cp/trex_stream.cpp
@@ -18,7 +18,7 @@ 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_stream_api.h>
+#include <trex_stream.h>
#include <cstddef>
/**************************************
diff --git a/src/stateless/trex_stream_api.h b/src/stateless/cp/trex_stream.h
index d3c0fb29..f5bc96ef 100644
--- a/src/stateless/trex_stream_api.h
+++ b/src/stateless/cp/trex_stream.h
@@ -18,8 +18,8 @@ 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_API_H__
-#define __TREX_STREAM_API_H__
+#ifndef __TREX_STREAM_H__
+#define __TREX_STREAM_H__
#include <unordered_map>
#include <vector>
@@ -205,5 +205,5 @@ private:
std::unordered_map<int, TrexStream *> m_stream_table;
};
-#endif /* __TREX_STREAM_API_H__ */
+#endif /* __TREX_STREAM_H__ */
diff --git a/src/stateless/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp
index 2e760ae9..2e760ae9 100644
--- a/src/stateless/trex_stream_vm.cpp
+++ b/src/stateless/cp/trex_stream_vm.cpp
diff --git a/src/stateless/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index 56edbcaf..56edbcaf 100644
--- a/src/stateless/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
new file mode 100644
index 00000000..3755b82c
--- /dev/null
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -0,0 +1,135 @@
+/*
+ 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_dp_core.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <trex_stateless.h>
+
+#include <bp_sim.h>
+
+#ifndef TREX_RPC_MOCK_SERVER
+
+// DPDK c++ issue
+#define UINT8_MAX 255
+#define UINT16_MAX 0xFFFF
+// DPDK c++ issue
+#endif
+
+#include <rte_ethdev.h>
+#include "mbuf.h"
+
+/**
+ * TEST
+ *
+ */
+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);
+ }
+ char *p = rte_pktmbuf_append(m, pkt_size);
+ assert(p);
+ /* set pkt data */
+ memcpy(p,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);
+
+ return (0);
+}
+
+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();
+}
+
+/***************************
+ * DP core
+ *
+ **************************/
+TrexStatelessDpCore::TrexStatelessDpCore(uint8_t core_id) : m_core_id(core_id) {
+}
+
+/**
+ * main function for DP core
+ *
+ */
+void
+TrexStatelessDpCore::run() {
+ printf("\nOn DP core %d\n", m_core_id);
+ while (true) {
+ test_inject_dummy_pkt();
+ rte_pause();
+ }
+}
+
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
new file mode 100644
index 00000000..4b09b752
--- /dev/null
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -0,0 +1,43 @@
+/*
+ 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_DP_CORE_H__
+#define __TREX_STATELESS_DP_CORE_H__
+
+#include <stdint.h>
+
+/**
+ * stateless DP core object
+ *
+ */
+class TrexStatelessDpCore {
+public:
+
+ TrexStatelessDpCore(uint8_t core_id);
+
+ /* starts the DP core run */
+ void run();
+
+private:
+ void test_inject_dummy_pkt();
+ uint8_t m_core_id;
+};
+
+#endif /* __TREX_STATELESS_DP_CORE_H__ */
diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp
deleted file mode 100644
index 0eb96f05..00000000
--- a/src/stateless/trex_stateless.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- 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_api.h>
-
-using namespace std;
-
-/***********************************************************
- * Trex stateless object
- *
- **********************************************************/
-TrexStateless::TrexStateless() {
- m_is_configured = false;
-}
-
-/**
- * one time configuration of the stateless object
- *
- */
-void TrexStateless::configure(uint8_t port_count) {
-
- TrexStateless& instance = get_instance_internal();
-
- if (instance.m_is_configured) {
- throw TrexException("re-configuration of stateless object is not allowed");
- }
-
- instance.m_port_count = port_count;
- instance.m_ports = new TrexStatelessPort*[port_count];
-
- for (int i = 0; i < instance.m_port_count; i++) {
- instance.m_ports[i] = new TrexStatelessPort(i);
- }
-
- instance.m_is_configured = true;
-}
-
-TrexStateless::~TrexStateless() {
- for (int i = 0; i < m_port_count; i++) {
- delete m_ports[i];
- }
-
- delete [] m_ports;
-}
-
-TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) {
- if (port_id >= m_port_count) {
- throw TrexException("index out of range");
- }
-
- return m_ports[port_id];
-
-}
-
-uint8_t TrexStateless::get_port_count() {
- return m_port_count;
-}
-
-/***************************
- * trex stateless port
- *
- **************************/
-TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
- m_port_state = PORT_STATE_UP_IDLE;
- clear_owner();
- m_stats = {0};
-}
-
-
-/**
- * starts the traffic on the port
- *
- */
-TrexStatelessPort::rc_e
-TrexStatelessPort::start_traffic(void) {
-
- if (m_port_state != PORT_STATE_UP_IDLE) {
- return (RC_ERR_BAD_STATE_FOR_OP);
- }
-
- if (get_stream_table()->size() == 0) {
- return (RC_ERR_NO_STREAMS);
- }
-
- m_port_state = PORT_STATE_TRANSMITTING;
-
- /* real code goes here */
- return (RC_OK);
-}
-
-void
-TrexStatelessPort::stop_traffic(void) {
-
- /* real code goes here */
- if (m_port_state == PORT_STATE_TRANSMITTING) {
- m_port_state = PORT_STATE_UP_IDLE;
- }
-}
-
-/**
-* access the stream table
-*
-*/
-TrexStreamTable * TrexStatelessPort::get_stream_table() {
- return &m_stream_table;
-}
-
-
-std::string
-TrexStatelessPort::get_state_as_string() {
-
- switch (get_state()) {
- case PORT_STATE_DOWN:
- return "down";
-
- case PORT_STATE_UP_IDLE:
- return "idle";
-
- case PORT_STATE_TRANSMITTING:
- return "transmitting";
- }
-
- return "unknown";
-}
-
-void
-TrexStatelessPort::get_properties(string &driver, string &speed) {
-
- /* take this from DPDK */
- driver = "e1000";
- speed = "1 Gbps";
-}
-
-
-/**
- * generate a random connection handler
- *
- */
-std::string
-TrexStatelessPort::generate_handler() {
- std::stringstream ss;
-
- static const char alphanum[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- /* generate 8 bytes of random handler */
- for (int i = 0; i < 8; ++i) {
- ss << alphanum[rand() % (sizeof(alphanum) - 1)];
- }
-
- return (ss.str());
-}
diff --git a/src/tuple_gen.cpp b/src/tuple_gen.cpp
index e408f275..3c05cf05 100755
--- a/src/tuple_gen.cpp
+++ b/src/tuple_gen.cpp
@@ -57,7 +57,7 @@ void CClientPool::Create(IP_DIST_t dist_value,
uint32_t max_ip,
double l_flow,
double t_cps,
- CFlowGenList* fl_list,
+ CFlowGenListMac* mac_info,
bool has_mac_map,
uint16_t tcp_aging,
uint16_t udp_aging) {
@@ -65,10 +65,10 @@ void CClientPool::Create(IP_DIST_t dist_value,
set_dist(dist_value);
uint32_t total_ip = max_ip - min_ip +1;
uint32_t avail_ip = total_ip;
- if (has_mac_map && (fl_list!=NULL)) {
+ if (has_mac_map && (mac_info!=NULL)) {
for(int idx=0;idx<total_ip;idx++){
mac_addr_align_t *mac_adr = NULL;
- mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+ mac_adr = mac_info->get_mac_addr_by_ip(min_ip+idx);
if (mac_adr == NULL) {
avail_ip--;
}
@@ -86,7 +86,7 @@ void CClientPool::Create(IP_DIST_t dist_value,
if (has_mac_map) {
for(int idx=0;idx<total_ip;idx++){
mac_addr_align_t *mac_adr = NULL;
- mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+ mac_adr = mac_info->get_mac_addr_by_ip( min_ip+idx);
if (mac_adr != NULL) {
m_ip_info[idx] = new CClientInfoL(has_mac_map);
m_ip_info[idx]->set_ip(min_ip+idx);
@@ -103,7 +103,7 @@ void CClientPool::Create(IP_DIST_t dist_value,
if (has_mac_map) {
for(int idx=0;idx<total_ip;idx++){
mac_addr_align_t *mac_adr = NULL;
- mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+ mac_adr = mac_info->get_mac_addr_by_ip(min_ip+idx);
if (mac_adr != NULL) {
m_ip_info[idx] = new CClientInfo(has_mac_map);
m_ip_info[idx]->set_ip(min_ip+idx);
@@ -123,20 +123,19 @@ void CClientPool::Create(IP_DIST_t dist_value,
CreateBase();
}
-void delay(int msec);
bool CTupleGeneratorSmart::add_client_pool(IP_DIST_t client_dist,
uint32_t min_client,
uint32_t max_client,
double l_flow,
double t_cps,
- CFlowGenList* fl_list,
+ CFlowGenListMac* mac_info,
uint16_t tcp_aging,
uint16_t udp_aging){
assert(max_client>=min_client);
CClientPool* pool = new CClientPool();
pool->Create(client_dist, min_client, max_client,
- l_flow, t_cps, fl_list, has_mac_mapping,
+ l_flow, t_cps, mac_info, m_has_mac_mapping,
tcp_aging, udp_aging);
m_client_pool.push_back(pool);
@@ -171,13 +170,13 @@ bool CTupleGeneratorSmart::Create(uint32_t _id,
m_thread_id = thread_id;
m_id = _id;
m_was_init=true;
- has_mac_mapping = has_mac;
+ m_has_mac_mapping = has_mac;
return(true);
}
void CTupleGeneratorSmart::Delete(){
m_was_init=false;
- has_mac_mapping = false;
+ m_has_mac_mapping = false;
for (int idx=0;idx<m_client_pool.size();idx++) {
m_client_pool[idx]->Delete();
@@ -246,30 +245,12 @@ void operator >> (const YAML::Node& node, CTupleGenPoolYaml & fi) {
fi.m_tcp_aging_sec = 0;
fi.m_udp_aging_sec = 0;
fi.m_dual_interface_mask = 0;
- try {
- utl_yaml_read_uint32(node,"clients_per_gb",fi.m_number_of_clients_per_gb);
- } catch ( const std::exception& e ) {
- ;}
- try {
- utl_yaml_read_uint32(node,"min_clients",fi.m_min_clients);
- } catch ( const std::exception& e ) {
- ;}
- try {
- utl_yaml_read_ip_addr(node,"dual_port_mask",fi.m_dual_interface_mask);
- } catch ( const std::exception& e ) {
- ;}
- try {
- utl_yaml_read_uint16(node,"tcp_aging",fi.m_tcp_aging_sec);
- } catch ( const std::exception& e ) {
- ;}
- try {
- utl_yaml_read_uint16(node,"udp_aging",fi.m_udp_aging_sec);
- } catch ( const std::exception& e ) {
- ;}
- try {
- node["track_ports"] >> fi.m_is_bundling;
- } catch ( const std::exception& e ) {
- ;}
+ utl_yaml_read_uint32(node,"clients_per_gb",fi.m_number_of_clients_per_gb);
+ utl_yaml_read_uint32(node,"min_clients",fi.m_min_clients);
+ utl_yaml_read_ip_addr(node,"dual_port_mask",fi.m_dual_interface_mask);
+ utl_yaml_read_uint16(node,"tcp_aging",fi.m_tcp_aging_sec);
+ utl_yaml_read_uint16(node,"udp_aging",fi.m_udp_aging_sec);
+ utl_yaml_read_bool(node,"track_ports",fi.m_is_bundling);
}
void copy_global_pool_para(CTupleGenPoolYaml & src, CTupleGenPoolYaml & dst) {
if (src.m_number_of_clients_per_gb == 0)
diff --git a/src/tuple_gen.h b/src/tuple_gen.h
index fb856538..29adbd69 100755
--- a/src/tuple_gen.h
+++ b/src/tuple_gen.h
@@ -37,10 +37,97 @@ limitations under the License.
#include "common/c_common.h"
#include <bitset>
#include <yaml-cpp/yaml.h>
-
+#include <mac_mapping.h>
#include <random>
+class CTupleBase {
+public:
+ CTupleBase() {
+ m_client_mac.inused = UNUSED;
+ }
+ uint32_t getClient() {
+ return m_client_ip;
+ }
+ void setClient(uint32_t ip) {
+ m_client_ip = ip;
+ }
+ uint32_t getClientId() {
+ return m_client_idx;
+ }
+ void setClientId(uint32_t id) {
+ m_client_idx = id;
+ }
+
+ uint32_t getServer(){
+ return m_server_ip;
+ }
+ void setServer(uint32_t ip) {
+ m_server_ip = ip;
+ }
+ uint32_t getServerId(){
+ return m_server_idx;
+ }
+ void setServerId(uint32_t id) {
+ m_server_idx = id;
+ }
+ uint16_t getServerPort() {
+ return m_server_port;
+ }
+ void setServerPort(uint16_t port) {
+ m_server_port = port;
+ }
+ uint16_t getClientPort() {
+ return m_client_port;
+ }
+ void setClientPort(uint16_t port) {
+ m_client_port = port;
+ }
+ mac_addr_align_t* getClientMac() {
+ return &m_client_mac;
+ }
+ void setClientMac(mac_addr_align_t* mac_info) {
+ if (mac_info != NULL) {
+ memcpy(&m_client_mac, mac_info, sizeof(mac_addr_align_t));
+ m_client_mac.inused = INUSED;
+ } else {
+ m_client_mac.inused = UNUSED;
+ }
+ }
+ void setClientTuple(uint32_t ip,mac_addr_align_t*mac,uint16_t port) {
+ setClient(ip);
+ setClientMac(mac);
+ setClientPort(port);
+ }
+ void setClientAll2(uint32_t id, uint32_t ip,uint16_t port) {
+ setClientId(id);
+ setClient(ip);
+ setClientPort(port);
+ }
+
+ void setServerAll(uint32_t id, uint32_t ip) {
+ setServerId(id);
+ setServer(ip);
+ }
+ void getClientAll(uint32_t & id, uint32_t & ip, uint32_t & port) {
+ id = getClientId();
+ ip = getClient();
+ port = getClientPort();
+ }
+ void getServerAll(uint32_t & id, uint32_t & ip) {
+ id = getServerId();
+ ip = getServer();
+ }
+private:
+ uint32_t m_client_ip;
+ uint32_t m_client_idx;
+ uint32_t m_server_ip;
+ uint32_t m_server_idx;
+ mac_addr_align_t m_client_mac;
+ uint16_t m_client_port;
+ uint16_t m_server_port;
+};
+
/*
@@ -59,9 +146,8 @@ limitations under the License.
#define FOREACH(vector) for(int i=0;i<vector.size();i++)
-/* Client distribution */
-
+/* Client distribution */
typedef enum {
cdSEQ_DIST = 0,
cdRANDOM_DIST = 1,
@@ -69,22 +155,6 @@ typedef enum {
cdMAX_DIST = 3
} IP_DIST_t ;
-#define INUSED 0
-#define UNUSED 1
-typedef struct mac_addr_align_ {
-public:
- uint8_t mac[6];
- uint8_t inused;
- uint8_t pad;
-} mac_addr_align_t;
-
-typedef struct mac_mapping_ {
- mac_addr_align_t mac;
- uint32_t ip;
-} mac_mapping_t;
-
-
-
/* For type 1, we generator port by maintaining a 64K bit array for each port.
* In this case, we cannot support large number of clients due to memory exhausted.
*
@@ -99,13 +169,13 @@ typedef struct mac_mapping_ {
#define TYPE2 1
#define MAX_TYPE 3
-
class CIpInfoBase {
public:
virtual mac_addr_align_t* get_mac() { return NULL;}
virtual void set_mac(mac_addr_align_t*){;}
virtual uint16_t get_new_free_port() = 0;
virtual void return_port(uint16_t a) = 0;
+ virtual void generate_tuple(CTupleBase & tuple) = 0;
virtual void return_all_ports() = 0;
uint32_t get_ip() {
return m_ip;
@@ -113,7 +183,8 @@ class CIpInfoBase {
void set_ip(uint32_t ip) {
m_ip = ip;
}
- public:
+ virtual ~CIpInfoBase() {}
+ protected:
uint32_t m_ip;
};
@@ -233,31 +304,37 @@ class CIpInfo : public CIpInfoBase {
};
class CClientInfo : public CIpInfo {
- public:
- CClientInfo (bool has_mac) {
- if (has_mac==true) {
- m_mac = new mac_addr_align_t();
- } else {
- m_mac = NULL;
- }
- }
- CClientInfo () {
+public:
+ CClientInfo (bool has_mac) {
+ if (has_mac==true) {
+ m_mac = new mac_addr_align_t();
+ } else {
m_mac = NULL;
}
-
- mac_addr_align_t* get_mac() {
- return m_mac;
- }
- void set_mac(mac_addr_align_t *mac) {
- memcpy(m_mac, mac, sizeof(mac_addr_align_t));
- }
- ~CClientInfo() {
- if (m_mac!=NULL){
- delete m_mac;
- }
+ }
+ CClientInfo () {
+ m_mac = NULL;
+ }
+
+ mac_addr_align_t* get_mac() {
+ return m_mac;
+ }
+ void set_mac(mac_addr_align_t *mac) {
+ memcpy(m_mac, mac, sizeof(mac_addr_align_t));
+ }
+ ~CClientInfo() {
+ if (m_mac!=NULL){
+ delete m_mac;
+ m_mac=NULL;
}
- private:
- mac_addr_align_t *m_mac;
+ }
+
+ void generate_tuple(CTupleBase & tuple) {
+ tuple.setClientTuple(m_ip, m_mac,
+ get_new_free_port());
+ }
+private:
+ mac_addr_align_t *m_mac;
};
class CClientInfoL : public CIpInfoL {
@@ -272,100 +349,44 @@ public:
CClientInfoL () {
m_mac = NULL;
}
-
+
mac_addr_align_t* get_mac() {
return m_mac;
}
+
void set_mac(mac_addr_align_t *mac) {
memcpy(m_mac, mac, sizeof(mac_addr_align_t));
}
+
~CClientInfoL() {
- if (m_mac!=NULL) {
+ if (m_mac!=NULL){
delete m_mac;
+ m_mac=NULL;
}
}
+
+ void generate_tuple(CTupleBase & tuple) {
+ tuple.setClientTuple(m_ip, m_mac,
+ get_new_free_port());
+ }
private:
mac_addr_align_t *m_mac;
};
class CServerInfo : public CIpInfo {
- ;
+ void generate_tuple(CTupleBase & tuple) {
+ tuple.setServer(m_ip);
+ }
};
class CServerInfoL : public CIpInfoL {
- ;
-};
-
-
-class CTupleBase {
-public:
- CTupleBase() {
- m_client_mac.inused = UNUSED;
- }
- uint32_t getClient() {
- return m_client_ip;
- }
- void setClient(uint32_t ip) {
- m_client_ip = ip;
- }
- uint32_t getClientId() {
- return m_client_idx;
- }
- void setClientId(uint32_t id) {
- m_client_idx = id;
- }
-
- uint32_t getServer(){
- return m_server_ip;
- }
- void setServer(uint32_t ip) {
- m_server_ip = ip;
- }
- uint32_t getServerId(){
- return m_server_idx;
- }
- void setServerId(uint32_t id) {
- m_server_idx = id;
- }
- uint16_t getServerPort() {
- return m_server_port;
- }
- void setServerPort(uint16_t port) {
- m_server_port = port;
- }
- uint16_t getClientPort() {
- return m_client_port;
- }
- void setClientPort(uint16_t port) {
- m_client_port = port;
- }
- mac_addr_align_t* getClientMac() {
- return &m_client_mac;
- }
- void setClientMac(mac_addr_align_t* mac_info) {
- if (mac_info != NULL) {
- memcpy(&m_client_mac, mac_info, sizeof(mac_addr_align_t));
- m_client_mac.inused = INUSED;
- } else {
- m_client_mac.inused = UNUSED;
- }
- }
-private:
- uint32_t m_client_ip;
- uint32_t m_client_idx;
- uint32_t m_server_ip;
- uint32_t m_server_idx;
- mac_addr_align_t m_client_mac;
- uint16_t m_client_port;
- uint16_t m_server_port;
+ void generate_tuple(CTupleBase & tuple) {
+ tuple.setServer(m_ip);
+ }
};
-class CFlowGenList;
-mac_addr_align_t * get_mac_addr_by_ip(CFlowGenList *fl_list,
- uint32_t ip);
-bool is_mac_info_conf(CFlowGenList *fl_list);
class CIpPool {
public:
@@ -381,14 +402,15 @@ class CIpPool {
m_active_alloc++;
return (port);
}
- bool is_valid_ip(uint32_t ip){
+
+ bool is_valid_ip(uint32_t ip){
CIpInfoBase* ip_front = m_ip_info.front();
CIpInfoBase* ip_back = m_ip_info.back();
if ((ip>=ip_front->get_ip()) &&
(ip<=ip_back->get_ip())) {
return(true);
}
- printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%x\n",
+ printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%p\n",
ip, ip_front->get_ip(),
ip_back->get_ip(),this);
return(false);
@@ -422,6 +444,9 @@ class CIpPool {
inc_cur_idx();
return res_idx;
}
+
+
+
void set_dist(IP_DIST_t dist) {
if (dist>=cdMAX_DIST) {
m_dist = cdSEQ_DIST;
@@ -491,13 +516,20 @@ class CIpPool {
class CClientPool : public CIpPool {
public:
- void GenerateTuple(CTupleBase & tuple) {
- uint32_t idx = generate_ip();
- tuple.setClientId(idx);
- tuple.setClient(get_ip(idx));
- tuple.setClientMac(get_mac(idx));
- tuple.setClientPort(GenerateOnePort(idx));
+
+ uint32_t GenerateTuple(CTupleBase & tuple) {
+ uint32_t idx = generate_ip();
+ CIpInfoBase* ip_info = m_ip_info[idx];
+ ip_info->generate_tuple(tuple);
+
+ tuple.setClientId(idx);
+ if (tuple.getClientPort()==ILLEGAL_PORT) {
+ m_port_allocation_error++;
+ }
+ m_active_alloc++;
+ return idx;
}
+
uint16_t get_tcp_aging() {
return m_tcp_aging;
}
@@ -509,10 +541,11 @@ public:
uint32_t max_ip,
double l_flow,
double t_cps,
- CFlowGenList* fl_list,
+ CFlowGenListMac* mac_info,
bool has_mac_map,
uint16_t tcp_aging,
uint16_t udp_aging);
+
public:
uint16_t m_tcp_aging;
uint16_t m_udp_aging;
@@ -568,11 +601,9 @@ private:
class CServerPool : public CServerPoolBase {
public:
- CIpPool *gen;
void GenerateTuple(CTupleBase & tuple) {
uint32_t idx = gen->generate_ip();
- tuple.setServerId(idx);
- tuple.setServer(gen->get_ip(idx));
+ tuple.setServerAll(idx, gen->get_ip(idx));
}
uint16_t GenerateOnePort(uint32_t idx) {
return gen->GenerateOnePort(idx);
@@ -587,11 +618,14 @@ public:
if (gen!=NULL) {
gen->Delete();
delete gen;
+ gen=NULL;
}
}
uint32_t get_total_ips() {
return gen->m_ip_info.size();
}
+private:
+ CIpPool *gen;
};
/* generate for each template */
@@ -648,7 +682,7 @@ public:
public:
CTupleGeneratorSmart(){
m_was_init=false;
- has_mac_mapping = false;
+ m_has_mac_mapping = false;
}
bool Create(uint32_t _id,
uint32_t thread_id, bool has_mac=false);
@@ -672,7 +706,7 @@ public:
uint32_t max_client,
double l_flow,
double t_cps,
- CFlowGenList* fl_list,
+ CFlowGenListMac* mac_info,
uint16_t tcp_aging,
uint16_t udp_aging);
bool add_server_pool(IP_DIST_t server_dist,
@@ -699,7 +733,7 @@ private:
std::vector<CClientPool*> m_client_pool;
std::vector<CServerPoolBase*> m_server_pool;
bool m_was_init;
- bool has_mac_mapping;
+ bool m_has_mac_mapping;
};
class CTupleTemplateGeneratorSmart {
@@ -718,15 +752,13 @@ public:
m_server_gen->GenerateTuple(tuple);
m_cache_client_ip = tuple.getClient();
m_cache_client_idx = tuple.getClientId();
- m_cache_server_ip = tuple.getServer();
- m_cache_server_idx = tuple.getServerId();
+ tuple.getServerAll(m_cache_server_idx, m_cache_server_ip);
}else{
- tuple.setServer(m_cache_server_ip);
- tuple.setServerId(m_cache_server_idx);
- tuple.setClient(m_cache_client_ip);
- tuple.setClientId(m_cache_client_idx);
- tuple.setClientPort(
- m_client_gen->GenerateOnePort(m_cache_client_idx));
+ tuple.setServerAll(m_cache_server_idx,
+ m_cache_server_ip);
+ tuple.setClientAll2(m_cache_client_idx,
+ m_cache_client_ip,
+ m_client_gen->GenerateOnePort(m_cache_client_idx));
}
m_cnt++;
if (m_cnt>=m_w) {
diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp
index 237e85af..5f3ca735 100755
--- a/src/utl_yaml.cpp
+++ b/src/utl_yaml.cpp
@@ -70,13 +70,15 @@ bool utl_yaml_read_ip_addr(const YAML::Node& node,
std::string tmp;
uint32_t ip;
bool res=false;
- try {
+ if ( node.FindValue(name) ) {
node[name] >> tmp ;
if ( my_inet_pton4((char *)tmp.c_str(), (unsigned char *)&ip) ){
val=PKT_NTOHL(ip);
res=true;
+ }else{
+ printf(" ERROR not a valid ip %s \n",(char *)tmp.c_str());
+ exit(-1);
}
- }catch ( const std::exception& e ) {
}
return (res);
}
@@ -85,14 +87,11 @@ bool utl_yaml_read_uint32(const YAML::Node& node,
std::string name,
uint32_t & val){
bool res=false;
-
- try {
+ if ( node.FindValue(name) ) {
node[name] >> val ;
res=true;
- }catch ( const std::exception& e ) {
}
return (res);
-
}
bool utl_yaml_read_uint16(const YAML::Node& node,
@@ -100,12 +99,10 @@ bool utl_yaml_read_uint16(const YAML::Node& node,
uint16_t & val){
uint32_t val_tmp;
bool res=false;
-
- try {
+ if ( node.FindValue(name) ) {
node[name] >> val_tmp ;
val = (uint16_t)val_tmp;
res=true;
- }catch ( const std::exception& e ) {
}
}
@@ -113,10 +110,9 @@ bool utl_yaml_read_bool(const YAML::Node& node,
std::string name,
bool & val){
bool res=false;
- try {
+ if ( node.FindValue(name) ) {
node[name] >> val ;
res=true;
- }catch ( const std::exception& e ) {
}
return( res);
}