From b77fef12a08d6d964e522eea6b2d846dfcc98b08 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 26 Oct 2015 18:13:18 +0200 Subject: RPC control plane now integarted with DPDK --- src/stateless/cp/trex_stateless.cpp | 162 +++++++++++----------------- src/stateless/cp/trex_stateless.h | 74 +++++-------- src/stateless/cp/trex_stateless_port.cpp | 98 +++-------------- src/stateless/cp/trex_stateless_port.h | 74 ------------- src/stateless/dp/trex_stateless_dp_core.cpp | 135 ----------------------- src/stateless/dp/trex_stateless_dp_core.h | 43 -------- 6 files changed, 102 insertions(+), 484 deletions(-) delete mode 100644 src/stateless/dp/trex_stateless_dp_core.cpp delete mode 100644 src/stateless/dp/trex_stateless_dp_core.h (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 72762e26..e0e95450 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -31,55 +31,58 @@ using namespace std; * Trex stateless object * **********************************************************/ -TrexStateless::TrexStateless() { - m_is_configured = false; -} - /** - * configure the singleton stateless object * */ -void TrexStateless::configure(const TrexStatelessCfg &cfg) { - - TrexStateless& instance = get_instance_internal(); - - /* check status */ - if (instance.m_is_configured) { - throw TrexException("re-configuration of stateless object is not allowed"); - } +TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) { /* create RPC servers */ /* set both servers to mutex each other */ - instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &instance.m_global_cp_lock); - instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); + m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &m_global_cp_lock); + m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); /* configure ports */ + m_port_count = cfg.m_port_count; - instance.m_port_count = cfg.m_port_count; - - for (int i = 0; i < instance.m_port_count; i++) { - instance.m_ports.push_back(new TrexStatelessPort(i)); + for (int i = 0; i < m_port_count; i++) { + m_ports.push_back(new TrexStatelessPort(i)); } - /* cores */ - instance.m_dp_core_count = cfg.m_dp_core_count; - for (int i = 0; i < instance.m_dp_core_count; i++) { - instance.m_dp_cores.push_back(new TrexStatelessDpCore(i)); + m_platform_api = cfg.m_platform_api; +} + +/** + * release all memory + * + * @author imarom (08-Oct-15) + */ +TrexStateless::~TrexStateless() { + + /* release memory for ports */ + for (auto port : m_ports) { + delete port; } + m_ports.clear(); + + /* stops the RPC server */ + m_rpc_server->stop(); + delete m_rpc_server; + + m_rpc_server = NULL; - /* done */ - instance.m_is_configured = true; + delete m_platform_api; + m_platform_api = NULL; } + /** * starts the control plane side * */ void TrexStateless::launch_control_plane() { - //std::cout << "\n on control/master core \n"; /* pin this process to the current running CPU any new thread will be called on the same CPU @@ -94,39 +97,6 @@ TrexStateless::launch_control_plane() { m_rpc_server->start(); } -void -TrexStateless::launch_on_dp_core(uint8_t core_id) { - m_dp_cores[core_id - 1]->run(); -} - -/** - * destroy the singleton and release all memory - * - * @author imarom (08-Oct-15) - */ -void -TrexStateless::destroy() { - TrexStateless& instance = get_instance_internal(); - - if (!instance.m_is_configured) { - return; - } - - /* release memory for ports */ - for (auto port : instance.m_ports) { - delete port; - } - instance.m_ports.clear(); - - /* stops the RPC server */ - instance.m_rpc_server->stop(); - delete instance.m_rpc_server; - - instance.m_rpc_server = NULL; - - /* done */ - instance.m_is_configured = false; -} /** * fetch a port by ID @@ -148,57 +118,32 @@ TrexStateless::get_port_count() { uint8_t TrexStateless::get_dp_core_count() { - return m_dp_core_count; -} - -void -TrexStateless::update_stats() { - - /* update CPU util. - TODO - */ - m_stats.m_stats.m_cpu_util = 0; - - /* for every port update and accumulate */ - for (uint8_t i = 0; i < m_port_count; i++) { - m_ports[i]->update_stats(); - - const TrexPortStats & port_stats = m_ports[i]->get_stats(); - - m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps; - m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps; - - m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps; - m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps; - - m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts; - m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts; - - m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes; - m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes; - - m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors; - } + return m_platform_api->get_dp_core_count(); } void TrexStateless::encode_stats(Json::Value &global) { - global["cpu_util"] = m_stats.m_stats.m_cpu_util; + const TrexPlatformApi *api = get_stateless_obj()->get_platform_api(); + + TrexPlatformGlobalStats stats; + api->get_global_stats(stats); - global["tx_bps"] = m_stats.m_stats.m_tx_bps; - global["rx_bps"] = m_stats.m_stats.m_rx_bps; + global["cpu_util"] = stats.m_stats.m_cpu_util; - global["tx_pps"] = m_stats.m_stats.m_tx_pps; - global["rx_pps"] = m_stats.m_stats.m_rx_pps; + global["tx_bps"] = stats.m_stats.m_tx_bps; + global["rx_bps"] = stats.m_stats.m_rx_bps; - global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); - global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); + global["tx_pps"] = stats.m_stats.m_tx_pps; + global["rx_pps"] = stats.m_stats.m_rx_pps; - global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); - global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); + global["total_tx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_tx_pkts); + global["total_rx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_rx_pkts); - global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); + global["total_tx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_tx_bytes); + global["total_rx_bytes"] = Json::Value::UInt64(stats.m_stats.m_total_rx_bytes); + + global["tx_rx_errors"] = Json::Value::UInt64(stats.m_stats.m_tx_rx_errors); for (uint8_t i = 0; i < m_port_count; i++) { std::stringstream ss; @@ -210,3 +155,20 @@ TrexStateless::encode_stats(Json::Value &global) { } } +/** + * generate a snapshot for publish (async publish) + * + */ +void +TrexStateless::generate_publish_snapshot(std::string &snapshot) { + Json::FastWriter writer; + Json::Value root; + + root["name"] = "trex-stateless-info"; + root["type"] = 0; + + /* stateless specific info goes here */ + root["data"] = Json::nullValue; + + snapshot = writer.write(root); +} diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 649b25dd..758707a2 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -29,9 +29,10 @@ limitations under the License. #include #include -#include #include +#include + /** * generic exception for errors * TODO: move this to a better place @@ -88,17 +89,17 @@ public: /* default values */ TrexStatelessCfg() { m_port_count = 0; - m_dp_core_count = 0; m_rpc_req_resp_cfg = NULL; m_rpc_async_cfg = NULL; - m_rpc_server_verbose = false; + m_rpc_server_verbose = false; + m_platform_api = NULL; } const TrexRpcServerConfig *m_rpc_req_resp_cfg; const TrexRpcServerConfig *m_rpc_async_cfg; + const TrexPlatformApi *m_platform_api; bool m_rpc_server_verbose; uint8_t m_port_count; - uint8_t m_dp_core_count; }; /** @@ -113,27 +114,8 @@ public: * reconfiguration is not allowed * an exception will be thrown */ - static void configure(const TrexStatelessCfg &cfg); - - /** - * destroy the instance - * - */ - static void destroy(); - - /** - * singleton public get instance - * - */ - static TrexStateless& get_instance() { - TrexStateless& instance = get_instance_internal(); - - if (!instance.m_is_configured) { - throw TrexException("object is not configured"); - } - - return instance; - } + TrexStateless(const TrexStatelessCfg &cfg); + ~TrexStateless(); /** * starts the control plane side @@ -152,12 +134,6 @@ public: uint8_t get_dp_core_count(); - /** - * update all the stats (deep update) - * (include all the ports and global stats) - * - */ - void update_stats(); /** * fetch all the stats @@ -165,22 +141,21 @@ public: */ void encode_stats(Json::Value &global); + /** + * generate a snapshot for publish + */ + void generate_publish_snapshot(std::string &snapshot); -protected: - TrexStateless(); - - static TrexStateless& get_instance_internal () { - static TrexStateless instance; - return instance; + const TrexPlatformApi * get_platform_api() { + return (m_platform_api); } - /* c++ 2011 style singleton */ +protected: + + /* no copy or assignment */ TrexStateless(TrexStateless const&) = delete; void operator=(TrexStateless const&) = delete; - /* status */ - bool m_is_configured; - /* RPC server array */ TrexRpcServer *m_rpc_server; @@ -188,15 +163,20 @@ protected: std::vector m_ports; uint8_t m_port_count; - /* cores */ - std::vector m_dp_cores; - uint8_t m_dp_core_count; - - /* stats */ - TrexStatelessStats m_stats; + /* platform API */ + const TrexPlatformApi *m_platform_api; std::mutex m_global_cp_lock; }; +/** + * an anchor function + * + * @author imarom (25-Oct-15) + * + * @return TrexStateless& + */ +TrexStateless * get_stateless_obj(); + #endif /* __TREX_STATELESS_H__ */ diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index a31847a5..6b77b107 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -130,99 +130,27 @@ TrexStatelessPort::generate_handler() { return (ss.str()); } -/** - * update stats for the port - * - */ -void -TrexStatelessPort::update_stats() { - struct rte_eth_stats stats; - rte_eth_stats_get(m_port_id, &stats); - - /* copy straight values */ - m_stats.m_stats.m_total_tx_bytes = stats.obytes; - m_stats.m_stats.m_total_rx_bytes = stats.ibytes; - - m_stats.m_stats.m_total_tx_pkts = stats.opackets; - m_stats.m_stats.m_total_rx_pkts = stats.ipackets; - - /* calculate stats */ - m_stats.m_stats.m_tx_bps = m_stats.m_bw_tx_bps.add(stats.obytes); - m_stats.m_stats.m_rx_bps = m_stats.m_bw_rx_bps.add(stats.ibytes); - - m_stats.m_stats.m_tx_pps = m_stats.m_bw_tx_pps.add(stats.opackets); - m_stats.m_stats.m_rx_pps = m_stats.m_bw_rx_pps.add(stats.ipackets); - -} - -const TrexPortStats & -TrexStatelessPort::get_stats() { - return m_stats; -} void TrexStatelessPort::encode_stats(Json::Value &port) { - port["tx_bps"] = m_stats.m_stats.m_tx_bps; - port["rx_bps"] = m_stats.m_stats.m_rx_bps; - - 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); -} + const TrexPlatformApi *api = get_stateless_obj()->get_platform_api(); + TrexPlatformInterfaceStats stats; + api->get_interface_stats(m_port_id, stats); + port["tx_bps"] = stats.m_stats.m_tx_bps; + port["rx_bps"] = stats.m_stats.m_rx_bps; -/*************************** - * BW measurement - * - **************************/ -/* TODO: move this to a common place */ -BWMeasure::BWMeasure() { - reset(); -} + port["tx_pps"] = stats.m_stats.m_tx_pps; + port["rx_pps"] = stats.m_stats.m_rx_pps; -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); -} + port["total_tx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_tx_pkts); + port["total_rx_pkts"] = Json::Value::UInt64(stats.m_stats.m_total_rx_pkts); -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) -/** - * bandwidth measurement class - * - */ -class BWMeasure { -public: - BWMeasure(); - void reset(void); - double add(uint64_t size); - -private: - double calc_MBsec(uint32_t dtime_msec, - uint64_t dbytes); - -public: - bool m_start; - uint32_t m_last_time_msec; - uint64_t m_last_bytes; - double m_last_result; -}; - -/** - * TRex stateless port stats - * - * @author imarom (24-Sep-15) - */ -class TrexPortStats { - -public: - TrexPortStats() { - m_stats = {0}; - - m_bw_tx_bps.reset(); - m_bw_rx_bps.reset(); - - m_bw_tx_pps.reset(); - m_bw_rx_pps.reset(); - } - -public: - - BWMeasure m_bw_tx_bps; - BWMeasure m_bw_rx_bps; - - BWMeasure m_bw_tx_pps; - BWMeasure m_bw_rx_pps; - - struct { - - double m_tx_bps; - double m_rx_bps; - - double m_tx_pps; - double m_rx_pps; - - uint64_t m_total_tx_pkts; - uint64_t m_total_rx_pkts; - - uint64_t m_total_tx_bytes; - uint64_t m_total_rx_bytes; - - uint64_t m_tx_rx_errors; - } m_stats; -}; - /** * describes a stateless port * @@ -202,14 +137,6 @@ public: } - /** - * update the values of the stats - * - */ - void update_stats(); - - const TrexPortStats & get_stats(); - /** * encode stats as JSON */ @@ -224,7 +151,6 @@ private: port_state_e m_port_state; std::string m_owner; std::string m_owner_handler; - TrexPortStats m_stats; }; #endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp deleted file mode 100644 index 3755b82c..00000000 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ /dev/null @@ -1,135 +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 -#include -#include -#include - -#include - -#ifndef TREX_RPC_MOCK_SERVER - -// DPDK c++ issue -#define UINT8_MAX 255 -#define UINT16_MAX 0xFFFF -// DPDK c++ issue -#endif - -#include -#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 deleted file mode 100644 index 4b09b752..00000000 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ /dev/null @@ -1,43 +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. -*/ -#ifndef __TREX_STATELESS_DP_CORE_H__ -#define __TREX_STATELESS_DP_CORE_H__ - -#include - -/** - * 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__ */ -- cgit From ea0b6efc3a41f425e46d81f4b6b8bbbf3238add1 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 27 Oct 2015 19:25:03 +0200 Subject: working cont. stream on 1 core --- src/stateless/cp/trex_stateless_port.cpp | 38 +++++- src/stateless/cp/trex_stream.h | 4 + src/stateless/dp/trex_stateless_dp_core.cpp | 137 +++++++++++++++++++++ src/stateless/dp/trex_stateless_dp_core.h | 120 ++++++++++++++++++ .../messaging/trex_stateless_messaging.cpp | 60 +++++++++ src/stateless/messaging/trex_stateless_messaging.h | 88 +++++++++++++ 6 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 src/stateless/dp/trex_stateless_dp_core.cpp create mode 100644 src/stateless/dp/trex_stateless_dp_core.h create mode 100644 src/stateless/messaging/trex_stateless_messaging.cpp create mode 100644 src/stateless/messaging/trex_stateless_messaging.h (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 6b77b107..92d0a7f8 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -18,8 +18,11 @@ 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 #include +#include + #include #ifndef TREX_RPC_MOCK_SERVER @@ -61,7 +64,32 @@ TrexStatelessPort::start_traffic(void) { m_port_state = PORT_STATE_TRANSMITTING; - /* real code goes here */ + + /* ************* A HACK FOR NOW *************/ + /* we support only one stream continious */ + if (get_stream_table()->size() != 1) { + return (RC_ERR_FAILED_TO_COMPILE_STREAMS); + } + + TrexStream *stream; + for (auto it = get_stream_table()->begin(); it != get_stream_table()->end(); it++ ) { + stream = (*it).second; + } + + /* support only cont streams */ + TrexStreamContinuous *cont_stream = dynamic_cast(stream); + if (!cont_stream) { + return (RC_ERR_FAILED_TO_COMPILE_STREAMS); + } + + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(cont_stream->m_pkt.binary, cont_stream->m_pkt.len, cont_stream->get_pps()); + + // FIXME (add the right core list) + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); + + ring->Enqueue((CGenNode *)start_msg); + return (RC_OK); } @@ -72,6 +100,14 @@ TrexStatelessPort::stop_traffic(void) { if (m_port_state == PORT_STATE_TRANSMITTING) { m_port_state = PORT_STATE_UP_IDLE; } + + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(); + + // FIXME (add the right core list) + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); + + ring->Enqueue((CGenNode *)stop_msg); } /** diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index f5bc96ef..91e64d23 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -41,6 +41,7 @@ class TrexStream { friend class TrexRpcCmdAddStream; friend class TrexRpcCmdGetStream; friend class TrexStreamTable; + friend class TrexStatelessPort; public: TrexStream(uint8_t port_id, uint32_t stream_id); @@ -197,6 +198,9 @@ public: */ int size(); + std::unordered_map::iterator begin() {return m_stream_table.begin();} + std::unordered_map::iterator end() {return m_stream_table.end();} + private: /** * holds all the stream in a hash table by stream id 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..20eadfc5 --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -0,0 +1,137 @@ +/* + 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 +#include + +#include + +typedef struct dp_node_extended_info_ { + double next_time_offset; +} dp_node_extended_info_st; + +TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { + m_thread_id = thread_id; + m_core = core; + + m_state = STATE_IDLE; + + CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp(); + + m_ring_from_cp = cp_dp->getRingCpToDp(thread_id); + m_ring_to_cp = cp_dp->getRingDpToCp(thread_id); +} + +void +TrexStatelessDpCore::start() { + + /* creates a maintenace job using the scheduler */ + CGenNode * node_sync = m_core->create_node() ; + node_sync->m_type = CGenNode::FLOW_SYNC; + node_sync->m_time = m_core->m_cur_time_sec + SYNC_TIME_OUT; + m_core->m_node_gen.add_node(node_sync); + + double old_offset = 0.0; + m_core->m_node_gen.flush_file(100000000, 0.0, false, m_core, old_offset); + +} + +void +TrexStatelessDpCore::handle_pkt_event(CGenNode *node) { + + /* if port has stopped - no transmition */ + if (m_state == STATE_IDLE) { + return; + } + + m_core->m_node_gen.m_v_if->send_node(node); + + CGenNodeStateless *node_sl = (CGenNodeStateless *)node; + + /* in case of continues */ + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node_sl->get_opaque_storage(); + node->m_time += opaque->next_time_offset; + + /* insert a new event */ + m_core->m_node_gen.m_p_queue.push(node); +} + +void +TrexStatelessDpCore::start_const_traffic(const uint8_t *pkt, + uint16_t pkt_len, + double pps) { + + CGenNodeStateless *node = m_core->create_node_sl(); + + /* add periodic */ + node->m_type = CGenNode::STATELESS_PKT; + node->m_time = m_core->m_cur_time_sec + 0.0 /* STREAM ISG */; + node->m_flags = 0; + + /* set socket id */ + node->set_socket_id(m_core->m_node_gen.m_socket_id); + + /* build a mbuf from a packet */ + uint16_t pkt_size = pkt_len; + const uint8_t *stream_pkt = pkt; + + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); + opaque->next_time_offset = 1.0 / pps; + + /* allocate const mbuf */ + rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); + assert(m); + + char *p = rte_pktmbuf_append(m, pkt_size); + assert(p); + /* copy the packet */ + memcpy(p,stream_pkt,pkt_size); + + /* set dir 0 or 1 client or server */ + pkt_dir_t dir = 0; + node->set_mbuf_cache_dir(dir); + + /* TBD repace the mac if req we should add flag */ + m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, m); + + /* set the packet as a readonly */ + node->set_cache_mbuf(m); + + m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + + m_core->m_node_gen.add_node((CGenNode *)node); + +} + +void +TrexStatelessDpCore::stop_traffic() { + m_state = STATE_IDLE; +} + +/** + * handle a message from CP to DP + * + */ +void +TrexStatelessDpCore::handle_cp_msg(TrexStatelessCpToDpMsgBase *msg) { + msg->handle(this); + delete msg; +} + diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h new file mode 100644 index 00000000..65d894d2 --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -0,0 +1,120 @@ +/* + 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 +#include + +class TrexStatelessCpToDpMsgBase; +class TrexStatelessDpStart; +class CFlowGenListPerThread; +class CGenNode; + +class TrexStatelessDpCore { + +public: + + /* states */ + enum state_e { + STATE_IDLE, + STATE_TRANSMITTING + }; + + TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core); + + /** + * launch the stateless DP core code + * + */ + void start(); + + /** + * handle pkt event + * + * @author imarom (27-Oct-15) + */ + void handle_pkt_event(CGenNode *node); + + /** + * dummy traffic creator + * + * @author imarom (27-Oct-15) + * + * @param pkt + * @param pkt_len + */ + void start_const_traffic(const uint8_t *pkt, uint16_t pkt_len, double pps); + + /** + * stop all traffic for this core + * + */ + void stop_traffic(); + + /** + * check for and handle messages from CP + * + * @author imarom (27-Oct-15) + */ + void periodic_check_for_cp_messages() { + // doing this inline for performance reasons + + /* fast path */ + if ( likely ( m_ring_from_cp->isEmpty() ) ) { + return; + } + + while ( true ) { + CGenNode * node; + if (m_ring_from_cp->Dequeue(node) != 0) { + break; + } + + assert(node); + + TrexStatelessCpToDpMsgBase * msg = (TrexStatelessCpToDpMsgBase *)node; + handle_cp_msg(msg); + } + + } + +private: + /** + * handles a CP to DP message + * + * @author imarom (27-Oct-15) + * + * @param msg + */ + void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); + + uint8_t m_thread_id; + state_e m_state; + CNodeRing *m_ring_from_cp; + CNodeRing *m_ring_to_cp; + + /* pointer to the main object */ + CFlowGenListPerThread *m_core; +}; + +#endif /* __TREX_STATELESS_DP_CORE_H__ */ + diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp new file mode 100644 index 00000000..4cd5b416 --- /dev/null +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -0,0 +1,60 @@ +/* + 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 +#include +#include + +/************************* + start traffic message + ************************/ +TrexStatelessDpStart::TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps) { + assert(pkt); + assert(pkt_len > 0); + + m_pkt = new uint8_t[pkt_len]; + memcpy(m_pkt, pkt, pkt_len); + m_pkt_len = pkt_len; + + m_pps = pps; +} + +TrexStatelessDpStart::~TrexStatelessDpStart() { + if (m_pkt) { + delete m_pkt; + } +} + +bool +TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { + + dp_core->start_const_traffic(m_pkt, m_pkt_len, m_pps); + return true; +} + +/************************* + stop traffic message + ************************/ +bool +TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { + dp_core->stop_traffic(); + return true; +} + diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h new file mode 100644 index 00000000..af05aa4c --- /dev/null +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -0,0 +1,88 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_MESSAGING_H__ +#define __TREX_STATELESS_MESSAGING_H__ + +#include + +class TrexStatelessDpCore; + +/** + * defines the base class for CP to DP messages + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessCpToDpMsgBase() { + } + + virtual ~TrexStatelessCpToDpMsgBase() { + } + + /** + * virtual function to handle a message + * + */ + virtual bool handle(TrexStatelessDpCore *dp_core) = 0; +}; + +/** + * a message to start traffic + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps); + + ~TrexStatelessDpStart(); + + const uint8_t * get_pkt() { + return m_pkt; + } + + uint16_t get_pkt_len() { + return m_pkt_len; + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + +private: + uint8_t *m_pkt; + uint16_t m_pkt_len; + double m_pps; +}; + +/** + * a message to stop traffic + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessDpStop : public TrexStatelessCpToDpMsgBase { +public: + virtual bool handle(TrexStatelessDpCore *dp_core); +}; + + +#endif /* __TREX_STATELESS_MESSAGING_H__ */ -- cgit From cb8bc9bda11c951b8b91a635d8d4d6df8d5a0ab8 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 28 Oct 2015 12:45:57 +0200 Subject: support for multiple streams --- src/stateless/cp/trex_stateless_port.cpp | 26 +++-------- src/stateless/cp/trex_stream.cpp | 52 ++++++++++++++++++++++ src/stateless/cp/trex_stream.h | 32 +++++++++++++ src/stateless/dp/trex_stateless_dp_core.cpp | 12 +++-- src/stateless/dp/trex_stateless_dp_core.h | 5 ++- .../messaging/trex_stateless_messaging.cpp | 17 +++---- src/stateless/messaging/trex_stateless_messaging.h | 15 ++----- 7 files changed, 109 insertions(+), 50 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 92d0a7f8..d3828f53 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -58,32 +58,16 @@ TrexStatelessPort::start_traffic(void) { return (RC_ERR_BAD_STATE_FOR_OP); } - if (get_stream_table()->size() == 0) { - return (RC_ERR_NO_STREAMS); - } - - m_port_state = PORT_STATE_TRANSMITTING; - - - /* ************* A HACK FOR NOW *************/ - /* we support only one stream continious */ - if (get_stream_table()->size() != 1) { - return (RC_ERR_FAILED_TO_COMPILE_STREAMS); - } - - TrexStream *stream; - for (auto it = get_stream_table()->begin(); it != get_stream_table()->end(); it++ ) { - stream = (*it).second; - } + TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(); - /* support only cont streams */ - TrexStreamContinuous *cont_stream = dynamic_cast(stream); - if (!cont_stream) { + /* compile the streams */ + bool rc = get_stream_table()->compile(*compiled_obj); + if (!rc) { return (RC_ERR_FAILED_TO_COMPILE_STREAMS); } /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(cont_stream->m_pkt.binary, cont_stream->m_pkt.len, cont_stream->get_pps()); + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj); // FIXME (add the right core list) CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 182036f1..2fd91560 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -20,6 +20,7 @@ limitations under the License. */ #include #include +#include /************************************** * stream @@ -56,6 +57,29 @@ TrexStream::get_stream_json() { return m_stream_json; } +/************************************** + * stream compiled object + *************************************/ +TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { + for (auto &obj : m_objs) { + delete obj.m_pkt; + } + m_objs.clear(); +} + +void +TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len) { + obj_st obj; + + obj.m_pps = pps; + obj.m_pkt_len = pkt_len; + + obj.m_pkt = new uint8_t[pkt_len]; + memcpy(obj.m_pkt, pkt, pkt_len); + + m_objs.push_back(obj); +} + /************************************** * stream table *************************************/ @@ -114,3 +138,31 @@ void TrexStreamTable::get_stream_list(std::vector &stream_list) { int TrexStreamTable::size() { return m_stream_table.size(); } + + +bool +TrexStreamTable::compile(TrexStreamsCompiledObj &obj) { + + /* for now we do something trivial, */ + for (auto it = m_stream_table.begin(); it != m_stream_table.end(); it++ ) { + TrexStream *stream = (*it).second; + + if (!stream->m_enabled) { + continue; + } + if (!stream->m_self_start) { + continue; + } + + /* support only continous for now ... */ + TrexStreamContinuous *cont_stream = dynamic_cast(stream); + if (!cont_stream) { + continue; + } + + obj.add_compiled_stream(cont_stream->get_pps(), cont_stream->m_pkt.binary, cont_stream->m_pkt.len); + } + + return true; +} + diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 91e64d23..d422f9f4 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -149,6 +149,28 @@ protected: }; +/** + * compiled object for a table of streams + * + * @author imarom (28-Oct-15) + */ +class TrexStreamsCompiledObj { +public: + + TrexStreamsCompiledObj() {} + ~TrexStreamsCompiledObj(); + + void add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len); + + struct obj_st { + double m_pps; + uint8_t *m_pkt; + uint16_t m_pkt_len; + }; + + std::vector m_objs; +}; + /** * holds all the streams * @@ -192,6 +214,16 @@ public: */ void get_stream_list(std::vector &stream_list); + /** + * compiles all the streams in the table to a DP object that + * can be passed to the DP cores + * + * @author imarom (28-Oct-15) + * + * @return bool + */ + bool compile(TrexStreamsCompiledObj &obj); + /** * get the table size * diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 20eadfc5..0262a80a 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -20,6 +20,7 @@ limitations under the License. */ #include #include +#include #include @@ -74,10 +75,7 @@ TrexStatelessDpCore::handle_pkt_event(CGenNode *node) { } void -TrexStatelessDpCore::start_const_traffic(const uint8_t *pkt, - uint16_t pkt_len, - double pps) { - +TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pkt_len) { CGenNodeStateless *node = m_core->create_node_sl(); /* add periodic */ @@ -117,7 +115,13 @@ TrexStatelessDpCore::start_const_traffic(const uint8_t *pkt, m_state = TrexStatelessDpCore::STATE_TRANSMITTING; m_core->m_node_gen.add_node((CGenNode *)node); +} +void +TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { + for (auto single_stream : obj->m_objs) { + add_cont_stream(single_stream.m_pps, single_stream.m_pkt, single_stream.m_pkt_len); + } } void diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 65d894d2..da8484a6 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -28,6 +28,7 @@ class TrexStatelessCpToDpMsgBase; class TrexStatelessDpStart; class CFlowGenListPerThread; class CGenNode; +class TrexStreamsCompiledObj; class TrexStatelessDpCore { @@ -62,7 +63,7 @@ public: * @param pkt * @param pkt_len */ - void start_const_traffic(const uint8_t *pkt, uint16_t pkt_len, double pps); + void start_traffic(TrexStreamsCompiledObj *obj); /** * stop all traffic for this core @@ -107,6 +108,8 @@ private: */ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); + void add_cont_stream(double pps, const uint8_t *pkt, uint16_t pkt_len); + uint8_t m_thread_id; state_e m_state; CNodeRing *m_ring_from_cp; diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 4cd5b416..4ef508fc 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -20,32 +20,25 @@ limitations under the License. */ #include #include +#include #include /************************* start traffic message ************************/ -TrexStatelessDpStart::TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps) { - assert(pkt); - assert(pkt_len > 0); - - m_pkt = new uint8_t[pkt_len]; - memcpy(m_pkt, pkt, pkt_len); - m_pkt_len = pkt_len; - - m_pps = pps; +TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj) : m_obj(obj) { } TrexStatelessDpStart::~TrexStatelessDpStart() { - if (m_pkt) { - delete m_pkt; + if (m_obj) { + delete m_obj; } } bool TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { - dp_core->start_const_traffic(m_pkt, m_pkt_len, m_pps); + dp_core->start_traffic(m_obj); return true; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index af05aa4c..13f6c05a 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -24,6 +24,7 @@ limitations under the License. #include class TrexStatelessDpCore; +class TrexStreamsCompiledObj; /** * defines the base class for CP to DP messages @@ -54,24 +55,14 @@ public: class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { public: - TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps); + TrexStatelessDpStart(TrexStreamsCompiledObj *obj); ~TrexStatelessDpStart(); - const uint8_t * get_pkt() { - return m_pkt; - } - - uint16_t get_pkt_len() { - return m_pkt_len; - } - virtual bool handle(TrexStatelessDpCore *dp_core); private: - uint8_t *m_pkt; - uint16_t m_pkt_len; - double m_pps; + TrexStreamsCompiledObj *m_obj; }; /** -- cgit From 788ba38b545be2f76f290f73b16cbfc37f4fa187 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 28 Oct 2015 14:47:56 +0200 Subject: moved all stream compiling phase to a new file trex_streams_compiler.cpp --- src/stateless/cp/trex_stateless_port.cpp | 19 +++++-- src/stateless/cp/trex_stream.cpp | 63 ++++------------------ src/stateless/cp/trex_stream.h | 39 ++------------ src/stateless/dp/trex_stateless_dp_core.cpp | 4 +- .../messaging/trex_stateless_messaging.cpp | 2 +- 5 files changed, 34 insertions(+), 93 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index d3828f53..3e6e256f 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include #include @@ -58,14 +59,26 @@ TrexStatelessPort::start_traffic(void) { return (RC_ERR_BAD_STATE_FOR_OP); } - TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(); + if (get_stream_table()->size() == 0) { + return (RC_ERR_NO_STREAMS); + } + + /* fetch all the streams from the table */ + vector streams; + get_stream_table()->get_object_list(streams); - /* compile the streams */ - bool rc = get_stream_table()->compile(*compiled_obj); + /* compiler it */ + TrexStreamsCompiler compiler; + TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(); + + bool rc = compiler.compile(streams, *compiled_obj); if (!rc) { return (RC_ERR_FAILED_TO_COMPILE_STREAMS); } + /* move the state to transmiting */ + m_port_state = PORT_STATE_TRANSMITTING; + /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj); diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 2fd91560..ba306137 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -57,29 +57,6 @@ TrexStream::get_stream_json() { return m_stream_json; } -/************************************** - * stream compiled object - *************************************/ -TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { - for (auto &obj : m_objs) { - delete obj.m_pkt; - } - m_objs.clear(); -} - -void -TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len) { - obj_st obj; - - obj.m_pps = pps; - obj.m_pkt_len = pkt_len; - - obj.m_pkt = new uint8_t[pkt_len]; - memcpy(obj.m_pkt, pkt, pkt_len); - - m_objs.push_back(obj); -} - /************************************** * stream table *************************************/ @@ -127,42 +104,24 @@ TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { } } -void TrexStreamTable::get_stream_list(std::vector &stream_list) { - stream_list.clear(); +void TrexStreamTable::get_id_list(std::vector &id_list) { + id_list.clear(); for (auto stream : m_stream_table) { - stream_list.push_back(stream.first); + id_list.push_back(stream.first); } } -int TrexStreamTable::size() { - return m_stream_table.size(); -} - - -bool -TrexStreamTable::compile(TrexStreamsCompiledObj &obj) { - - /* for now we do something trivial, */ - for (auto it = m_stream_table.begin(); it != m_stream_table.end(); it++ ) { - TrexStream *stream = (*it).second; - - if (!stream->m_enabled) { - continue; - } - if (!stream->m_self_start) { - continue; - } - - /* support only continous for now ... */ - TrexStreamContinuous *cont_stream = dynamic_cast(stream); - if (!cont_stream) { - continue; - } +void TrexStreamTable::get_object_list(std::vector &object_list) { + object_list.clear(); - obj.add_compiled_stream(cont_stream->get_pps(), cont_stream->m_pkt.binary, cont_stream->m_pkt.len); + for (auto stream : m_stream_table) { + object_list.push_back(stream.second); } - return true; +} + +int TrexStreamTable::size() { + return m_stream_table.size(); } diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index d422f9f4..c8a15240 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -37,11 +37,6 @@ class TrexRpcCmdAddStream; * */ class TrexStream { - /* provide the RPC parser a way to access private fields */ - friend class TrexRpcCmdAddStream; - friend class TrexRpcCmdGetStream; - friend class TrexStreamTable; - friend class TrexStatelessPort; public: TrexStream(uint8_t port_id, uint32_t stream_id); @@ -57,7 +52,7 @@ public: /* access the stream json */ const Json::Value & get_stream_json(); -protected: +public: /* basic */ uint8_t m_port_id; uint32_t m_stream_id; @@ -149,28 +144,6 @@ protected: }; -/** - * compiled object for a table of streams - * - * @author imarom (28-Oct-15) - */ -class TrexStreamsCompiledObj { -public: - - TrexStreamsCompiledObj() {} - ~TrexStreamsCompiledObj(); - - void add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len); - - struct obj_st { - double m_pps; - uint8_t *m_pkt; - uint16_t m_pkt_len; - }; - - std::vector m_objs; -}; - /** * holds all the streams * @@ -212,17 +185,13 @@ public: * * @param stream_list */ - void get_stream_list(std::vector &stream_list); + void get_id_list(std::vector &id_list); /** - * compiles all the streams in the table to a DP object that - * can be passed to the DP cores - * - * @author imarom (28-Oct-15) + * populate a list with all the stream objects * - * @return bool */ - bool compile(TrexStreamsCompiledObj &obj); + void get_object_list(std::vector &object_list); /** * get the table size diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 0262a80a..f64686d4 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -20,7 +20,7 @@ limitations under the License. */ #include #include -#include +#include #include @@ -119,7 +119,7 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk void TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { - for (auto single_stream : obj->m_objs) { + for (auto single_stream : obj->get_objects()) { add_cont_stream(single_stream.m_pps, single_stream.m_pkt, single_stream.m_pkt_len); } } diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 4ef508fc..3c6a5933 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -20,7 +20,7 @@ limitations under the License. */ #include #include -#include +#include #include /************************* -- cgit From 6aad159d20ce35c76a54f7dc45e97ebc4477ba52 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 28 Oct 2015 18:56:46 +0200 Subject: compiler missing files --- src/stateless/cp/trex_streams_compiler.cpp | 81 ++++++++++++++++++++++++++++++ src/stateless/cp/trex_streams_compiler.h | 68 +++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/stateless/cp/trex_streams_compiler.cpp create mode 100644 src/stateless/cp/trex_streams_compiler.h (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp new file mode 100644 index 00000000..6c77ad0f --- /dev/null +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -0,0 +1,81 @@ +/* + 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 +#include +#include + +/************************************** + * stream compiled object + *************************************/ +TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { + for (auto &obj : m_objs) { + delete obj.m_pkt; + } + m_objs.clear(); +} + +void +TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len) { + obj_st obj; + + obj.m_pps = pps; + obj.m_pkt_len = pkt_len; + + obj.m_pkt = new uint8_t[pkt_len]; + memcpy(obj.m_pkt, pkt, pkt_len); + + m_objs.push_back(obj); +} + +/************************************** + * stream compiler + *************************************/ +bool +TrexStreamsCompiler::compile(const std::vector &streams, TrexStreamsCompiledObj &obj) { + /* for now we do something trivial, */ + for (auto stream : streams) { + + /* skip non-enabled streams */ + if (!stream->m_enabled) { + continue; + } + + /* for now skip also non self started streams */ + if (!stream->m_self_start) { + continue; + } + + /* for now support only continous ... */ + TrexStreamContinuous *cont_stream = dynamic_cast(stream); + if (!cont_stream) { + continue; + } + + /* add it */ + obj.add_compiled_stream(cont_stream->get_pps(), + cont_stream->m_pkt.binary, + cont_stream->m_pkt.len); + } + + return true; +} + diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h new file mode 100644 index 00000000..90253cdf --- /dev/null +++ b/src/stateless/cp/trex_streams_compiler.h @@ -0,0 +1,68 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STREAMS_COMPILER_H__ +#define __TREX_STREAMS_COMPILER_H__ + +#include +#include + +class TrexStreamsCompiler; +class TrexStream; + +/** + * compiled object for a table of streams + * + * @author imarom (28-Oct-15) + */ +class TrexStreamsCompiledObj { + friend class TrexStreamsCompiler; +public: + + TrexStreamsCompiledObj() {} + ~TrexStreamsCompiledObj(); + + struct obj_st { + double m_pps; + uint8_t *m_pkt; + uint16_t m_pkt_len; + }; + + const std::vector & get_objects() { + return m_objs; + } + +private: + void add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len); + std::vector m_objs; +}; + +class TrexStreamsCompiler { +public: + /** + * compiles a vector of streams to an object passable to the DP + * + * @author imarom (28-Oct-15) + * + */ + bool compile(const std::vector &streams, TrexStreamsCompiledObj &obj); +}; + +#endif /* __TREX_STREAMS_COMPILER_H__ */ -- cgit From 3978adceba8ce3861097747868da22bce379edd2 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 29 Oct 2015 14:24:29 +0200 Subject: some bug fixes: 1. added a active bit to all the active nodes - when a stop arrives it invalidates them for next time 2. some small flag issues in the stateless port --- src/stateless/cp/trex_stateless_port.cpp | 16 +++++++----- src/stateless/cp/trex_stateless_port.h | 2 +- src/stateless/dp/trex_stateless_dp_core.cpp | 40 +++++++++++++++++++++++------ src/stateless/dp/trex_stateless_dp_core.h | 9 +++++-- 4 files changed, 50 insertions(+), 17 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 3e6e256f..375d1f63 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -76,9 +76,6 @@ TrexStatelessPort::start_traffic(void) { return (RC_ERR_FAILED_TO_COMPILE_STREAMS); } - /* move the state to transmiting */ - m_port_state = PORT_STATE_TRANSMITTING; - /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj); @@ -87,15 +84,18 @@ TrexStatelessPort::start_traffic(void) { ring->Enqueue((CGenNode *)start_msg); + /* move the state to transmiting */ + m_port_state = PORT_STATE_TRANSMITTING; + return (RC_OK); } -void +TrexStatelessPort::rc_e TrexStatelessPort::stop_traffic(void) { /* real code goes here */ - if (m_port_state == PORT_STATE_TRANSMITTING) { - m_port_state = PORT_STATE_UP_IDLE; + if (m_port_state != PORT_STATE_TRANSMITTING) { + return (RC_ERR_BAD_STATE_FOR_OP); } /* generate a message to all the relevant DP cores to start transmitting */ @@ -105,6 +105,10 @@ TrexStatelessPort::stop_traffic(void) { CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); ring->Enqueue((CGenNode *)stop_msg); + + m_port_state = PORT_STATE_UP_IDLE; + + return (RC_OK); } /** diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 474fccf7..4851a4b5 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -62,7 +62,7 @@ public: * stop traffic * */ - void stop_traffic(void); + rc_e stop_traffic(void); /** * access the stream table diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index f64686d4..73387f0e 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -24,20 +24,27 @@ limitations under the License. #include +/** + * extended info for the stateless node + * TODO: + * static_assert(sizeof(dp_node_extended_info_st) <= sizeof(CGenNodeStateless::m_pad_end), "hello"); + */ typedef struct dp_node_extended_info_ { - double next_time_offset; + double next_time_offset; + uint8_t is_stream_active; + } dp_node_extended_info_st; TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; m_core = core; - m_state = STATE_IDLE; - CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp(); m_ring_from_cp = cp_dp->getRingCpToDp(thread_id); m_ring_to_cp = cp_dp->getRingDpToCp(thread_id); + + m_state = STATE_IDLE; } void @@ -57,17 +64,20 @@ TrexStatelessDpCore::start() { void TrexStatelessDpCore::handle_pkt_event(CGenNode *node) { - /* if port has stopped - no transmition */ - if (m_state == STATE_IDLE) { + //TODO: optimize the fast path here... + + CGenNodeStateless *node_sl = (CGenNodeStateless *)node; + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node_sl->get_opaque_storage(); + + /* is this stream active ? */ + if (!opaque->is_stream_active) { + m_core->free_node(node); return; } m_core->m_node_gen.m_v_if->send_node(node); - CGenNodeStateless *node_sl = (CGenNodeStateless *)node; - /* in case of continues */ - dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node_sl->get_opaque_storage(); node->m_time += opaque->next_time_offset; /* insert a new event */ @@ -92,6 +102,7 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); opaque->next_time_offset = 1.0 / pps; + opaque->is_stream_active = 1; /* allocate const mbuf */ rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); @@ -114,6 +125,10 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + /* keep track */ + m_active_nodes.push_back(node); + + /* schedule */ m_core->m_node_gen.add_node((CGenNode *)node); } @@ -126,6 +141,15 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { void TrexStatelessDpCore::stop_traffic() { + /* we cannot remove nodes not from the top of the queue so + for every active node - make sure next time + the scheduler invokes it, it will be free */ + for (auto node : m_active_nodes) { + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); + opaque->is_stream_active = 0; + } + m_active_nodes.clear(); + m_state = STATE_IDLE; } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index da8484a6..d95f7eeb 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -21,6 +21,8 @@ limitations under the License. #ifndef __TREX_STATELESS_DP_CORE_H__ #define __TREX_STATELESS_DP_CORE_H__ +#include + #include #include @@ -29,6 +31,7 @@ class TrexStatelessDpStart; class CFlowGenListPerThread; class CGenNode; class TrexStreamsCompiledObj; +class CGenNodeStateless; class TrexStatelessDpCore { @@ -85,11 +88,10 @@ public: } while ( true ) { - CGenNode * node; + CGenNode * node = NULL; if (m_ring_from_cp->Dequeue(node) != 0) { break; } - assert(node); TrexStatelessCpToDpMsgBase * msg = (TrexStatelessCpToDpMsgBase *)node; @@ -115,6 +117,9 @@ private: CNodeRing *m_ring_from_cp; CNodeRing *m_ring_to_cp; + /* holds the current active nodes */ + std::vector m_active_nodes; + /* pointer to the main object */ CFlowGenListPerThread *m_core; }; -- cgit From 9a820782c35c6de79d2e724a48087e8ee62fc72d Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 29 Oct 2015 18:15:17 +0200 Subject: Hanoch's review comments #1 : fixed performancei issue with the stateless node --- src/stateless/dp/trex_stateless_dp_core.cpp | 43 ++---------- src/stateless/dp/trex_stateless_dp_core.h | 10 +-- src/stateless/dp/trex_stream_node.h | 104 ++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 48 deletions(-) create mode 100644 src/stateless/dp/trex_stream_node.h (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 73387f0e..9c10504e 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -21,20 +21,10 @@ limitations under the License. #include #include #include +#include #include -/** - * extended info for the stateless node - * TODO: - * static_assert(sizeof(dp_node_extended_info_st) <= sizeof(CGenNodeStateless::m_pad_end), "hello"); - */ -typedef struct dp_node_extended_info_ { - double next_time_offset; - uint8_t is_stream_active; - -} dp_node_extended_info_st; - TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; m_core = core; @@ -61,29 +51,6 @@ TrexStatelessDpCore::start() { } -void -TrexStatelessDpCore::handle_pkt_event(CGenNode *node) { - - //TODO: optimize the fast path here... - - CGenNodeStateless *node_sl = (CGenNodeStateless *)node; - dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node_sl->get_opaque_storage(); - - /* is this stream active ? */ - if (!opaque->is_stream_active) { - m_core->free_node(node); - return; - } - - m_core->m_node_gen.m_v_if->send_node(node); - - /* in case of continues */ - node->m_time += opaque->next_time_offset; - - /* insert a new event */ - m_core->m_node_gen.m_p_queue.push(node); -} - void TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pkt_len) { CGenNodeStateless *node = m_core->create_node_sl(); @@ -100,9 +67,8 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk uint16_t pkt_size = pkt_len; const uint8_t *stream_pkt = pkt; - dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); - opaque->next_time_offset = 1.0 / pps; - opaque->is_stream_active = 1; + node->m_next_time_offset = 1.0 / pps; + node->m_is_stream_active = 1; /* allocate const mbuf */ rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); @@ -145,8 +111,7 @@ TrexStatelessDpCore::stop_traffic() { for every active node - make sure next time the scheduler invokes it, it will be free */ for (auto node : m_active_nodes) { - dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); - opaque->is_stream_active = 0; + node->m_is_stream_active = 0; } m_active_nodes.clear(); diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index d95f7eeb..fa3c5b22 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -29,9 +29,8 @@ limitations under the License. class TrexStatelessCpToDpMsgBase; class TrexStatelessDpStart; class CFlowGenListPerThread; -class CGenNode; -class TrexStreamsCompiledObj; class CGenNodeStateless; +class TrexStreamsCompiledObj; class TrexStatelessDpCore { @@ -51,13 +50,6 @@ public: */ void start(); - /** - * handle pkt event - * - * @author imarom (27-Oct-15) - */ - void handle_pkt_event(CGenNode *node); - /** * dummy traffic creator * diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h new file mode 100644 index 00000000..49481a5c --- /dev/null +++ b/src/stateless/dp/trex_stream_node.h @@ -0,0 +1,104 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STREAM_NODE_H__ +#define __TREX_STREAM_NODE_H__ + +#include + +class TrexStatelessDpCore; + +/* this is a event for stateless */ +struct CGenNodeStateless : public CGenNodeBase { +friend class TrexStatelessDpCore; + +private: + void * m_cache_mbuf; + + double m_next_time_offset; + uint8_t m_is_stream_active; + + /* pad to match the size of CGenNode */ + uint8_t m_pad_end[39]; + + +public: + + inline bool is_active() { + return m_is_stream_active; + } + + + /** + * main function to handle an event of a packet tx + * + */ + inline void handle(CFlowGenListPerThread *thread) { + + thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); + + /* in case of continues */ + m_time += m_next_time_offset; + + /* insert a new event */ + thread->m_node_gen.m_p_queue.push( (CGenNode *)this); + } + + void set_socket_id(socket_id_t socket){ + m_socket_id=socket; + } + + socket_id_t get_socket_id(){ + return ( m_socket_id ); + } + + inline void set_mbuf_cache_dir(pkt_dir_t dir){ + if (dir) { + m_flags |=NODE_FLAGS_DIR; + }else{ + m_flags &=~NODE_FLAGS_DIR; + } + } + + inline pkt_dir_t get_mbuf_cache_dir(){ + return ((pkt_dir_t)( m_flags &1)); + } + + + + inline void set_cache_mbuf(rte_mbuf_t * m){ + m_cache_mbuf=(void *)m; + m_flags |= NODE_FLAGS_MBUF_CACHE; + } + + inline rte_mbuf_t * get_cache_mbuf(){ + if ( m_flags &NODE_FLAGS_MBUF_CACHE ) { + return ((rte_mbuf_t *)m_cache_mbuf); + }else{ + return ((rte_mbuf_t *)0); + } + } + + +} __rte_cache_aligned; ; + +static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)"); + +#endif /* __TREX_STREAM_NODE_H__ */ -- cgit From a1971ec3a7f6cbe0aea1393a57aa17bf44deedac Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 1 Nov 2015 10:20:16 +0200 Subject: DP stop message now disables only port related nodes and not all of them --- src/stateless/cp/trex_stateless_port.cpp | 4 ++-- src/stateless/cp/trex_streams_compiler.cpp | 4 ++++ src/stateless/cp/trex_streams_compiler.h | 5 ++++- src/stateless/dp/trex_stateless_dp_core.cpp | 24 ++++++++++++++++------ src/stateless/dp/trex_stateless_dp_core.h | 2 +- src/stateless/dp/trex_stream_node.h | 5 +++-- .../messaging/trex_stateless_messaging.cpp | 2 +- src/stateless/messaging/trex_stateless_messaging.h | 7 +++++++ 8 files changed, 40 insertions(+), 13 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 375d1f63..feea5ed5 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -69,7 +69,7 @@ TrexStatelessPort::start_traffic(void) { /* compiler it */ TrexStreamsCompiler compiler; - TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(); + TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id); bool rc = compiler.compile(streams, *compiled_obj); if (!rc) { @@ -99,7 +99,7 @@ TrexStatelessPort::stop_traffic(void) { } /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(); + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); // FIXME (add the right core list) CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 6c77ad0f..2e544995 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -26,6 +26,9 @@ limitations under the License. /************************************** * stream compiled object *************************************/ +TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id) : m_port_id(port_id) { +} + TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { for (auto &obj : m_objs) { delete obj.m_pkt; @@ -37,6 +40,7 @@ void TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len) { obj_st obj; + obj.m_port_id = m_port_id; obj.m_pps = pps; obj.m_pkt_len = pkt_len; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 90253cdf..82318dec 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -36,13 +36,14 @@ class TrexStreamsCompiledObj { friend class TrexStreamsCompiler; public: - TrexStreamsCompiledObj() {} + TrexStreamsCompiledObj(uint8_t port_id); ~TrexStreamsCompiledObj(); struct obj_st { double m_pps; uint8_t *m_pkt; uint16_t m_pkt_len; + uint8_t m_port_id; }; const std::vector & get_objects() { @@ -52,6 +53,8 @@ public: private: void add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len); std::vector m_objs; + + uint8_t m_port_id; }; class TrexStreamsCompiler { diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 9c10504e..fd54256d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -89,13 +89,14 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk /* set the packet as a readonly */ node->set_cache_mbuf(m); - m_state = TrexStatelessDpCore::STATE_TRANSMITTING; - /* keep track */ m_active_nodes.push_back(node); /* schedule */ m_core->m_node_gen.add_node((CGenNode *)node); + + m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + } void @@ -106,16 +107,27 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { } void -TrexStatelessDpCore::stop_traffic() { +TrexStatelessDpCore::stop_traffic(uint8_t port_id) { /* we cannot remove nodes not from the top of the queue so for every active node - make sure next time the scheduler invokes it, it will be free */ for (auto node : m_active_nodes) { - node->m_is_stream_active = 0; + if (node->m_port_id == port_id) { + node->m_is_stream_active = 0; + } } - m_active_nodes.clear(); - m_state = STATE_IDLE; + /* remove all the non active nodes */ + auto pred = std::remove_if(m_active_nodes.begin(), + m_active_nodes.end(), + [](CGenNodeStateless *node) { return (!node->m_is_stream_active); }); + + m_active_nodes.erase(pred, m_active_nodes.end()); + + if (m_active_nodes.size() == 0) { + m_state = STATE_IDLE; + } + } /** diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index fa3c5b22..b71431ad 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -64,7 +64,7 @@ public: * stop all traffic for this core * */ - void stop_traffic(); + void stop_traffic(uint8_t port_id); /** * check for and handle messages from CP diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 49481a5c..92b428ab 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -34,9 +34,10 @@ private: double m_next_time_offset; uint8_t m_is_stream_active; + uint8_t m_port_id; /* pad to match the size of CGenNode */ - uint8_t m_pad_end[39]; + uint8_t m_pad_end[87]; public: @@ -97,7 +98,7 @@ public: } -} __rte_cache_aligned; ; +} __rte_cache_aligned; static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)"); diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 3c6a5933..3e754649 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -47,7 +47,7 @@ TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { ************************/ bool TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { - dp_core->stop_traffic(); + dp_core->stop_traffic(m_port_id); return true; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 13f6c05a..381e146d 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -72,7 +72,14 @@ private: */ class TrexStatelessDpStop : public TrexStatelessCpToDpMsgBase { public: + + TrexStatelessDpStop(uint8_t port_id) : m_port_id(port_id) { + } + virtual bool handle(TrexStatelessDpCore *dp_core); + +private: + uint8_t m_port_id; }; -- cgit From ee2c7f45e0bf973443b70eb8329811bcad44f83a Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 1 Nov 2015 14:28:28 +0200 Subject: stateless cores starts on IDLE - and starts the scheduler only when traffic is being transmitted if the traffic stops completely on the core - back to IDLE state --- src/stateless/dp/trex_stateless_dp_core.cpp | 44 +++++++++++++++++++++++++++-- src/stateless/dp/trex_stateless_dp_core.h | 13 +++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index fd54256d..306b23d0 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -37,9 +37,30 @@ TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThrea m_state = STATE_IDLE; } -void -TrexStatelessDpCore::start() { +/** + * in idle state loop, the processor most of the time sleeps + * and periodically checks for messages + * + * @author imarom (01-Nov-15) + */ +void +TrexStatelessDpCore::idle_state_loop() { + while (m_state == STATE_IDLE) { + periodic_check_for_cp_messages(); + delay(200); + } +} + +/** + * scehduler runs when traffic exists + * it will return when no more transmitting is done on this + * core + * + * @author imarom (01-Nov-15) + */ +void +TrexStatelessDpCore::start_scheduler() { /* creates a maintenace job using the scheduler */ CGenNode * node_sync = m_core->create_node() ; node_sync->m_type = CGenNode::FLOW_SYNC; @@ -48,7 +69,16 @@ TrexStatelessDpCore::start() { double old_offset = 0.0; m_core->m_node_gen.flush_file(100000000, 0.0, false, m_core, old_offset); +} + +void +TrexStatelessDpCore::start() { + + while (true) { + idle_state_loop(); + start_scheduler(); + } } void @@ -126,6 +156,16 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { if (m_active_nodes.size() == 0) { m_state = STATE_IDLE; + /* stop the scheduler */ + + CGenNode *node = m_core->create_node() ; + + node->m_type = CGenNode::EXIT_SCHED; + + /* make sure it will be scheduled after the current node */ + node->m_time = m_core->m_node_gen.m_p_queue.top()->m_time; + + m_core->m_node_gen.add_node(node); } } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index b71431ad..698cac2f 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -93,6 +93,19 @@ public: } private: + /** + * in idle state loop, the processor most of the time sleeps + * and periodically checks for messages + * + */ + void idle_state_loop(); + + /** + * real job is done when scheduler is launched + * + */ + void start_scheduler(); + /** * handles a CP to DP message * -- cgit From eacf2829c309011bf15d56b7b531b22ebeaf4d7d Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 1 Nov 2015 17:29:07 +0200 Subject: added support for 'mul' field in start_traffic RPC command --- src/stateless/cp/trex_stateless_port.cpp | 4 ++-- src/stateless/cp/trex_stateless_port.h | 2 +- src/stateless/cp/trex_streams_compiler.cpp | 4 ++-- src/stateless/cp/trex_streams_compiler.h | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index feea5ed5..a0b57b63 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -53,7 +53,7 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { * */ TrexStatelessPort::rc_e -TrexStatelessPort::start_traffic(void) { +TrexStatelessPort::start_traffic(double mul) { if (m_port_state != PORT_STATE_UP_IDLE) { return (RC_ERR_BAD_STATE_FOR_OP); @@ -69,7 +69,7 @@ TrexStatelessPort::start_traffic(void) { /* compiler it */ TrexStreamsCompiler compiler; - TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id); + TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, mul); bool rc = compiler.compile(streams, *compiled_obj); if (!rc) { diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 4851a4b5..79bde01b 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -56,7 +56,7 @@ public: * start traffic * */ - rc_e start_traffic(void); + rc_e start_traffic(double mul); /** * stop traffic diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 2e544995..5e2602ec 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -26,7 +26,7 @@ limitations under the License. /************************************** * stream compiled object *************************************/ -TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id) : m_port_id(port_id) { +TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) { } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { @@ -41,7 +41,7 @@ TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t p obj_st obj; obj.m_port_id = m_port_id; - obj.m_pps = pps; + obj.m_pps = pps * m_mul; obj.m_pkt_len = pkt_len; obj.m_pkt = new uint8_t[pkt_len]; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 82318dec..06f992ed 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -36,7 +36,7 @@ class TrexStreamsCompiledObj { friend class TrexStreamsCompiler; public: - TrexStreamsCompiledObj(uint8_t port_id); + TrexStreamsCompiledObj(uint8_t port_id, double m_mul); ~TrexStreamsCompiledObj(); struct obj_st { @@ -55,6 +55,7 @@ private: std::vector m_objs; uint8_t m_port_id; + double m_mul; }; class TrexStreamsCompiler { -- cgit From 7d7767e17b1a4e54a8934ded724f54dc5b6228ce Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 1 Nov 2015 18:03:17 +0200 Subject: added support for a new RPC command : sync_user provides a way to sync a console / GUI to the server for a specific user --- src/stateless/cp/trex_stateless.h | 4 ++++ src/stateless/cp/trex_stateless_port.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 758707a2..57c6ef1d 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -150,6 +150,10 @@ public: return (m_platform_api); } + const std::vector get_port_list() { + return m_ports; + } + protected: /* no copy or assignment */ diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 79bde01b..3e071954 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -142,6 +142,10 @@ public: */ void encode_stats(Json::Value &port); + uint8_t get_port_id() { + return m_port_id; + } + private: std::string generate_handler(); -- cgit From c0a49eef86df00d9497fa5701d5b9d4cbf4bacc2 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 3 Nov 2015 16:29:07 +0200 Subject: now support multiple interfaces / ports --- src/stateless/cp/trex_stateless_port.cpp | 28 ++++++++++++++++++++-------- src/stateless/cp/trex_stateless_port.h | 4 ++++ src/stateless/cp/trex_streams_compiler.cpp | 12 +++++++----- src/stateless/cp/trex_streams_compiler.h | 3 ++- src/stateless/dp/trex_stateless_dp_core.cpp | 26 ++++++++++++++++++++++---- src/stateless/dp/trex_stateless_dp_core.h | 6 +++++- 6 files changed, 60 insertions(+), 19 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index a0b57b63..a64ee92f 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -36,6 +36,9 @@ limitations under the License. #include #include +void +port_id_to_cores(uint8_t port_id, std::vector> &cores_id_list); + using namespace std; /*************************** @@ -79,10 +82,7 @@ TrexStatelessPort::start_traffic(double mul) { /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj); - // FIXME (add the right core list) - CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); - - ring->Enqueue((CGenNode *)start_msg); + send_message_to_dp(start_msg); /* move the state to transmiting */ m_port_state = PORT_STATE_TRANSMITTING; @@ -101,10 +101,7 @@ TrexStatelessPort::stop_traffic(void) { /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); - // FIXME (add the right core list) - CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); - - ring->Enqueue((CGenNode *)stop_msg); + send_message_to_dp(stop_msg); m_port_state = PORT_STATE_UP_IDLE; @@ -191,3 +188,18 @@ TrexStatelessPort::encode_stats(Json::Value &port) { port["tx_rx_errors"] = Json::Value::UInt64(stats.m_stats.m_tx_rx_errors); } +void +TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) { + + std::vector> cores_id_list; + + get_stateless_obj()->get_platform_api()->port_id_to_cores(m_port_id, cores_id_list); + + for (auto core_pair : cores_id_list) { + + /* send the message to the core */ + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_pair.first); + ring->Enqueue((CGenNode *)msg); + } + +} diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 3e071954..09183768 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -23,6 +23,8 @@ limitations under the License. #include +class TrexStatelessCpToDpMsgBase; + /** * describes a stateless port * @@ -150,6 +152,8 @@ private: std::string generate_handler(); + void send_message_to_dp(TrexStatelessCpToDpMsgBase *msg); + TrexStreamTable m_stream_table; uint8_t m_port_id; port_state_e m_port_state; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 5e2602ec..f394b971 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -37,12 +37,13 @@ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { } void -TrexStreamsCompiledObj::add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len) { +TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len) { obj_st obj; - obj.m_port_id = m_port_id; - obj.m_pps = pps * m_mul; - obj.m_pkt_len = pkt_len; + obj.m_isg_usec = isg_usec; + obj.m_port_id = m_port_id; + obj.m_pps = pps * m_mul; + obj.m_pkt_len = pkt_len; obj.m_pkt = new uint8_t[pkt_len]; memcpy(obj.m_pkt, pkt, pkt_len); @@ -75,7 +76,8 @@ TrexStreamsCompiler::compile(const std::vector &streams, TrexStrea } /* add it */ - obj.add_compiled_stream(cont_stream->get_pps(), + obj.add_compiled_stream(cont_stream->m_isg_usec, + cont_stream->get_pps(), cont_stream->m_pkt.binary, cont_stream->m_pkt.len); } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 06f992ed..752f76b2 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -40,6 +40,7 @@ public: ~TrexStreamsCompiledObj(); struct obj_st { + double m_isg_usec; double m_pps; uint8_t *m_pkt; uint16_t m_pkt_len; @@ -51,7 +52,7 @@ public: } private: - void add_compiled_stream(double pps, uint8_t *pkt, uint16_t pkt_len); + void add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len); std::vector m_objs; uint8_t m_port_id; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 306b23d0..5f4e553a 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -25,6 +25,11 @@ limitations under the License. #include +static inline double +usec_to_sec(double usec) { + return (usec / (1000 * 1000)); +} + TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; m_core = core; @@ -82,12 +87,20 @@ TrexStatelessDpCore::start() { } void -TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pkt_len) { +TrexStatelessDpCore::add_cont_stream(uint8_t port_id, + double isg_usec, + double pps, + const uint8_t *pkt, + uint16_t pkt_len) { + CGenNodeStateless *node = m_core->create_node_sl(); /* add periodic */ node->m_type = CGenNode::STATELESS_PKT; - node->m_time = m_core->m_cur_time_sec + 0.0 /* STREAM ISG */; + + node->m_time = m_core->m_cur_time_sec + usec_to_sec(isg_usec); + + pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(port_id); node->m_flags = 0; /* set socket id */ @@ -97,8 +110,10 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk uint16_t pkt_size = pkt_len; const uint8_t *stream_pkt = pkt; + /* stateless specific fields */ node->m_next_time_offset = 1.0 / pps; node->m_is_stream_active = 1; + node->m_port_id = port_id; /* allocate const mbuf */ rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); @@ -110,7 +125,6 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk memcpy(p,stream_pkt,pkt_size); /* set dir 0 or 1 client or server */ - pkt_dir_t dir = 0; node->set_mbuf_cache_dir(dir); /* TBD repace the mac if req we should add flag */ @@ -132,7 +146,11 @@ TrexStatelessDpCore::add_cont_stream(double pps, const uint8_t *pkt, uint16_t pk void TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { for (auto single_stream : obj->get_objects()) { - add_cont_stream(single_stream.m_pps, single_stream.m_pkt, single_stream.m_pkt_len); + add_cont_stream(single_stream.m_port_id, + single_stream.m_isg_usec, + single_stream.m_pps, + single_stream.m_pkt, + single_stream.m_pkt_len); } } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 698cac2f..f3b5ff62 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -115,7 +115,11 @@ private: */ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); - void add_cont_stream(double pps, const uint8_t *pkt, uint16_t pkt_len); + void add_cont_stream(uint8_t dir, + double isg, + double pps, + const uint8_t *pkt, + uint16_t pkt_len); uint8_t m_thread_id; state_e m_state; -- cgit From 6b241b37b4c0cd462c158c2dad28009ea817cd86 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 3 Nov 2015 17:45:44 +0200 Subject: support for multicore --- src/stateless/cp/trex_stateless_port.cpp | 2 +- src/stateless/cp/trex_streams_compiler.cpp | 19 ++++++++++++++++ src/stateless/cp/trex_streams_compiler.h | 6 ++++++ .../messaging/trex_stateless_messaging.cpp | 25 ++++++++++++++++++++++ src/stateless/messaging/trex_stateless_messaging.h | 15 +++++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index a64ee92f..3a8d2c14 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -199,7 +199,7 @@ TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) { /* send the message to the core */ CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_pair.first); - ring->Enqueue((CGenNode *)msg); + ring->Enqueue((CGenNode *)msg->clone()); } } diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index f394b971..06c0119a 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -51,6 +51,24 @@ TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t m_objs.push_back(obj); } +TrexStreamsCompiledObj * +TrexStreamsCompiledObj::clone() { + + TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id, m_mul); + + /** + * clone each element + */ + for (auto obj : m_objs) { + new_compiled_obj->add_compiled_stream(obj.m_isg_usec, + obj.m_pps, + obj.m_pkt, + obj.m_pkt_len); + } + + return new_compiled_obj; +} + /************************************** * stream compiler *************************************/ @@ -85,3 +103,4 @@ TrexStreamsCompiler::compile(const std::vector &streams, TrexStrea return true; } + diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 752f76b2..404fdd21 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -51,6 +51,12 @@ public: return m_objs; } + /** + * clone the compiled object + * + */ + TrexStreamsCompiledObj * clone(); + private: void add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len); std::vector m_objs; diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 3e754649..032559bc 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -29,6 +29,21 @@ limitations under the License. TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj) : m_obj(obj) { } + +/** + * clone for DP start message + * + */ +TrexStatelessCpToDpMsgBase * +TrexStatelessDpStart::clone() { + + TrexStreamsCompiledObj *new_obj = m_obj->clone(); + + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(new_obj); + + return new_msg; +} + TrexStatelessDpStart::~TrexStatelessDpStart() { if (m_obj) { delete m_obj; @@ -51,3 +66,13 @@ TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { return true; } +/** + * clone for DP stop message + * + */ +TrexStatelessCpToDpMsgBase * +TrexStatelessDpStop::clone() { + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStop(m_port_id); + + return new_msg; +} diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 381e146d..7978b7f9 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -45,6 +45,17 @@ public: * */ virtual bool handle(TrexStatelessDpCore *dp_core) = 0; + + + /** + * clone the current message + * + */ + virtual TrexStatelessCpToDpMsgBase * clone() = 0; + + /* no copy constructor */ + TrexStatelessCpToDpMsgBase(TrexStatelessCpToDpMsgBase &) = delete; + }; /** @@ -61,6 +72,8 @@ public: virtual bool handle(TrexStatelessDpCore *dp_core); + virtual TrexStatelessCpToDpMsgBase * clone(); + private: TrexStreamsCompiledObj *m_obj; }; @@ -78,6 +91,8 @@ public: virtual bool handle(TrexStatelessDpCore *dp_core); + virtual TrexStatelessCpToDpMsgBase * clone(); + private: uint8_t m_port_id; }; -- cgit From bc7d9ee81604fd33607569ac4f03ca8b91777b29 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 8 Nov 2015 11:39:09 +0200 Subject: code review notes: 1. performance improvement for stateless DP core object (direct object) 2. exit scheduler loop is now using a scheduled message and not IF 3. duration for inifinite is negative number 4. fixed stop_traffic scheduled node time --- src/stateless/dp/trex_stateless_dp_core.cpp | 16 +++++++++------- src/stateless/dp/trex_stateless_dp_core.h | 13 ++++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 5f4e553a..35ce43a8 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -30,7 +30,9 @@ usec_to_sec(double usec) { return (usec / (1000 * 1000)); } -TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { + +void +TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; m_core = core; @@ -73,7 +75,7 @@ TrexStatelessDpCore::start_scheduler() { m_core->m_node_gen.add_node(node_sync); double old_offset = 0.0; - m_core->m_node_gen.flush_file(100000000, 0.0, false, m_core, old_offset); + m_core->m_node_gen.flush_file(-1, 0.0, false, m_core, old_offset); } void @@ -176,14 +178,14 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { m_state = STATE_IDLE; /* stop the scheduler */ - CGenNode *node = m_core->create_node() ; + CGenNode *node = m_core->create_node() ; - node->m_type = CGenNode::EXIT_SCHED; + node->m_type = CGenNode::EXIT_SCHED; - /* make sure it will be scheduled after the current node */ - node->m_time = m_core->m_node_gen.m_p_queue.top()->m_time; + /* make sure it will be scheduled after the current node */ + node->m_time = m_core->m_cur_time_sec + 0.0001; - m_core->m_node_gen.add_node(node); + m_core->m_node_gen.add_node(node); } } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index f3b5ff62..f4dbad08 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -42,7 +42,18 @@ public: STATE_TRANSMITTING }; - TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core); + TrexStatelessDpCore() { + m_thread_id = 0; + m_core = NULL; + } + + /** + * "static constructor" + * + * @param thread_id + * @param core + */ + void create(uint8_t thread_id, CFlowGenListPerThread *core); /** * launch the stateless DP core code -- cgit From 5021dd5d8338e24557038d6c4ddc2f666d677903 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 8 Nov 2015 16:37:44 +0200 Subject: tests golden were updated because main loop exit model has changed (sometimes one more packet was written to the dump file) --- src/stateless/dp/trex_stateless_dp_core.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 35ce43a8..b2bd0152 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -76,6 +76,7 @@ TrexStatelessDpCore::start_scheduler() { double old_offset = 0.0; m_core->m_node_gen.flush_file(-1, 0.0, false, m_core, old_offset); + m_core->m_node_gen.close_file(m_core); } void -- cgit From 67bcc46be09049d2ca65c0af2aa6a2fe0821eb04 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 9 Nov 2015 10:40:11 +0200 Subject: DPDK target is now built with -Wall -Werror (with few expections) on both Fedora 18 and Ubunutu --- src/stateless/cp/trex_stateless_port.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 3a8d2c14..cb6fcc0e 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -27,9 +27,16 @@ limitations under the License. #include #ifndef TREX_RPC_MOCK_SERVER + // DPDK c++ issue -#define UINT8_MAX 255 -#define UINT16_MAX 0xFFFF +#ifndef UINT8_MAX + #define UINT8_MAX 255 +#endif + +#ifndef UINT16_MAX + #define UINT16_MAX 0xFFFF +#endif + // DPDK c++ issue #endif -- cgit From 9c32c36b6006d2a81e1a5658a1fb1616eff650f3 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 9 Nov 2015 17:10:24 +0200 Subject: moved logic to the port class also implemented the state machine for CP port --- src/stateless/cp/trex_stateless_port.cpp | 143 ++++++++++++++++++++++++------- src/stateless/cp/trex_stateless_port.h | 128 +++++++++++++++++++++------ 2 files changed, 214 insertions(+), 57 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index cb6fcc0e..b9206775 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -53,29 +53,47 @@ using namespace std; * **************************/ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { - m_port_state = PORT_STATE_UP_IDLE; + m_port_state = PORT_STATE_IDLE; clear_owner(); } +/** + * acquire the port + * + * @author imarom (09-Nov-15) + * + * @param user + * @param force + */ +void +TrexStatelessPort::acquire(const std::string &user, bool force) { + if ( (!is_free_to_aquire()) && (get_owner() != user) && (!force)) { + throw TrexRpcException("port is already taken by '" + get_owner() + "'"); + } + + set_owner(user); +} + +void +TrexStatelessPort::release(void) { + verify_state( ~(PORT_STATE_TX | PORT_STATE_PAUSE) ); + clear_owner(); +} + /** * starts the traffic on the port * */ -TrexStatelessPort::rc_e +void TrexStatelessPort::start_traffic(double mul) { - 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); - } + /* command allowed only on state stream */ + verify_state(PORT_STATE_STREAMS); /* fetch all the streams from the table */ vector streams; - get_stream_table()->get_object_list(streams); + get_object_list(streams); /* compiler it */ TrexStreamsCompiler compiler; @@ -83,7 +101,7 @@ TrexStatelessPort::start_traffic(double mul) { bool rc = compiler.compile(streams, *compiled_obj); if (!rc) { - return (RC_ERR_FAILED_TO_COMPILE_STREAMS); + throw TrexRpcException("Failed to compile streams"); } /* generate a message to all the relevant DP cores to start transmitting */ @@ -91,51 +109,94 @@ TrexStatelessPort::start_traffic(double mul) { send_message_to_dp(start_msg); - /* move the state to transmiting */ - m_port_state = PORT_STATE_TRANSMITTING; - - return (RC_OK); + change_state(PORT_STATE_TX); } -TrexStatelessPort::rc_e +/** + * stop traffic on port + * + * @author imarom (09-Nov-15) + * + * @return TrexStatelessPort::rc_e + */ +void TrexStatelessPort::stop_traffic(void) { - /* real code goes here */ - if (m_port_state != PORT_STATE_TRANSMITTING) { - return (RC_ERR_BAD_STATE_FOR_OP); - } + verify_state(PORT_STATE_TX); /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); send_message_to_dp(stop_msg); - m_port_state = PORT_STATE_UP_IDLE; + change_state(PORT_STATE_STREAMS); +} + +void +TrexStatelessPort::pause_traffic(void) { + + verify_state(PORT_STATE_TX); + + #if 0 + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); - return (RC_OK); + send_message_to_dp(stop_msg); + + m_port_state = PORT_STATE_UP_IDLE; + #endif + change_state(PORT_STATE_PAUSE); } -/** -* access the stream table -* -*/ -TrexStreamTable * TrexStatelessPort::get_stream_table() { - return &m_stream_table; +void +TrexStatelessPort::resume_traffic(void) { + + verify_state(PORT_STATE_PAUSE); + + #if 0 + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + + send_message_to_dp(stop_msg); + + m_port_state = PORT_STATE_UP_IDLE; + #endif + change_state(PORT_STATE_TX); } +void +TrexStatelessPort::update_traffic(double mul) { + + verify_state(PORT_STATE_STREAMS | PORT_STATE_TX | PORT_STATE_PAUSE); + + #if 0 + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + + send_message_to_dp(stop_msg); + + m_port_state = PORT_STATE_UP_IDLE; + #endif +} std::string -TrexStatelessPort::get_state_as_string() { +TrexStatelessPort::get_state_as_string() const { switch (get_state()) { case PORT_STATE_DOWN: return "down"; - case PORT_STATE_UP_IDLE: - return "idle"; + case PORT_STATE_IDLE: + return "no streams"; + + case PORT_STATE_STREAMS: + return "with streams, idle"; - case PORT_STATE_TRANSMITTING: + case PORT_STATE_TX: return "transmitting"; + + case PORT_STATE_PAUSE: + return "paused"; } return "unknown"; @@ -149,6 +210,24 @@ TrexStatelessPort::get_properties(string &driver, string &speed) { speed = "1 Gbps"; } +bool +TrexStatelessPort::verify_state(int state, bool should_throw) const { + if ( (state & m_port_state) == 0 ) { + if (should_throw) { + throw TrexRpcException("command cannot be executed on current state: '" + get_state_as_string() + "'"); + } else { + return false; + } + } + + return true; +} + +void +TrexStatelessPort::change_state(port_state_e new_state) { + + m_port_state = new_state; +} /** * generate a random connection handler diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 09183768..90bf936e 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -37,9 +37,11 @@ public: * port state */ enum port_state_e { - PORT_STATE_DOWN, - PORT_STATE_UP_IDLE, - PORT_STATE_TRANSMITTING + PORT_STATE_DOWN = 0x1, + PORT_STATE_IDLE = 0x2, + PORT_STATE_STREAMS = 0x4, + PORT_STATE_TX = 0x8, + PORT_STATE_PAUSE = 0x10, }; /** @@ -53,30 +55,54 @@ public: }; TrexStatelessPort(uint8_t port_id); + + /** + * acquire port + * throws TrexException in case of an error + */ + void acquire(const std::string &user, bool force = false); + + /** + * release the port from the current user + * throws TrexException in case of an error + */ + void release(void); /** * start traffic - * + * throws TrexException in case of an error */ - rc_e start_traffic(double mul); + void start_traffic(double mul); /** * stop traffic - * + * throws TrexException in case of an error + */ + void stop_traffic(void); + + /** + * pause traffic + * throws TrexException in case of an error */ - rc_e stop_traffic(void); + void pause_traffic(void); /** - * access the stream table + * resume traffic + * throws TrexException in case of an error + */ + void resume_traffic(void); + + /** + * update current traffic on port * */ - TrexStreamTable *get_stream_table(); + void update_traffic(double mul); /** * get the port state * */ - port_state_e get_state() { + port_state_e get_state() const { return m_port_state; } @@ -84,7 +110,7 @@ public: * port state as string * */ - std::string get_state_as_string(); + std::string get_state_as_string() const; /** * fill up properties of the port @@ -96,6 +122,7 @@ public: */ void get_properties(std::string &driver, std::string &speed); + /** * query for ownership * @@ -113,10 +140,69 @@ public: return m_owner_handler; } - bool is_free_to_aquire() { - return (m_owner == "none"); + + bool verify_owner_handler(const std::string &handler) { + + return ( (m_owner != "none") && (m_owner_handler == handler) ); + } + /** + * encode stats as JSON + */ + void encode_stats(Json::Value &port); + + uint8_t get_port_id() { + return m_port_id; + } + + /** + * delegators + * + */ + + void add_stream(TrexStream *stream) { + verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS); + + m_stream_table.add_stream(stream); + + change_state(PORT_STATE_STREAMS); + } + + void remove_stream(TrexStream *stream) { + verify_state(PORT_STATE_STREAMS); + + m_stream_table.remove_stream(stream); + + if (m_stream_table.size() == 0) { + change_state(PORT_STATE_IDLE); + } + } + + void remove_and_delete_all_streams() { + verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS); + + m_stream_table.remove_and_delete_all_streams(); + + change_state(PORT_STATE_IDLE); + } + + TrexStream * get_stream_by_id(uint32_t stream_id) { + return m_stream_table.get_stream_by_id(stream_id); + } + + void get_id_list(std::vector &id_list) { + m_stream_table.get_id_list(id_list); + } + + void get_object_list(std::vector &object_list) { + m_stream_table.get_object_list(object_list); + } + +private: + + + /** * take ownership of the server array * this is static @@ -133,22 +219,14 @@ public: m_owner_handler = ""; } - bool verify_owner_handler(const std::string &handler) { - - return ( (m_owner != "none") && (m_owner_handler == handler) ); - + bool is_free_to_aquire() { + return (m_owner == "none"); } - /** - * encode stats as JSON - */ - void encode_stats(Json::Value &port); - uint8_t get_port_id() { - return m_port_id; - } + bool verify_state(int state, bool should_throw = true) const; -private: + void change_state(port_state_e new_state); std::string generate_handler(); -- cgit From 467382a7611f478d66cf58c1307f079239f7bac6 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 11 Nov 2015 13:48:02 +0200 Subject: lightweight console --- src/stateless/cp/trex_stateless_port.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index b9206775..907b9cf4 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -122,7 +122,9 @@ TrexStatelessPort::start_traffic(double mul) { void TrexStatelessPort::stop_traffic(void) { - verify_state(PORT_STATE_TX); + if (m_port_state != PORT_STATE_TX) { + return; + } /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); -- cgit From e9c6fde1c28b2c51ea164b0df929c9c44ee6f444 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 11 Nov 2015 14:54:33 +0200 Subject: a bug causing rate to be sqaure --- src/stateless/cp/trex_streams_compiler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 06c0119a..0b2549a0 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -54,7 +54,8 @@ TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t TrexStreamsCompiledObj * TrexStreamsCompiledObj::clone() { - TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id, m_mul); + /* use multiplier of 1 to avoid double mult */ + TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id, 1); /** * clone each element @@ -66,6 +67,9 @@ TrexStreamsCompiledObj::clone() { obj.m_pkt_len); } + /* fix the multiplier */ + new_compiled_obj->m_mul = m_mul; + return new_compiled_obj; } -- cgit From cc352e04fd45913132f3e1ddc86d88571c926879 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 11 Nov 2015 15:37:46 +0200 Subject: add first stl test and cleanup valgrind --- src/stateless/cp/trex_stream.h | 4 +- src/stateless/cp/trex_streams_compiler.cpp | 2 +- src/stateless/dp/trex_stateless_dp_core.cpp | 44 +++++++++++++++++++++- src/stateless/dp/trex_stateless_dp_core.h | 10 +++++ src/stateless/dp/trex_stream_node.h | 10 ++++- src/stateless/messaging/trex_stateless_messaging.h | 1 + 6 files changed, 65 insertions(+), 6 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index c8a15240..d1a44909 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -40,7 +40,7 @@ class TrexStream { public: TrexStream(uint8_t port_id, uint32_t stream_id); - virtual ~TrexStream() = 0; + virtual ~TrexStream(); /* defines the min max per packet supported */ static const uint32_t MIN_PKT_SIZE_BYTES = 1; @@ -88,6 +88,8 @@ public: /* original template provided by requester */ Json::Value m_stream_json; + + }; /** diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 06c0119a..667da158 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -31,7 +31,7 @@ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { for (auto &obj : m_objs) { - delete obj.m_pkt; + delete [] obj.m_pkt; } m_objs.clear(); } diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index b2bd0152..c9e47090 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -31,6 +31,18 @@ usec_to_sec(double usec) { } + +void CGenNodeStateless::free_stl_node(){ + /* if we have cache mbuf free it */ + rte_mbuf_t * m=get_cache_mbuf(); + if (m) { + rte_pktmbuf_free(m); + m_cache_mbuf=0; + } +} + + + void TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; @@ -79,16 +91,41 @@ TrexStatelessDpCore::start_scheduler() { m_core->m_node_gen.close_file(m_core); } + +void +TrexStatelessDpCore::run_once(){ + + idle_state_loop(); + start_scheduler(); +} + + void TrexStatelessDpCore::start() { while (true) { - idle_state_loop(); + run_once(); + } +} + +void +TrexStatelessDpCore::add_duration(uint8_t port_id, + double duration){ + if (duration > 0.0) { + + CGenNode *node = m_core->create_node() ; + + node->m_type = CGenNode::EXIT_SCHED; + + /* make sure it will be scheduled after the current node */ + node->m_time = m_core->m_cur_time_sec + duration ; + + m_core->m_node_gen.add_node(node); - start_scheduler(); } } + void TrexStatelessDpCore::add_cont_stream(uint8_t port_id, double isg_usec, @@ -155,6 +192,9 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { single_stream.m_pkt, single_stream.m_pkt_len); } + + /* TBD need to fix this */ + add_duration(0,10.0); } void diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index f4dbad08..a23e81c9 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -45,6 +45,7 @@ public: TrexStatelessDpCore() { m_thread_id = 0; m_core = NULL; + m_duration = -1; } /** @@ -61,6 +62,10 @@ public: */ void start(); + + /* exit after batch of commands */ + void run_once(); + /** * dummy traffic creator * @@ -126,6 +131,9 @@ private: */ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); + void add_duration(uint8_t port_id, + double duration); + void add_cont_stream(uint8_t dir, double isg, double pps, @@ -142,6 +150,8 @@ private: /* pointer to the main object */ CFlowGenListPerThread *m_core; + + double m_duration; }; #endif /* __TREX_STATELESS_DP_CORE_H__ */ diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 92b428ab..2ffe04c3 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -22,6 +22,7 @@ limitations under the License. #define __TREX_STREAM_NODE_H__ #include +#include class TrexStatelessDpCore; @@ -42,6 +43,7 @@ private: public: + inline bool is_active() { return m_is_stream_active; } @@ -82,8 +84,6 @@ public: return ((pkt_dir_t)( m_flags &1)); } - - inline void set_cache_mbuf(rte_mbuf_t * m){ m_cache_mbuf=(void *)m; m_flags |= NODE_FLAGS_MBUF_CACHE; @@ -97,6 +97,12 @@ public: } } + void free_stl_node(); + + + void Dump(FILE *fd){ + fprintf(fd," %f, %lu, %lu \n",m_time,(ulong)m_port_id,(ulong)get_mbuf_cache_dir()); + } } __rte_cache_aligned; diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 7978b7f9..d288fc83 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -74,6 +74,7 @@ public: virtual TrexStatelessCpToDpMsgBase * clone(); + private: TrexStreamsCompiledObj *m_obj; }; -- cgit From d5361e483d135e60b1b40a05b283cf704697504a Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 11 Nov 2015 15:48:44 +0200 Subject: remove default duration --- src/stateless/dp/trex_stateless_dp_core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index c9e47090..480606e8 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -194,7 +194,7 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { } /* TBD need to fix this */ - add_duration(0,10.0); + //add_duration(0,10.0); } void -- cgit From 6294136db42a3327049c67c12eab4684c4abbe47 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 11 Nov 2015 16:14:28 +0200 Subject: fix duration for stl tests --- src/stateless/cp/trex_streams_compiler.cpp | 4 +++- src/stateless/cp/trex_streams_compiler.h | 8 ++++++++ src/stateless/dp/trex_stateless_dp_core.cpp | 13 +++++++------ src/stateless/dp/trex_stateless_dp_core.h | 4 ++-- 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 8238bac7..7891077b 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -34,6 +34,7 @@ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { delete [] obj.m_pkt; } m_objs.clear(); + m_duration_sim=-1.0; } void @@ -67,9 +68,10 @@ TrexStreamsCompiledObj::clone() { obj.m_pkt_len); } - /* fix the multiplier */ new_compiled_obj->m_mul = m_mul; + new_compiled_obj->m_duration_sim = m_duration_sim; + return new_compiled_obj; } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 404fdd21..d86d16c6 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -51,6 +51,13 @@ public: return m_objs; } + void set_simulation_duration(double duration){ + m_duration_sim=duration; + } + + double get_simulation_duration(){ + return (m_duration_sim); + } /** * clone the compiled object * @@ -63,6 +70,7 @@ private: uint8_t m_port_id; double m_mul; + double m_duration_sim; /* duration for all simulation */ }; class TrexStreamsCompiler { diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 480606e8..e1664bd9 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -109,10 +109,8 @@ TrexStatelessDpCore::start() { } void -TrexStatelessDpCore::add_duration(uint8_t port_id, - double duration){ +TrexStatelessDpCore::add_duration(double duration){ if (duration > 0.0) { - CGenNode *node = m_core->create_node() ; node->m_type = CGenNode::EXIT_SCHED; @@ -121,7 +119,6 @@ TrexStatelessDpCore::add_duration(uint8_t port_id, node->m_time = m_core->m_cur_time_sec + duration ; m_core->m_node_gen.add_node(node); - } } @@ -193,8 +190,12 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { single_stream.m_pkt_len); } - /* TBD need to fix this */ - //add_duration(0,10.0); + double duration=obj->get_simulation_duration(); + printf("duration %f \n",duration); + + if ( duration >0.0){ + add_duration( duration ); + } } void diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index a23e81c9..51f882b2 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -131,8 +131,8 @@ private: */ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); - void add_duration(uint8_t port_id, - double duration); + /* add global exit */ + void add_duration(double duration); void add_cont_stream(uint8_t dir, double isg, -- cgit From 151266e34245b99ce4cac70d82be79bfb5a3ebf9 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 11 Nov 2015 22:10:05 +0200 Subject: add support for multi-burst --- src/stateless/cp/trex_stream.h | 42 +++++++++----- src/stateless/cp/trex_streams_compiler.cpp | 29 ++-------- src/stateless/cp/trex_streams_compiler.h | 13 +++-- src/stateless/dp/trex_stateless_dp_core.cpp | 61 +++++++++++++------ src/stateless/dp/trex_stateless_dp_core.h | 7 +-- src/stateless/dp/trex_stream_node.h | 90 ++++++++++++++++++++++++++--- 6 files changed, 166 insertions(+), 76 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index d1a44909..5e6ac19a 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -38,6 +38,15 @@ class TrexRpcCmdAddStream; */ class TrexStream { +public: + enum STREAM_TYPE { + stNONE = 0, + stCONTINUOUS = 4, + stSINGLE_BURST = 5, + stMULTI_BURST = 6 + }; + + public: TrexStream(uint8_t port_id, uint32_t stream_id); virtual ~TrexStream(); @@ -52,8 +61,14 @@ public: /* access the stream json */ const Json::Value & get_stream_json(); + double get_pps() { + return m_pps; + } + + public: /* basic */ + uint8_t m_type; uint8_t m_port_id; uint32_t m_stream_id; @@ -85,6 +100,8 @@ public: } m_rx_check; + double m_pps; + /* original template provided by requester */ Json::Value m_stream_json; @@ -98,15 +115,10 @@ public: */ class TrexStreamContinuous : public TrexStream { public: - TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) { + TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id) { + m_type= TrexStream::stCONTINUOUS; + m_pps=pps; } - - double get_pps() { - return m_pps; - } - -protected: - double m_pps; }; /** @@ -117,13 +129,14 @@ class TrexStreamBurst : public TrexStream { public: TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, double pps) : TrexStream(port_id, stream_id), - m_total_pkts(total_pkts), - m_pps(pps) { + m_total_pkts(total_pkts){ + m_type= TrexStream::stSINGLE_BURST; + m_pps=pps; + } -protected: +public: uint32_t m_total_pkts; - double m_pps; }; /** @@ -138,9 +151,10 @@ public: double pps, uint32_t num_bursts, double ibg_usec) : TrexStreamBurst(port_id, stream_id, pkts_per_burst, pps), m_num_bursts(num_bursts), m_ibg_usec(ibg_usec) { - + m_type= TrexStream::stMULTI_BURST; } -protected: + +public: uint32_t m_num_bursts; double m_ibg_usec; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 7891077b..c7b881c5 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -30,24 +30,15 @@ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_ } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { - for (auto &obj : m_objs) { - delete [] obj.m_pkt; - } m_objs.clear(); m_duration_sim=-1.0; } void -TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len) { +TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { obj_st obj; - obj.m_isg_usec = isg_usec; - obj.m_port_id = m_port_id; - obj.m_pps = pps * m_mul; - obj.m_pkt_len = pkt_len; - - obj.m_pkt = new uint8_t[pkt_len]; - memcpy(obj.m_pkt, pkt, pkt_len); + obj.m_stream = stream; m_objs.push_back(obj); } @@ -62,10 +53,7 @@ TrexStreamsCompiledObj::clone() { * clone each element */ for (auto obj : m_objs) { - new_compiled_obj->add_compiled_stream(obj.m_isg_usec, - obj.m_pps, - obj.m_pkt, - obj.m_pkt_len); + new_compiled_obj->add_compiled_stream(obj.m_stream); } new_compiled_obj->m_mul = m_mul; @@ -93,17 +81,8 @@ TrexStreamsCompiler::compile(const std::vector &streams, TrexStrea continue; } - /* for now support only continous ... */ - TrexStreamContinuous *cont_stream = dynamic_cast(stream); - if (!cont_stream) { - continue; - } - /* add it */ - obj.add_compiled_stream(cont_stream->m_isg_usec, - cont_stream->get_pps(), - cont_stream->m_pkt.binary, - cont_stream->m_pkt.len); + obj.add_compiled_stream(stream); } return true; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index d86d16c6..78ac1ac7 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -40,11 +40,8 @@ public: ~TrexStreamsCompiledObj(); struct obj_st { - double m_isg_usec; - double m_pps; - uint8_t *m_pkt; - uint16_t m_pkt_len; - uint8_t m_port_id; + + TrexStream * m_stream; }; const std::vector & get_objects() { @@ -64,8 +61,12 @@ public: */ TrexStreamsCompiledObj * clone(); + double get_multiplier(){ + return (m_mul); + } + private: - void add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len); + void add_compiled_stream(TrexStream * stream); std::vector m_objs; uint8_t m_port_id; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index e1664bd9..899e14be 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include #include @@ -124,33 +125,64 @@ TrexStatelessDpCore::add_duration(double duration){ void -TrexStatelessDpCore::add_cont_stream(uint8_t port_id, - double isg_usec, - double pps, - const uint8_t *pkt, - uint16_t pkt_len) { +TrexStatelessDpCore::add_cont_stream(TrexStream * stream, + TrexStreamsCompiledObj *comp) { CGenNodeStateless *node = m_core->create_node_sl(); /* add periodic */ node->m_type = CGenNode::STATELESS_PKT; - node->m_time = m_core->m_cur_time_sec + usec_to_sec(isg_usec); + node->m_time = m_core->m_cur_time_sec + usec_to_sec(stream->m_isg_usec); - pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(port_id); + pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(stream->m_port_id); node->m_flags = 0; /* set socket id */ node->set_socket_id(m_core->m_node_gen.m_socket_id); /* build a mbuf from a packet */ - uint16_t pkt_size = pkt_len; - const uint8_t *stream_pkt = pkt; + + uint16_t pkt_size = stream->m_pkt.len; + const uint8_t *stream_pkt = stream->m_pkt.binary; + + TrexStreamBurst * lpburst; + TrexStreamMultiBurst * lpmulti; + + node->m_stream_type = stream->m_type; + node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ; + /* stateless specific fields */ - node->m_next_time_offset = 1.0 / pps; + switch ( stream->m_type ) { + + case TrexStream::stCONTINUOUS : + break; + + case TrexStream::stSINGLE_BURST : + node->m_stream_type = TrexStream::stMULTI_BURST; + lpburst = (TrexStreamBurst *)stream; + node->m_single_burst = lpburst->m_total_pkts; + node->m_single_burst_refill = lpburst->m_total_pkts; + node->m_multi_bursts = 1; /* single burst in multi burst of 1 */ + node->m_ibg_sec = 0.0; + break; + + case TrexStream::stMULTI_BURST : + lpmulti =(TrexStreamMultiBurst *)stream; + + node->m_single_burst = lpmulti->m_total_pkts; + node->m_single_burst_refill = lpmulti->m_total_pkts ; + node->m_multi_bursts = lpmulti->m_num_bursts; + node->m_ibg_sec = usec_to_sec( lpmulti->m_ibg_usec ); + break; + default: + + assert(0); + }; + node->m_is_stream_active = 1; - node->m_port_id = port_id; + node->m_port_id = stream->m_port_id; /* allocate const mbuf */ rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); @@ -183,15 +215,10 @@ TrexStatelessDpCore::add_cont_stream(uint8_t port_id, void TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { for (auto single_stream : obj->get_objects()) { - add_cont_stream(single_stream.m_port_id, - single_stream.m_isg_usec, - single_stream.m_pps, - single_stream.m_pkt, - single_stream.m_pkt_len); + add_cont_stream(single_stream.m_stream,obj); } double duration=obj->get_simulation_duration(); - printf("duration %f \n",duration); if ( duration >0.0){ add_duration( duration ); diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 51f882b2..1029213d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -31,6 +31,7 @@ class TrexStatelessDpStart; class CFlowGenListPerThread; class CGenNodeStateless; class TrexStreamsCompiledObj; +class TrexStream; class TrexStatelessDpCore { @@ -134,11 +135,7 @@ private: /* add global exit */ void add_duration(double duration); - void add_cont_stream(uint8_t dir, - double isg, - double pps, - const uint8_t *pkt, - uint16_t pkt_len); + void add_cont_stream(TrexStream * stream,TrexStreamsCompiledObj *comp); uint8_t m_thread_id; state_e m_state; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 2ffe04c3..e4cf964d 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -25,6 +25,7 @@ limitations under the License. #include class TrexStatelessDpCore; +#include /* this is a event for stateless */ struct CGenNodeStateless : public CGenNodeBase { @@ -33,28 +34,51 @@ friend class TrexStatelessDpCore; private: void * m_cache_mbuf; - double m_next_time_offset; + double m_next_time_offset; /* in sec */ + double m_ibg_sec; /* inter burst time in sec */ + + uint8_t m_is_stream_active; uint8_t m_port_id; + uint8_t m_stream_type; /* TrexStream::STREAM_TYPE */ + uint8_t m_pad; + + uint32_t m_single_burst; /* the number of bursts in case of burst */ + uint32_t m_single_burst_refill; + + uint32_t m_multi_bursts; /* in case of multi_burst how many bursts */ + + /* pad to match the size of CGenNode */ - uint8_t m_pad_end[87]; + uint8_t m_pad_end[65]; public: + inline uint8_t get_stream_type(){ + return (m_stream_type); + } + + inline uint32_t get_single_burst_cnt(){ + return (m_single_burst); + } + + inline double get_multi_ibg_sec(){ + return (m_ibg_sec); + } + + inline uint32_t get_multi_burst_cnt(){ + return (m_multi_bursts); + } + inline bool is_active() { return m_is_stream_active; } - - /** - * main function to handle an event of a packet tx - * - */ - inline void handle(CFlowGenListPerThread *thread) { + inline void handle_continues(CFlowGenListPerThread *thread) { thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); /* in case of continues */ @@ -64,6 +88,51 @@ public: thread->m_node_gen.m_p_queue.push( (CGenNode *)this); } + inline void handle_multi_burst(CFlowGenListPerThread *thread) { + thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); + + m_single_burst--; + if (m_single_burst > 0 ) { + /* in case of continues */ + m_time += m_next_time_offset; + + thread->m_node_gen.m_p_queue.push( (CGenNode *)this); + }else{ + m_multi_bursts--; + if ( m_multi_bursts == 0 ) { + /* stop */ + m_is_stream_active =0; + }else{ + m_time += m_ibg_sec; + m_single_burst = m_single_burst_refill; + + } + thread->m_node_gen.m_p_queue.push( (CGenNode *)this); + } + } + + + /** + * main function to handle an event of a packet tx + * + * + * + */ + + inline void handle(CFlowGenListPerThread *thread) { + + if (m_stream_type == TrexStream::stCONTINUOUS ) { + handle_continues(thread) ; + }else{ + if (m_stream_type == TrexStream::stMULTI_BURST) { + handle_multi_burst(thread); + }else{ + assert(0); + } + } + + } + void set_socket_id(socket_id_t socket){ m_socket_id=socket; } @@ -106,6 +175,9 @@ public: } __rte_cache_aligned; -static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)"); +static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)" ); + + + #endif /* __TREX_STREAM_NODE_H__ */ -- cgit From 45b71cff9d0465b77f82e4cd40b64a9f3183c1c7 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 12 Nov 2015 15:33:30 +0200 Subject: refactor stream object --- src/stateless/cp/trex_stream.cpp | 9 +- src/stateless/cp/trex_stream.h | 132 ++++++++++++++++------------ src/stateless/cp/trex_streams_compiler.cpp | 7 +- src/stateless/dp/trex_stateless_dp_core.cpp | 18 ++-- 4 files changed, 93 insertions(+), 73 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index ba306137..1a05257c 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -25,9 +25,11 @@ limitations under the License. /************************************** * stream *************************************/ -TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { +TrexStream::TrexStream(uint8_t type, + uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { /* default values */ + m_type = type; m_isg_usec = 0; m_next_stream_id = -1; m_enabled = false; @@ -38,6 +40,11 @@ TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id) m_rx_check.m_enable = false; + + m_pps=-1.0; + m_burst_total_pkts=0; + m_num_bursts=1; + m_ibg_usec=0.0; } TrexStream::~TrexStream() { diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 5e6ac19a..151723ad 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -29,9 +29,28 @@ limitations under the License. #include #include +#include +#include class TrexRpcCmdAddStream; + +struct CStreamPktData { + uint8_t *binary; + uint16_t len; + + std::string meta; + +public: + inline void clone(uint8_t * in_binary, + uint32_t in_pkt_size){ + binary = new uint8_t[in_pkt_size]; + len = in_pkt_size; + memcpy(binary,in_binary,in_pkt_size); + } +}; + + /** * Stateless Stream * @@ -48,7 +67,7 @@ public: public: - TrexStream(uint8_t port_id, uint32_t stream_id); + TrexStream(uint8_t type,uint8_t port_id, uint32_t stream_id); virtual ~TrexStream(); /* defines the min max per packet supported */ @@ -65,6 +84,53 @@ public: return m_pps; } + void set_pps(double pps){ + m_pps = pps; + } + + void set_type(uint8_t type){ + m_type = type; + } + + uint8_t get_type(void){ + return ( m_type ); + } + + + + void set_multi_burst(uint32_t burst_total_pkts, + uint32_t num_bursts, + double ibg_usec){ + m_burst_total_pkts = burst_total_pkts; + m_num_bursts = num_bursts; + m_ibg_usec = ibg_usec; + } + + void set_signle_burtst(uint32_t burst_total_pkts){ + set_multi_burst(burst_total_pkts,1,0.0); + } + + /* create new stream */ + TrexStream * clone_as_dp(){ + TrexStream * dp=new TrexStream(m_type,m_port_id,m_stream_id); + + + dp->m_isg_usec = m_isg_usec; + dp->m_next_stream_id = m_next_stream_id; + + dp->m_enabled = m_enabled; + dp->m_self_start = m_self_start; + + /* deep copy */ + dp->m_pkt.clone(m_pkt.binary,m_pkt.len); + + dp->m_rx_check = m_rx_check; + dp->m_pps = m_pps; + dp->m_burst_total_pkts = m_burst_total_pkts; + dp->m_num_bursts = m_num_bursts; + dp->m_ibg_usec = m_ibg_usec ; + return (dp); + } public: /* basic */ @@ -80,13 +146,9 @@ public: /* indicators */ bool m_enabled; bool m_self_start; - + + CStreamPktData m_pkt; /* pkt */ - struct { - uint8_t *binary; - uint16_t len; - std::string meta; - } m_pkt; /* VM */ StreamVm m_vm; @@ -102,63 +164,17 @@ public: double m_pps; + uint32_t m_burst_total_pkts; /* valid in case of burst stSINGLE_BURST,stMULTI_BURST*/ - /* original template provided by requester */ - Json::Value m_stream_json; - - -}; + uint32_t m_num_bursts; /* valid in case of stMULTI_BURST */ -/** - * continuous stream - * - */ -class TrexStreamContinuous : public TrexStream { -public: - TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id) { - m_type= TrexStream::stCONTINUOUS; - m_pps=pps; - } -}; - -/** - * single burst - * - */ -class TrexStreamBurst : public TrexStream { -public: - TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, double pps) : - TrexStream(port_id, stream_id), - m_total_pkts(total_pkts){ - m_type= TrexStream::stSINGLE_BURST; - m_pps=pps; + double m_ibg_usec; /* valid in case of stMULTI_BURST */ - } + /* original template provided by requester */ + Json::Value m_stream_json; -public: - uint32_t m_total_pkts; }; -/** - * multi burst - * - */ -class TrexStreamMultiBurst : public TrexStreamBurst { -public: - TrexStreamMultiBurst(uint8_t port_id, - uint32_t stream_id, - uint32_t pkts_per_burst, - double pps, - uint32_t num_bursts, - double ibg_usec) : TrexStreamBurst(port_id, stream_id, pkts_per_burst, pps), m_num_bursts(num_bursts), m_ibg_usec(ibg_usec) { - m_type= TrexStream::stMULTI_BURST; - } - -public: - uint32_t m_num_bursts; - double m_ibg_usec; - -}; /** * holds all the streams diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index c7b881c5..80cdb31c 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -27,18 +27,21 @@ limitations under the License. * stream compiled object *************************************/ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) { + m_duration_sim=-1.0; } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { + for (auto obj : m_objs) { + delete obj.m_stream; + } m_objs.clear(); - m_duration_sim=-1.0; } void TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { obj_st obj; - obj.m_stream = stream; + obj.m_stream = stream->clone_as_dp(); m_objs.push_back(obj); } diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 899e14be..96c18dbd 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -146,9 +146,6 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, uint16_t pkt_size = stream->m_pkt.len; const uint8_t *stream_pkt = stream->m_pkt.binary; - TrexStreamBurst * lpburst; - TrexStreamMultiBurst * lpmulti; - node->m_stream_type = stream->m_type; node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ; @@ -161,20 +158,17 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, case TrexStream::stSINGLE_BURST : node->m_stream_type = TrexStream::stMULTI_BURST; - lpburst = (TrexStreamBurst *)stream; - node->m_single_burst = lpburst->m_total_pkts; - node->m_single_burst_refill = lpburst->m_total_pkts; + node->m_single_burst = stream->m_burst_total_pkts; + node->m_single_burst_refill = stream->m_burst_total_pkts; node->m_multi_bursts = 1; /* single burst in multi burst of 1 */ node->m_ibg_sec = 0.0; break; case TrexStream::stMULTI_BURST : - lpmulti =(TrexStreamMultiBurst *)stream; - - node->m_single_burst = lpmulti->m_total_pkts; - node->m_single_burst_refill = lpmulti->m_total_pkts ; - node->m_multi_bursts = lpmulti->m_num_bursts; - node->m_ibg_sec = usec_to_sec( lpmulti->m_ibg_usec ); + node->m_single_burst = stream->m_burst_total_pkts; + node->m_single_burst_refill = stream->m_burst_total_pkts; + node->m_multi_bursts = stream->m_num_bursts; + node->m_ibg_sec = usec_to_sec( stream->m_ibg_usec ); break; default: -- cgit From 78c6593c5a2d3d2242be7fc659d15eac6b869358 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 12 Nov 2015 16:33:05 +0200 Subject: DRAFT - only for internal purpose --- src/stateless/cp/trex_stateless_port.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 907b9cf4..7f2382d3 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -186,22 +186,22 @@ TrexStatelessPort::get_state_as_string() const { switch (get_state()) { case PORT_STATE_DOWN: - return "down"; + return "DOWN"; case PORT_STATE_IDLE: - return "no streams"; + return "IDLE"; case PORT_STATE_STREAMS: - return "with streams, idle"; + return "STREAMS"; case PORT_STATE_TX: - return "transmitting"; + return "TX"; case PORT_STATE_PAUSE: - return "paused"; + return "PAUSE"; } - return "unknown"; + return "UNKNOWN"; } void -- cgit From 94b1238942da24e47fb3e689bf695e815a604eb0 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 15 Nov 2015 18:15:14 +0200 Subject: added duration to the RPC server (and all the way to the DP) *STILL NEEDS FIXING THE DP STOP SCHED MESSAGE" --- src/stateless/cp/trex_stateless_port.cpp | 4 ++-- src/stateless/cp/trex_stateless_port.h | 2 +- src/stateless/cp/trex_streams_compiler.cpp | 3 --- src/stateless/cp/trex_streams_compiler.h | 8 -------- src/stateless/dp/trex_stateless_dp_core.cpp | 6 ++---- src/stateless/dp/trex_stateless_dp_core.h | 2 +- src/stateless/messaging/trex_stateless_messaging.cpp | 6 +++--- src/stateless/messaging/trex_stateless_messaging.h | 3 ++- 8 files changed, 11 insertions(+), 23 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 7f2382d3..cbc5a328 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -86,7 +86,7 @@ TrexStatelessPort::release(void) { * */ void -TrexStatelessPort::start_traffic(double mul) { +TrexStatelessPort::start_traffic(double mul, double duration) { /* command allowed only on state stream */ verify_state(PORT_STATE_STREAMS); @@ -105,7 +105,7 @@ TrexStatelessPort::start_traffic(double mul) { } /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj); + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj, duration); send_message_to_dp(start_msg); diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 90bf936e..b533f793 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -72,7 +72,7 @@ public: * start traffic * throws TrexException in case of an error */ - void start_traffic(double mul); + void start_traffic(double mul, double duration = -1); /** * stop traffic diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 80cdb31c..580db51c 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -27,7 +27,6 @@ limitations under the License. * stream compiled object *************************************/ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) { - m_duration_sim=-1.0; } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { @@ -61,8 +60,6 @@ TrexStreamsCompiledObj::clone() { new_compiled_obj->m_mul = m_mul; - new_compiled_obj->m_duration_sim = m_duration_sim; - return new_compiled_obj; } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 78ac1ac7..44c8a0fc 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -48,13 +48,6 @@ public: return m_objs; } - void set_simulation_duration(double duration){ - m_duration_sim=duration; - } - - double get_simulation_duration(){ - return (m_duration_sim); - } /** * clone the compiled object * @@ -71,7 +64,6 @@ private: uint8_t m_port_id; double m_mul; - double m_duration_sim; /* duration for all simulation */ }; class TrexStreamsCompiler { diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 96c18dbd..eabd6fdb 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -207,14 +207,12 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, } void -TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { +TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, double duration) { for (auto single_stream : obj->get_objects()) { add_cont_stream(single_stream.m_stream,obj); } - double duration=obj->get_simulation_duration(); - - if ( duration >0.0){ + if ( duration > 0.0 ){ add_duration( duration ); } } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 1029213d..7448d215 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -75,7 +75,7 @@ public: * @param pkt * @param pkt_len */ - void start_traffic(TrexStreamsCompiledObj *obj); + void start_traffic(TrexStreamsCompiledObj *obj, double duration = -1); /** * stop all traffic for this core diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 032559bc..d8ebc52c 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -26,7 +26,7 @@ limitations under the License. /************************* start traffic message ************************/ -TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj) : m_obj(obj) { +TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj, double duration) : m_obj(obj), m_duration(duration) { } @@ -39,7 +39,7 @@ TrexStatelessDpStart::clone() { TrexStreamsCompiledObj *new_obj = m_obj->clone(); - TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(new_obj); + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(new_obj, m_duration); return new_msg; } @@ -53,7 +53,7 @@ TrexStatelessDpStart::~TrexStatelessDpStart() { bool TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { - dp_core->start_traffic(m_obj); + dp_core->start_traffic(m_obj, m_duration); return true; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index d288fc83..90897665 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -66,7 +66,7 @@ public: class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { public: - TrexStatelessDpStart(TrexStreamsCompiledObj *obj); + TrexStatelessDpStart(TrexStreamsCompiledObj *obj, double duration); ~TrexStatelessDpStart(); @@ -77,6 +77,7 @@ public: private: TrexStreamsCompiledObj *m_obj; + double m_duration; }; /** -- cgit From d16ebf0b67ae8e339fd9367c313a786a8172b1b0 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 16 Nov 2015 18:28:01 +0200 Subject: basic compiler checks added checks against: 1. duplicate stream IDs 2. pointing to non existent streams 3. 'dead streams' - unreachable by any other stream --- src/stateless/cp/trex_stream.h | 8 +- src/stateless/cp/trex_streams_compiler.cpp | 301 ++++++++++++++++++++++++++++- src/stateless/cp/trex_streams_compiler.h | 26 ++- 3 files changed, 323 insertions(+), 12 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 151723ad..c2628cc3 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -92,21 +92,21 @@ public: m_type = type; } - uint8_t get_type(void){ + uint8_t get_type(void) const { return ( m_type ); } void set_multi_burst(uint32_t burst_total_pkts, - uint32_t num_bursts, - double ibg_usec){ + uint32_t num_bursts, + double ibg_usec) { m_burst_total_pkts = burst_total_pkts; m_num_bursts = num_bursts; m_ibg_usec = ibg_usec; } - void set_signle_burtst(uint32_t burst_total_pkts){ + void set_single_burst(uint32_t burst_total_pkts){ set_multi_burst(burst_total_pkts,1,0.0); } diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 580db51c..0c3b4ef0 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -19,9 +19,116 @@ See the License for the specific language governing permissions and limitations under the License. */ -#include +#include +#include #include #include +#include +#include +#include + +/** + * describes a graph node in the pre compile check + * + * @author imarom (16-Nov-15) + */ +class GraphNode { +public: + GraphNode(TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) { + marked = false; + } + + uint32_t get_stream_id() const { + return m_stream->m_stream_id; + } + + const TrexStream *m_stream; + GraphNode *m_next; + std::vector m_parents; + bool marked; +}; + +/** + * node map + * + */ +class GraphNodeMap { +public: + + GraphNodeMap() : m_dead_end(NULL, NULL) { + + } + + bool add(GraphNode *node) { + if (has(node->get_stream_id())) { + return false; + } + + m_nodes[node->get_stream_id()] = node; + + if (node->m_stream->m_self_start) { + m_roots.push_back(node); + } + + return true; + } + + bool has(uint32_t stream_id) { + + return (get(stream_id) != NULL); + } + + GraphNode * get(uint32_t stream_id) { + + if (stream_id == -1) { + return &m_dead_end; + } + + auto search = m_nodes.find(stream_id); + + if (search != m_nodes.end()) { + return search->second; + } else { + return NULL; + } + } + + void clear_marks() { + for (auto node : m_nodes) { + node.second->marked = false; + } + } + + void get_unmarked(std::vector &unmarked) { + for (auto node : m_nodes) { + if (!node.second->marked) { + unmarked.push_back(node.second); + } + } + } + + + ~GraphNodeMap() { + for (auto node : m_nodes) { + delete node.second; + } + m_nodes.clear(); + } + + std::vector & get_roots() { + return m_roots; + } + + + std::unordered_map get_nodes() { + return m_nodes; + } + +private: + std::unordered_map m_nodes; + std::vector m_roots; + GraphNode m_dead_end; +}; /************************************** * stream compiled object @@ -63,11 +170,196 @@ TrexStreamsCompiledObj::clone() { return new_compiled_obj; } +void +TrexStreamsCompiler::add_warning(const std::string &warning) { + m_warnings.push_back("*** warning: " + warning); +} + +void +TrexStreamsCompiler::err(const std::string &err) { + throw TrexException("*** error: " + err); +} + +void +TrexStreamsCompiler::check_stream(const TrexStream *stream) { + std::stringstream ss; + + /* cont. stream can point only on itself */ + if (stream->get_type() == TrexStream::stCONTINUOUS) { + if (stream->m_next_stream_id != -1) { + ss << "continous stream '" << stream->m_stream_id << "' cannot point on another stream"; + err(ss.str()); + } + } +} + +void +TrexStreamsCompiler::allocate_pass(const std::vector &streams, + GraphNodeMap *nodes) { + std::stringstream ss; + + /* first pass - allocate all nodes and check for duplicates */ + for (auto stream : streams) { + + /* skip non enabled streams */ + if (!stream->m_enabled) { + continue; + } + + /* sanity check on the stream itself */ + check_stream(stream); + + /* duplicate stream id ? */ + if (nodes->has(stream->m_stream_id)) { + ss << "duplicate instance of stream id " << stream->m_stream_id; + err(ss.str()); + } + + GraphNode *node = new GraphNode(stream, NULL); + + /* add to the map */ + assert(nodes->add(node)); + } + +} + +/** + * on this pass we direct the graph to point to the right nodes + * + */ +void +TrexStreamsCompiler::direct_pass(GraphNodeMap *nodes) { + + /* second pass - direct the graph */ + for (auto p : nodes->get_nodes()) { + + GraphNode *node = p.second; + const TrexStream *stream = node->m_stream; + + /* check the stream points on an existing stream */ + GraphNode *next_node = nodes->get(stream->m_next_stream_id); + if (!next_node) { + std::stringstream ss; + ss << "stream " << node->get_stream_id() << " is pointing on non existent stream " << stream->m_next_stream_id; + err(ss.str()); + } + + node->m_next = next_node; + + /* do we have more than one parent ? */ + next_node->m_parents.push_back(node); + } + + + /* check for multiple parents */ + for (auto p : nodes->get_nodes()) { + GraphNode *node = p.second; + + if (node->m_parents.size() > 0 ) { + std::stringstream ss; + + ss << "stream " << node->get_stream_id() << " is triggered by multiple streams: "; + for (auto x : node->m_parents) { + ss << x->get_stream_id() << " "; + } + + add_warning(ss.str()); + } + } +} + +/** + * mark sure all the streams are reachable + * + */ +void +TrexStreamsCompiler::check_for_unreachable_streams(GraphNodeMap *nodes) { + /* start with the roots */ + std::vector next_nodes = nodes->get_roots(); + + + nodes->clear_marks(); + + /* run BFS from all the roots */ + while (!next_nodes.empty()) { + + /* pull one */ + GraphNode *node = next_nodes.back(); + next_nodes.pop_back(); + if (node->marked) { + continue; + } + + node->marked = true; + + if (node->m_next != NULL) { + next_nodes.push_back(node->m_next); + } + + } + + std::vector unmarked; + nodes->get_unmarked(unmarked); + + if (!unmarked.empty()) { + std::stringstream ss; + for (auto node : unmarked) { + ss << "stream " << node->get_stream_id() << " is unreachable from any other stream\n"; + } + err(ss.str()); + } + + +} + +/** + * check validation of streams for compile + * + * @author imarom (16-Nov-15) + * + * @param streams + * @param fail_msg + * + * @return bool + */ +void +TrexStreamsCompiler::pre_compile_check(const std::vector &streams) { + + GraphNodeMap nodes; + + m_warnings.clear(); + + /* allocate nodes */ + allocate_pass(streams, &nodes); + + /* direct the graph */ + direct_pass(&nodes); + + /* check for non reachable streams inside the graph */ + check_for_unreachable_streams(&nodes); + +} + /************************************** * stream compiler *************************************/ bool -TrexStreamsCompiler::compile(const std::vector &streams, TrexStreamsCompiledObj &obj) { +TrexStreamsCompiler::compile(const std::vector &streams, + TrexStreamsCompiledObj &obj, + std::string *fail_msg) { + + /* compile checks */ + try { + pre_compile_check(streams); + } catch (const TrexException &ex) { + if (fail_msg) { + *fail_msg = ex.what(); + } else { + std::cout << ex.what(); + } + return false; + } + /* for now we do something trivial, */ for (auto stream : streams) { @@ -76,11 +368,6 @@ TrexStreamsCompiler::compile(const std::vector &streams, TrexStrea continue; } - /* for now skip also non self started streams */ - if (!stream->m_self_start) { - continue; - } - /* add it */ obj.add_compiled_stream(stream); } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 44c8a0fc..42cfc5b8 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -23,9 +23,11 @@ limitations under the License. #include #include +#include class TrexStreamsCompiler; class TrexStream; +class GraphNodeMap; /** * compiled object for a table of streams @@ -68,13 +70,35 @@ private: class TrexStreamsCompiler { public: + /** * compiles a vector of streams to an object passable to the DP * * @author imarom (28-Oct-15) * */ - bool compile(const std::vector &streams, TrexStreamsCompiledObj &obj); + bool compile(const std::vector &streams, TrexStreamsCompiledObj &obj, std::string *fail_msg = NULL); + + /** + * + * returns a reference pointer to the last compile warnings + * if no warnings were produced - the vector is empty + */ + const std::vector & get_last_compile_warnings() { + return m_warnings; + } + +private: + + void pre_compile_check(const std::vector &streams); + void allocate_pass(const std::vector &streams, GraphNodeMap *nodes); + void direct_pass(GraphNodeMap *nodes); + void check_for_unreachable_streams(GraphNodeMap *nodes); + void check_stream(const TrexStream *stream); + void add_warning(const std::string &warning); + void err(const std::string &err); + + std::vector m_warnings; }; #endif /* __TREX_STREAMS_COMPILER_H__ */ -- cgit From 3b8eb91e17f8f4647b4ba9a78ba485f5c490bfac Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Mon, 16 Nov 2015 21:02:14 +0200 Subject: clean termination - stateless and stateful - fix pure virtual function error --- src/stateless/dp/trex_stateless_dp_core.cpp | 12 ++++++++++++ src/stateless/dp/trex_stateless_dp_core.h | 3 +++ src/stateless/messaging/trex_stateless_messaging.cpp | 20 ++++++++++++++++++++ src/stateless/messaging/trex_stateless_messaging.h | 17 +++++++++++++++++ 4 files changed, 52 insertions(+) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 96c18dbd..25984dfc 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -72,6 +72,14 @@ TrexStatelessDpCore::idle_state_loop() { } } + + +void TrexStatelessDpCore::quit_main_loop(){ + m_core->set_terminate_mode(true); /* mark it as terminated */ + add_duration(0.0001); /* add message to terminate */ +} + + /** * scehduler runs when traffic exists * it will return when no more transmitting is done on this @@ -106,6 +114,10 @@ TrexStatelessDpCore::start() { while (true) { run_once(); + + if ( m_core->is_terminated_by_master() ) { + break; + } } } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 1029213d..54fad240 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -109,6 +109,9 @@ public: } + /* quit the main loop, work in both stateless in stateful, don't free memory trigger from master */ + void quit_main_loop(); + private: /** * in idle state loop, the processor most of the time sleeps diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 032559bc..f529642d 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -76,3 +76,23 @@ TrexStatelessDpStop::clone() { return new_msg; } + + + +TrexStatelessCpToDpMsgBase * +TrexStatelessDpQuit::clone(){ + + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpQuit(); + + return new_msg; +} + + + +bool TrexStatelessDpQuit::handle(TrexStatelessDpCore *dp_core){ + + /* quit */ + dp_core->quit_main_loop(); + return (true); +} + diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index d288fc83..d1621708 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -98,5 +99,21 @@ private: uint8_t m_port_id; }; +/** + * a message to Quit the datapath traffic. support only stateless for now + * + * @author hhaim + */ +class TrexStatelessDpQuit : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpQuit() { + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + + virtual TrexStatelessCpToDpMsgBase * clone(); +}; + #endif /* __TREX_STATELESS_MESSAGING_H__ */ -- cgit From 07e6795a7497151e0920c82337cca6cfb5c3c3cd Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 17 Nov 2015 15:26:41 +0200 Subject: checkpoint before merge --- src/stateless/dp/trex_stateless_dp_core.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index eabd6fdb..07e03678 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -248,7 +248,13 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { m_core->m_node_gen.add_node(node); } - + + /* send a message to the control plane to + generate an async event that traffic has stopped + */ + //CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(m_core->m_thread_id); + //ring->Enqueue((CGenNode *)msg->clone()); + } /** -- cgit From 0e8c9ae666d61897cb405c469a71be09d54a649b Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 18 Nov 2015 16:23:55 +0200 Subject: add support for a program of streams. refactor the dp code --- src/stateless/cp/trex_stream.cpp | 65 ++++ src/stateless/cp/trex_stream.h | 21 +- src/stateless/cp/trex_streams_compiler.cpp | 64 +++- src/stateless/cp/trex_streams_compiler.h | 12 +- src/stateless/dp/trex_stateless_dp_core.cpp | 328 ++++++++++++++++++--- src/stateless/dp/trex_stateless_dp_core.h | 92 +++++- src/stateless/dp/trex_stream_node.h | 101 ++++++- .../messaging/trex_stateless_messaging.cpp | 21 +- src/stateless/messaging/trex_stateless_messaging.h | 30 +- 9 files changed, 666 insertions(+), 68 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 1a05257c..5203b2a2 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -25,6 +25,71 @@ limitations under the License. /************************************** * stream *************************************/ + + +std::string TrexStream::get_stream_type_str(stream_type_t stream_type){ + + std::string res; + + + switch (stream_type) { + + case stCONTINUOUS : + res="stCONTINUOUS "; + break; + + case stSINGLE_BURST : + res="stSINGLE_BURST "; + break; + + case stMULTI_BURST : + res="stMULTI_BURST "; + break; + default: + res="Unknow "; + }; + return(res); +} + + +void TrexStream::Dump(FILE *fd){ + + fprintf(fd,"\n"); + fprintf(fd,"==> Stream_id : %lu \n",(ulong)m_stream_id); + fprintf(fd," Enabled : %lu \n",(ulong)(m_enabled?1:0)); + fprintf(fd," Self_start : %lu \n",(ulong)(m_self_start?1:0)); + + if (m_next_stream_id>=0) { + fprintf(fd," Nex_stream_id : %lu \n",(ulong)m_next_stream_id); + }else { + fprintf(fd," Nex_stream_id : %d \n",m_next_stream_id); + } + + fprintf(fd," Port_id : %lu \n",(ulong)m_port_id); + + if (m_isg_usec>0.0) { + fprintf(fd," isg : %6.2f \n",m_isg_usec); + } + fprintf(fd," type : %s \n",get_stream_type_str(m_type).c_str()); + + if ( m_type == TrexStream::stCONTINUOUS ) { + fprintf(fd," pps : %f \n",m_pps); + } + if (m_type == TrexStream::stSINGLE_BURST) { + fprintf(fd," pps : %f \n",m_pps); + fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); + } + if (m_type == TrexStream::stMULTI_BURST) { + fprintf(fd," pps : %f \n",m_pps); + fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); + fprintf(fd," mburst : %lu \n",(ulong)m_num_bursts); + if (m_ibg_usec>0.0) { + fprintf(fd," m_ibg_usec : %f \n",m_ibg_usec); + } + } +} + + TrexStream::TrexStream(uint8_t type, uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index c2628cc3..0634829e 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -65,6 +66,9 @@ public: stMULTI_BURST = 6 }; + typedef uint8_t stream_type_t ; + + static std::string get_stream_type_str(stream_type_t stream_type); public: TrexStream(uint8_t type,uint8_t port_id, uint32_t stream_id); @@ -80,6 +84,12 @@ public: /* access the stream json */ const Json::Value & get_stream_json(); + /* compress the stream id to be zero based */ + void fix_dp_stream_id(uint32_t my_stream_id,int next_stream_id){ + m_stream_id = my_stream_id; + m_next_stream_id = next_stream_id; + } + double get_pps() { return m_pps; } @@ -96,6 +106,14 @@ public: return ( m_type ); } + bool is_dp_next_stream(){ + if (m_next_stream_id<0) { + return (false); + }else{ + return (true); + } + } + void set_multi_burst(uint32_t burst_total_pkts, @@ -132,11 +150,12 @@ public: return (dp); } + void Dump(FILE *fd); public: /* basic */ uint8_t m_type; uint8_t m_port_id; - uint32_t m_stream_id; + uint32_t m_stream_id; /* id from RPC can be anything */ /* config fields */ diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 0c3b4ef0..bdfc3c01 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -36,6 +36,7 @@ class GraphNode { public: GraphNode(TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) { marked = false; + m_compressed_stream_id=-1; } uint32_t get_stream_id() const { @@ -46,6 +47,7 @@ public: GraphNode *m_next; std::vector m_parents; bool marked; + int m_compressed_stream_id; }; /** @@ -143,8 +145,10 @@ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { m_objs.clear(); } + void -TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { +TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream){ + obj_st obj; obj.m_stream = stream->clone_as_dp(); @@ -152,6 +156,26 @@ TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { m_objs.push_back(obj); } +void +TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream, + uint32_t my_dp_id, int next_dp_id) { + obj_st obj; + + obj.m_stream = stream->clone_as_dp(); + /* compress the id's*/ + obj.m_stream->fix_dp_stream_id(my_dp_id,next_dp_id); + + m_objs.push_back(obj); +} + +void TrexStreamsCompiledObj::Dump(FILE *fd){ + for (auto obj : m_objs) { + obj.m_stream->Dump(fd); + } +} + + + TrexStreamsCompiledObj * TrexStreamsCompiledObj::clone() { @@ -197,6 +221,8 @@ void TrexStreamsCompiler::allocate_pass(const std::vector &streams, GraphNodeMap *nodes) { std::stringstream ss; + uint32_t compressed_stream_id=0; + /* first pass - allocate all nodes and check for duplicates */ for (auto stream : streams) { @@ -216,6 +242,10 @@ TrexStreamsCompiler::allocate_pass(const std::vector &streams, } GraphNode *node = new GraphNode(stream, NULL); + /* allocate new compressed id */ + node->m_compressed_stream_id = compressed_stream_id; + + compressed_stream_id++; /* add to the map */ assert(nodes->add(node)); @@ -323,9 +353,8 @@ TrexStreamsCompiler::check_for_unreachable_streams(GraphNodeMap *nodes) { * @return bool */ void -TrexStreamsCompiler::pre_compile_check(const std::vector &streams) { - - GraphNodeMap nodes; +TrexStreamsCompiler::pre_compile_check(const std::vector &streams, + GraphNodeMap & nodes) { m_warnings.clear(); @@ -348,9 +377,20 @@ TrexStreamsCompiler::compile(const std::vector &streams, TrexStreamsCompiledObj &obj, std::string *fail_msg) { +#if 0 + fprintf(stdout,"------------pre compile \n"); + for (auto stream : streams) { + stream->Dump(stdout); + } + fprintf(stdout,"------------pre compile \n"); +#endif + + GraphNodeMap nodes; + + /* compile checks */ try { - pre_compile_check(streams); + pre_compile_check(streams,nodes); } catch (const TrexException &ex) { if (fail_msg) { *fail_msg = ex.what(); @@ -360,6 +400,7 @@ TrexStreamsCompiler::compile(const std::vector &streams, return false; } + /* for now we do something trivial, */ for (auto stream : streams) { @@ -368,8 +409,19 @@ TrexStreamsCompiler::compile(const std::vector &streams, continue; } + int new_id= nodes.get(stream->m_stream_id)->m_compressed_stream_id; + assert(new_id>=0); + uint32_t my_stream_id = (uint32_t)new_id; + int my_next_stream_id=-1; + if (stream->m_next_stream_id>=0) { + my_next_stream_id=nodes.get(stream->m_next_stream_id)->m_compressed_stream_id; + } + /* add it */ - obj.add_compiled_stream(stream); + obj.add_compiled_stream(stream, + my_stream_id, + my_next_stream_id + ); } return true; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 42cfc5b8..200f7ce9 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -50,6 +50,10 @@ public: return m_objs; } + uint8_t get_port_id(){ + return (m_port_id); + } + /** * clone the compiled object * @@ -60,8 +64,13 @@ public: return (m_mul); } + void Dump(FILE *fd); + private: + void add_compiled_stream(TrexStream * stream, + uint32_t my_dp_id, int next_dp_id); void add_compiled_stream(TrexStream * stream); + std::vector m_objs; uint8_t m_port_id; @@ -90,7 +99,8 @@ public: private: - void pre_compile_check(const std::vector &streams); + void pre_compile_check(const std::vector &streams, + GraphNodeMap & nodes); void allocate_pass(const std::vector &streams, GraphNodeMap *nodes); void direct_pass(GraphNodeMap *nodes); void check_for_unreachable_streams(GraphNodeMap *nodes); diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index b25a4cfc..640fdb4d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -26,12 +27,83 @@ limitations under the License. #include -static inline double -usec_to_sec(double usec) { - return (usec / (1000 * 1000)); + +void CDpOneStream::Delete(CFlowGenListPerThread * core){ + assert(m_node->get_state() == CGenNodeStateless::ss_INACTIVE); + core->free_node((CGenNode *)m_node); + delete m_dp_stream; + m_node=0; + m_dp_stream=0; +} + +void CDpOneStream::DeleteOnlyStream(){ + assert(m_dp_stream); + delete m_dp_stream; + m_dp_stream=0; +} + +int CGenNodeStateless::get_stream_id(){ + if (m_state ==CGenNodeStateless::ss_FREE_RESUSE) { + return (-1); // not valid + } + assert(m_ref_stream_info); + return ((int)m_ref_stream_info->m_stream_id); +} + + +void CGenNodeStateless::DumpHeader(FILE *fd){ + fprintf(fd," pkt_id, time, port , action , state, stream_id , stype , m-burst# , burst# \n"); + +} +void CGenNodeStateless::Dump(FILE *fd){ + fprintf(fd," %2.4f, %3lu, %s,%s, %3d, %s, %3lu, %3lu \n", + m_time, + (ulong)m_port_id, + "s-pkt", //action + get_stream_state_str(m_state ).c_str(), + get_stream_id(), //stream_id + TrexStream::get_stream_type_str(m_stream_type).c_str(), //stype + (ulong)m_multi_bursts, + (ulong)m_single_burst + ); +} + + +void CGenNodeStateless::refresh(){ + + /* refill the stream info */ + m_single_burst = m_single_burst_refill; + m_multi_bursts = m_ref_stream_info->m_num_bursts; + m_state = CGenNodeStateless::ss_ACTIVE; +} + + + +void CGenNodeCommand::free_command(){ + assert(m_cmd); + delete m_cmd; } +std::string CGenNodeStateless::get_stream_state_str(stream_state_t stream_state){ + std::string res; + + switch (stream_state) { + case CGenNodeStateless::ss_FREE_RESUSE : + res="FREE "; + break; + case CGenNodeStateless::ss_INACTIVE : + res="INACTIVE "; + break; + case CGenNodeStateless::ss_ACTIVE : + res="ACTIVE "; + break; + default: + res="Unknow "; + }; + return(res); +} + void CGenNodeStateless::free_stl_node(){ /* if we have cache mbuf free it */ @@ -43,11 +115,54 @@ void CGenNodeStateless::free_stl_node(){ } +bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){ + m_active_streams-=d; /* reduce the number of streams */ + if (m_active_streams == 0) { + return (true); + } + return (false); +} + + +void TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ + + assert(m_state==TrexStatelessDpPerPort::ppSTATE_TRANSMITTING); + + for (auto dp_stream : m_active_nodes) { + CGenNodeStateless * node =dp_stream.m_node; + assert(node->get_port_id() == port_id); + if ( node->get_state() == CGenNodeStateless::ss_ACTIVE) { + node->mark_for_free(); + m_active_streams--; + dp_stream.DeleteOnlyStream(); + + }else{ + dp_stream.Delete(m_core); + } + } + + /* active stream should be zero */ + assert(m_active_streams==0); + m_active_nodes.clear(); + m_state=TrexStatelessDpPerPort::ppSTATE_IDLE; +} + + +void TrexStatelessDpPerPort::create(CFlowGenListPerThread * core){ + m_core=core; + m_state=TrexStatelessDpPerPort::ppSTATE_IDLE; + m_port_id=0; + m_active_streams=0; + m_active_nodes.clear(); +} + + void TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) { m_thread_id = thread_id; m_core = core; + m_local_port_offset = 2*core->getDualPortId(); CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp(); @@ -55,8 +170,54 @@ TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) { m_ring_to_cp = cp_dp->getRingDpToCp(thread_id); m_state = STATE_IDLE; + + int i; + for (i=0; im_port_id); + bool schedule =false; + + bool to_stop_port=false; + + if (next_node == NULL) { + /* there is no next stream , reduce the number of active streams*/ + to_stop_port = lp_port->update_number_of_active_streams(1); + + }else{ + uint8_t state=next_node->get_state(); + + /* can't be FREE_RESUSE */ + assert(state != CGenNodeStateless::ss_FREE_RESUSE); + if (next_node->get_state() == CGenNodeStateless::ss_INACTIVE ) { + + /* refill start info and scedule, no update in active streams */ + next_node->refresh(); + schedule = true; + + }else{ + to_stop_port = lp_port->update_number_of_active_streams(1); + } + } + + if ( to_stop_port ) { + /* call stop port explictly to move the state */ + stop_traffic(cur_node->m_port_id); + } + + return ( schedule ); } + + /** * in idle state loop, the processor most of the time sleeps * and periodically checks for messages @@ -76,7 +237,8 @@ TrexStatelessDpCore::idle_state_loop() { void TrexStatelessDpCore::quit_main_loop(){ m_core->set_terminate_mode(true); /* mark it as terminated */ - add_duration(0.0001); /* add message to terminate */ + m_state = STATE_TERMINATE; + add_global_duration(0.0001); } @@ -97,6 +259,7 @@ TrexStatelessDpCore::start_scheduler() { double old_offset = 0.0; m_core->m_node_gen.flush_file(-1, 0.0, false, m_core, old_offset); + /* TBD do we need that ? */ m_core->m_node_gen.close_file(m_core); } @@ -105,6 +268,11 @@ void TrexStatelessDpCore::run_once(){ idle_state_loop(); + + if ( m_state == STATE_TERMINATE ){ + return; + } + start_scheduler(); } @@ -121,8 +289,25 @@ TrexStatelessDpCore::start() { } } -void -TrexStatelessDpCore::add_duration(double duration){ +/* only if both port are idle we can exit */ +void +TrexStatelessDpCore::schedule_exit(){ + + CGenNodeCommand *node = (CGenNodeCommand *)m_core->create_node() ; + + node->m_type = CGenNode::COMMAND; + + node->m_cmd = new TrexStatelessDpCanQuit(); + + /* make sure it will be scheduled after the current node */ + node->m_time = m_core->m_cur_time_sec ; + + m_core->m_node_gen.add_node((CGenNode *)node); +} + + +void +TrexStatelessDpCore::add_global_duration(double duration){ if (duration > 0.0) { CGenNode *node = m_core->create_node() ; @@ -135,9 +320,28 @@ TrexStatelessDpCore::add_duration(double duration){ } } +/* add per port exit */ +void +TrexStatelessDpCore::add_port_duration(double duration, + uint8_t port_id){ + if (duration > 0.0) { + CGenNodeCommand *node = (CGenNodeCommand *)m_core->create_node() ; + + node->m_type = CGenNode::COMMAND; + + /* make sure it will be scheduled after the current node */ + node->m_time = m_core->m_cur_time_sec + duration ; + + node->m_cmd = new TrexStatelessDpStop(port_id); + + m_core->m_node_gen.add_node((CGenNode *)node); + } +} + void -TrexStatelessDpCore::add_cont_stream(TrexStream * stream, +TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, + TrexStream * stream, TrexStreamsCompiledObj *comp) { CGenNodeStateless *node = m_core->create_node_sl(); @@ -145,6 +349,19 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, /* add periodic */ node->m_type = CGenNode::STATELESS_PKT; + node->m_ref_stream_info = stream->clone_as_dp(); + + node->m_next_stream=0; /* will be fixed later */ + + + if ( stream->m_self_start ){ + /* if self start it is in active mode */ + node->m_state =CGenNodeStateless::ss_ACTIVE; + lp_port->m_active_streams++; + }else{ + node->m_state =CGenNodeStateless::ss_INACTIVE; + } + node->m_time = m_core->m_cur_time_sec + usec_to_sec(stream->m_isg_usec); pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(stream->m_port_id); @@ -166,6 +383,10 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, switch ( stream->m_type ) { case TrexStream::stCONTINUOUS : + node->m_single_burst=0; + node->m_single_burst_refill=0; + node->m_multi_bursts=0; + node->m_ibg_sec = 0.0; break; case TrexStream::stSINGLE_BURST : @@ -187,7 +408,6 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, assert(0); }; - node->m_is_stream_active = 1; node->m_port_id = stream->m_port_id; /* allocate const mbuf */ @@ -208,59 +428,93 @@ TrexStatelessDpCore::add_cont_stream(TrexStream * stream, /* set the packet as a readonly */ node->set_cache_mbuf(m); - /* keep track */ - m_active_nodes.push_back(node); + CDpOneStream one_stream; + + one_stream.m_dp_stream = node->m_ref_stream_info; + one_stream.m_node =node; + + lp_port->m_active_nodes.push_back(one_stream); /* schedule */ m_core->m_node_gen.add_node((CGenNode *)node); - m_state = TrexStatelessDpCore::STATE_TRANSMITTING; - } void -TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, double duration) { +TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, + double duration) { + +#if 0 + /* TBD to remove ! */ + obj->Dump(stdout); +#endif + + TrexStatelessDpPerPort * lp_port=get_port_db(obj->get_port_id()); + lp_port->m_active_streams = 0; + /* no nodes in the list */ + assert(lp_port->m_active_nodes.size()==0); + + for (auto single_stream : obj->get_objects()) { + /* all commands should be for the same port */ + assert(obj->get_port_id() == single_stream.m_stream->m_port_id); + add_cont_stream(lp_port,single_stream.m_stream,obj); + } + + uint32_t nodes = lp_port->m_active_nodes.size(); + /* find next stream */ + assert(nodes == obj->get_objects().size()); + + int cnt=0; + + /* set the next_stream pointer */ for (auto single_stream : obj->get_objects()) { - add_cont_stream(single_stream.m_stream,obj); + + if (single_stream.m_stream->is_dp_next_stream() ) { + int stream_id = single_stream.m_stream->m_next_stream_id; + assert(stream_idm_active_nodes[cnt].m_node->m_next_stream = lp_port->m_active_nodes[stream_id].m_node ; + } + cnt++; } + lp_port->m_state =TrexStatelessDpPerPort::ppSTATE_TRANSMITTING; + m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + + if ( duration > 0.0 ){ - add_duration( duration ); + add_port_duration( duration ,obj->get_port_id() ); + } +} + + +bool TrexStatelessDpCore::are_all_ports_idle(){ + + bool res=true; + int i; + for (i=0; im_port_id == port_id) { - node->m_is_stream_active = 0; - } - } - /* remove all the non active nodes */ - auto pred = std::remove_if(m_active_nodes.begin(), - m_active_nodes.end(), - [](CGenNodeStateless *node) { return (!node->m_is_stream_active); }); + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); - m_active_nodes.erase(pred, m_active_nodes.end()); + lp_port->stop_traffic(port_id); - if (m_active_nodes.size() == 0) { - m_state = STATE_IDLE; - /* stop the scheduler */ + if ( are_all_ports_idle() ) { - CGenNode *node = m_core->create_node() ; - - node->m_type = CGenNode::EXIT_SCHED; - - /* make sure it will be scheduled after the current node */ - node->m_time = m_core->m_cur_time_sec + 0.0001; - - m_core->m_node_gen.add_node(node); + schedule_exit(); } - } /** diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index aaa6eed3..28fff2fb 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -33,6 +34,52 @@ class CGenNodeStateless; class TrexStreamsCompiledObj; class TrexStream; + +class CDpOneStream { +public: + void Create(){ + } + + void Delete(CFlowGenListPerThread * core); + void DeleteOnlyStream(); + + CGenNodeStateless * m_node; // schedule node + TrexStream * m_dp_stream; // stream info +}; + +class TrexStatelessDpPerPort { + +public: + /* states */ + enum state_e { + ppSTATE_IDLE, + ppSTATE_TRANSMITTING + }; + +public: + TrexStatelessDpPerPort(){ + } + + void create(CFlowGenListPerThread * core); + + void stop_traffic(uint8_t port_id); + + bool update_number_of_active_streams(uint32_t d); + +public: + + state_e m_state; + uint8_t m_port_id; + + uint32_t m_active_streams; /* how many active streams on this port */ + + std::vector m_active_nodes; /* holds the current active nodes */ + CFlowGenListPerThread * m_core ; +}; + +/* for now */ +#define NUM_PORTS_PER_CORE 2 + class TrexStatelessDpCore { public: @@ -40,7 +87,9 @@ public: /* states */ enum state_e { STATE_IDLE, - STATE_TRANSMITTING + STATE_TRANSMITTING, + STATE_TERMINATE, + }; TrexStatelessDpCore() { @@ -83,6 +132,11 @@ public: */ void stop_traffic(uint8_t port_id); + + /* return if all ports are idel */ + bool are_all_ports_idle(); + + /** * check for and handle messages from CP * @@ -112,7 +166,23 @@ public: /* quit the main loop, work in both stateless in stateful, don't free memory trigger from master */ void quit_main_loop(); + bool set_stateless_next_node(CGenNodeStateless * cur_node, + CGenNodeStateless * next_node); + private: + + + TrexStatelessDpPerPort * get_port_db(uint8_t port_id){ + assert((m_local_port_offset==port_id) ||(m_local_port_offset+1==port_id)); + uint8_t local_port_id = port_id -m_local_port_offset; + assert(local_port_id m_active_nodes; + TrexStatelessDpPerPort m_ports[NUM_PORTS_PER_CORE]; /* pointer to the main object */ - CFlowGenListPerThread *m_core; + CFlowGenListPerThread * m_core; double m_duration; }; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index e4cf964d..1e53887b 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -1,5 +1,6 @@ /* Itay Marom + Hanoh Haim Cisco Systems, Inc. */ @@ -27,20 +28,51 @@ limitations under the License. class TrexStatelessDpCore; #include +class TrexStatelessCpToDpMsgBase; + +struct CGenNodeCommand : public CGenNodeBase { + +friend class TrexStatelessDpCore; + +public: + TrexStatelessCpToDpMsgBase * m_cmd; + + uint8_t m_pad_end[104]; + +public: + void free_command(); + +} __rte_cache_aligned;; + + +static_assert(sizeof(CGenNodeCommand) == sizeof(CGenNode), "sizeof(CGenNodeCommand) != sizeof(CGenNode)" ); + /* this is a event for stateless */ struct CGenNodeStateless : public CGenNodeBase { friend class TrexStatelessDpCore; +public: + enum { + ss_FREE_RESUSE =1, /* should be free by scheduler */ + ss_INACTIVE =2, /* will be active by other stream or stopped */ + ss_ACTIVE =3 /* the stream is active */ + }; + typedef uint8_t stream_state_t ; + + static std::string get_stream_state_str(stream_state_t stream_state); + private: + /* cache line 0 */ + /* important stuff here */ void * m_cache_mbuf; double m_next_time_offset; /* in sec */ double m_ibg_sec; /* inter burst time in sec */ - uint8_t m_is_stream_active; + stream_state_t m_state; uint8_t m_port_id; - uint8_t m_stream_type; /* TrexStream::STREAM_TYPE */ + uint8_t m_stream_type; /* see TrexStream::STREAM_TYPE ,stream_type_t */ uint8_t m_pad; uint32_t m_single_burst; /* the number of bursts in case of burst */ @@ -48,14 +80,40 @@ private: uint32_t m_multi_bursts; /* in case of multi_burst how many bursts */ - + /* cache line 1 */ + TrexStream * m_ref_stream_info; /* the stream info */ + CGenNodeStateless * m_next_stream; /* pad to match the size of CGenNode */ - uint8_t m_pad_end[65]; + uint8_t m_pad_end[56]; + + public: + uint8_t get_port_id(){ + return (m_port_id); + } + + + /* we restart the stream, schedule it using stream isg */ + inline void update_refresh_time(double cur_time){ + m_time = cur_time + usec_to_sec(m_ref_stream_info->m_isg_usec); + } + + inline bool is_mask_for_free(){ + return (get_state() == CGenNodeStateless::ss_FREE_RESUSE ?true:false); + + } + inline void mark_for_free(){ + set_state(CGenNodeStateless::ss_FREE_RESUSE); + /* only to be safe */ + m_ref_stream_info= NULL; + m_next_stream= NULL; + + } + inline uint8_t get_stream_type(){ return (m_stream_type); } @@ -72,11 +130,16 @@ public: return (m_multi_bursts); } + inline void set_state(stream_state_t new_state){ + m_state=new_state; + } - inline bool is_active() { - return m_is_stream_active; + + inline stream_state_t get_state() { + return m_state; } + void refresh(); inline void handle_continues(CFlowGenListPerThread *thread) { thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); @@ -100,14 +163,22 @@ public: }else{ m_multi_bursts--; if ( m_multi_bursts == 0 ) { - /* stop */ - m_is_stream_active =0; + set_state(CGenNodeStateless::ss_INACTIVE); + if ( thread->set_stateless_next_node(this,m_next_stream) ){ + /* update the next stream time using isg */ + m_next_stream->update_refresh_time(m_time); + + thread->m_node_gen.m_p_queue.push( (CGenNode *)m_next_stream); + }else{ + // in case of zero we will schedule a command to stop + // will be called from set_stateless_next_node + } + }else{ m_time += m_ibg_sec; m_single_burst = m_single_burst_refill; - + thread->m_node_gen.m_p_queue.push( (CGenNode *)this); } - thread->m_node_gen.m_p_queue.push( (CGenNode *)this); } } @@ -168,10 +239,14 @@ public: void free_stl_node(); +public: + /* debug functions */ - void Dump(FILE *fd){ - fprintf(fd," %f, %lu, %lu \n",m_time,(ulong)m_port_id,(ulong)get_mbuf_cache_dir()); - } + int get_stream_id(); + + static void DumpHeader(FILE *fd); + + void Dump(FILE *fd); } __rte_cache_aligned; diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 2e3acffd..856fd9e3 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -88,7 +89,6 @@ TrexStatelessDpQuit::clone(){ } - bool TrexStatelessDpQuit::handle(TrexStatelessDpCore *dp_core){ /* quit */ @@ -96,3 +96,22 @@ bool TrexStatelessDpQuit::handle(TrexStatelessDpCore *dp_core){ return (true); } + +bool TrexStatelessDpCanQuit::handle(TrexStatelessDpCore *dp_core){ + + if ( dp_core->are_all_ports_idle() ){ + /* if all ports are idle quit now */ + set_quit(true); + } + return (true); +} + +TrexStatelessCpToDpMsgBase * +TrexStatelessDpCanQuit::clone(){ + + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpCanQuit(); + + return new_msg; +} + + diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 6473a6a4..7dc307c7 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -36,6 +36,7 @@ class TrexStatelessCpToDpMsgBase { public: TrexStatelessCpToDpMsgBase() { + m_quit_scheduler=false; } virtual ~TrexStatelessCpToDpMsgBase() { @@ -54,9 +55,19 @@ public: */ virtual TrexStatelessCpToDpMsgBase * clone() = 0; + /* do we want to quit scheduler, can be set by handle function */ + void set_quit(bool enable){ + m_quit_scheduler=enable; + } + + bool is_quit(){ + return ( m_quit_scheduler); + } + /* no copy constructor */ TrexStatelessCpToDpMsgBase(TrexStatelessCpToDpMsgBase &) = delete; - +private: + bool m_quit_scheduler; }; /** @@ -116,5 +127,22 @@ public: virtual TrexStatelessCpToDpMsgBase * clone(); }; +/** + * a message to check if both port are idel and exit + * + * @author hhaim + */ +class TrexStatelessDpCanQuit : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpCanQuit() { + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + + virtual TrexStatelessCpToDpMsgBase * clone(); +}; + + #endif /* __TREX_STATELESS_MESSAGING_H__ */ -- cgit From a2625fbfa24a812b950c1a95ef067e6fa169a3cf Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 19 Nov 2015 09:08:28 +0200 Subject: add a test for stream program --- src/stateless/dp/trex_stateless_dp_core.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 640fdb4d..c4fdd44b 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -435,9 +435,10 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, lp_port->m_active_nodes.push_back(one_stream); - /* schedule */ - m_core->m_node_gen.add_node((CGenNode *)node); - + /* schedule only if active */ + if (node->m_state == CGenNodeStateless::ss_ACTIVE) { + m_core->m_node_gen.add_node((CGenNode *)node); + } } void -- cgit From 91a4e6cc117076d3f5d34437581f7ffe91e6892b Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 19 Nov 2015 10:44:39 +0200 Subject: another stream program tests --- src/stateless/dp/trex_stateless_dp_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 28fff2fb..85afcf8f 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -88,7 +88,7 @@ public: enum state_e { STATE_IDLE, STATE_TRANSMITTING, - STATE_TERMINATE, + STATE_TERMINATE }; -- cgit From a7317d45787669af71ca8c65fd1e51f8a47d2c1e Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 19 Nov 2015 12:35:16 +0200 Subject: async events (DP to CP) --- src/stateless/cp/trex_stateless.cpp | 2 +- src/stateless/cp/trex_stateless_port.cpp | 56 +++++++++++++--- src/stateless/cp/trex_stateless_port.h | 38 +++++++++-- src/stateless/cp/trex_streams_compiler.h | 4 ++ src/stateless/dp/trex_stateless_dp_core.cpp | 13 ++-- src/stateless/dp/trex_stateless_dp_core.h | 9 +++ .../messaging/trex_stateless_messaging.cpp | 23 ++++++- src/stateless/messaging/trex_stateless_messaging.h | 76 ++++++++++++++++++---- 8 files changed, 188 insertions(+), 33 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index e0e95450..6ef24a7b 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -47,7 +47,7 @@ TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) { m_port_count = cfg.m_port_count; for (int i = 0; i < m_port_count; i++) { - m_ports.push_back(new TrexStatelessPort(i)); + m_ports.push_back(new TrexStatelessPort(i, cfg.m_platform_api)); } m_platform_api = cfg.m_platform_api; diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index cbc5a328..13d0fc9f 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -52,9 +52,25 @@ using namespace std; * trex stateless port * **************************/ -TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { +TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api) { + std::vector> core_pair_list; + + m_port_id = port_id; + m_port_state = PORT_STATE_IDLE; clear_owner(); + + /* get the DP cores belonging to this port */ + api->port_id_to_cores(m_port_id, core_pair_list); + + for (auto core_pair : core_pair_list) { + + /* send the core id */ + m_cores_id_list.push_back(core_pair.first); + } + + /* init the events DP DB */ + m_dp_events.create(this); } @@ -105,11 +121,16 @@ TrexStatelessPort::start_traffic(double mul, double duration) { } /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(compiled_obj, duration); + m_event_id = m_dp_events.generate_event_id(); + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_event_id, compiled_obj, duration); + + change_state(PORT_STATE_TX); send_message_to_dp(start_msg); - change_state(PORT_STATE_TX); + /* mark that DP event of stoppped is possible */ + m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, m_event_id); + } /** @@ -279,15 +300,32 @@ TrexStatelessPort::encode_stats(Json::Value &port) { void TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) { - std::vector> cores_id_list; - - get_stateless_obj()->get_platform_api()->port_id_to_cores(m_port_id, cores_id_list); - - for (auto core_pair : cores_id_list) { + for (auto core_id : m_cores_id_list) { /* send the message to the core */ - CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_pair.first); + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_id); ring->Enqueue((CGenNode *)msg->clone()); } } + +/** + * when a DP (async) event occurs - handle it + * + */ +void +TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { + switch (event_type) { + + case TrexDpPortEvent::EVENT_STOP: + /* set a stop event */ + change_state(PORT_STATE_STREAMS); + /* send a ZMQ event */ + break; + + default: + assert(0); + + } + printf("hey"); +} diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index b533f793..da75284e 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -22,7 +22,9 @@ limitations under the License. #define __TREX_STATELESS_PORT_H__ #include +#include +class TrexPlatformApi; class TrexStatelessCpToDpMsgBase; /** @@ -31,6 +33,8 @@ class TrexStatelessCpToDpMsgBase; * @author imarom (31-Aug-15) */ class TrexStatelessPort { + friend class TrexDpPortEvent; + public: /** @@ -54,7 +58,7 @@ public: RC_ERR_FAILED_TO_COMPILE_STREAMS }; - TrexStatelessPort(uint8_t port_id); + TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api); /** * acquire port @@ -199,6 +203,10 @@ public: m_stream_table.get_object_list(object_list); } + TrexDpPortEvents & get_dp_events() { + return m_dp_events; + } + private: @@ -224,6 +232,10 @@ private: } + const std::vector get_core_id_list () { + return m_cores_id_list; + } + bool verify_state(int state, bool should_throw = true) const; void change_state(port_state_e new_state); @@ -232,11 +244,25 @@ private: void send_message_to_dp(TrexStatelessCpToDpMsgBase *msg); - TrexStreamTable m_stream_table; - uint8_t m_port_id; - port_state_e m_port_state; - std::string m_owner; - std::string m_owner_handler; + /** + * triggered when event occurs + * + */ + void on_dp_event_occured(TrexDpPortEvent::event_e event_type); + + + TrexStreamTable m_stream_table; + uint8_t m_port_id; + port_state_e m_port_state; + std::string m_owner; + std::string m_owner_handler; + + /* holds the DP cores associated with this port */ + //std::vector> m_cores_id_list; + std::vector m_cores_id_list; + + TrexDpPortEvents m_dp_events; + int m_event_id; }; #endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 42cfc5b8..c80dddef 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -60,6 +60,10 @@ public: return (m_mul); } + uint8_t get_port_id() { + return m_port_id; + } + private: void add_compiled_stream(TrexStream * stream); std::vector m_objs; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 0747c1a0..4a74d9e5 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -227,6 +227,7 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, double duration) if ( duration > 0.0 ){ add_duration( duration ); } + } void @@ -261,11 +262,15 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { m_core->m_node_gen.add_node(node); } - /* send a message to the control plane to - generate an async event that traffic has stopped + /* inform the control plane we stopped - this might be a async stop + (streams ended) */ - //CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(m_core->m_thread_id); - //ring->Enqueue((CGenNode *)msg->clone()); + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(m_core->m_thread_id); + TrexStatelessDpToCpMsgBase *event_msg = new TrexDpPortEventMsg(m_core->m_thread_id, + port_id, + TrexDpPortEvent::EVENT_STOP, + get_event_id()); + ring->Enqueue((CGenNode *)event_msg); } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index aaa6eed3..d07e1d3a 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -112,6 +112,14 @@ public: /* quit the main loop, work in both stateless in stateful, don't free memory trigger from master */ void quit_main_loop(); + void set_event_id(int event_id) { + m_event_id = event_id; + } + + int get_event_id() { + return m_event_id; + } + private: /** * in idle state loop, the processor most of the time sleeps @@ -152,6 +160,7 @@ private: CFlowGenListPerThread *m_core; double m_duration; + int m_event_id; }; #endif /* __TREX_STATELESS_DP_CORE_H__ */ diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 2e3acffd..a2d00f8b 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -21,12 +21,17 @@ limitations under the License. #include #include #include +#include + #include /************************* start traffic message ************************/ -TrexStatelessDpStart::TrexStatelessDpStart(TrexStreamsCompiledObj *obj, double duration) : m_obj(obj), m_duration(duration) { +TrexStatelessDpStart::TrexStatelessDpStart(int event_id, TrexStreamsCompiledObj *obj, double duration) { + m_event_id = event_id; + m_obj = obj; + m_duration = duration; } @@ -39,7 +44,7 @@ TrexStatelessDpStart::clone() { TrexStreamsCompiledObj *new_obj = m_obj->clone(); - TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(new_obj, m_duration); + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(m_event_id, new_obj, m_duration); return new_msg; } @@ -53,7 +58,12 @@ TrexStatelessDpStart::~TrexStatelessDpStart() { bool TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { + /* mark the event id for DP response */ + dp_core->set_event_id(m_event_id); + + /* staet traffic */ dp_core->start_traffic(m_obj, m_duration); + return true; } @@ -96,3 +106,12 @@ bool TrexStatelessDpQuit::handle(TrexStatelessDpCore *dp_core){ return (true); } + +/************************* messages from DP to CP **********************/ +bool +TrexDpPortEventMsg::handle() { + TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_port_id); + port->get_dp_events().handle_event(m_event_type, m_thread_id, m_event_id); + + return (true); +} diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 6473a6a4..3fb1ef84 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -23,6 +23,7 @@ limitations under the License. #define __TREX_STATELESS_MESSAGING_H__ #include +#include class TrexStatelessDpCore; class TrexStreamsCompiledObj; @@ -41,12 +42,8 @@ public: virtual ~TrexStatelessCpToDpMsgBase() { } - /** - * virtual function to handle a message - * - */ - virtual bool handle(TrexStatelessDpCore *dp_core) = 0; + virtual bool handle(TrexStatelessDpCore *dp_core) = 0; /** * clone the current message @@ -57,6 +54,8 @@ public: /* no copy constructor */ TrexStatelessCpToDpMsgBase(TrexStatelessCpToDpMsgBase &) = delete; +protected: + int m_event_id; }; /** @@ -67,16 +66,17 @@ public: class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { public: - TrexStatelessDpStart(TrexStreamsCompiledObj *obj, double duration); + TrexStatelessDpStart(int m_event_id, TrexStreamsCompiledObj *obj, double duration); ~TrexStatelessDpStart(); - virtual bool handle(TrexStatelessDpCore *dp_core); - virtual TrexStatelessCpToDpMsgBase * clone(); + virtual bool handle(TrexStatelessDpCore *dp_core); private: + + int m_event_id; TrexStreamsCompiledObj *m_obj; double m_duration; }; @@ -92,10 +92,10 @@ public: TrexStatelessDpStop(uint8_t port_id) : m_port_id(port_id) { } - virtual bool handle(TrexStatelessDpCore *dp_core); - virtual TrexStatelessCpToDpMsgBase * clone(); + virtual bool handle(TrexStatelessDpCore *dp_core); + private: uint8_t m_port_id; }; @@ -111,10 +111,64 @@ public: TrexStatelessDpQuit() { } - virtual bool handle(TrexStatelessDpCore *dp_core); virtual TrexStatelessCpToDpMsgBase * clone(); + + virtual bool handle(TrexStatelessDpCore *dp_core); + +}; + +/************************* messages from DP to CP **********************/ + +/** + * defines the base class for CP to DP messages + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessDpToCpMsgBase { +public: + + TrexStatelessDpToCpMsgBase() { + } + + virtual ~TrexStatelessDpToCpMsgBase() { + } + + /** + * virtual function to handle a message + * + */ + virtual bool handle() = 0; + + /* no copy constructor */ + TrexStatelessDpToCpMsgBase(TrexStatelessDpToCpMsgBase &) = delete; + }; +/** + * a message indicating an event has happened on a port at the + * DP + * + */ +class TrexDpPortEventMsg : public TrexStatelessDpToCpMsgBase { +public: + + TrexDpPortEventMsg(int thread_id, uint8_t port_id, TrexDpPortEvent::event_e type, int event_id) { + m_thread_id = thread_id; + m_port_id = port_id; + m_event_type = type; + m_event_id = event_id; + } + + virtual bool handle(); + +private: + int m_thread_id; + uint8_t m_port_id; + TrexDpPortEvent::event_e m_event_type; + int m_event_id; + +}; #endif /* __TREX_STATELESS_MESSAGING_H__ */ + -- cgit From 2ae2e4e860194ee8d2b5ec5c4a1375751f51dd98 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 19 Nov 2015 17:17:38 +0200 Subject: full async DP stop support --- src/stateless/cp/trex_stateless.cpp | 2 ++ src/stateless/cp/trex_stateless.h | 9 +++++++++ src/stateless/cp/trex_stateless_port.cpp | 6 +++++- src/stateless/messaging/trex_stateless_messaging.h | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 6ef24a7b..a4522837 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -51,6 +51,8 @@ TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) { } m_platform_api = cfg.m_platform_api; + m_publisher = cfg.m_publisher; + } /** diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 57c6ef1d..5c11be1e 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -30,6 +30,7 @@ limitations under the License. #include #include #include +#include #include @@ -93,6 +94,7 @@ public: m_rpc_async_cfg = NULL; m_rpc_server_verbose = false; m_platform_api = NULL; + m_publisher = NULL; } const TrexRpcServerConfig *m_rpc_req_resp_cfg; @@ -100,6 +102,7 @@ public: const TrexPlatformApi *m_platform_api; bool m_rpc_server_verbose; uint8_t m_port_count; + TrexPublisher *m_publisher; }; /** @@ -150,6 +153,10 @@ public: return (m_platform_api); } + TrexPublisher * get_publisher() { + return m_publisher; + } + const std::vector get_port_list() { return m_ports; } @@ -170,6 +177,8 @@ protected: /* platform API */ const TrexPlatformApi *m_platform_api; + TrexPublisher *m_publisher; + std::mutex m_global_cp_lock; }; diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 13d0fc9f..489e2172 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -315,17 +315,21 @@ TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) { */ void TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { + Json::Value data; + switch (event_type) { case TrexDpPortEvent::EVENT_STOP: /* set a stop event */ change_state(PORT_STATE_STREAMS); /* send a ZMQ event */ + + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STOPPED, data); break; default: assert(0); } - printf("hey"); } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 445e9378..ffb36124 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -192,6 +192,22 @@ public: virtual bool handle(); + int get_thread_id() { + return m_thread_id; + } + + uint8_t get_port_id() { + return m_port_id; + } + + TrexDpPortEvent::event_e get_event_type() { + return m_event_type; + } + + int get_event_id() { + return m_event_id; + } + private: int m_thread_id; uint8_t m_port_id; -- cgit From 34191e258a032cf78a171752eece903bb06f6751 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 19 Nov 2015 17:47:42 +0200 Subject: disable stop event when you got it as a sync request --- src/stateless/cp/trex_dp_port_events.cpp | 5 +++++ src/stateless/cp/trex_dp_port_events.h | 6 ++++++ src/stateless/cp/trex_stateless_port.cpp | 3 +++ 3 files changed, 14 insertions(+) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_dp_port_events.cpp b/src/stateless/cp/trex_dp_port_events.cpp index 533ab605..f74068a3 100644 --- a/src/stateless/cp/trex_dp_port_events.cpp +++ b/src/stateless/cp/trex_dp_port_events.cpp @@ -64,6 +64,11 @@ TrexDpPortEvents::wait_for_event(TrexDpPortEvent::event_e ev, int event_id, int m_events[ev].wait_for_event(event_id, timeout_ms); } +void +TrexDpPortEvents::disable(TrexDpPortEvent::event_e ev) { + m_events[ev].disable(); +} + /** * handle an event * diff --git a/src/stateless/cp/trex_dp_port_events.h b/src/stateless/cp/trex_dp_port_events.h index 309288df..557e590b 100644 --- a/src/stateless/cp/trex_dp_port_events.h +++ b/src/stateless/cp/trex_dp_port_events.h @@ -146,6 +146,12 @@ public: */ void wait_for_event(TrexDpPortEvent::event_e ev, int event_id, int timeout_ms = -1); + /** + * disable an event (don't care) + * + */ + void disable(TrexDpPortEvent::event_e ev); + /** * event has occured * diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 489e2172..43960d5e 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -153,6 +153,9 @@ TrexStatelessPort::stop_traffic(void) { send_message_to_dp(stop_msg); change_state(PORT_STATE_STREAMS); + + /* mask out the DP stop event */ + m_dp_events.disable(TrexDpPortEvent::EVENT_STOP); } void -- cgit From 90e283923e5d860803eae5996a1247b1390ea36a Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 19 Nov 2015 18:14:58 +0200 Subject: a bug in back to back start/stop --- src/stateless/cp/trex_dp_port_events.cpp | 4 ++-- src/stateless/cp/trex_stateless_port.cpp | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_dp_port_events.cpp b/src/stateless/cp/trex_dp_port_events.cpp index f74068a3..ba327e59 100644 --- a/src/stateless/cp/trex_dp_port_events.cpp +++ b/src/stateless/cp/trex_dp_port_events.cpp @@ -175,9 +175,9 @@ TrexDpPortEvent::handle_event(int thread_id, int event_id) { return; } - /* check the event id is matching the required event */ + /* check the event id is matching the required event - if not maybe its an old signal */ if (event_id != m_event_id) { - err(thread_id, event_id, "event key mismatch"); + return; } /* mark sure no double signal */ diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 43960d5e..795c0f12 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -122,14 +122,14 @@ TrexStatelessPort::start_traffic(double mul, double duration) { /* generate a message to all the relevant DP cores to start transmitting */ m_event_id = m_dp_events.generate_event_id(); + /* mark that DP event of stoppped is possible */ + m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, m_event_id); + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_event_id, compiled_obj, duration); change_state(PORT_STATE_TX); send_message_to_dp(start_msg); - - /* mark that DP event of stoppped is possible */ - m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, m_event_id); } @@ -147,15 +147,16 @@ TrexStatelessPort::stop_traffic(void) { return; } + /* mask out the DP stop event */ + m_dp_events.disable(TrexDpPortEvent::EVENT_STOP); + /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); send_message_to_dp(stop_msg); change_state(PORT_STATE_STREAMS); - - /* mask out the DP stop event */ - m_dp_events.disable(TrexDpPortEvent::EVENT_STOP); + } void -- cgit From b094110ef86889a0694dc71503c5610abaf47ebe Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 19 Nov 2015 22:13:55 +0200 Subject: BUG: didn't do all the states per port on the DP - now fixed --- src/stateless/cp/trex_stateless_port.cpp | 6 ++--- src/stateless/cp/trex_stateless_port.h | 2 -- src/stateless/dp/trex_stateless_dp_core.cpp | 2 +- src/stateless/dp/trex_stateless_dp_core.h | 27 ++++++++++++++-------- .../messaging/trex_stateless_messaging.cpp | 11 ++++++--- src/stateless/messaging/trex_stateless_messaging.h | 8 ++++--- 6 files changed, 35 insertions(+), 21 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 795c0f12..fbc5f7c7 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -121,11 +121,11 @@ TrexStatelessPort::start_traffic(double mul, double duration) { } /* generate a message to all the relevant DP cores to start transmitting */ - m_event_id = m_dp_events.generate_event_id(); + int event_id = m_dp_events.generate_event_id(); /* mark that DP event of stoppped is possible */ - m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, m_event_id); + m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, event_id); - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_event_id, compiled_obj, duration); + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_obj, duration); change_state(PORT_STATE_TX); diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index da75284e..73157c15 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -258,11 +258,9 @@ private: std::string m_owner_handler; /* holds the DP cores associated with this port */ - //std::vector> m_cores_id_list; std::vector m_cores_id_list; TrexDpPortEvents m_dp_events; - int m_event_id; }; #endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index cde34a4b..6db66661 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -525,7 +525,7 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { TrexStatelessDpToCpMsgBase *event_msg = new TrexDpPortEventMsg(m_core->m_thread_id, port_id, TrexDpPortEvent::EVENT_STOP, - get_event_id()); + lp_port->get_event_id()); ring->Enqueue((CGenNode *)event_msg); } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 7ee5abc4..c0bbe702 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -66,6 +66,18 @@ public: bool update_number_of_active_streams(uint32_t d); + state_e get_state() { + return m_state; + } + + void set_event_id(int event_id) { + m_event_id = event_id; + } + + int get_event_id() { + return m_event_id; + } + public: state_e m_state; @@ -75,6 +87,7 @@ public: std::vector m_active_nodes; /* holds the current active nodes */ CFlowGenListPerThread * m_core ; + int m_event_id; }; /* for now */ @@ -166,19 +179,13 @@ public: /* quit the main loop, work in both stateless in stateful, don't free memory trigger from master */ void quit_main_loop(); - void set_event_id(int event_id) { - m_event_id = event_id; - } - - int get_event_id() { - return m_event_id; + state_e get_state() { + return m_state; } bool set_stateless_next_node(CGenNodeStateless * cur_node, CGenNodeStateless * next_node); -private: - TrexStatelessDpPerPort * get_port_db(uint8_t port_id){ assert((m_local_port_offset==port_id) ||(m_local_port_offset+1==port_id)); @@ -188,6 +195,9 @@ private: } + +private: + void schedule_exit(); @@ -236,7 +246,6 @@ private: CFlowGenListPerThread * m_core; double m_duration; - int m_event_id; }; #endif /* __TREX_STATELESS_DP_CORE_H__ */ diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index c92ad68a..629fe24c 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -29,7 +29,8 @@ limitations under the License. /************************* start traffic message ************************/ -TrexStatelessDpStart::TrexStatelessDpStart(int event_id, TrexStreamsCompiledObj *obj, double duration) { +TrexStatelessDpStart::TrexStatelessDpStart(uint8_t port_id, int event_id, TrexStreamsCompiledObj *obj, double duration) { + m_port_id = port_id; m_event_id = event_id; m_obj = obj; m_duration = duration; @@ -45,7 +46,7 @@ TrexStatelessDpStart::clone() { TrexStreamsCompiledObj *new_obj = m_obj->clone(); - TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(m_event_id, new_obj, m_duration); + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(m_port_id, m_event_id, new_obj, m_duration); return new_msg; } @@ -60,7 +61,7 @@ bool TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { /* mark the event id for DP response */ - dp_core->set_event_id(m_event_id); + dp_core->get_port_db(m_port_id)->set_event_id(m_event_id); /* staet traffic */ dp_core->start_traffic(m_obj, m_duration); @@ -73,6 +74,10 @@ TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { ************************/ bool TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { + if (dp_core->get_port_db(m_port_id)->get_state() == TrexStatelessDpPerPort::ppSTATE_IDLE) { + return true; + } + dp_core->stop_traffic(m_port_id); return true; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index ffb36124..2fb5a024 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -77,7 +77,7 @@ protected: class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { public: - TrexStatelessDpStart(int m_event_id, TrexStreamsCompiledObj *obj, double duration); + TrexStatelessDpStart(uint8_t m_port_id, int m_event_id, TrexStreamsCompiledObj *obj, double duration); ~TrexStatelessDpStart(); @@ -87,9 +87,11 @@ public: private: - int m_event_id; + uint8_t m_port_id; + int m_event_id; TrexStreamsCompiledObj *m_obj; - double m_duration; + double m_duration; + }; /** -- cgit From 8c1cf5d7690fd3e44d196fc6453a2bc5db5a3c9b Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sat, 21 Nov 2015 18:22:55 +0200 Subject: fix crash in case of CNTL-C --- src/stateless/dp/trex_stateless_dp_core.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index c4fdd44b..a6fe3f56 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -126,7 +126,11 @@ bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){ void TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ - assert(m_state==TrexStatelessDpPerPort::ppSTATE_TRANSMITTING); + /* there could be race of stop after stop */ + if (m_state == TrexStatelessDpPerPort::ppSTATE_IDLE) { + assert(m_active_streams==0); + return; + } for (auto dp_stream : m_active_nodes) { CGenNodeStateless * node =dp_stream.m_node; @@ -259,8 +263,10 @@ TrexStatelessDpCore::start_scheduler() { double old_offset = 0.0; m_core->m_node_gen.flush_file(-1, 0.0, false, m_core, old_offset); - /* TBD do we need that ? */ - m_core->m_node_gen.close_file(m_core); + /* bail out in case of terminate */ + if (m_state != TrexStatelessDpCore::STATE_TERMINATE) { + m_core->m_node_gen.close_file(m_core); + } } -- cgit From 36dc8ea51adffce882e542123111baad7a1a7ea7 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sat, 21 Nov 2015 23:00:43 +0200 Subject: add back to back test of DP --- src/stateless/dp/trex_stateless_dp_core.cpp | 11 ++++++++--- src/stateless/dp/trex_stateless_dp_core.h | 2 +- src/stateless/messaging/trex_stateless_messaging.cpp | 3 --- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index e17c9075..6430e520 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -124,12 +124,12 @@ bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){ } -void TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ +bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ /* there could be race of stop after stop */ if (m_state == TrexStatelessDpPerPort::ppSTATE_IDLE) { assert(m_active_streams==0); - return; + return false; } for (auto dp_stream : m_active_nodes) { @@ -149,6 +149,7 @@ void TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ assert(m_active_streams==0); m_active_nodes.clear(); m_state=TrexStatelessDpPerPort::ppSTATE_IDLE; + return (true); } @@ -517,7 +518,11 @@ TrexStatelessDpCore::stop_traffic(uint8_t port_id) { TrexStatelessDpPerPort * lp_port = get_port_db(port_id); - lp_port->stop_traffic(port_id); + if ( lp_port->stop_traffic(port_id) == false){ + /* nothing to do ! already stopped */ + return; + } + if ( are_all_ports_idle() ) { diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index c0bbe702..326bbe30 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -62,7 +62,7 @@ public: void create(CFlowGenListPerThread * core); - void stop_traffic(uint8_t port_id); + bool stop_traffic(uint8_t port_id); bool update_number_of_active_streams(uint32_t d); diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 629fe24c..c861d0fa 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -74,9 +74,6 @@ TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { ************************/ bool TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { - if (dp_core->get_port_db(m_port_id)->get_state() == TrexStatelessDpPerPort::ppSTATE_IDLE) { - return true; - } dp_core->stop_traffic(m_port_id); return true; -- cgit From 3408c03067a85789b2128352fdc2343ab707ae32 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sun, 22 Nov 2015 13:02:08 +0200 Subject: fix stop on duration per port --- src/stateless/dp/trex_stateless_dp_core.cpp | 56 +++++++++++++++------- src/stateless/dp/trex_stateless_dp_core.h | 13 +++-- src/stateless/dp/trex_stream_node.h | 1 + .../messaging/trex_stateless_messaging.cpp | 25 +++++++--- src/stateless/messaging/trex_stateless_messaging.h | 41 ++++++++++++++++ 5 files changed, 109 insertions(+), 27 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 6430e520..f8afb3bb 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -78,9 +78,10 @@ void CGenNodeStateless::refresh(){ } - void CGenNodeCommand::free_command(){ + assert(m_cmd); + m_cmd->on_node_remove(); delete m_cmd; } @@ -124,14 +125,23 @@ bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){ } -bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id){ +bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id, + bool stop_on_id, + int event_id){ - /* there could be race of stop after stop */ if (m_state == TrexStatelessDpPerPort::ppSTATE_IDLE) { assert(m_active_streams==0); return false; } + /* there could be race of stop after stop */ + if ( stop_on_id ) { + if (event_id != m_event_id){ + /* we can't stop it is an old message */ + return false; + } + } + for (auto dp_stream : m_active_nodes) { CGenNodeStateless * node =dp_stream.m_node; assert(node->get_port_id() == port_id); @@ -215,7 +225,7 @@ bool TrexStatelessDpCore::set_stateless_next_node(CGenNodeStateless * cur_node, if ( to_stop_port ) { /* call stop port explictly to move the state */ - stop_traffic(cur_node->m_port_id); + stop_traffic(cur_node->m_port_id,false,0); } return ( schedule ); @@ -330,7 +340,8 @@ TrexStatelessDpCore::add_global_duration(double duration){ /* add per port exit */ void TrexStatelessDpCore::add_port_duration(double duration, - uint8_t port_id){ + uint8_t port_id, + int event_id){ if (duration > 0.0) { CGenNodeCommand *node = (CGenNodeCommand *)m_core->create_node() ; @@ -339,7 +350,16 @@ TrexStatelessDpCore::add_port_duration(double duration, /* make sure it will be scheduled after the current node */ node->m_time = m_core->m_cur_time_sec + duration ; - node->m_cmd = new TrexStatelessDpStop(port_id); + TrexStatelessDpStop * cmd=new TrexStatelessDpStop(port_id); + + + /* test this */ + m_core->m_non_active_nodes++; + cmd->set_core_ptr(m_core); + cmd->set_event_id(event_id); + cmd->set_wait_for_event_id(true); + + node->m_cmd = cmd; m_core->m_node_gen.add_node((CGenNode *)node); } @@ -450,15 +470,14 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, void TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, - double duration) { + double duration, + int event_id) { -#if 0 - /* TBD to remove ! */ - obj->Dump(stdout); -#endif TrexStatelessDpPerPort * lp_port=get_port_db(obj->get_port_id()); lp_port->m_active_streams = 0; + lp_port->set_event_id(event_id); + /* no nodes in the list */ assert(lp_port->m_active_nodes.size()==0); @@ -491,7 +510,7 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, if ( duration > 0.0 ){ - add_port_duration( duration ,obj->get_port_id() ); + add_port_duration( duration ,obj->get_port_id(),event_id ); } } @@ -511,23 +530,26 @@ bool TrexStatelessDpCore::are_all_ports_idle(){ void -TrexStatelessDpCore::stop_traffic(uint8_t port_id) { +TrexStatelessDpCore::stop_traffic(uint8_t port_id, + bool stop_on_id, + int event_id) { /* we cannot remove nodes not from the top of the queue so for every active node - make sure next time the scheduler invokes it, it will be free */ TrexStatelessDpPerPort * lp_port = get_port_db(port_id); - if ( lp_port->stop_traffic(port_id) == false){ + if ( lp_port->stop_traffic(port_id,stop_on_id,event_id) == false){ /* nothing to do ! already stopped */ + //printf(" skip .. %f\n",m_core->m_cur_time_sec); return; } - +#if 0 if ( are_all_ports_idle() ) { - - schedule_exit(); + /* just a place holder if we will need to do somthing in that case */ } +#endif /* inform the control plane we stopped - this might be a async stop (streams ended) diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 326bbe30..187c40d8 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -62,7 +62,9 @@ public: void create(CFlowGenListPerThread * core); - bool stop_traffic(uint8_t port_id); + bool stop_traffic(uint8_t port_id, + bool stop_on_id, + int event_id); bool update_number_of_active_streams(uint32_t d); @@ -137,13 +139,15 @@ public: * @param pkt * @param pkt_len */ - void start_traffic(TrexStreamsCompiledObj *obj, double duration = -1); + void start_traffic(TrexStreamsCompiledObj *obj, + double duration, + int m_event_id); /** * stop all traffic for this core * */ - void stop_traffic(uint8_t port_id); + void stop_traffic(uint8_t port_id,bool stop_on_id, int event_id); /* return if all ports are idel */ @@ -225,7 +229,8 @@ private: void add_port_duration(double duration, - uint8_t port_id); + uint8_t port_id, + int event_id); void add_global_duration(double duration); diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 1e53887b..20e32b78 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -29,6 +29,7 @@ class TrexStatelessDpCore; #include class TrexStatelessCpToDpMsgBase; +class CFlowGenListPerThread; struct CGenNodeCommand : public CGenNodeBase { diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index c861d0fa..bbd4b68c 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -23,6 +23,7 @@ limitations under the License. #include #include #include +#include #include @@ -60,11 +61,8 @@ TrexStatelessDpStart::~TrexStatelessDpStart() { bool TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { - /* mark the event id for DP response */ - dp_core->get_port_db(m_port_id)->set_event_id(m_event_id); - /* staet traffic */ - dp_core->start_traffic(m_obj, m_duration); + dp_core->start_traffic(m_obj, m_duration,m_event_id); return true; } @@ -75,17 +73,32 @@ TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { bool TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { - dp_core->stop_traffic(m_port_id); + + dp_core->stop_traffic(m_port_id,m_stop_only_for_event_id,m_event_id); return true; } + +void TrexStatelessDpStop::on_node_remove(){ + if ( m_core ) { + assert(m_core->m_non_active_nodes>0); + m_core->m_non_active_nodes--; + } +} + + /** * clone for DP stop message * */ TrexStatelessCpToDpMsgBase * TrexStatelessDpStop::clone() { - TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStop(m_port_id); + TrexStatelessDpStop *new_msg = new TrexStatelessDpStop(m_port_id); + + new_msg->set_event_id(m_event_id); + new_msg->set_wait_for_event_id(m_stop_only_for_event_id); + /* set back pointer to master */ + new_msg->set_core_ptr(m_core); return new_msg; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 2fb5a024..afa5953a 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -27,6 +27,7 @@ limitations under the License. class TrexStatelessDpCore; class TrexStreamsCompiledObj; +class CFlowGenListPerThread; /** * defines the base class for CP to DP messages @@ -61,6 +62,10 @@ public: return ( m_quit_scheduler); } + /* this node is called from scheduler in case the node is free */ + virtual void on_node_remove(){ + } + /* no copy constructor */ TrexStatelessCpToDpMsgBase(TrexStatelessCpToDpMsgBase &) = delete; @@ -103,14 +108,50 @@ class TrexStatelessDpStop : public TrexStatelessCpToDpMsgBase { public: TrexStatelessDpStop(uint8_t port_id) : m_port_id(port_id) { + m_stop_only_for_event_id=false; + m_event_id=0; + m_core = NULL; } virtual TrexStatelessCpToDpMsgBase * clone(); + virtual bool handle(TrexStatelessDpCore *dp_core); + void set_core_ptr(CFlowGenListPerThread * core){ + m_core = core; + } + + CFlowGenListPerThread * get_core_ptr(){ + return ( m_core); + } + + + void set_event_id(int event_id){ + m_event_id = event_id; + } + + void set_wait_for_event_id(bool wait){ + m_stop_only_for_event_id = wait; + } + + virtual void on_node_remove(); + + + bool get_is_stop_by_event_id(){ + return (m_stop_only_for_event_id); + } + + int get_event_id(){ + return (m_event_id); + } + private: uint8_t m_port_id; + bool m_stop_only_for_event_id; + int m_event_id; + CFlowGenListPerThread * m_core ; + }; /** -- cgit From bd8b640077591377375f2ab5ec6c542119ead0a2 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Sun, 22 Nov 2015 18:02:22 +0200 Subject: dp support for pause/resume only continues is supported --- src/stateless/dp/trex_stateless_dp_core.cpp | 52 ++++++++++++++++++++++ src/stateless/dp/trex_stateless_dp_core.h | 18 +++++++- src/stateless/dp/trex_stream_node.h | 19 +++++++- .../messaging/trex_stateless_messaging.cpp | 25 +++++++++++ src/stateless/messaging/trex_stateless_messaging.h | 36 +++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index f8afb3bb..03b13d6c 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -124,6 +124,37 @@ bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){ return (false); } +bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){ + + /* we are working with continues streams so we must be in transmit mode */ + assert(m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE); + + for (auto dp_stream : m_active_nodes) { + CGenNodeStateless * node =dp_stream.m_node; + assert(node->get_port_id() == port_id); + assert(node->is_pause() == true); + node->set_pause(false); + } + m_state = TrexStatelessDpPerPort::ppSTATE_TRANSMITTING; + return (true); +} + + +bool TrexStatelessDpPerPort::pause_traffic(uint8_t port_id){ + + /* we are working with continues streams so we must be in transmit mode */ + assert(m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING); + + for (auto dp_stream : m_active_nodes) { + CGenNodeStateless * node =dp_stream.m_node; + assert(node->get_port_id() == port_id); + assert(node->is_pause() == false); + node->set_pause(true); + } + m_state = TrexStatelessDpPerPort::ppSTATE_PAUSE; + return (true); +} + bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id, bool stop_on_id, @@ -294,6 +325,8 @@ TrexStatelessDpCore::run_once(){ } + + void TrexStatelessDpCore::start() { @@ -402,6 +435,7 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, uint16_t pkt_size = stream->m_pkt.len; const uint8_t *stream_pkt = stream->m_pkt.binary; + node->m_pause =0; node->m_stream_type = stream->m_type; node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ; @@ -529,6 +563,24 @@ bool TrexStatelessDpCore::are_all_ports_idle(){ } +void +TrexStatelessDpCore::resume_traffic(uint8_t port_id){ + + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); + + lp_port->resume_traffic(port_id); +} + + +void +TrexStatelessDpCore::pause_traffic(uint8_t port_id){ + + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); + + lp_port->pause_traffic(port_id); +} + + void TrexStatelessDpCore::stop_traffic(uint8_t port_id, bool stop_on_id, diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 187c40d8..eda1ae59 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -53,7 +53,9 @@ public: /* states */ enum state_e { ppSTATE_IDLE, - ppSTATE_TRANSMITTING + ppSTATE_TRANSMITTING, + ppSTATE_PAUSE + }; public: @@ -62,6 +64,10 @@ public: void create(CFlowGenListPerThread * core); + bool pause_traffic(uint8_t port_id); + + bool resume_traffic(uint8_t port_id); + bool stop_traffic(uint8_t port_id, bool stop_on_id, int event_id); @@ -143,7 +149,17 @@ public: double duration, int m_event_id); + + /* pause the streams, work only if all are continues */ + void pause_traffic(uint8_t port_id); + + + + void resume_traffic(uint8_t port_id); + + /** + * * stop all traffic for this core * */ diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 20e32b78..ccf99eaa 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -48,6 +48,7 @@ public: static_assert(sizeof(CGenNodeCommand) == sizeof(CGenNode), "sizeof(CGenNodeCommand) != sizeof(CGenNode)" ); + /* this is a event for stateless */ struct CGenNodeStateless : public CGenNodeBase { friend class TrexStatelessDpCore; @@ -74,7 +75,7 @@ private: stream_state_t m_state; uint8_t m_port_id; uint8_t m_stream_type; /* see TrexStream::STREAM_TYPE ,stream_type_t */ - uint8_t m_pad; + uint8_t m_pause; uint32_t m_single_burst; /* the number of bursts in case of burst */ uint32_t m_single_burst_refill; @@ -112,7 +113,18 @@ public: /* only to be safe */ m_ref_stream_info= NULL; m_next_stream= NULL; + } + bool is_pause(){ + return (m_pause==1?true:false); + } + + void set_pause(bool enable){ + if ( enable ){ + m_pause=1; + }else{ + m_pause=0; + } } inline uint8_t get_stream_type(){ @@ -143,7 +155,10 @@ public: void refresh(); inline void handle_continues(CFlowGenListPerThread *thread) { - thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); + + if (unlikely (is_pause()==false)) { + thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); + } /* in case of continues */ m_time += m_next_time_offset; diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index bbd4b68c..ec8b7839 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -87,6 +87,31 @@ void TrexStatelessDpStop::on_node_remove(){ } +TrexStatelessCpToDpMsgBase * TrexStatelessDpPause::clone(){ + + TrexStatelessDpPause *new_msg = new TrexStatelessDpPause(m_port_id); + return new_msg; +} + + +bool TrexStatelessDpPause::handle(TrexStatelessDpCore *dp_core){ + dp_core->pause_traffic(m_port_id); + return (true); +} + + + +TrexStatelessCpToDpMsgBase * TrexStatelessDpResume::clone(){ + TrexStatelessDpResume *new_msg = new TrexStatelessDpResume(m_port_id); + return new_msg; +} + +bool TrexStatelessDpResume::handle(TrexStatelessDpCore *dp_core){ + dp_core->resume_traffic(m_port_id); + return (true); +} + + /** * clone for DP stop message * diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index afa5953a..6bd0dbe3 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -99,6 +99,42 @@ private: }; +class TrexStatelessDpPause : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpPause(uint8_t port_id) : m_port_id(port_id) { + } + + + virtual TrexStatelessCpToDpMsgBase * clone(); + + + virtual bool handle(TrexStatelessDpCore *dp_core); + + +private: + uint8_t m_port_id; +}; + + +class TrexStatelessDpResume : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpResume(uint8_t port_id) : m_port_id(port_id) { + } + + + virtual TrexStatelessCpToDpMsgBase * clone(); + + + virtual bool handle(TrexStatelessDpCore *dp_core); + + +private: + uint8_t m_port_id; +}; + + /** * a message to stop traffic * -- cgit From 54c1f0fc29b3d4580f7a13cffbe625fe88e37b16 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Mon, 23 Nov 2015 14:10:19 +0200 Subject: add pause/resume into the console --- src/stateless/cp/trex_stateless_port.cpp | 25 +++++++++++++++---------- src/stateless/cp/trex_stateless_port.h | 5 +++++ src/stateless/cp/trex_streams_compiler.cpp | 7 ++++++- src/stateless/cp/trex_streams_compiler.h | 5 +++++ src/stateless/dp/trex_stateless_dp_core.cpp | 1 + 5 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index fbc5f7c7..40392e68 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -127,6 +127,9 @@ TrexStatelessPort::start_traffic(double mul, double duration) { TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_obj, duration); + m_last_all_streams_continues = compiled_obj->get_all_streams_continues(); + m_last_duration =duration; + change_state(PORT_STATE_TX); send_message_to_dp(start_msg); @@ -143,7 +146,8 @@ TrexStatelessPort::start_traffic(double mul, double duration) { void TrexStatelessPort::stop_traffic(void) { - if (m_port_state != PORT_STATE_TX) { + if (!( (m_port_state == PORT_STATE_TX) + || (m_port_state ==PORT_STATE_PAUSE) )) { return; } @@ -164,14 +168,18 @@ TrexStatelessPort::pause_traffic(void) { verify_state(PORT_STATE_TX); - #if 0 - /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + if (m_last_all_streams_continues == false) { + throw TrexRpcException(" pause is supported when all streams are in continues mode "); + } + + if ( m_last_duration>0.0 ) { + throw TrexRpcException(" pause is supported when duration is not enable is start command "); + } + + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpPause(m_port_id); send_message_to_dp(stop_msg); - m_port_state = PORT_STATE_UP_IDLE; - #endif change_state(PORT_STATE_PAUSE); } @@ -180,14 +188,11 @@ TrexStatelessPort::resume_traffic(void) { verify_state(PORT_STATE_PAUSE); - #if 0 /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpResume(m_port_id); send_message_to_dp(stop_msg); - m_port_state = PORT_STATE_UP_IDLE; - #endif change_state(PORT_STATE_TX); } diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 73157c15..006ec97c 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -207,6 +207,8 @@ public: return m_dp_events; } + + private: @@ -260,6 +262,9 @@ private: /* holds the DP cores associated with this port */ std::vector m_cores_id_list; + bool m_last_all_streams_continues; + double m_last_duration; + TrexDpPortEvents m_dp_events; }; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index bdfc3c01..302863ae 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -136,6 +136,7 @@ private: * stream compiled object *************************************/ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) { + m_all_continues=false; } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { @@ -401,6 +402,7 @@ TrexStreamsCompiler::compile(const std::vector &streams, } + bool all_continues=true; /* for now we do something trivial, */ for (auto stream : streams) { @@ -408,6 +410,9 @@ TrexStreamsCompiler::compile(const std::vector &streams, if (!stream->m_enabled) { continue; } + if (stream->get_type() != TrexStream::stCONTINUOUS ) { + all_continues=false; + } int new_id= nodes.get(stream->m_stream_id)->m_compressed_stream_id; assert(new_id>=0); @@ -423,7 +428,7 @@ TrexStreamsCompiler::compile(const std::vector &streams, my_next_stream_id ); } - + obj.m_all_continues =all_continues; return true; } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 200f7ce9..17ca3c74 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -64,6 +64,10 @@ public: return (m_mul); } + bool get_all_streams_continues(){ + return (m_all_continues); + } + void Dump(FILE *fd); private: @@ -73,6 +77,7 @@ private: std::vector m_objs; + bool m_all_continues; uint8_t m_port_id; double m_mul; }; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 03b13d6c..9b4a6ad9 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -160,6 +160,7 @@ bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id, bool stop_on_id, int event_id){ + if (m_state == TrexStatelessDpPerPort::ppSTATE_IDLE) { assert(m_active_streams==0); return false; -- cgit From 1f6977d1e109acba69f1bf2230d6b9f5e4aae54e Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 23 Nov 2015 18:02:14 +0200 Subject: add stream graph + support for console to use any of the following bps, kbps, mbps, gbps, pps, kpps, mbps percentage is not working yet --- src/stateless/cp/trex_stateless_port.cpp | 33 ++++- src/stateless/cp/trex_stateless_port.h | 2 + src/stateless/cp/trex_stream.cpp | 2 + src/stateless/cp/trex_stream.h | 11 +- src/stateless/cp/trex_streams_compiler.cpp | 186 +++++++++++++++++++++++++++-- src/stateless/cp/trex_streams_compiler.h | 80 +++++++++++++ 6 files changed, 305 insertions(+), 9 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index fbc5f7c7..7dc217a3 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -111,9 +111,12 @@ TrexStatelessPort::start_traffic(double mul, double duration) { vector streams; get_object_list(streams); + /* split it per core */ + double per_core_mul = mul / m_cores_id_list.size(); + /* compiler it */ TrexStreamsCompiler compiler; - TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, mul); + TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, per_core_mul); bool rc = compiler.compile(streams, *compiled_obj); if (!rc) { @@ -133,6 +136,34 @@ TrexStatelessPort::start_traffic(double mul, double duration) { } +void +TrexStatelessPort::start_traffic_max_bps(double max_bps, double duration) { + /* fetch all the streams from the table */ + vector streams; + get_object_list(streams); + + TrexStreamsGraph graph; + const TrexStreamsGraphObj &obj = graph.generate(streams); + double m = (max_bps / obj.get_max_bps()); + + /* call the main function */ + start_traffic(m, duration); +} + +void +TrexStatelessPort::start_traffic_max_pps(double max_pps, double duration) { + /* fetch all the streams from the table */ + vector streams; + get_object_list(streams); + + TrexStreamsGraph graph; + const TrexStreamsGraphObj &obj = graph.generate(streams); + double m = (max_pps / obj.get_max_pps()); + + /* call the main function */ + start_traffic(m, duration); +} + /** * stop traffic on port * diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 73157c15..9b74741c 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -77,6 +77,8 @@ public: * throws TrexException in case of an error */ void start_traffic(double mul, double duration = -1); + void start_traffic_max_bps(double max_bps, double duration = -1); + void start_traffic_max_pps(double max_pps, double duration = -1); /** * stop traffic diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 5203b2a2..cad603e2 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -21,6 +21,7 @@ limitations under the License. #include #include #include +#include /************************************** * stream @@ -129,6 +130,7 @@ TrexStream::get_stream_json() { return m_stream_json; } + /************************************** * stream table *************************************/ diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 0634829e..5baba840 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -90,7 +90,7 @@ public: m_next_stream_id = next_stream_id; } - double get_pps() { + double get_pps() const { return m_pps; } @@ -150,6 +150,15 @@ public: return (dp); } + + double get_burst_length_usec() const { + return ( (m_burst_total_pkts / m_pps) * 1000 ); + } + + double get_bps() const { + return (m_pps * m_pkt.len * 8); + } + void Dump(FILE *fd); public: /* basic */ diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index bdfc3c01..f36de1b4 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -34,19 +34,25 @@ limitations under the License. */ class GraphNode { public: - GraphNode(TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) { - marked = false; + GraphNode(const TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) { + m_marked = false; m_compressed_stream_id=-1; + } uint32_t get_stream_id() const { return m_stream->m_stream_id; } + uint32_t get_next_stream_id() const { + return m_stream->m_next_stream_id; + + } + const TrexStream *m_stream; GraphNode *m_next; std::vector m_parents; - bool marked; + bool m_marked; int m_compressed_stream_id; }; @@ -97,13 +103,13 @@ public: void clear_marks() { for (auto node : m_nodes) { - node.second->marked = false; + node.second->m_marked = false; } } void get_unmarked(std::vector &unmarked) { for (auto node : m_nodes) { - if (!node.second->marked) { + if (!node.second->m_marked) { unmarked.push_back(node.second); } } @@ -132,6 +138,7 @@ private: GraphNode m_dead_end; }; + /************************************** * stream compiled object *************************************/ @@ -316,11 +323,11 @@ TrexStreamsCompiler::check_for_unreachable_streams(GraphNodeMap *nodes) { /* pull one */ GraphNode *node = next_nodes.back(); next_nodes.pop_back(); - if (node->marked) { + if (node->m_marked) { continue; } - node->marked = true; + node->m_marked = true; if (node->m_next != NULL) { next_nodes.push_back(node->m_next); @@ -422,9 +429,174 @@ TrexStreamsCompiler::compile(const std::vector &streams, my_stream_id, my_next_stream_id ); + } return true; } +/************************************** + * streams graph + *************************************/ + +void +TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, const TrexStream *stream) { + TrexStreamsGraphObj::rate_event_st start_event; + TrexStreamsGraphObj::rate_event_st stop_event; + + switch (stream->get_type()) { + case TrexStream::stCONTINUOUS: + + start_event.time = offset_usec + stream->m_isg_usec; + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + m_graph_obj.add_rate_event(start_event); + + /* no more events after this stream */ + offset_usec = -1; + + break; + + case TrexStream::stSINGLE_BURST: + + /* start event */ + start_event.time = offset_usec + stream->m_isg_usec; + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + m_graph_obj.add_rate_event(start_event); + + /* stop event */ + stop_event.time = start_event.time + stream->get_burst_length_usec(); + stop_event.diff_pps = -(start_event.diff_pps); + stop_event.diff_bps = -(start_event.diff_bps); + m_graph_obj.add_rate_event(stop_event); + + /* next stream starts from here */ + offset_usec = stop_event.time; + + break; + + case TrexStream::stMULTI_BURST: + + double delay = stream->m_isg_usec; + + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + + stop_event.diff_pps = -(start_event.diff_pps); + stop_event.diff_bps = -(start_event.diff_bps); + + for (int i = 0; i < stream->m_num_bursts; i++) { + + start_event.time = offset_usec + delay; + m_graph_obj.add_rate_event(start_event); + + stop_event.time = start_event.time + stream->get_burst_length_usec(); + m_graph_obj.add_rate_event(stop_event); + + delay = stream->m_ibg_usec; + + offset_usec = stop_event.time; + } + + break; + } +} + +void +TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { + + + std::unordered_map loop_hash; + + + uint32_t stream_id = root_stream_id; + double offset = 0; + + while (true) { + + const TrexStream *stream = m_streams_hash.at(stream_id); + /* add the node to the hash for loop detection */ + loop_hash[stream_id] = true; + + add_rate_events_for_stream(offset, stream); + + /* do we have a next stream ? */ + if (stream->m_next_stream_id == -1) { + break; + } + + /* loop detection */ + + auto search = loop_hash.find(stream->m_next_stream_id); + if (search != loop_hash.end()) { + break; + } + + /* handle the next one */ + stream_id = stream->m_next_stream_id; + } +} + +const TrexStreamsGraphObj & +TrexStreamsGraph::generate(const std::vector &streams) { + std::vector root_streams; + + + for (TrexStream *stream : streams) { + + /* for fast search we populate all the streams in a hash */ + m_streams_hash[stream->m_stream_id] = stream; + + /* hold all the self start nodes in a vector */ + if (stream->m_self_start) { + root_streams.push_back(stream->m_stream_id); + } + } + + /* for each node - scan until done or loop */ + for (uint32_t root_id : root_streams) { + generate_graph_for_one_root(root_id); + } + + + m_graph_obj.generate(); + + return m_graph_obj; +} + +/************************************** + * streams graph object + *************************************/ +void +TrexStreamsGraphObj::find_max_rate() { + double max_rate_pps = 0; + double current_rate_pps = 0; + + double max_rate_bps = 0; + double current_rate_bps = 0; + + /* now we simply walk the list and hold the max */ + for (auto &ev : m_rate_events) { + current_rate_pps += ev.diff_pps; + current_rate_bps += ev.diff_bps; + + max_rate_pps = std::max(max_rate_pps, current_rate_pps); + max_rate_bps = std::max(max_rate_bps, current_rate_bps); + } + + m_max_pps = max_rate_pps; + m_max_bps = max_rate_bps; +} + +static +bool event_compare (const TrexStreamsGraphObj::rate_event_st &first, const TrexStreamsGraphObj::rate_event_st &second) { + return (first.time < second.time); +} + +void +TrexStreamsGraphObj::generate() { + m_rate_events.sort(event_compare); + find_max_rate(); +} diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 200f7ce9..28a9bd10 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -23,7 +23,9 @@ limitations under the License. #include #include +#include #include +#include class TrexStreamsCompiler; class TrexStream; @@ -109,6 +111,84 @@ private: void err(const std::string &err); std::vector m_warnings; + +}; + +class TrexStreamsGraph; + +/************************************** + * streams graph object + * + * holds the step graph for bandwidth + *************************************/ +class TrexStreamsGraphObj { + friend class TrexStreamsGraph; + +public: + + /** + * rate event is defined by those: + * time - the time of the event on the timeline + * diff - what is the nature of the change ? + * + * @author imarom (23-Nov-15) + */ + struct rate_event_st { + double time; + double diff_pps; + double diff_bps; + }; + + double get_max_pps() const { + return m_max_pps; + } + + double get_max_bps() const { + return m_max_bps; + } + + +private: + + void add_rate_event(const rate_event_st &ev) { + m_rate_events.push_back(ev); + } + + void generate(); + void find_max_rate(); + + double m_max_pps; + double m_max_bps; + + /* list of rate events */ + std::list m_rate_events; +}; + +/** + * graph creator + * + * @author imarom (23-Nov-15) + */ +class TrexStreamsGraph { +public: + + /** + * generate a sequence graph for streams + * + */ + const TrexStreamsGraphObj & generate(const std::vector &streams); + +private: + + void generate_graph_for_one_root(uint32_t root_stream_id); + + void add_rate_events_for_stream(double &offset, const TrexStream *stream); + + /* for fast processing of streams */ + std::unordered_map m_streams_hash; + + /* main object to hold the graph - returned to the user */ + TrexStreamsGraphObj m_graph_obj; }; #endif /* __TREX_STREAMS_COMPILER_H__ */ -- cgit From 161a85c57c3d2a165e4fa94140d67db05714a7d3 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 24 Nov 2015 11:52:33 +0200 Subject: bug fixes for the graph --- src/stateless/cp/trex_stream.h | 5 +- src/stateless/cp/trex_streams_compiler.cpp | 170 +++++++++++++++++++++-------- src/stateless/cp/trex_streams_compiler.h | 7 ++ 3 files changed, 135 insertions(+), 47 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 5baba840..3e48d7e4 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -152,11 +152,12 @@ public: double get_burst_length_usec() const { - return ( (m_burst_total_pkts / m_pps) * 1000 ); + return ( (m_burst_total_pkts / m_pps) * 1000 * 1000); } double get_bps() const { - return (m_pps * m_pkt.len * 8); + /* packet length + 4 CRC bytes to bits and multiplied by PPS */ + return (m_pps * (m_pkt.len + 4) * 8); } void Dump(FILE *fd); diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index f36de1b4..f97b15b9 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -439,86 +439,154 @@ TrexStreamsCompiler::compile(const std::vector &streams, * streams graph *************************************/ +/** + * for each stream we create the right rate events (up/down) + * + * @author imarom (24-Nov-15) + * + * @param offset_usec + * @param stream + */ void TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, const TrexStream *stream) { - TrexStreamsGraphObj::rate_event_st start_event; - TrexStreamsGraphObj::rate_event_st stop_event; switch (stream->get_type()) { + case TrexStream::stCONTINUOUS: + add_rate_events_for_stream_cont(offset_usec, stream); + return; + + case TrexStream::stSINGLE_BURST: + add_rate_events_for_stream_single_burst(offset_usec, stream); + return; - start_event.time = offset_usec + stream->m_isg_usec; - start_event.diff_pps = stream->get_pps(); - start_event.diff_bps = stream->get_bps(); - m_graph_obj.add_rate_event(start_event); + case TrexStream::stMULTI_BURST: + add_rate_events_for_stream_multi_burst(offset_usec, stream); + return; + } +} - /* no more events after this stream */ - offset_usec = -1; +/** + * continous stream + * + */ +void +TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const TrexStream *stream) { - break; - - case TrexStream::stSINGLE_BURST: + TrexStreamsGraphObj::rate_event_st start_event; - /* start event */ - start_event.time = offset_usec + stream->m_isg_usec; - start_event.diff_pps = stream->get_pps(); - start_event.diff_bps = stream->get_bps(); - m_graph_obj.add_rate_event(start_event); + /* for debug purposes */ + start_event.stream_id = stream->m_stream_id; - /* stop event */ - stop_event.time = start_event.time + stream->get_burst_length_usec(); - stop_event.diff_pps = -(start_event.diff_pps); - stop_event.diff_bps = -(start_event.diff_bps); - m_graph_obj.add_rate_event(stop_event); + start_event.time = offset_usec + stream->m_isg_usec; + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + m_graph_obj.add_rate_event(start_event); - /* next stream starts from here */ - offset_usec = stop_event.time; + /* no more events after this stream */ + offset_usec = -1; +} + +/** + * single burst stream + * + */ +void +TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, const TrexStream *stream) { + TrexStreamsGraphObj::rate_event_st start_event; + TrexStreamsGraphObj::rate_event_st stop_event; - break; - case TrexStream::stMULTI_BURST: + /* for debug purposes */ + start_event.stream_id = stream->m_stream_id; + stop_event.stream_id = stream->m_stream_id; + + /* start event */ + start_event.time = offset_usec + stream->m_isg_usec; + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + m_graph_obj.add_rate_event(start_event); + + /* stop event */ + stop_event.time = start_event.time + stream->get_burst_length_usec(); + stop_event.diff_pps = -(start_event.diff_pps); + stop_event.diff_bps = -(start_event.diff_bps); + m_graph_obj.add_rate_event(stop_event); + + /* next stream starts from here */ + offset_usec = stop_event.time; - double delay = stream->m_isg_usec; +} - start_event.diff_pps = stream->get_pps(); - start_event.diff_bps = stream->get_bps(); +/** + * multi burst stream + * + */ +void +TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, const TrexStream *stream) { + TrexStreamsGraphObj::rate_event_st start_event; + TrexStreamsGraphObj::rate_event_st stop_event; - stop_event.diff_pps = -(start_event.diff_pps); - stop_event.diff_bps = -(start_event.diff_bps); + /* first the delay is the inter stream gap */ + double delay = stream->m_isg_usec; + + /* for debug purposes */ + + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps = stream->get_bps(); + start_event.stream_id = stream->m_stream_id; - for (int i = 0; i < stream->m_num_bursts; i++) { + stop_event.diff_pps = -(start_event.diff_pps); + stop_event.diff_bps = -(start_event.diff_bps); + stop_event.stream_id = stream->m_stream_id; - start_event.time = offset_usec + delay; - m_graph_obj.add_rate_event(start_event); + /* for each burst create up/down events */ + for (int i = 0; i < stream->m_num_bursts; i++) { - stop_event.time = start_event.time + stream->get_burst_length_usec(); - m_graph_obj.add_rate_event(stop_event); + start_event.time = offset_usec + delay; + m_graph_obj.add_rate_event(start_event); - delay = stream->m_ibg_usec; + stop_event.time = start_event.time + stream->get_burst_length_usec(); + m_graph_obj.add_rate_event(stop_event); - offset_usec = stop_event.time; - } + /* after the first burst, the delay is inter burst gap */ + delay = stream->m_ibg_usec; - break; + offset_usec = stop_event.time; } } +/** + * for a single root we can until done or a loop detected + * + * @author imarom (24-Nov-15) + * + * @param root_stream_id + */ void TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { - std::unordered_map loop_hash; - + std::stringstream ss; uint32_t stream_id = root_stream_id; double offset = 0; while (true) { + const TrexStream *stream; + + /* fetch the stream from the hash - if it is not present, report an error */ + try { + stream = m_streams_hash.at(stream_id); + } catch (const std::out_of_range &e) { + ss << "stream id " << stream_id << " does not exists"; + throw TrexException(ss.str()); + } - const TrexStream *stream = m_streams_hash.at(stream_id); /* add the node to the hash for loop detection */ loop_hash[stream_id] = true; + /* create the right rate events for the stream */ add_rate_events_for_stream(offset, stream); /* do we have a next stream ? */ @@ -527,7 +595,6 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { } /* loop detection */ - auto search = loop_hash.find(stream->m_next_stream_id); if (search != loop_hash.end()) { break; @@ -538,13 +605,25 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { } } +/** + * for a vector of streams generate a graph of BW + * see graph object for more details + * + */ const TrexStreamsGraphObj & TrexStreamsGraph::generate(const std::vector &streams) { std::vector root_streams; - + /* before anything we create a hash streams ID + and grab the root nodes + */ for (TrexStream *stream : streams) { - + + /* skip non enabled streams */ + if (!stream->m_enabled) { + continue; + } + /* for fast search we populate all the streams in a hash */ m_streams_hash[stream->m_stream_id] = stream; @@ -578,6 +657,7 @@ TrexStreamsGraphObj::find_max_rate() { /* now we simply walk the list and hold the max */ for (auto &ev : m_rate_events) { + current_rate_pps += ev.diff_pps; current_rate_bps += ev.diff_bps; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 28a9bd10..9f0c1f8e 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -137,6 +137,7 @@ public: double time; double diff_pps; double diff_bps; + uint32_t stream_id; }; double get_max_pps() const { @@ -147,6 +148,9 @@ public: return m_max_bps; } + const std::list & get_events() const { + return m_rate_events; + } private: @@ -183,6 +187,9 @@ private: void generate_graph_for_one_root(uint32_t root_stream_id); void add_rate_events_for_stream(double &offset, const TrexStream *stream); + void add_rate_events_for_stream_cont(double &offset_usec, const TrexStream *stream); + void add_rate_events_for_stream_single_burst(double &offset_usec, const TrexStream *stream); + void add_rate_events_for_stream_multi_burst(double &offset_usec, const TrexStream *stream); /* for fast processing of streams */ std::unordered_map m_streams_hash; -- cgit From 045d0f8f31b2e68b8f726377fabb3205b5d19cf5 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 24 Nov 2015 18:40:16 +0200 Subject: added support for percentage on start also added info about the correct interface driver and speed from DPDK layer --- src/stateless/cp/trex_stateless_port.cpp | 11 ++++++----- src/stateless/cp/trex_stateless_port.h | 7 +++++-- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index be1bea12..5f1a3bca 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -56,10 +56,12 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api std::vector> core_pair_list; m_port_id = port_id; - m_port_state = PORT_STATE_IDLE; clear_owner(); + /* get the platform specific data */ + api->get_interface_info(port_id, m_driver_name, m_speed); + /* get the DP cores belonging to this port */ api->port_id_to_cores(m_port_id, core_pair_list); @@ -266,11 +268,10 @@ TrexStatelessPort::get_state_as_string() const { } void -TrexStatelessPort::get_properties(string &driver, string &speed) { +TrexStatelessPort::get_properties(std::string &driver, TrexPlatformApi::driver_speed_e &speed) { - /* take this from DPDK */ - driver = "e1000"; - speed = "1 Gbps"; + driver = m_driver_name; + speed = m_speed; } bool diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 6adb5fef..20acd927 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -23,8 +23,8 @@ limitations under the License. #include #include +#include -class TrexPlatformApi; class TrexStatelessCpToDpMsgBase; /** @@ -126,7 +126,7 @@ public: * @param driver * @param speed */ - void get_properties(std::string &driver, std::string &speed); + void get_properties(std::string &driver, TrexPlatformApi::driver_speed_e &speed); /** @@ -260,6 +260,9 @@ private: port_state_e m_port_state; std::string m_owner; std::string m_owner_handler; + std::string m_driver_name; + + TrexPlatformApi::driver_speed_e m_speed; /* holds the DP cores associated with this port */ std::vector m_cores_id_list; -- cgit From b6ec2066653319b60385de1d4117165eb88890a1 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Nov 2015 07:39:39 -0500 Subject: fixed a bug with default start command in the console also added clear events and more types of events --- src/stateless/cp/trex_stateless_port.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 5f1a3bca..2fd948fd 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -139,6 +139,9 @@ TrexStatelessPort::start_traffic(double mul, double duration) { send_message_to_dp(start_msg); + Json::Value data; + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data); } void @@ -194,6 +197,10 @@ TrexStatelessPort::stop_traffic(void) { change_state(PORT_STATE_STREAMS); + Json::Value data; + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STOPPED, data); + } void @@ -366,7 +373,7 @@ TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { /* send a ZMQ event */ data["port_id"] = m_port_id; - get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STOPPED, data); + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_FINISHED_TX, data); break; default: -- cgit From 12a19244693cacbd77ca0a8e43f382a10f773f91 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 25 Nov 2015 17:20:44 +0200 Subject: move to real idle in case of stop --- src/stateless/dp/trex_stateless_dp_core.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/stateless') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 9b4a6ad9..4e429c8f 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -309,6 +309,7 @@ TrexStatelessDpCore::start_scheduler() { /* bail out in case of terminate */ if (m_state != TrexStatelessDpCore::STATE_TERMINATE) { m_core->m_node_gen.close_file(m_core); + m_state = STATE_IDLE; /* we exit from all ports and we have nothing to do, we move to IDLE state */ } } -- cgit From d9a11302236095e055247295021bdfce6c988802 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 26 Nov 2015 02:30:03 -0500 Subject: added support for 'update' --- src/stateless/cp/trex_stateless_port.cpp | 27 +++++++---------- src/stateless/cp/trex_stateless_port.h | 14 +++++++-- src/stateless/dp/trex_stateless_dp_core.cpp | 34 ++++++++++++++++++---- src/stateless/dp/trex_stateless_dp_core.h | 16 ++++++++-- src/stateless/dp/trex_stream_node.h | 12 +++++++- .../messaging/trex_stateless_messaging.cpp | 16 ++++++++++ src/stateless/messaging/trex_stateless_messaging.h | 20 +++++++++++++ 7 files changed, 111 insertions(+), 28 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 2fd948fd..8e18a5bf 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -144,32 +144,29 @@ TrexStatelessPort::start_traffic(double mul, double duration) { get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data); } -void -TrexStatelessPort::start_traffic_max_bps(double max_bps, double duration) { + +double +TrexStatelessPort::calculate_m_from_bps(double max_bps) { /* fetch all the streams from the table */ vector streams; get_object_list(streams); TrexStreamsGraph graph; const TrexStreamsGraphObj &obj = graph.generate(streams); - double m = (max_bps / obj.get_max_bps()); - /* call the main function */ - start_traffic(m, duration); + return (max_bps / obj.get_max_bps()); } -void -TrexStatelessPort::start_traffic_max_pps(double max_pps, double duration) { +double +TrexStatelessPort::calculate_m_from_pps(double max_pps) { /* fetch all the streams from the table */ vector streams; get_object_list(streams); TrexStreamsGraph graph; const TrexStreamsGraphObj &obj = graph.generate(streams); - double m = (max_pps / obj.get_max_pps()); - /* call the main function */ - start_traffic(m, duration); + return (max_pps / obj.get_max_pps()); } /** @@ -239,16 +236,14 @@ TrexStatelessPort::resume_traffic(void) { void TrexStatelessPort::update_traffic(double mul) { - verify_state(PORT_STATE_STREAMS | PORT_STATE_TX | PORT_STATE_PAUSE); + verify_state(PORT_STATE_TX | PORT_STATE_PAUSE); - #if 0 /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + double per_core_mul = mul / m_cores_id_list.size(); + TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, per_core_mul); - send_message_to_dp(stop_msg); + send_message_to_dp(update_msg); - m_port_state = PORT_STATE_UP_IDLE; - #endif } std::string diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 20acd927..b061a414 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -77,8 +77,18 @@ public: * throws TrexException in case of an error */ void start_traffic(double mul, double duration = -1); - void start_traffic_max_bps(double max_bps, double duration = -1); - void start_traffic_max_pps(double max_pps, double duration = -1); + + /** + * given a BPS rate calculate ther correct M for this port + * + */ + double calculate_m_from_bps(double max_bps); + + /** + * given a PPS rate calculate the correct M for this port + * + */ + double calculate_m_from_pps(double max_pps); /** * stop traffic diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 4e429c8f..dd4937cd 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -139,6 +139,20 @@ bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){ return (true); } +bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) { + + assert( (m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING || + (m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE)) ); + + for (auto dp_stream : m_active_nodes) { + CGenNodeStateless * node = dp_stream.m_node; + assert(node->get_port_id() == port_id); + + node->set_multiplier(mul); + } + + return (true); +} bool TrexStatelessDpPerPort::pause_traffic(uint8_t port_id){ @@ -402,9 +416,9 @@ TrexStatelessDpCore::add_port_duration(double duration, void -TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, - TrexStream * stream, - TrexStreamsCompiledObj *comp) { +TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, + TrexStream * stream, + TrexStreamsCompiledObj *comp) { CGenNodeStateless *node = m_core->create_node_sl(); @@ -439,8 +453,8 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, node->m_pause =0; node->m_stream_type = stream->m_type; - node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ; - + node->m_base_pps = stream->get_pps(); + node->set_multiplier(comp->get_multiplier()); /* stateless specific fields */ switch ( stream->m_type ) { @@ -520,7 +534,7 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, for (auto single_stream : obj->get_objects()) { /* all commands should be for the same port */ assert(obj->get_port_id() == single_stream.m_stream->m_port_id); - add_cont_stream(lp_port,single_stream.m_stream,obj); + add_stream(lp_port,single_stream.m_stream,obj); } uint32_t nodes = lp_port->m_active_nodes.size(); @@ -582,6 +596,14 @@ TrexStatelessDpCore::pause_traffic(uint8_t port_id){ lp_port->pause_traffic(port_id); } +void +TrexStatelessDpCore::update_traffic(uint8_t port_id, double mul) { + + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); + + lp_port->update_traffic(port_id, mul); +} + void TrexStatelessDpCore::stop_traffic(uint8_t port_id, diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index eda1ae59..563159b2 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -68,6 +68,8 @@ public: bool resume_traffic(uint8_t port_id); + bool update_traffic(uint8_t port_id, double mul); + bool stop_traffic(uint8_t port_id, bool stop_on_id, int event_id); @@ -158,6 +160,14 @@ public: void resume_traffic(uint8_t port_id); + /** + * update current traffic rate + * + * @author imarom (25-Nov-15) + * + */ + void update_traffic(uint8_t port_id, double mul); + /** * * stop all traffic for this core @@ -250,9 +260,9 @@ private: void add_global_duration(double duration); - void add_cont_stream(TrexStatelessDpPerPort * lp_port, - TrexStream * stream, - TrexStreamsCompiledObj *comp); + void add_stream(TrexStatelessDpPerPort * lp_port, + TrexStream * stream, + TrexStreamsCompiledObj *comp); uint8_t m_thread_id; uint8_t m_local_port_offset; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index ccf99eaa..5997376f 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -86,8 +86,9 @@ private: TrexStream * m_ref_stream_info; /* the stream info */ CGenNodeStateless * m_next_stream; + double m_base_pps; /* pad to match the size of CGenNode */ - uint8_t m_pad_end[56]; + uint8_t m_pad_end[48]; @@ -99,6 +100,15 @@ public: } + /** + * calculate the time offset based + * on the PPS and multiplier + * + */ + void set_multiplier(double mul) { + m_next_time_offset = 1.0 / (m_base_pps * mul) ; + } + /* we restart the stream, schedule it using stream isg */ inline void update_refresh_time(double cur_time){ m_time = cur_time + usec_to_sec(m_ref_stream_info->m_isg_usec); diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index ec8b7839..3210f29a 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -163,6 +163,22 @@ TrexStatelessDpCanQuit::clone(){ return new_msg; } +/************************* + update traffic message + ************************/ +bool +TrexStatelessDpUpdate::handle(TrexStatelessDpCore *dp_core) { + dp_core->update_traffic(m_port_id, m_mul); + + return true; +} + +TrexStatelessCpToDpMsgBase * +TrexStatelessDpUpdate::clone() { + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_mul); + + return new_msg; +} /************************* messages from DP to CP **********************/ bool diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 6bd0dbe3..7390be60 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -225,6 +225,26 @@ public: }; +/** + * update message + */ +class TrexStatelessDpUpdate : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpUpdate(uint8_t port_id, double mul) { + m_port_id = port_id; + m_mul = mul; + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + + virtual TrexStatelessCpToDpMsgBase * clone(); + +private: + uint8_t m_port_id; + double m_mul; +}; + /************************* messages from DP to CP **********************/ -- cgit From 59548ae8f65f8aa387900a321b437b8501046fde Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 26 Nov 2015 06:26:27 -0500 Subject: Hanoch's review - changed update model to differential also, graph is calculated on demand and once for each update --- src/stateless/cp/trex_stateless_port.cpp | 103 +++++++++++++++------ src/stateless/cp/trex_stateless_port.h | 59 +++++++++--- src/stateless/cp/trex_streams_compiler.cpp | 18 ++-- src/stateless/cp/trex_streams_compiler.h | 9 +- src/stateless/dp/trex_stateless_dp_core.cpp | 11 +-- src/stateless/dp/trex_stateless_dp_core.h | 2 +- src/stateless/dp/trex_stream_node.h | 8 +- .../messaging/trex_stateless_messaging.cpp | 4 +- src/stateless/messaging/trex_stateless_messaging.h | 6 +- 9 files changed, 151 insertions(+), 69 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 8e18a5bf..8346b61d 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -104,17 +104,21 @@ TrexStatelessPort::release(void) { * */ void -TrexStatelessPort::start_traffic(double mul, double duration) { +TrexStatelessPort::start_traffic(const TrexStatelessPort::mul_st &mul, double duration) { /* command allowed only on state stream */ verify_state(PORT_STATE_STREAMS); + /* just making sure no leftovers... */ + delete_streams_graph(); + + /* calculate the effective M */ + double per_core_mul = calculate_effective_mul(mul); + /* fetch all the streams from the table */ vector streams; get_object_list(streams); - /* split it per core */ - double per_core_mul = mul / m_cores_id_list.size(); /* compiler it */ TrexStreamsCompiler compiler; @@ -127,6 +131,7 @@ TrexStatelessPort::start_traffic(double mul, double duration) { /* generate a message to all the relevant DP cores to start transmitting */ int event_id = m_dp_events.generate_event_id(); + /* mark that DP event of stoppped is possible */ m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, event_id); @@ -142,32 +147,11 @@ TrexStatelessPort::start_traffic(double mul, double duration) { Json::Value data; data["port_id"] = m_port_id; get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data); -} - -double -TrexStatelessPort::calculate_m_from_bps(double max_bps) { - /* fetch all the streams from the table */ - vector streams; - get_object_list(streams); - - TrexStreamsGraph graph; - const TrexStreamsGraphObj &obj = graph.generate(streams); - - return (max_bps / obj.get_max_bps()); + /* save the per core multiplier for update messages */ + m_current_per_core_m = per_core_mul; } -double -TrexStatelessPort::calculate_m_from_pps(double max_pps) { - /* fetch all the streams from the table */ - vector streams; - get_object_list(streams); - - TrexStreamsGraph graph; - const TrexStreamsGraphObj &obj = graph.generate(streams); - - return (max_pps / obj.get_max_pps()); -} /** * stop traffic on port @@ -180,10 +164,13 @@ void TrexStatelessPort::stop_traffic(void) { if (!( (m_port_state == PORT_STATE_TX) - || (m_port_state ==PORT_STATE_PAUSE) )) { + || (m_port_state == PORT_STATE_PAUSE) )) { return; } + /* delete any previous graphs */ + delete_streams_graph(); + /* mask out the DP stop event */ m_dp_events.disable(TrexDpPortEvent::EVENT_STOP); @@ -234,16 +221,20 @@ TrexStatelessPort::resume_traffic(void) { } void -TrexStatelessPort::update_traffic(double mul) { +TrexStatelessPort::update_traffic(const TrexStatelessPort::mul_st &mul) { verify_state(PORT_STATE_TX | PORT_STATE_PAUSE); /* generate a message to all the relevant DP cores to start transmitting */ - double per_core_mul = mul / m_cores_id_list.size(); - TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, per_core_mul); + double new_per_core_m = calculate_effective_mul(mul); + double factor = new_per_core_m / m_current_per_core_m; + + TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, factor); send_message_to_dp(update_msg); + m_current_per_core_m = new_per_core_m; + } std::string @@ -376,3 +367,55 @@ TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { } } + +/** + * calculate an effective M based on requirments + * + */ +double +TrexStatelessPort::calculate_effective_mul(const mul_st &mul) { + + /* for a simple factor request - calculate the multiplier per core */ + if (mul.type == MUL_FACTOR) { + return (mul.value / m_cores_id_list.size()); + } + + /* we now need the graph - generate it if we don't have it (happens once) */ + if (!m_graph_obj) { + generate_streams_graph(); + } + + /* now we can calculate the effective M */ + if (mul.type == MUL_MAX_BPS) { + return ( (mul.value / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); + } else if (mul.type == MUL_MAX_PPS) { + return ( (mul.value / m_graph_obj->get_max_pps()) / m_cores_id_list.size()); + } else { + assert(0); + } +} + +void +TrexStatelessPort::generate_streams_graph() { + + /* dispose of the old one */ + if (m_graph_obj) { + delete_streams_graph(); + } + + /* fetch all the streams from the table */ + vector streams; + get_object_list(streams); + + TrexStreamsGraph graph; + m_graph_obj = graph.generate(streams); +} + +void +TrexStatelessPort::delete_streams_graph() { + if (m_graph_obj) { + delete m_graph_obj; + m_graph_obj = NULL; + } +} + diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index b061a414..7d20f338 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -26,6 +26,7 @@ limitations under the License. #include class TrexStatelessCpToDpMsgBase; +class TrexStreamsGraphObj; /** * describes a stateless port @@ -58,6 +59,24 @@ public: RC_ERR_FAILED_TO_COMPILE_STREAMS }; + /** + * defines the type of multipler passed to start + */ + enum mul_type_e { + MUL_FACTOR, + MUL_MAX_BPS, + MUL_MAX_PPS + }; + + /** + * multiplier object + */ + typedef struct { + mul_type_e type; + double value; + } mul_st; + + TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api); /** @@ -76,19 +95,7 @@ public: * start traffic * throws TrexException in case of an error */ - void start_traffic(double mul, double duration = -1); - - /** - * given a BPS rate calculate ther correct M for this port - * - */ - double calculate_m_from_bps(double max_bps); - - /** - * given a PPS rate calculate the correct M for this port - * - */ - double calculate_m_from_pps(double max_pps); + void start_traffic(const mul_st &mul, double duration = -1); /** * stop traffic @@ -112,7 +119,7 @@ public: * update current traffic on port * */ - void update_traffic(double mul); + void update_traffic(const mul_st &mul); /** * get the port state @@ -265,6 +272,26 @@ private: void on_dp_event_occured(TrexDpPortEvent::event_e event_type); + /** + * calculate effective M per core + * + */ + double calculate_effective_mul(const mul_st &mul); + + /** + * generates a graph of streams graph + * + */ + void generate_streams_graph(); + + /** + * dispose of it + * + * @author imarom (26-Nov-15) + */ + void delete_streams_graph(); + + TrexStreamTable m_stream_table; uint8_t m_port_id; port_state_e m_port_state; @@ -279,8 +306,12 @@ private: bool m_last_all_streams_continues; double m_last_duration; + double m_current_per_core_m; TrexDpPortEvents m_dp_events; + + /* holds a graph of streams rate*/ + const TrexStreamsGraphObj *m_graph_obj; }; #endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index b28989be..c8aa1e40 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -486,7 +486,7 @@ TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const Tre start_event.time = offset_usec + stream->m_isg_usec; start_event.diff_pps = stream->get_pps(); start_event.diff_bps = stream->get_bps(); - m_graph_obj.add_rate_event(start_event); + m_graph_obj->add_rate_event(start_event); /* no more events after this stream */ offset_usec = -1; @@ -510,13 +510,13 @@ TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, c start_event.time = offset_usec + stream->m_isg_usec; start_event.diff_pps = stream->get_pps(); start_event.diff_bps = stream->get_bps(); - m_graph_obj.add_rate_event(start_event); + m_graph_obj->add_rate_event(start_event); /* stop event */ stop_event.time = start_event.time + stream->get_burst_length_usec(); stop_event.diff_pps = -(start_event.diff_pps); stop_event.diff_bps = -(start_event.diff_bps); - m_graph_obj.add_rate_event(stop_event); + m_graph_obj->add_rate_event(stop_event); /* next stream starts from here */ offset_usec = stop_event.time; @@ -549,10 +549,10 @@ TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, co for (int i = 0; i < stream->m_num_bursts; i++) { start_event.time = offset_usec + delay; - m_graph_obj.add_rate_event(start_event); + m_graph_obj->add_rate_event(start_event); stop_event.time = start_event.time + stream->get_burst_length_usec(); - m_graph_obj.add_rate_event(stop_event); + m_graph_obj->add_rate_event(stop_event); /* after the first burst, the delay is inter burst gap */ delay = stream->m_ibg_usec; @@ -615,8 +615,12 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { * see graph object for more details * */ -const TrexStreamsGraphObj & +const TrexStreamsGraphObj * TrexStreamsGraph::generate(const std::vector &streams) { + + /* main object to hold the graph - returned to the user */ + m_graph_obj = new TrexStreamsGraphObj(); + std::vector root_streams; /* before anything we create a hash streams ID @@ -644,7 +648,7 @@ TrexStreamsGraph::generate(const std::vector &streams) { } - m_graph_obj.generate(); + m_graph_obj->generate(); return m_graph_obj; } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 70a31c5e..a4c12f8d 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -171,6 +171,7 @@ private: /* list of rate events */ std::list m_rate_events; + }; /** @@ -181,11 +182,15 @@ private: class TrexStreamsGraph { public: + TrexStreamsGraph() { + m_graph_obj = NULL; + } + /** * generate a sequence graph for streams * */ - const TrexStreamsGraphObj & generate(const std::vector &streams); + const TrexStreamsGraphObj * generate(const std::vector &streams); private: @@ -200,7 +205,7 @@ private: std::unordered_map m_streams_hash; /* main object to hold the graph - returned to the user */ - TrexStreamsGraphObj m_graph_obj; + TrexStreamsGraphObj *m_graph_obj; }; #endif /* __TREX_STREAMS_COMPILER_H__ */ diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index dd4937cd..9b62fabd 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -139,7 +139,7 @@ bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){ return (true); } -bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) { +bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double factor) { assert( (m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING || (m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE)) ); @@ -148,7 +148,7 @@ bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) { CGenNodeStateless * node = dp_stream.m_node; assert(node->get_port_id() == port_id); - node->set_multiplier(mul); + node->update_rate(factor); } return (true); @@ -453,8 +453,7 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, node->m_pause =0; node->m_stream_type = stream->m_type; - node->m_base_pps = stream->get_pps(); - node->set_multiplier(comp->get_multiplier()); + node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()); /* stateless specific fields */ switch ( stream->m_type ) { @@ -597,11 +596,11 @@ TrexStatelessDpCore::pause_traffic(uint8_t port_id){ } void -TrexStatelessDpCore::update_traffic(uint8_t port_id, double mul) { +TrexStatelessDpCore::update_traffic(uint8_t port_id, double factor) { TrexStatelessDpPerPort * lp_port = get_port_db(port_id); - lp_port->update_traffic(port_id, mul); + lp_port->update_traffic(port_id, factor); } diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 563159b2..7dc4a2b2 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -68,7 +68,7 @@ public: bool resume_traffic(uint8_t port_id); - bool update_traffic(uint8_t port_id, double mul); + bool update_traffic(uint8_t port_id, double factor); bool stop_traffic(uint8_t port_id, bool stop_on_id, diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 5997376f..111af845 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -86,9 +86,8 @@ private: TrexStream * m_ref_stream_info; /* the stream info */ CGenNodeStateless * m_next_stream; - double m_base_pps; /* pad to match the size of CGenNode */ - uint8_t m_pad_end[48]; + uint8_t m_pad_end[56]; @@ -105,8 +104,9 @@ public: * on the PPS and multiplier * */ - void set_multiplier(double mul) { - m_next_time_offset = 1.0 / (m_base_pps * mul) ; + void update_rate(double factor) { + /* update the inter packet gap */ + m_next_time_offset = m_next_time_offset / factor; } /* we restart the stream, schedule it using stream isg */ diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 3210f29a..257de168 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -168,14 +168,14 @@ TrexStatelessDpCanQuit::clone(){ ************************/ bool TrexStatelessDpUpdate::handle(TrexStatelessDpCore *dp_core) { - dp_core->update_traffic(m_port_id, m_mul); + dp_core->update_traffic(m_port_id, m_factor); return true; } TrexStatelessCpToDpMsgBase * TrexStatelessDpUpdate::clone() { - TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_mul); + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_factor); return new_msg; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 7390be60..d56596bf 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -231,9 +231,9 @@ public: class TrexStatelessDpUpdate : public TrexStatelessCpToDpMsgBase { public: - TrexStatelessDpUpdate(uint8_t port_id, double mul) { + TrexStatelessDpUpdate(uint8_t port_id, double factor) { m_port_id = port_id; - m_mul = mul; + m_factor = factor; } virtual bool handle(TrexStatelessDpCore *dp_core); @@ -242,7 +242,7 @@ public: private: uint8_t m_port_id; - double m_mul; + double m_factor; }; -- cgit From 4c94931c5de8673433d3bf22999ecc84d41e0595 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 29 Nov 2015 08:38:38 -0500 Subject: support for update +/- request --- src/stateless/cp/trex_stateless_port.cpp | 135 ++++++++++++++++++++++++++----- src/stateless/cp/trex_stateless_port.h | 82 ++++++++++++++----- 2 files changed, 177 insertions(+), 40 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 8346b61d..95bdca0b 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -104,7 +104,7 @@ TrexStatelessPort::release(void) { * */ void -TrexStatelessPort::start_traffic(const TrexStatelessPort::mul_st &mul, double duration) { +TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) { /* command allowed only on state stream */ verify_state(PORT_STATE_STREAMS); @@ -112,7 +112,9 @@ TrexStatelessPort::start_traffic(const TrexStatelessPort::mul_st &mul, double du /* just making sure no leftovers... */ delete_streams_graph(); - /* calculate the effective M */ + /* on start - we can only provide absolute values */ + assert(mul.m_op == TrexPortMultiplier::OP_ABS); + double per_core_mul = calculate_effective_mul(mul); /* fetch all the streams from the table */ @@ -221,19 +223,41 @@ TrexStatelessPort::resume_traffic(void) { } void -TrexStatelessPort::update_traffic(const TrexStatelessPort::mul_st &mul) { +TrexStatelessPort::update_traffic(const TrexPortMultiplier &mul) { + + double factor; verify_state(PORT_STATE_TX | PORT_STATE_PAUSE); /* generate a message to all the relevant DP cores to start transmitting */ double new_per_core_m = calculate_effective_mul(mul); - double factor = new_per_core_m / m_current_per_core_m; + + switch (mul.m_op) { + case TrexPortMultiplier::OP_ABS: + factor = new_per_core_m / m_current_per_core_m; + break; + + case TrexPortMultiplier::OP_ADD: + factor = (m_current_per_core_m + new_per_core_m) / m_current_per_core_m; + break; + + case TrexPortMultiplier::OP_SUB: + factor = (m_current_per_core_m - new_per_core_m) / m_current_per_core_m; + if (factor <= 0) { + throw TrexRpcException("Update request will lower traffic to less than zero"); + } + break; + + default: + assert(0); + break; + } TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, factor); send_message_to_dp(update_msg); - m_current_per_core_m = new_per_core_m; + m_current_per_core_m *= factor; } @@ -368,16 +392,29 @@ TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { } } -/** - * calculate an effective M based on requirments - * - */ +uint64_t +TrexStatelessPort::get_port_speed_bps() { + switch (m_speed) { + case TrexPlatformApi::SPEED_1G: + return (1LLU * 1000 * 1000 * 1000); + + case TrexPlatformApi::SPEED_10G: + return (10LLU * 1000 * 1000 * 1000); + + case TrexPlatformApi::SPEED_40G: + return (40LLU * 1000 * 1000 * 1000); + + default: + return 0; + } +} + double -TrexStatelessPort::calculate_effective_mul(const mul_st &mul) { +TrexStatelessPort::calculate_effective_mul(const TrexPortMultiplier &mul) { /* for a simple factor request - calculate the multiplier per core */ - if (mul.type == MUL_FACTOR) { - return (mul.value / m_cores_id_list.size()); + if (mul.m_type == TrexPortMultiplier::MUL_FACTOR) { + return (mul.m_value / m_cores_id_list.size()); } /* we now need the graph - generate it if we don't have it (happens once) */ @@ -385,16 +422,30 @@ TrexStatelessPort::calculate_effective_mul(const mul_st &mul) { generate_streams_graph(); } - /* now we can calculate the effective M */ - if (mul.type == MUL_MAX_BPS) { - return ( (mul.value / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); - } else if (mul.type == MUL_MAX_PPS) { - return ( (mul.value / m_graph_obj->get_max_pps()) / m_cores_id_list.size()); - } else { + switch (mul.m_type) { + case TrexPortMultiplier::MUL_BPS: + return ( (mul.m_value / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); + + case TrexPortMultiplier::MUL_PPS: + return ( (mul.m_value / m_graph_obj->get_max_pps()) / m_cores_id_list.size()); + + case TrexPortMultiplier::MUL_PERCENTAGE: + /* if abs percentage is from the line speed - otherwise its from the current speed */ + + if (mul.m_op == TrexPortMultiplier::OP_ABS) { + double required = (mul.m_value / 100.0) * get_port_speed_bps(); + return ( (required / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); + } else { + return (m_current_per_core_m * (mul.m_value / 100.0)); + } + + default: assert(0); } + } + void TrexStatelessPort::generate_streams_graph() { @@ -419,3 +470,51 @@ TrexStatelessPort::delete_streams_graph() { } } + + +/*************************** + * port multiplier + * + **************************/ +const std::initializer_list TrexPortMultiplier::g_types = {"raw", "bps", "pps", "percentage"}; +const std::initializer_list TrexPortMultiplier::g_ops = {"abs", "add", "sub"}; + +TrexPortMultiplier:: +TrexPortMultiplier(const std::string &type_str, const std::string &op_str, double value) { + mul_type_e type; + mul_op_e op; + + if (type_str == "raw") { + type = MUL_FACTOR; + + } else if (type_str == "bps") { + type = MUL_BPS; + + } else if (type_str == "pps") { + type = MUL_PPS; + + } else if (type_str == "percentage") { + type = MUL_PERCENTAGE; + } else { + throw TrexException("bad type str: " + type_str); + } + + if (op_str == "abs") { + op = OP_ABS; + + } else if (op_str == "add") { + op = OP_ADD; + + } else if (op_str == "sub") { + op = OP_SUB; + + } else { + throw TrexException("bad op str: " + op_str); + } + + m_type = type; + m_op = op; + m_value = value; + +} + diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 7d20f338..45eb16e8 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -27,6 +27,7 @@ limitations under the License. class TrexStatelessCpToDpMsgBase; class TrexStreamsGraphObj; +class TrexPortMultiplier; /** * describes a stateless port @@ -59,24 +60,7 @@ public: RC_ERR_FAILED_TO_COMPILE_STREAMS }; - /** - * defines the type of multipler passed to start - */ - enum mul_type_e { - MUL_FACTOR, - MUL_MAX_BPS, - MUL_MAX_PPS - }; - - /** - * multiplier object - */ - typedef struct { - mul_type_e type; - double value; - } mul_st; - - + TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api); /** @@ -95,7 +79,7 @@ public: * start traffic * throws TrexException in case of an error */ - void start_traffic(const mul_st &mul, double duration = -1); + void start_traffic(const TrexPortMultiplier &mul, double duration = -1); /** * stop traffic @@ -119,7 +103,7 @@ public: * update current traffic on port * */ - void update_traffic(const mul_st &mul); + void update_traffic(const TrexPortMultiplier &mul); /** * get the port state @@ -227,7 +211,6 @@ public: } - private: @@ -276,7 +259,13 @@ private: * calculate effective M per core * */ - double calculate_effective_mul(const mul_st &mul); + double calculate_effective_mul(const TrexPortMultiplier &mul); + + /** + * get port speed in bits per second + * + */ + uint64_t get_port_speed_bps(); /** * generates a graph of streams graph @@ -314,4 +303,53 @@ private: const TrexStreamsGraphObj *m_graph_obj; }; + + +/** + * port multiplier object + * + */ +class TrexPortMultiplier { +public: + + + /** + * defines the type of multipler passed to start + */ + enum mul_type_e { + MUL_FACTOR, + MUL_BPS, + MUL_PPS, + MUL_PERCENTAGE + }; + + /** + * multiplier can be absolute value + * increment value or subtract value + */ + enum mul_op_e { + OP_ABS, + OP_ADD, + OP_SUB + }; + + + TrexPortMultiplier(mul_type_e type, mul_op_e op, double value) { + m_type = type; + m_op = op; + m_value = value; + } + + TrexPortMultiplier(const std::string &type_str, const std::string &op_str, double value); + + +public: + static const std::initializer_list g_types; + static const std::initializer_list g_ops; + + mul_type_e m_type; + mul_op_e m_op; + double m_value; +}; + #endif /* __TREX_STATELESS_PORT_H__ */ -- cgit From a48cd6471a2d82e5d78e8abe85b065f66a388e11 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 1 Dec 2015 03:46:21 -0500 Subject: 1. fixed ZMQ message limitation 2. added some scale yamls for IMIX (300 streams, 1000 streams) 3. return objects are always complex objects (not strings) - for backward compatability 4. some minor adjustments to ZMQ socket timeouts --- src/stateless/cp/trex_stateless_port.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 45eb16e8..2d15a1cc 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -79,7 +79,7 @@ public: * start traffic * throws TrexException in case of an error */ - void start_traffic(const TrexPortMultiplier &mul, double duration = -1); + void start_traffic(const TrexPortMultiplier &mul, double duration); /** * stop traffic @@ -211,6 +211,14 @@ public: } + /** + * returns the traffic multiplier currently being used by the DP + * + */ + double get_multiplier() { + return (m_current_per_core_m * m_cores_id_list.size()); + } + private: -- cgit From a6af2a8e624c62d9a347215321c6562f28879d97 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 3 Dec 2015 06:07:20 -0500 Subject: various fixes (each one is a minor one) --- src/stateless/cp/trex_stateless_port.cpp | 35 +++++++++++++++++++++++++++--- src/stateless/cp/trex_stateless_port.h | 25 ++++++++++++++++----- src/stateless/cp/trex_streams_compiler.cpp | 2 +- src/stateless/cp/trex_streams_compiler.h | 1 + 4 files changed, 54 insertions(+), 9 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 95bdca0b..25fae038 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -126,9 +126,10 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) TrexStreamsCompiler compiler; TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, per_core_mul); - bool rc = compiler.compile(streams, *compiled_obj); + std::string fail_msg; + bool rc = compiler.compile(streams, *compiled_obj, &fail_msg); if (!rc) { - throw TrexRpcException("Failed to compile streams"); + throw TrexRpcException(fail_msg); } /* generate a message to all the relevant DP cores to start transmitting */ @@ -393,7 +394,7 @@ TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) { } uint64_t -TrexStatelessPort::get_port_speed_bps() { +TrexStatelessPort::get_port_speed_bps() const { switch (m_speed) { case TrexPlatformApi::SPEED_1G: return (1LLU * 1000 * 1000 * 1000); @@ -518,3 +519,31 @@ TrexPortMultiplier(const std::string &type_str, const std::string &op_str, doubl } +const TrexStreamsGraphObj * +TrexStatelessPort::validate(void) { + + /* first compile the graph */ + + vector streams; + get_object_list(streams); + + if (streams.size() == 0) { + throw TrexException("no streams attached to port"); + } + + TrexStreamsCompiler compiler; + TrexStreamsCompiledObj compiled_obj(m_port_id, 1); + + std::string fail_msg; + bool rc = compiler.compile(streams, compiled_obj, &fail_msg); + if (!rc) { + throw TrexException(fail_msg); + } + + /* now create a stream graph */ + if (!m_graph_obj) { + generate_streams_graph(); + } + + return m_graph_obj; +} diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 2d15a1cc..dbaac21d 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -75,6 +75,16 @@ public: */ void release(void); + /** + * validate the state of the port before start + * it will return a stream graph + * containing information about the streams + * configured on this port + * + * on error it throws TrexException + */ + const TrexStreamsGraphObj *validate(void); + /** * start traffic * throws TrexException in case of an error @@ -172,6 +182,7 @@ public: verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS); m_stream_table.add_stream(stream); + delete_streams_graph(); change_state(PORT_STATE_STREAMS); } @@ -180,6 +191,7 @@ public: verify_state(PORT_STATE_STREAMS); m_stream_table.remove_stream(stream); + delete_streams_graph(); if (m_stream_table.size() == 0) { change_state(PORT_STATE_IDLE); @@ -190,6 +202,7 @@ public: verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS); m_stream_table.remove_and_delete_all_streams(); + delete_streams_graph(); change_state(PORT_STATE_IDLE); } @@ -219,6 +232,12 @@ public: return (m_current_per_core_m * m_cores_id_list.size()); } + /** + * get port speed in bits per second + * + */ + uint64_t get_port_speed_bps() const; + private: @@ -269,11 +288,7 @@ private: */ double calculate_effective_mul(const TrexPortMultiplier &mul); - /** - * get port speed in bits per second - * - */ - uint64_t get_port_speed_bps(); + /** * generates a graph of streams graph diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index c8aa1e40..1c601f85 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -219,7 +219,7 @@ TrexStreamsCompiler::check_stream(const TrexStream *stream) { /* cont. stream can point only on itself */ if (stream->get_type() == TrexStream::stCONTINUOUS) { if (stream->m_next_stream_id != -1) { - ss << "continous stream '" << stream->m_stream_id << "' cannot point on another stream"; + ss << "continous stream '" << stream->m_stream_id << "' cannot point to another stream"; err(ss.str()); } } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index a4c12f8d..c1cf3811 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -157,6 +157,7 @@ public: return m_rate_events; } + private: void add_rate_event(const rate_event_st &ev) { -- cgit From 3aa3a83fe7b7d066ac910140c58cef1939de2baa Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 3 Dec 2015 11:14:22 -0500 Subject: burst bug - generate compiler object per core send message per core instead of duplicating it --- src/stateless/cp/trex_stateless_port.cpp | 105 ++++++++++++------- src/stateless/cp/trex_stateless_port.h | 26 ++++- src/stateless/cp/trex_stream.h | 9 +- src/stateless/cp/trex_streams_compiler.cpp | 152 ++++++++++++++++++---------- src/stateless/cp/trex_streams_compiler.h | 36 +++---- src/stateless/dp/trex_stateless_dp_core.cpp | 2 +- 6 files changed, 213 insertions(+), 117 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 25fae038..10e863c5 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -115,7 +115,7 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) /* on start - we can only provide absolute values */ assert(mul.m_op == TrexPortMultiplier::OP_ABS); - double per_core_mul = calculate_effective_mul(mul); + double factor = calculate_effective_factor(mul); /* fetch all the streams from the table */ vector streams; @@ -123,11 +123,16 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) /* compiler it */ - TrexStreamsCompiler compiler; - TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, per_core_mul); - + std::vector compiled_objs; std::string fail_msg; - bool rc = compiler.compile(streams, *compiled_obj, &fail_msg); + + TrexStreamsCompiler compiler; + bool rc = compiler.compile(m_port_id, + get_dp_core_count(), + factor, + streams, + compiled_objs, + &fail_msg); if (!rc) { throw TrexRpcException(fail_msg); } @@ -138,21 +143,29 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) /* mark that DP event of stoppped is possible */ m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, event_id); - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_obj, duration); - - m_last_all_streams_continues = compiled_obj->get_all_streams_continues(); - m_last_duration =duration; + /* update object status */ + m_factor = factor; + m_last_all_streams_continues = compiled_objs[0]->get_all_streams_continues(); + m_last_duration = duration; change_state(PORT_STATE_TX); - send_message_to_dp(start_msg); + + /* update the DP - messages will be freed by the DP */ + int index = 0; + for (auto core_id : m_cores_id_list) { + + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_objs[index], duration); + send_message_to_dp(core_id, start_msg); + + index++; + } + /* update subscribers */ Json::Value data; data["port_id"] = m_port_id; get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data); - - /* save the per core multiplier for update messages */ - m_current_per_core_m = per_core_mul; + } @@ -180,7 +193,7 @@ TrexStatelessPort::stop_traffic(void) { /* generate a message to all the relevant DP cores to start transmitting */ TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); - send_message_to_dp(stop_msg); + send_message_to_all_dp(stop_msg); change_state(PORT_STATE_STREAMS); @@ -203,9 +216,9 @@ TrexStatelessPort::pause_traffic(void) { throw TrexRpcException(" pause is supported when duration is not enable is start command "); } - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpPause(m_port_id); + TrexStatelessCpToDpMsgBase *pause_msg = new TrexStatelessDpPause(m_port_id); - send_message_to_dp(stop_msg); + send_message_to_all_dp(pause_msg); change_state(PORT_STATE_PAUSE); } @@ -216,9 +229,9 @@ TrexStatelessPort::resume_traffic(void) { verify_state(PORT_STATE_PAUSE); /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpResume(m_port_id); + TrexStatelessCpToDpMsgBase *resume_msg = new TrexStatelessDpResume(m_port_id); - send_message_to_dp(stop_msg); + send_message_to_all_dp(resume_msg); change_state(PORT_STATE_TX); } @@ -231,19 +244,19 @@ TrexStatelessPort::update_traffic(const TrexPortMultiplier &mul) { verify_state(PORT_STATE_TX | PORT_STATE_PAUSE); /* generate a message to all the relevant DP cores to start transmitting */ - double new_per_core_m = calculate_effective_mul(mul); + double new_factor = calculate_effective_factor(mul); switch (mul.m_op) { case TrexPortMultiplier::OP_ABS: - factor = new_per_core_m / m_current_per_core_m; + factor = new_factor / m_factor; break; case TrexPortMultiplier::OP_ADD: - factor = (m_current_per_core_m + new_per_core_m) / m_current_per_core_m; + factor = (m_factor + new_factor) / m_factor; break; case TrexPortMultiplier::OP_SUB: - factor = (m_current_per_core_m - new_per_core_m) / m_current_per_core_m; + factor = (m_factor - new_factor) / m_factor; if (factor <= 0) { throw TrexRpcException("Update request will lower traffic to less than zero"); } @@ -256,9 +269,9 @@ TrexStatelessPort::update_traffic(const TrexPortMultiplier &mul) { TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, factor); - send_message_to_dp(update_msg); + send_message_to_all_dp(update_msg); - m_current_per_core_m *= factor; + m_factor *= factor; } @@ -357,15 +370,22 @@ TrexStatelessPort::encode_stats(Json::Value &port) { } void -TrexStatelessPort::send_message_to_dp(TrexStatelessCpToDpMsgBase *msg) { +TrexStatelessPort::send_message_to_all_dp(TrexStatelessCpToDpMsgBase *msg) { for (auto core_id : m_cores_id_list) { - - /* send the message to the core */ - CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_id); - ring->Enqueue((CGenNode *)msg->clone()); + send_message_to_dp(core_id, msg->clone()); } + /* original was not sent - delete it */ + delete msg; +} + +void +TrexStatelessPort::send_message_to_dp(uint8_t core_id, TrexStatelessCpToDpMsgBase *msg) { + + /* send the message to the core */ + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(core_id); + ring->Enqueue((CGenNode *)msg); } /** @@ -411,11 +431,11 @@ TrexStatelessPort::get_port_speed_bps() const { } double -TrexStatelessPort::calculate_effective_mul(const TrexPortMultiplier &mul) { +TrexStatelessPort::calculate_effective_factor(const TrexPortMultiplier &mul) { - /* for a simple factor request - calculate the multiplier per core */ + /* for a simple factor request */ if (mul.m_type == TrexPortMultiplier::MUL_FACTOR) { - return (mul.m_value / m_cores_id_list.size()); + return (mul.m_value); } /* we now need the graph - generate it if we don't have it (happens once) */ @@ -425,19 +445,19 @@ TrexStatelessPort::calculate_effective_mul(const TrexPortMultiplier &mul) { switch (mul.m_type) { case TrexPortMultiplier::MUL_BPS: - return ( (mul.m_value / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); + return (mul.m_value / m_graph_obj->get_max_bps()); case TrexPortMultiplier::MUL_PPS: - return ( (mul.m_value / m_graph_obj->get_max_pps()) / m_cores_id_list.size()); + return (mul.m_value / m_graph_obj->get_max_pps()); case TrexPortMultiplier::MUL_PERCENTAGE: /* if abs percentage is from the line speed - otherwise its from the current speed */ if (mul.m_op == TrexPortMultiplier::OP_ABS) { double required = (mul.m_value / 100.0) * get_port_speed_bps(); - return ( (required / m_graph_obj->get_max_bps()) / m_cores_id_list.size()); + return (required / m_graph_obj->get_max_bps()); } else { - return (m_current_per_core_m * (mul.m_value / 100.0)); + return (m_factor * (mul.m_value / 100.0)); } default: @@ -532,14 +552,23 @@ TrexStatelessPort::validate(void) { } TrexStreamsCompiler compiler; - TrexStreamsCompiledObj compiled_obj(m_port_id, 1); + std::vector compiled_objs; std::string fail_msg; - bool rc = compiler.compile(streams, compiled_obj, &fail_msg); + bool rc = compiler.compile(m_port_id, + get_dp_core_count(), + 1.0, + streams, + compiled_objs, + &fail_msg); if (!rc) { throw TrexException(fail_msg); } + for (auto obj : compiled_objs) { + delete obj; + } + /* now create a stream graph */ if (!m_graph_obj) { generate_streams_graph(); diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index dbaac21d..28e42a17 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -224,12 +224,20 @@ public: } + /** + * returns the number of DP cores linked to this port + * + */ + uint8_t get_dp_core_count() { + return m_cores_id_list.size(); + } + /** * returns the traffic multiplier currently being used by the DP * */ double get_multiplier() { - return (m_current_per_core_m * m_cores_id_list.size()); + return (m_factor); } /** @@ -273,7 +281,17 @@ private: std::string generate_handler(); - void send_message_to_dp(TrexStatelessCpToDpMsgBase *msg); + /** + * send message to all cores using duplicate + * + */ + void send_message_to_all_dp(TrexStatelessCpToDpMsgBase *msg); + + /** + * send message to specific DP core + * + */ + void send_message_to_dp(uint8_t core_id, TrexStatelessCpToDpMsgBase *msg); /** * triggered when event occurs @@ -286,7 +304,7 @@ private: * calculate effective M per core * */ - double calculate_effective_mul(const TrexPortMultiplier &mul); + double calculate_effective_factor(const TrexPortMultiplier &mul); @@ -318,7 +336,7 @@ private: bool m_last_all_streams_continues; double m_last_duration; - double m_current_per_core_m; + double m_factor; TrexDpPortEvents m_dp_events; diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 3e48d7e4..b991b05f 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -129,12 +129,13 @@ public: } /* create new stream */ - TrexStream * clone_as_dp(){ - TrexStream * dp=new TrexStream(m_type,m_port_id,m_stream_id); + TrexStream * clone_as_dp() const { + + TrexStream *dp = new TrexStream(m_type,m_port_id,m_stream_id); - dp->m_isg_usec = m_isg_usec; - dp->m_next_stream_id = m_next_stream_id; + dp->m_isg_usec = m_isg_usec; + dp->m_next_stream_id = m_next_stream_id; dp->m_enabled = m_enabled; dp->m_self_start = m_self_start; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 1c601f85..36b165d1 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -142,8 +142,9 @@ private: /************************************** * stream compiled object *************************************/ -TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) { - m_all_continues=false; +TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id) { + m_port_id = port_id; + m_all_continues = false; } TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { @@ -155,53 +156,40 @@ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { void -TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream){ +TrexStreamsCompiledObj::add_compiled_stream(TrexStream *stream){ obj_st obj; - obj.m_stream = stream->clone_as_dp(); + obj.m_stream = stream; m_objs.push_back(obj); } -void -TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream, - uint32_t my_dp_id, int next_dp_id) { - obj_st obj; - - obj.m_stream = stream->clone_as_dp(); - /* compress the id's*/ - obj.m_stream->fix_dp_stream_id(my_dp_id,next_dp_id); - - m_objs.push_back(obj); -} - -void TrexStreamsCompiledObj::Dump(FILE *fd){ - for (auto obj : m_objs) { - obj.m_stream->Dump(fd); - } -} - - TrexStreamsCompiledObj * TrexStreamsCompiledObj::clone() { - /* use multiplier of 1 to avoid double mult */ - TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id, 1); + TrexStreamsCompiledObj *new_compiled_obj = new TrexStreamsCompiledObj(m_port_id); /** * clone each element */ for (auto obj : m_objs) { - new_compiled_obj->add_compiled_stream(obj.m_stream); + TrexStream *new_stream = obj.m_stream->clone_as_dp(); + new_compiled_obj->add_compiled_stream(new_stream); } - new_compiled_obj->m_mul = m_mul; - return new_compiled_obj; + +} + +void TrexStreamsCompiledObj::Dump(FILE *fd){ + for (auto obj : m_objs) { + obj.m_stream->Dump(fd); + } } + void TrexStreamsCompiler::add_warning(const std::string &warning) { m_warnings.push_back("*** warning: " + warning); @@ -381,12 +369,14 @@ TrexStreamsCompiler::pre_compile_check(const std::vector &streams, * stream compiler *************************************/ bool -TrexStreamsCompiler::compile(const std::vector &streams, - TrexStreamsCompiledObj &obj, - std::string *fail_msg) { +TrexStreamsCompiler::compile(uint8_t port_id, + uint8_t dp_core_count, + double factor, + const std::vector &streams, + std::vector &objs, + std::string *fail_msg) { #if 0 - fprintf(stdout,"------------pre compile \n"); for (auto stream : streams) { stream->Dump(stdout); } @@ -398,7 +388,7 @@ TrexStreamsCompiler::compile(const std::vector &streams, /* compile checks */ try { - pre_compile_check(streams,nodes); + pre_compile_check(streams, nodes); } catch (const TrexException &ex) { if (fail_msg) { *fail_msg = ex.what(); @@ -408,38 +398,94 @@ TrexStreamsCompiler::compile(const std::vector &streams, return false; } + /* check if all are cont. streams */ + bool all_continues = true; + for (const auto stream : streams) { + if (stream->get_type() != TrexStream::stCONTINUOUS) { + all_continues = false; + break; + } + } + + /* allocate objects for all DP cores */ + for (uint8_t i = 0; i < dp_core_count; i++) { + TrexStreamsCompiledObj *obj = new TrexStreamsCompiledObj(port_id); + obj->m_all_continues = all_continues; + objs.push_back(obj); + } - bool all_continues=true; - /* for now we do something trivial, */ + /* compile all the streams */ for (auto stream : streams) { /* skip non-enabled streams */ if (!stream->m_enabled) { continue; } - if (stream->get_type() != TrexStream::stCONTINUOUS ) { - all_continues=false; - } - - int new_id= nodes.get(stream->m_stream_id)->m_compressed_stream_id; - assert(new_id>=0); - uint32_t my_stream_id = (uint32_t)new_id; - int my_next_stream_id=-1; - if (stream->m_next_stream_id>=0) { - my_next_stream_id=nodes.get(stream->m_next_stream_id)->m_compressed_stream_id; - } - - /* add it */ - obj.add_compiled_stream(stream, - my_stream_id, - my_next_stream_id - ); + + /* compile a single stream to all cores */ + compile_stream(stream, factor, dp_core_count, objs, nodes); } - obj.m_all_continues =all_continues; + return true; } +/** + * compiles a single stream to DP objects + * + * @author imarom (03-Dec-15) + * + */ +void +TrexStreamsCompiler::compile_stream(const TrexStream *stream, + double factor, + uint8_t dp_core_count, + std::vector &objs, + GraphNodeMap &nodes) { + + + /* fix the stream ids */ + int new_id = nodes.get(stream->m_stream_id)->m_compressed_stream_id; + assert(new_id >= 0); + + int new_next_id = -1; + if (stream->m_next_stream_id >= 0) { + new_next_id = nodes.get(stream->m_next_stream_id)->m_compressed_stream_id; + } + + /* calculate rate */ + double per_core_rate = (stream->m_pps * (factor / dp_core_count)); + int per_core_burst_total_pkts = (stream->m_burst_total_pkts / dp_core_count); + + std::vector per_core_streams(dp_core_count); + + /* for each core - creates its own version of the stream */ + for (uint8_t i = 0; i < dp_core_count; i++) { + TrexStream *dp_stream = stream->clone_as_dp(); + + /* fix stream ID */ + dp_stream->fix_dp_stream_id(new_id, new_next_id); + + + /* adjust rate and packets count */ + dp_stream->m_pps = per_core_rate; + dp_stream->m_burst_total_pkts = per_core_burst_total_pkts; + + per_core_streams[i] = dp_stream; + } + + /* take care of remainder from a burst */ + int burst_remainder = stream->m_burst_total_pkts - (per_core_burst_total_pkts * dp_core_count); + per_core_streams[0]->m_burst_total_pkts += burst_remainder; + + /* attach the compiled stream of every core to its object */ + for (uint8_t i = 0; i < dp_core_count; i++) { + objs[i]->add_compiled_stream(per_core_streams[i]); + } + + +} + /************************************** * streams graph *************************************/ diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index c1cf3811..93a63061 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -38,9 +38,10 @@ class GraphNodeMap; */ class TrexStreamsCompiledObj { friend class TrexStreamsCompiler; + public: - TrexStreamsCompiledObj(uint8_t port_id, double m_mul); + TrexStreamsCompiledObj(uint8_t port_id); ~TrexStreamsCompiledObj(); struct obj_st { @@ -56,32 +57,22 @@ public: return (m_port_id); } - /** - * clone the compiled object - * - */ - TrexStreamsCompiledObj * clone(); - - double get_multiplier(){ - return (m_mul); - } - bool get_all_streams_continues(){ return (m_all_continues); } void Dump(FILE *fd); + TrexStreamsCompiledObj* clone(); + private: - void add_compiled_stream(TrexStream * stream, - uint32_t my_dp_id, int next_dp_id); - void add_compiled_stream(TrexStream * stream); + void add_compiled_stream(TrexStream *stream); + std::vector m_objs; bool m_all_continues; uint8_t m_port_id; - double m_mul; }; class TrexStreamsCompiler { @@ -93,7 +84,13 @@ public: * @author imarom (28-Oct-15) * */ - bool compile(const std::vector &streams, TrexStreamsCompiledObj &obj, std::string *fail_msg = NULL); + bool compile(uint8_t port_id, + uint8_t dp_core_count, + double factor, + const std::vector &streams, + std::vector &objs, + std::string *fail_msg = NULL); + /** * @@ -115,8 +112,13 @@ private: void add_warning(const std::string &warning); void err(const std::string &err); + void compile_stream(const TrexStream *stream, + double factor, + uint8_t dp_core_count, + std::vector &objs, + GraphNodeMap &nodes); + std::vector m_warnings; - }; class TrexStreamsGraph; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 9b62fabd..22ca922d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -453,7 +453,7 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, node->m_pause =0; node->m_stream_type = stream->m_type; - node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()); + node->m_next_time_offset = 1.0 / stream->get_pps(); /* stateless specific fields */ switch ( stream->m_type ) { -- cgit From 23e1f07edcd8289f09a1477c416ce260d1a0a804 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 6 Dec 2015 03:53:35 -0500 Subject: moved gtest to new compile API --- src/stateless/cp/trex_stateless_port.cpp | 8 ++++---- src/stateless/cp/trex_streams_compiler.cpp | 4 ++-- src/stateless/cp/trex_streams_compiler.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 10e863c5..0e45bf0b 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -128,10 +128,10 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration) TrexStreamsCompiler compiler; bool rc = compiler.compile(m_port_id, - get_dp_core_count(), - factor, streams, compiled_objs, + get_dp_core_count(), + factor, &fail_msg); if (!rc) { throw TrexRpcException(fail_msg); @@ -556,10 +556,10 @@ TrexStatelessPort::validate(void) { std::string fail_msg; bool rc = compiler.compile(m_port_id, - get_dp_core_count(), - 1.0, streams, compiled_objs, + get_dp_core_count(), + 1.0, &fail_msg); if (!rc) { throw TrexException(fail_msg); diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 36b165d1..d83e4ab6 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -370,10 +370,10 @@ TrexStreamsCompiler::pre_compile_check(const std::vector &streams, *************************************/ bool TrexStreamsCompiler::compile(uint8_t port_id, - uint8_t dp_core_count, - double factor, const std::vector &streams, std::vector &objs, + uint8_t dp_core_count, + double factor, std::string *fail_msg) { #if 0 diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 93a63061..e193a749 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -85,10 +85,10 @@ public: * */ bool compile(uint8_t port_id, - uint8_t dp_core_count, - double factor, const std::vector &streams, std::vector &objs, + uint8_t dp_core_count = 1, + double factor = 1.0, std::string *fail_msg = NULL); -- cgit From 0fc30adae2fc5708baef74d36e97a174b078f332 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 7 Dec 2015 09:08:02 -0500 Subject: added 'dry' option to start command this enables showing a profile map before starting --- src/stateless/cp/trex_streams_compiler.cpp | 9 +++++++++ src/stateless/cp/trex_streams_compiler.h | 19 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index d83e4ab6..478e09f8 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -536,6 +536,9 @@ TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const Tre /* no more events after this stream */ offset_usec = -1; + + /* also mark we have an inifite time */ + m_graph_obj->m_expected_duration = -1; } /** @@ -648,6 +651,7 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { /* loop detection */ auto search = loop_hash.find(stream->m_next_stream_id); if (search != loop_hash.end()) { + m_graph_obj->on_loop_detection(); break; } @@ -720,6 +724,11 @@ TrexStreamsGraphObj::find_max_rate() { max_rate_bps = std::max(max_rate_bps, current_rate_bps); } + /* if not mark as inifite - get the last event time */ + if (m_expected_duration != -1) { + m_expected_duration = m_rate_events.back().time; + } + m_max_pps = max_rate_pps; m_max_bps = max_rate_bps; } diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index e193a749..7fe2dbf2 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -133,6 +133,12 @@ class TrexStreamsGraphObj { public: + TrexStreamsGraphObj() { + m_max_pps = 0; + m_max_bps = 0; + m_expected_duration = 0; + } + /** * rate event is defined by those: * time - the time of the event on the timeline @@ -155,6 +161,10 @@ public: return m_max_bps; } + int get_duration() const { + return m_expected_duration; + } + const std::list & get_events() const { return m_rate_events; } @@ -162,6 +172,10 @@ public: private: + void on_loop_detection() { + m_expected_duration = -1; + } + void add_rate_event(const rate_event_st &ev) { m_rate_events.push_back(ev); } @@ -169,8 +183,9 @@ private: void generate(); void find_max_rate(); - double m_max_pps; - double m_max_bps; + double m_max_pps; + double m_max_bps; + int m_expected_duration; /* list of rate events */ std::list m_rate_events; -- cgit From 95c2405d6373ca3c6b69efc3faf293cd41a55c76 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 9 Dec 2015 15:01:25 -0500 Subject: read only support --- src/stateless/cp/trex_stateless_port.cpp | 101 ++++++++++++++++------- src/stateless/cp/trex_stateless_port.h | 133 +++++++++++++++++++------------ 2 files changed, 157 insertions(+), 77 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 0e45bf0b..96194321 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -57,7 +57,6 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api m_port_id = port_id; m_port_state = PORT_STATE_IDLE; - clear_owner(); /* get the platform specific data */ api->get_interface_info(port_id, m_driver_name, m_speed); @@ -85,18 +84,42 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api * @param force */ void -TrexStatelessPort::acquire(const std::string &user, bool force) { - if ( (!is_free_to_aquire()) && (get_owner() != user) && (!force)) { - throw TrexRpcException("port is already taken by '" + get_owner() + "'"); +TrexStatelessPort::acquire(const std::string &user, uint32_t session_id, bool force) { + + /* if port is free - just take it */ + if (get_owner().is_free()) { + get_owner().own(user, session_id); + return; + } + + /* not free - but it might be the same user that owns the port */ + if ( (get_owner().get_name() == user) && (get_owner().get_session_id() == session_id) ) { + return; + } + + /* so different session id or different user */ + if (force) { + get_owner().own(user, session_id); + + /* inform the other client of the steal... */ + Json::Value data; + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_FORCE_ACQUIRED, data); + + } else { + /* not same user or session id and not force - report error */ + if (get_owner().get_name() == user) { + throw TrexRpcException("port is already owned by another session of '" + user + "'"); + } else { + throw TrexRpcException("port is already taken by '" + get_owner().get_name() + "'"); + } } - set_owner(user); } void TrexStatelessPort::release(void) { - verify_state( ~(PORT_STATE_TX | PORT_STATE_PAUSE) ); - clear_owner(); + get_owner().release(); } /** @@ -221,6 +244,10 @@ TrexStatelessPort::pause_traffic(void) { send_message_to_all_dp(pause_msg); change_state(PORT_STATE_PAUSE); + + Json::Value data; + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_PAUSED, data); } void @@ -234,6 +261,11 @@ TrexStatelessPort::resume_traffic(void) { send_message_to_all_dp(resume_msg); change_state(PORT_STATE_TX); + + + Json::Value data; + data["port_id"] = m_port_id; + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_RESUMED, data); } void @@ -324,27 +356,6 @@ TrexStatelessPort::change_state(port_state_e new_state) { m_port_state = new_state; } -/** - * 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()); -} - void TrexStatelessPort::encode_stats(Json::Value &port) { @@ -576,3 +587,37 @@ TrexStatelessPort::validate(void) { return m_graph_obj; } + + +/************* Trex Port Owner **************/ + +TrexPortOwner::TrexPortOwner() { + m_is_free = true; + + /* for handlers random generation */ + srand(time(NULL)); +} + +/** + * generate a random connection handler + * + */ +std::string +TrexPortOwner::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()); +} + +const std::string TrexPortOwner::g_unowned_name = ""; +const std::string TrexPortOwner::g_unowned_handler = ""; diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 28e42a17..1310fdb2 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -29,6 +29,82 @@ class TrexStatelessCpToDpMsgBase; class TrexStreamsGraphObj; class TrexPortMultiplier; +/** + * TRex port owner can perform + * write commands + * while port is owned - others can + * do read only commands + * + */ +class TrexPortOwner { +public: + + TrexPortOwner(); + + /** + * is port free to acquire + */ + bool is_free() { + return m_is_free; + } + + void release() { + m_is_free = true; + m_owner_name = ""; + m_handler = ""; + } + + bool is_owned_by(const std::string &user) { + return ( !m_is_free && (m_owner_name == user) ); + } + + void own(const std::string &owner_name, uint32_t session_id) { + + /* save user data */ + m_owner_name = owner_name; + m_session_id = session_id; + + /* internal data */ + m_handler = generate_handler(); + m_is_free = false; + } + + bool verify(const std::string &handler) { + return ( (!m_is_free) && (m_handler == handler) ); + } + + const std::string &get_name() { + return (!m_is_free ? m_owner_name : g_unowned_name); + } + + const std::string &get_handler() { + return (!m_is_free ? m_handler : g_unowned_handler); + } + + uint32_t get_session_id() { + return m_session_id; + } + +private: + std::string generate_handler(); + + /* is this port owned by someone ? */ + bool m_is_free; + + /* user provided info - name and session id */ + std::string m_owner_name; + uint32_t m_session_id; + + /* handler genereated internally */ + std::string m_handler; + + + /* just references defaults... */ + static const std::string g_unowned_name; + static const std::string g_unowned_handler; +}; + + /** * describes a stateless port * @@ -67,7 +143,7 @@ public: * acquire port * throws TrexException in case of an error */ - void acquire(const std::string &user, bool force = false); + void acquire(const std::string &user, uint32_t session_id, bool force = false); /** * release the port from the current user @@ -140,29 +216,6 @@ public: void get_properties(std::string &driver, TrexPlatformApi::driver_speed_e &speed); - /** - * query for ownership - * - */ - const std::string &get_owner() { - return m_owner; - } - - /** - * owner handler - * for the connection - * - */ - const std::string &get_owner_handler() { - return m_owner_handler; - } - - - bool verify_owner_handler(const std::string &handler) { - - return ( (m_owner != "none") && (m_owner_handler == handler) ); - - } /** * encode stats as JSON @@ -246,29 +299,11 @@ public: */ uint64_t get_port_speed_bps() const; -private: - - - - /** - * take ownership of the server array - * this is static - * ownership is total - * - */ - void set_owner(const std::string &owner) { - m_owner = owner; - m_owner_handler = generate_handler(); - } - - void clear_owner() { - m_owner = "none"; - m_owner_handler = ""; + TrexPortOwner & get_owner() { + return m_owner; } - bool is_free_to_aquire() { - return (m_owner == "none"); - } +private: const std::vector get_core_id_list () { @@ -325,14 +360,12 @@ private: TrexStreamTable m_stream_table; uint8_t m_port_id; port_state_e m_port_state; - std::string m_owner; - std::string m_owner_handler; std::string m_driver_name; TrexPlatformApi::driver_speed_e m_speed; /* holds the DP cores associated with this port */ - std::vector m_cores_id_list; + std::vector m_cores_id_list; bool m_last_all_streams_continues; double m_last_duration; @@ -342,8 +375,10 @@ private: /* holds a graph of streams rate*/ const TrexStreamsGraphObj *m_graph_obj; -}; + /* owner information */ + TrexPortOwner m_owner; +}; /** -- cgit From 7567166ca52bd136ce08c06dcbd48c0dfd67210f Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 10 Dec 2015 03:43:55 -0500 Subject: removed session id - not necessary --- src/stateless/cp/trex_stateless_port.cpp | 12 +++--------- src/stateless/cp/trex_stateless_port.h | 11 +++-------- 2 files changed, 6 insertions(+), 17 deletions(-) (limited to 'src/stateless') diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 96194321..9770c735 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -84,22 +84,16 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api * @param force */ void -TrexStatelessPort::acquire(const std::string &user, uint32_t session_id, bool force) { +TrexStatelessPort::acquire(const std::string &user, bool force) { /* if port is free - just take it */ if (get_owner().is_free()) { - get_owner().own(user, session_id); + get_owner().own(user); return; } - /* not free - but it might be the same user that owns the port */ - if ( (get_owner().get_name() == user) && (get_owner().get_session_id() == session_id) ) { - return; - } - - /* so different session id or different user */ if (force) { - get_owner().own(user, session_id); + get_owner().own(user); /* inform the other client of the steal... */ Json::Value data; diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 1310fdb2..4988b46a 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -58,11 +58,10 @@ public: return ( !m_is_free && (m_owner_name == user) ); } - void own(const std::string &owner_name, uint32_t session_id) { + void own(const std::string &owner_name) { /* save user data */ m_owner_name = owner_name; - m_session_id = session_id; /* internal data */ m_handler = generate_handler(); @@ -81,9 +80,6 @@ public: return (!m_is_free ? m_handler : g_unowned_handler); } - uint32_t get_session_id() { - return m_session_id; - } private: std::string generate_handler(); @@ -91,9 +87,8 @@ private: /* is this port owned by someone ? */ bool m_is_free; - /* user provided info - name and session id */ + /* user provided info */ std::string m_owner_name; - uint32_t m_session_id; /* handler genereated internally */ std::string m_handler; @@ -143,7 +138,7 @@ public: * acquire port * throws TrexException in case of an error */ - void acquire(const std::string &user, uint32_t session_id, bool force = false); + void acquire(const std::string &user, bool force = false); /** * release the port from the current user -- cgit