diff options
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 @@ -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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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); } |