From f47239654fb47d9de81fdb47fc9a16f3f205082f Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 7 Oct 2015 17:07:18 +0200 Subject: added some dir structure to the stateless --- src/stateless/cp/trex_stateless.cpp | 137 ++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/stateless/cp/trex_stateless.cpp (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp new file mode 100644 index 00000000..0b7947a0 --- /dev/null +++ b/src/stateless/cp/trex_stateless.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 + +using namespace std; + +/*********************************************************** + * Trex stateless object + * + **********************************************************/ +TrexStateless::TrexStateless() { + m_is_configured = false; +} + +/** + * one time configuration of the stateless object + * + */ +void TrexStateless::configure(uint8_t port_count) { + + TrexStateless& instance = get_instance_internal(); + + if (instance.m_is_configured) { + throw TrexException("re-configuration of stateless object is not allowed"); + } + + instance.m_port_count = port_count; + instance.m_ports = new TrexStatelessPort*[port_count]; + + for (int i = 0; i < instance.m_port_count; i++) { + instance.m_ports[i] = new TrexStatelessPort(i); + } + + instance.m_is_configured = true; +} + +TrexStateless::~TrexStateless() { + for (int i = 0; i < m_port_count; i++) { + delete m_ports[i]; + } + + delete [] m_ports; +} + +TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) { + if (port_id >= m_port_count) { + throw TrexException("index out of range"); + } + + return m_ports[port_id]; + +} + +uint8_t TrexStateless::get_port_count() { + return m_port_count; +} + +void +TrexStateless::update_stats() { + + /* update CPU util. */ + #ifdef TREX_RPC_MOCK_SERVER + m_stats.m_stats.m_cpu_util = 0; + #else + m_stats.m_stats.m_cpu_util = 0; + #endif + + /* for every port update and accumulate */ + for (uint8_t i = 0; i < m_port_count; i++) { + m_ports[i]->update_stats(); + + const TrexPortStats & port_stats = m_ports[i]->get_stats(); + + m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps; + m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps; + + m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps; + m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps; + + m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts; + m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts; + + m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes; + m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes; + + m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors; + } +} + +void +TrexStateless::encode_stats(Json::Value &global) { + + global["cpu_util"] = m_stats.m_stats.m_cpu_util; + + global["tx_bps"] = m_stats.m_stats.m_tx_bps; + global["rx_bps"] = m_stats.m_stats.m_rx_bps; + + global["tx_pps"] = m_stats.m_stats.m_tx_pps; + global["rx_pps"] = m_stats.m_stats.m_rx_pps; + + global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); + global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); + + global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); + global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); + + global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); + + for (uint8_t i = 0; i < m_port_count; i++) { + std::stringstream ss; + + ss << "port " << i; + Json::Value &port_section = global[ss.str()]; + + m_ports[i]->encode_stats(port_section); + } +} + -- cgit 1.2.3-korg From 74b648a86c16933680b03a736afe3f0305b4f6d2 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 8 Oct 2015 08:34:43 +0200 Subject: some file renaming --- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 2 +- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 4 +- src/rpc-server/trex_rpc_async_server.cpp | 2 +- src/rpc-server/trex_rpc_cmd.cpp | 2 +- src/rpc-server/trex_rpc_server_mock.cpp | 2 +- src/stateless/cp/trex_stateless.cpp | 2 +- src/stateless/cp/trex_stateless.h | 142 +++++++++++++++ src/stateless/cp/trex_stateless_api.h | 142 --------------- src/stateless/cp/trex_stateless_port.cpp | 2 +- src/stateless/cp/trex_stateless_port.h | 2 +- src/stateless/cp/trex_stream.cpp | 2 +- src/stateless/cp/trex_stream.h | 209 +++++++++++++++++++++++ src/stateless/cp/trex_stream_api.h | 209 ----------------------- 13 files changed, 361 insertions(+), 361 deletions(-) create mode 100644 src/stateless/cp/trex_stateless.h delete mode 100644 src/stateless/cp/trex_stateless_api.h create mode 100644 src/stateless/cp/trex_stream.h delete mode 100644 src/stateless/cp/trex_stream_api.h (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 3a0a12f8..b440fa81 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -21,7 +21,7 @@ limitations under the License. #include "trex_rpc_cmds.h" #include -#include +#include #include #include diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 97c2b791..812d819e 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -20,8 +20,8 @@ limitations under the License. */ #include "trex_rpc_cmds.h" #include -#include -#include +#include +#include #include #include diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp index 40d16dfe..01f03af3 100644 --- a/src/rpc-server/trex_rpc_async_server.cpp +++ b/src/rpc-server/trex_rpc_async_server.cpp @@ -24,7 +24,7 @@ limitations under the License. */ #define _GLIBCXX_USE_NANOSLEEP -#include +#include #include #include #include diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index f7cb5259..920a8d30 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -20,7 +20,7 @@ limitations under the License. */ #include #include -#include +#include #include trex_rpc_cmd_rc_e diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp index 16aa6774..32635c75 100644 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ b/src/rpc-server/trex_rpc_server_mock.cpp @@ -20,7 +20,7 @@ limitations under the License. */ #include -#include +#include #include #include diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 0b7947a0..92f54bc4 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -#include +#include #include using namespace std; diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h new file mode 100644 index 00000000..74e88846 --- /dev/null +++ b/src/stateless/cp/trex_stateless.h @@ -0,0 +1,142 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_H__ +#define __TREX_STATELESS_H__ + +#include +#include +#include + +#include + +/** + * generic exception for errors + * TODO: move this to a better place + */ +class TrexException : public std::runtime_error +{ +public: + TrexException() : std::runtime_error("") { + + } + TrexException(const std::string &what) : std::runtime_error(what) { + } +}; + +class TrexStatelessPort; + +/** + * unified stats + * + * @author imarom (06-Oct-15) + */ +class TrexStatelessStats { +public: + TrexStatelessStats() { + m_stats = {0}; + } + + struct { + double m_cpu_util; + + double m_tx_bps; + double m_rx_bps; + + double m_tx_pps; + double m_rx_pps; + + uint64_t m_total_tx_pkts; + uint64_t m_total_rx_pkts; + + uint64_t m_total_tx_bytes; + uint64_t m_total_rx_bytes; + + uint64_t m_tx_rx_errors; + } m_stats; +}; + +/** + * defines the T-Rex stateless operation mode + * + */ +class TrexStateless { +public: + + /** + * configure the stateless object singelton + * reconfiguration is not allowed + * an exception will be thrown + */ + static void configure(uint8_t port_count); + + /** + * singleton public get instance + * + */ + static TrexStateless& get_instance() { + TrexStateless& instance = get_instance_internal(); + + if (!instance.m_is_configured) { + throw TrexException("object is not configured"); + } + + return instance; + } + + TrexStatelessPort * get_port_by_id(uint8_t port_id); + uint8_t get_port_count(); + + /** + * update all the stats (deep update) + * (include all the ports and global stats) + * + */ + void update_stats(); + + /** + * fetch all the stats + * + */ + void encode_stats(Json::Value &global); + + +protected: + TrexStateless(); + ~TrexStateless(); + + static TrexStateless& get_instance_internal () { + static TrexStateless instance; + return instance; + } + + /* c++ 2011 style singleton */ + TrexStateless(TrexStateless const&) = delete; + void operator=(TrexStateless const&) = delete; + + bool m_is_configured; + TrexStatelessPort **m_ports; + uint8_t m_port_count; + + TrexStatelessStats m_stats; +}; + +#endif /* __TREX_STATELESS_H__ */ + diff --git a/src/stateless/cp/trex_stateless_api.h b/src/stateless/cp/trex_stateless_api.h deleted file mode 100644 index e2bf4e1c..00000000 --- a/src/stateless/cp/trex_stateless_api.h +++ /dev/null @@ -1,142 +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_API_H__ -#define __TREX_STATELESS_API_H__ - -#include -#include -#include - -#include - -/** - * generic exception for errors - * TODO: move this to a better place - */ -class TrexException : public std::runtime_error -{ -public: - TrexException() : std::runtime_error("") { - - } - TrexException(const std::string &what) : std::runtime_error(what) { - } -}; - -class TrexStatelessPort; - -/** - * unified stats - * - * @author imarom (06-Oct-15) - */ -class TrexStatelessStats { -public: - TrexStatelessStats() { - m_stats = {0}; - } - - struct { - double m_cpu_util; - - double m_tx_bps; - double m_rx_bps; - - double m_tx_pps; - double m_rx_pps; - - uint64_t m_total_tx_pkts; - uint64_t m_total_rx_pkts; - - uint64_t m_total_tx_bytes; - uint64_t m_total_rx_bytes; - - uint64_t m_tx_rx_errors; - } m_stats; -}; - -/** - * defines the T-Rex stateless operation mode - * - */ -class TrexStateless { -public: - - /** - * configure the stateless object singelton - * reconfiguration is not allowed - * an exception will be thrown - */ - static void configure(uint8_t port_count); - - /** - * singleton public get instance - * - */ - static TrexStateless& get_instance() { - TrexStateless& instance = get_instance_internal(); - - if (!instance.m_is_configured) { - throw TrexException("object is not configured"); - } - - return instance; - } - - TrexStatelessPort * get_port_by_id(uint8_t port_id); - uint8_t get_port_count(); - - /** - * update all the stats (deep update) - * (include all the ports and global stats) - * - */ - void update_stats(); - - /** - * fetch all the stats - * - */ - void encode_stats(Json::Value &global); - - -protected: - TrexStateless(); - ~TrexStateless(); - - static TrexStateless& get_instance_internal () { - static TrexStateless instance; - return instance; - } - - /* c++ 2011 style singleton */ - TrexStateless(TrexStateless const&) = delete; - void operator=(TrexStateless const&) = delete; - - bool m_is_configured; - TrexStatelessPort **m_ports; - uint8_t m_port_count; - - TrexStatelessStats m_stats; -}; - -#endif /* __TREX_STATELESS_API_H__ */ - diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 7322ef8a..031efb58 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -#include +#include #include #include diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index ea98ddae..a19fd981 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -21,7 +21,7 @@ limitations under the License. #ifndef __TREX_STATELESS_PORT_H__ #define __TREX_STATELESS_PORT_H__ -#include +#include /** * TRex stateless port stats diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 8bf04748..182036f1 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -#include +#include #include /************************************** diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h new file mode 100644 index 00000000..f5bc96ef --- /dev/null +++ b/src/stateless/cp/trex_stream.h @@ -0,0 +1,209 @@ +/* + 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_H__ +#define __TREX_STREAM_H__ + +#include +#include +#include +#include + +#include + +#include + +class TrexRpcCmdAddStream; + +/** + * Stateless Stream + * + */ +class TrexStream { + /* provide the RPC parser a way to access private fields */ + friend class TrexRpcCmdAddStream; + friend class TrexRpcCmdGetStream; + friend class TrexStreamTable; + +public: + TrexStream(uint8_t port_id, uint32_t stream_id); + virtual ~TrexStream() = 0; + + /* defines the min max per packet supported */ + static const uint32_t MIN_PKT_SIZE_BYTES = 1; + static const uint32_t MAX_PKT_SIZE_BYTES = 9000; + + /* provides storage for the stream json*/ + void store_stream_json(const Json::Value &stream_json); + + /* access the stream json */ + const Json::Value & get_stream_json(); + +protected: + /* basic */ + uint8_t m_port_id; + uint32_t m_stream_id; + + + /* config fields */ + double m_isg_usec; + int m_next_stream_id; + + /* indicators */ + bool m_enabled; + bool m_self_start; + + /* pkt */ + struct { + uint8_t *binary; + uint16_t len; + std::string meta; + } m_pkt; + + /* VM */ + StreamVm m_vm; + + /* RX check */ + struct { + bool m_enable; + bool m_seq_enabled; + bool m_latency; + uint32_t m_stream_id; + + } m_rx_check; + + + /* original template provided by requester */ + Json::Value m_stream_json; +}; + +/** + * continuous stream + * + */ +class TrexStreamContinuous : public TrexStream { +public: + TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) { + } + + double get_pps() { + return m_pps; + } + +protected: + double m_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_pps(pps) { + } + +protected: + uint32_t m_total_pkts; + double m_pps; +}; + +/** + * 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) { + + } +protected: + uint32_t m_num_bursts; + double m_ibg_usec; + +}; + +/** + * holds all the streams + * + */ +class TrexStreamTable { +public: + + TrexStreamTable(); + ~TrexStreamTable(); + + /** + * add a stream + * if a previous one exists, the old one will be deleted + */ + void add_stream(TrexStream *stream); + + /** + * remove a stream + */ + void remove_stream(TrexStream *stream); + + /** + * remove all streams on the table + * memory will be deleted + */ + void remove_and_delete_all_streams(); + + /** + * fetch a stream if exists + * o.w NULL + * + */ + TrexStream * get_stream_by_id(uint32_t stream_id); + + /** + * populate a list with all the stream IDs + * + * @author imarom (06-Sep-15) + * + * @param stream_list + */ + void get_stream_list(std::vector &stream_list); + + /** + * get the table size + * + */ + int size(); + +private: + /** + * holds all the stream in a hash table by stream id + * + */ + std::unordered_map m_stream_table; +}; + +#endif /* __TREX_STREAM_H__ */ + diff --git a/src/stateless/cp/trex_stream_api.h b/src/stateless/cp/trex_stream_api.h deleted file mode 100644 index d3c0fb29..00000000 --- a/src/stateless/cp/trex_stream_api.h +++ /dev/null @@ -1,209 +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_STREAM_API_H__ -#define __TREX_STREAM_API_H__ - -#include -#include -#include -#include - -#include - -#include - -class TrexRpcCmdAddStream; - -/** - * Stateless Stream - * - */ -class TrexStream { - /* provide the RPC parser a way to access private fields */ - friend class TrexRpcCmdAddStream; - friend class TrexRpcCmdGetStream; - friend class TrexStreamTable; - -public: - TrexStream(uint8_t port_id, uint32_t stream_id); - virtual ~TrexStream() = 0; - - /* defines the min max per packet supported */ - static const uint32_t MIN_PKT_SIZE_BYTES = 1; - static const uint32_t MAX_PKT_SIZE_BYTES = 9000; - - /* provides storage for the stream json*/ - void store_stream_json(const Json::Value &stream_json); - - /* access the stream json */ - const Json::Value & get_stream_json(); - -protected: - /* basic */ - uint8_t m_port_id; - uint32_t m_stream_id; - - - /* config fields */ - double m_isg_usec; - int m_next_stream_id; - - /* indicators */ - bool m_enabled; - bool m_self_start; - - /* pkt */ - struct { - uint8_t *binary; - uint16_t len; - std::string meta; - } m_pkt; - - /* VM */ - StreamVm m_vm; - - /* RX check */ - struct { - bool m_enable; - bool m_seq_enabled; - bool m_latency; - uint32_t m_stream_id; - - } m_rx_check; - - - /* original template provided by requester */ - Json::Value m_stream_json; -}; - -/** - * continuous stream - * - */ -class TrexStreamContinuous : public TrexStream { -public: - TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) { - } - - double get_pps() { - return m_pps; - } - -protected: - double m_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_pps(pps) { - } - -protected: - uint32_t m_total_pkts; - double m_pps; -}; - -/** - * 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) { - - } -protected: - uint32_t m_num_bursts; - double m_ibg_usec; - -}; - -/** - * holds all the streams - * - */ -class TrexStreamTable { -public: - - TrexStreamTable(); - ~TrexStreamTable(); - - /** - * add a stream - * if a previous one exists, the old one will be deleted - */ - void add_stream(TrexStream *stream); - - /** - * remove a stream - */ - void remove_stream(TrexStream *stream); - - /** - * remove all streams on the table - * memory will be deleted - */ - void remove_and_delete_all_streams(); - - /** - * fetch a stream if exists - * o.w NULL - * - */ - TrexStream * get_stream_by_id(uint32_t stream_id); - - /** - * populate a list with all the stream IDs - * - * @author imarom (06-Sep-15) - * - * @param stream_list - */ - void get_stream_list(std::vector &stream_list); - - /** - * get the table size - * - */ - int size(); - -private: - /** - * holds all the stream in a hash table by stream id - * - */ - std::unordered_map m_stream_table; -}; - -#endif /* __TREX_STREAM_API_H__ */ - -- cgit 1.2.3-korg From 09c9d77dc2f5a89924bd27226727220801a5df13 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 8 Oct 2015 10:23:33 +0200 Subject: fixed some bugs in the async server also added affinity to the stateless main object --- src/gtest/rpc_test.cpp | 10 +---- src/rpc-server/trex_rpc_async_server.cpp | 6 +-- src/rpc-server/trex_rpc_server.cpp | 13 +++++-- src/rpc-server/trex_rpc_server_api.h | 4 +- src/rpc-server/trex_rpc_server_mock.cpp | 35 +++++++++++------- src/stateless/cp/trex_stateless.cpp | 63 +++++++++++++++++++++++++++----- src/stateless/cp/trex_stateless.h | 44 +++++++++++++++++++--- 7 files changed, 129 insertions(+), 46 deletions(-) (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 4084b664..250d5342 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -42,12 +42,6 @@ protected: m_verbose = false; - TrexRpcServerConfig req_resp_cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050); - TrexRpcServerConfig async_cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5051); - - m_rpc = new TrexRpcServer(req_resp_cfg, async_cfg); - m_rpc->start(); - m_context = zmq_ctx_new (); m_socket = zmq_socket (m_context, ZMQ_REQ); zmq_connect (m_socket, "tcp://localhost:5050"); @@ -55,9 +49,6 @@ protected: } virtual void TearDown() { - m_rpc->stop(); - - delete m_rpc; zmq_close(m_socket); zmq_term(m_context); } @@ -658,3 +649,4 @@ TEST_F(RpcTestOwned, start_stop_traffic) { send_request(request, response); EXPECT_EQ(response["result"], "ACK"); } + diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp index 01f03af3..3313e42e 100644 --- a/src/rpc-server/trex_rpc_async_server.cpp +++ b/src/rpc-server/trex_rpc_async_server.cpp @@ -87,13 +87,13 @@ TrexRpcServerAsync::_rpc_thread_cb() { /* relax for some time */ std::this_thread::sleep_for (std::chrono::milliseconds(1000)); - } + + /* must be closed from the same thread */ + zmq_close(m_socket); } void TrexRpcServerAsync::_stop_rpc_thread() { - m_is_running = false; - this->m_thread->join(); zmq_term(m_context); } diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index 18265a0e..8749c9b4 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -113,13 +113,18 @@ get_current_date_time() { const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); -TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg, - const TrexRpcServerConfig &async_cfg) { +TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg, + const TrexRpcServerConfig *async_cfg) { /* add the request response server */ - m_servers.push_back(new TrexRpcServerReqRes(req_resp_cfg)); + if (req_resp_cfg) { + m_servers.push_back(new TrexRpcServerReqRes(*req_resp_cfg)); + } + /* add async publisher */ - m_servers.push_back(new TrexRpcServerAsync(async_cfg)); + if (async_cfg) { + m_servers.push_back(new TrexRpcServerAsync(*async_cfg)); + } } TrexRpcServer::~TrexRpcServer() { diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index 5a7cad48..327c6eaa 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -140,8 +140,8 @@ class TrexRpcServer { public: /* creates the collection of servers using configurations */ - TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg, - const TrexRpcServerConfig &async_cfg); + TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg, + const TrexRpcServerConfig *async_cfg); ~TrexRpcServer(); diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp index 32635c75..8dae42d7 100644 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ b/src/rpc-server/trex_rpc_server_mock.cpp @@ -44,31 +44,39 @@ int gtest_main(int argc, char **argv); int main(int argc, char *argv[]) { - /* configure the stateless object with 4 ports */ - TrexStateless::configure(4); + bool is_gtest = false; - // gtest ? + // gtest ? if (argc > 1) { if (string(argv[1]) != "--ut") { cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n"; exit(-1); } - return gtest_main(argc, argv); + is_gtest = true; } - cout << "\n-= Starting RPC Server Mock =-\n\n"; - cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; + /* configure the stateless object with 4 ports */ + TrexStatelessCfg cfg; TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); - TrexRpcServer rpc(rpc_req_resp_cfg, rpc_async_cfg); + cfg.m_port_count = 4; + cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg; + cfg.m_rpc_async_cfg = &rpc_async_cfg; + cfg.m_rpc_server_verbose = (is_gtest ? false : true); - /* init the RPC server */ - rpc.start(); + TrexStateless::create(cfg); - cout << "Setting Server To Full Verbose\n\n"; - rpc.set_verbose(true); + /* gtest handling */ + if (is_gtest) { + int rc = gtest_main(argc, argv); + TrexStateless::destroy(); + return rc; + } + + cout << "\n-= Starting RPC Server Mock =-\n\n"; + cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; cout << "Server Started\n\n"; @@ -76,7 +84,6 @@ int main(int argc, char *argv[]) { sleep(1); } - rpc.stop(); - - + TrexStateless::destroy(); } + diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 92f54bc4..1e7e2dfa 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -21,6 +21,8 @@ limitations under the License. #include #include +#include + using namespace std; /*********************************************************** @@ -31,36 +33,79 @@ TrexStateless::TrexStateless() { m_is_configured = false; } + /** - * one time configuration of the stateless object + * creates the singleton stateless object * */ -void TrexStateless::configure(uint8_t port_count) { +void TrexStateless::create(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"); } - instance.m_port_count = port_count; - instance.m_ports = new TrexStatelessPort*[port_count]; + /* pin this process to the current running CPU + any new thread will be called on the same CPU + (control plane restriction) + */ + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(sched_getcpu(), &mask); + sched_setaffinity(0, sizeof(mask), &mask); + + /* start RPC servers */ + instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg); + instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); + instance.m_rpc_server->start(); + + /* configure ports */ + + instance.m_port_count = cfg.m_port_count; for (int i = 0; i < instance.m_port_count; i++) { - instance.m_ports[i] = new TrexStatelessPort(i); + instance.m_ports.push_back(new TrexStatelessPort(i)); } + /* done */ instance.m_is_configured = true; } -TrexStateless::~TrexStateless() { - for (int i = 0; i < m_port_count; i++) { - delete m_ports[i]; +/** + * 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; } - delete [] m_ports; + /* release memory for ports */ + for (auto port : instance.m_ports) { + delete port; + } + instance.m_ports.clear(); + + /* stops the RPC server */ + instance.m_rpc_server->stop(); + delete instance.m_rpc_server; + + instance.m_rpc_server = NULL; + + /* done */ + instance.m_is_configured = false; } +/** + * fetch a port by ID + * + */ TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) { if (port_id >= m_port_count) { throw TrexException("index out of range"); diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 74e88846..02eda7e2 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -26,6 +26,7 @@ limitations under the License. #include #include +#include /** * generic exception for errors @@ -73,6 +74,27 @@ public: } m_stats; }; +/** + * config object for stateless object + * + * @author imarom (08-Oct-15) + */ +class TrexStatelessCfg { +public: + /* default values */ + TrexStatelessCfg() { + m_port_count = 0; + m_rpc_req_resp_cfg = NULL; + m_rpc_async_cfg = NULL; + m_rpc_server_verbose = false; + } + + const TrexRpcServerConfig *m_rpc_req_resp_cfg; + const TrexRpcServerConfig *m_rpc_async_cfg; + bool m_rpc_server_verbose; + uint8_t m_port_count; +}; + /** * defines the T-Rex stateless operation mode * @@ -85,7 +107,13 @@ public: * reconfiguration is not allowed * an exception will be thrown */ - static void configure(uint8_t port_count); + static void create(const TrexStatelessCfg &cfg); + + /** + * destroy the instance + * + */ + static void destroy(); /** * singleton public get instance @@ -115,12 +143,11 @@ public: * fetch all the stats * */ - void encode_stats(Json::Value &global); + void encode_stats(Json::Value &global); protected: TrexStateless(); - ~TrexStateless(); static TrexStateless& get_instance_internal () { static TrexStateless instance; @@ -131,10 +158,17 @@ protected: TrexStateless(TrexStateless const&) = delete; void operator=(TrexStateless const&) = delete; + /* status */ bool m_is_configured; - TrexStatelessPort **m_ports; - uint8_t m_port_count; + /* RPC server array */ + TrexRpcServer *m_rpc_server; + + /* ports */ + std::vector m_ports; + uint8_t m_port_count; + + /* stats */ TrexStatelessStats m_stats; }; -- cgit 1.2.3-korg From d7af282dc1cd629c251a937c9aa88a9a5a47030b Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 8 Oct 2015 17:39:51 +0200 Subject: first integration with DPDK layer --- linux_dpdk/ws_main.py | 14 ++- src/bp_sim.h | 21 +++- src/main_dpdk.cpp | 135 ++++++++++++++++++----- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 2 +- src/rpc-server/trex_rpc_server_mock.cpp | 5 +- src/stateless/cp/trex_stateless.cpp | 59 +++++++--- src/stateless/cp/trex_stateless.h | 27 ++++- 7 files changed, 211 insertions(+), 52 deletions(-) (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 6aad508a..b1fd8761 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -141,6 +141,7 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/', src_list=[ 'trex_rpc_server.cpp', 'trex_rpc_req_resp_server.cpp', + 'trex_rpc_async_server.cpp', 'trex_rpc_jsonrpc_v2_parser.cpp', 'trex_rpc_cmds_table.cpp', 'trex_rpc_cmd.cpp', @@ -148,8 +149,16 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/', 'commands/trex_rpc_cmd_test.cpp', 'commands/trex_rpc_cmd_general.cpp', 'commands/trex_rpc_cmd_stream.cpp', + ]) +# stateless code +stateless_src = SrcGroup(dir='src/stateless/cp/', + src_list=['trex_stream.cpp', + 'trex_stream_vm.cpp', + 'trex_stateless.cpp', + 'trex_stateless_port.cpp' + ]) # JSON package json_src = SrcGroup(dir='external_libs/json', src_list=[ @@ -346,6 +355,9 @@ bp =SrcGroups([ cmn_src , net_src , yaml_src, + rpc_server_src, + json_src, + stateless_src, version_src ]); @@ -400,7 +412,7 @@ includes_path =''' ../src/pal/linux_dpdk/ ../src/ ../src/rpc-server/ - ../src/stateless/ + ../src/stateless/cp/ ../external_libs/yaml-cpp/include/ ../external_libs/zmq/include/ diff --git a/src/bp_sim.h b/src/bp_sim.h index 29b9a724..2f445cb7 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -688,6 +688,15 @@ public: RUN_FLAGS_RXCHECK_CONST_TS =1, }; + /** + * different running modes for Trex + */ + enum trex_run_mode_e { + RUN_MODE_INVALID, + RUN_MODE_BATCH, + RUN_MODE_INTERACTIVE + }; + public: CParserOption(){ m_factor=1.0; @@ -707,6 +716,7 @@ public: m_run_flags=0; prefix=""; m_mac_splitter=0; + m_run_mode = RUN_MODE_INVALID; } CPreviewMode preview; @@ -730,13 +740,14 @@ public: uint8_t m_mac_splitter; uint8_t m_pad; + trex_run_mode_e m_run_mode; - std::string cfg_file; - std::string mac_file; - std::string platform_cfg_file; + std::string cfg_file; + std::string mac_file; + std::string platform_cfg_file; - std::string out_file; - std::string prefix; + std::string out_file; + std::string prefix; CMacAddrCfg m_mac_addr[MAX_LATENCY_PORTS]; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 820fb3fa..e3d13f2b 100755 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -55,6 +55,7 @@ limitations under the License. #include #include #include +#include #include <../linux_dpdk/version.h> extern "C" { @@ -426,7 +427,8 @@ static char global_loglevel_str[20]; // cores =0==1,1*2,2,3,4,5,6 // An enum for all the option types enum { OPT_HELP, - OPT_CFG, + OPT_MODE_BATCH, + OPT_MODE_INTERACTIVE, OPT_NODE_DUMP, OPT_UT, OPT_FILE_OUT, @@ -478,15 +480,16 @@ enum { OPT_HELP, */ static CSimpleOpt::SOption parser_options[] = { - { OPT_HELP, "-?", SO_NONE }, - { OPT_HELP, "-h", SO_NONE }, - { OPT_HELP, "--help", SO_NONE }, - { OPT_UT, "--ut", SO_NONE }, - { OPT_CFG, "-f", SO_REQ_SEP}, - { OPT_PLAT_CFG_FILE,"--cfg", SO_REQ_SEP}, - { OPT_REAL_TIME , "-r", SO_NONE }, - { OPT_SINGLE_CORE , "-s", SO_NONE }, - { OPT_FILE_OUT , "-o" , SO_REQ_SEP}, + { OPT_HELP, "-?", SO_NONE }, + { OPT_HELP, "-h", SO_NONE }, + { OPT_HELP, "--help", SO_NONE }, + { OPT_UT, "--ut", SO_NONE }, + { OPT_MODE_BATCH, "-f", SO_REQ_SEP}, + { OPT_MODE_INTERACTIVE, "-i", SO_NONE }, + { OPT_PLAT_CFG_FILE, "--cfg", SO_REQ_SEP}, + { OPT_REAL_TIME , "-r", SO_NONE }, + { OPT_SINGLE_CORE, "-s", SO_NONE }, + { OPT_FILE_OUT, "-o" , SO_REQ_SEP}, { OPT_FLIP_CLIENT_SERVER,"--flip",SO_NONE }, { OPT_FLOW_FLIP_CLIENT_SERVER,"-p",SO_NONE }, { OPT_FLOW_FLIP_CLIENT_SERVER_SIDE,"-e",SO_NONE }, @@ -533,13 +536,18 @@ static CSimpleOpt::SOption parser_options[] = static int usage(){ - printf(" Usage: t-rex-64 [OPTION] -f cfg.yaml -c cores \n"); + printf(" Usage: t-rex-64 [MODE] [OPTION] -f cfg.yaml -c cores \n"); printf(" \n"); printf(" \n"); - printf(" options \n"); + + printf(" mode \n\n"); printf(" -f [file] : YAML file with template configuration \n"); + printf(" -i : launch TRex in interactive mode (RPC server)\n"); printf(" \n\n"); - printf(" --mac [file] : YAML file with configuration \n"); + + printf(" options \n\n"); + + printf(" --mac [file] : YAML file with configuration \n"); printf(" \n\n"); printf(" -r : realtime enable \n"); printf(" \n\n"); @@ -612,7 +620,8 @@ static int usage(){ printf(" --mac-spread : Spread the destination mac-order by this factor. e.g 2 will generate the traffic to 2 devices DEST-MAC ,DEST-MAC+1 \n"); printf(" maximum is up to 128 devices \n"); - printf(" simulation mode : \n"); + + printf("\n simulation mode : \n"); printf(" Using this mode you can generate the traffic into a pcap file and learn how trex works \n"); printf(" With this version you must be SUDO to use this mode ( I know this is not normal ) \n"); printf(" you can use the Linux CEL version of t-rex to do it without super user \n"); @@ -653,6 +662,7 @@ static int usage(){ printf(" Open Source Components / Libraries \n"); printf(" DPDK (BSD) \n"); printf(" YAML-CPP (BSD) \n"); + printf(" JSONCPP (MIT) \n"); printf(" \n"); printf(" Open Source Binaries \n"); printf(" ZMQ (LGPL v3plus) \n"); @@ -667,6 +677,11 @@ static int usage(){ int gtest_main(int argc, char **argv) ; +static void parse_err(const std::string &msg) { + std::cout << "\nArgument Parsing Error: \n\n" << "*** "<< msg << "\n\n"; + exit(-1); +} + static int parse_options(int argc, char *argv[], CParserOption* po, bool first_time ) { CSimpleOpt args(argc, argv, parser_options); @@ -679,36 +694,55 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t int res1; uint32_t tmp_data; + po->m_run_mode = CParserOption::RUN_MODE_INVALID; while ( args.Next() ){ if (args.LastError() == SO_SUCCESS) { switch (args.OptionId()) { + case OPT_UT : - printf(" Supported only in simulation \n"); - res1=0; - exit(res1); + parse_err("Supported only in simulation"); break; + case OPT_HELP: usage(); return -1; - case OPT_CFG: + + case OPT_MODE_BATCH: + if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) { + parse_err("Please specify single run mode"); + } + po->m_run_mode = CParserOption::RUN_MODE_BATCH; po->cfg_file = args.OptionArg(); break; + + case OPT_MODE_INTERACTIVE: + if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) { + parse_err("Please specify single run mode"); + } + po->m_run_mode = CParserOption::RUN_MODE_INTERACTIVE; + break; + case OPT_NO_KEYBOARD_INPUT : po->preview.set_no_keyboard(true); break; + case OPT_MAC_FILE : po->mac_file = args.OptionArg(); break; + case OPT_PLAT_CFG_FILE : po->platform_cfg_file = args.OptionArg(); break; + case OPT_SINGLE_CORE : po->preview.setSingleCore(true); break; + case OPT_IPV6: po->preview.set_ipv6_mode_enable(true); break; + case OPT_VLAN: po->preview.set_vlan_mode_enable(true); break; @@ -726,6 +760,7 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t printf(" warning -r is deprecated, real time is not needed any more , it is the default \n"); po->preview.setRealTime(true); break; + case OPT_NO_FLOW_CONTROL: po->preview.set_disable_flow_control_setting(true); break; @@ -832,21 +867,20 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t } // End of while - if ((po->cfg_file =="") ) { - printf("Invalid combination of parameters you must add -f with configuration file \n"); - return -1; + if ((po->m_run_mode == CParserOption::RUN_MODE_INVALID) ) { + parse_err("Please provide single run mode (e.g. batch or interactive)"); } if ( po->m_mac_splitter > 128 ){ - printf("maximum mac spreading is 128 you set it to %d \n",po->m_mac_splitter); - return -1; + std::stringstream ss; + ss << "maximum mac spreading is 128 you set it to: " << po->m_mac_splitter; + parse_err(ss.str()); } if ( po->preview.get_learn_mode_enable() ){ if ( po->preview.get_ipv6_mode_enable() ){ - printf("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n"); - printf("if you think it is important,open a defect \n"); - return -1; + parse_err("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n" \ + "if you think it is important,open a defect \n"); } if ( po->is_latency_disabled() ){ /* set latency thread */ @@ -3863,6 +3897,7 @@ int CGlobalPortCfg::run_in_master(){ std::string json; bool was_stopped=false; + while ( true ) { if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ){ @@ -3976,6 +4011,7 @@ int CGlobalPortCfg::run_in_master(){ break; } } + m_mg.stop(); delay(1000); if ( was_stopped ){ @@ -4172,7 +4208,18 @@ static int latency_one_lcore(__attribute__((unused)) void *dummy) } +static int stateless_entry(__attribute__((unused)) void *dummy) { + CPlatformSocketInfo * lpsock=&CGlobalInfo::m_socket; + physical_thread_id_t phy_id = rte_lcore_id(); + + if (lpsock->thread_phy_is_master( phy_id )) { + TrexStateless::get_instance().launch_control_plane(); + } else { + TrexStateless::get_instance().launch_on_dp_core(); + } + return (0); +} static int slave_one_lcore(__attribute__((unused)) void *dummy) { @@ -4381,7 +4428,37 @@ int sim_load_list_of_cap_files(CParserOption * op){ +static int +launch_stateless_trex() { + CPlatformSocketInfo *lpsock=&CGlobalInfo::m_socket; + CParserOption *lpop= &CGlobalInfo::m_options; + CPlatformYamlInfo *cg=&global_platform_cfg_info; + + TrexStatelessCfg cfg; + + TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); + TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); + cfg.m_dp_core_count = lpop->preview.getCores(); + cfg.m_port_count = lpop->m_expected_portd; + cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg; + cfg.m_rpc_async_cfg = &rpc_async_cfg; + cfg.m_rpc_server_verbose = true; + + TrexStateless::configure(cfg); + + printf("\nStarting T-Rex Stateless\n"); + printf("Starting RPC Server...\n\n"); + + rte_eal_mp_remote_launch(stateless_entry, NULL, CALL_MASTER); + + unsigned lcore_id; + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) + return -1; + } + return (0); +} @@ -4436,6 +4513,11 @@ int main_test(int argc , char * argv[]){ rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); } + /* patch here */ + if (CGlobalInfo::m_options.m_run_mode == CParserOption::RUN_MODE_INTERACTIVE) { + return launch_stateless_trex(); + } + time_init(); @@ -4518,6 +4600,7 @@ int main_test(int argc , char * argv[]){ if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } + ports_cfg.stop_master(); ports_cfg.Delete(); utl_termio_reset(); diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index b440fa81..ae87d749 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -155,7 +155,7 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { section["uptime"] = TrexRpcServer::get_server_uptime(); /* FIXME: core count */ - section["dp_core_count"] = 1; + section["dp_core_count"] = instance.get_dp_core_count(); section["core_type"] = get_cpu_model(); /* ports */ diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp index 8dae42d7..de43f92f 100644 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ b/src/rpc-server/trex_rpc_server_mock.cpp @@ -62,11 +62,14 @@ int main(int argc, char *argv[]) { TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); cfg.m_port_count = 4; + cfg.m_dp_core_count = 2; cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg; cfg.m_rpc_async_cfg = &rpc_async_cfg; cfg.m_rpc_server_verbose = (is_gtest ? false : true); - TrexStateless::create(cfg); + TrexStateless::configure(cfg); + + TrexStateless::get_instance().launch_control_plane(); /* gtest handling */ if (is_gtest) { diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 1e7e2dfa..872fdd92 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -22,6 +22,8 @@ limitations under the License. #include #include +#include +#include using namespace std; @@ -35,10 +37,10 @@ TrexStateless::TrexStateless() { /** - * creates the singleton stateless object + * configure the singleton stateless object * */ -void TrexStateless::create(const TrexStatelessCfg &cfg) { +void TrexStateless::configure(const TrexStatelessCfg &cfg) { TrexStateless& instance = get_instance_internal(); @@ -47,19 +49,9 @@ void TrexStateless::create(const TrexStatelessCfg &cfg) { throw TrexException("re-configuration of stateless object is not allowed"); } - /* pin this process to the current running CPU - any new thread will be called on the same CPU - (control plane restriction) - */ - cpu_set_t mask; - CPU_ZERO(&mask); - CPU_SET(sched_getcpu(), &mask); - sched_setaffinity(0, sizeof(mask), &mask); - - /* start RPC servers */ + /* create RPC servers */ instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg); instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); - instance.m_rpc_server->start(); /* configure ports */ @@ -69,10 +61,43 @@ void TrexStateless::create(const TrexStatelessCfg &cfg) { instance.m_ports.push_back(new TrexStatelessPort(i)); } + /* cores */ + instance.m_dp_core_count = cfg.m_dp_core_count; + /* done */ instance.m_is_configured = true; } +/** + * starts the control plane side + * + */ +void +TrexStateless::launch_control_plane() { + //std::cout << "\n on control/master core \n"; + + /* pin this process to the current running CPU + any new thread will be called on the same CPU + (control plane restriction) + */ + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(sched_getcpu(), &mask); + sched_setaffinity(0, sizeof(mask), &mask); + + /* start RPC server */ + m_rpc_server->start(); +} + +void +TrexStateless::launch_on_dp_core() { + //std::cout << "\n on DP core \n"; + + while (true) { + sleep(1); + } +} + /** * destroy the singleton and release all memory * @@ -115,10 +140,16 @@ TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) { } -uint8_t TrexStateless::get_port_count() { +uint8_t +TrexStateless::get_port_count() { return m_port_count; } +uint8_t +TrexStateless::get_dp_core_count() { + return m_dp_core_count; +} + void TrexStateless::update_stats() { diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 02eda7e2..5c674fd6 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -83,9 +83,10 @@ class TrexStatelessCfg { public: /* default values */ TrexStatelessCfg() { - m_port_count = 0; - m_rpc_req_resp_cfg = NULL; - m_rpc_async_cfg = NULL; + 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; } @@ -93,6 +94,7 @@ public: const TrexRpcServerConfig *m_rpc_async_cfg; bool m_rpc_server_verbose; uint8_t m_port_count; + uint8_t m_dp_core_count; }; /** @@ -107,7 +109,7 @@ public: * reconfiguration is not allowed * an exception will be thrown */ - static void create(const TrexStatelessCfg &cfg); + static void configure(const TrexStatelessCfg &cfg); /** * destroy the instance @@ -129,9 +131,23 @@ public: return instance; } + /** + * starts the control plane side + * + */ + void launch_control_plane(); + + /** + * launch on a single DP core + * + */ + void launch_on_dp_core(); + TrexStatelessPort * get_port_by_id(uint8_t port_id); uint8_t get_port_count(); + uint8_t get_dp_core_count(); + /** * update all the stats (deep update) * (include all the ports and global stats) @@ -168,6 +184,9 @@ protected: std::vector m_ports; uint8_t m_port_count; + /* cores */ + uint8_t m_dp_core_count; + /* stats */ TrexStatelessStats m_stats; }; -- cgit 1.2.3-korg From 3b827c9584c28d3f1f573e372f646edfe9f5f007 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 11 Oct 2015 10:18:01 +0200 Subject: some DP base files --- linux_dpdk/ws_main.py | 12 +++++---- src/main_dpdk.cpp | 2 +- src/stateless/cp/trex_stateless.cpp | 11 ++++---- src/stateless/cp/trex_stateless.h | 11 +++++--- src/stateless/cp/trex_stateless_port.cpp | 13 ++++++++- src/stateless/dp/trex_stateless_dp_core.cpp | 37 +++++++++++++++++++++++++ src/stateless/dp/trex_stateless_dp_core.h | 42 +++++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 src/stateless/dp/trex_stateless_dp_core.cpp create mode 100644 src/stateless/dp/trex_stateless_dp_core.h (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index b1fd8761..61a9d4f3 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -153,11 +153,12 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/', ]) # stateless code -stateless_src = SrcGroup(dir='src/stateless/cp/', - src_list=['trex_stream.cpp', - 'trex_stream_vm.cpp', - 'trex_stateless.cpp', - 'trex_stateless_port.cpp' +stateless_src = SrcGroup(dir='src/stateless/', + src_list=['cp/trex_stream.cpp', + 'cp/trex_stream_vm.cpp', + 'cp/trex_stateless.cpp', + 'cp/trex_stateless_port.cpp', + 'dp/trex_stateless_dp_core.cpp' ]) # JSON package json_src = SrcGroup(dir='external_libs/json', @@ -413,6 +414,7 @@ includes_path =''' ../src/pal/linux_dpdk/ ../src/rpc-server/ ../src/stateless/cp/ + ../src/stateless/dp/ ../external_libs/yaml-cpp/include/ ../external_libs/zmq/include/ diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index e3d13f2b..36d5052e 100755 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -4215,7 +4215,7 @@ static int stateless_entry(__attribute__((unused)) void *dummy) { if (lpsock->thread_phy_is_master( phy_id )) { TrexStateless::get_instance().launch_control_plane(); } else { - TrexStateless::get_instance().launch_on_dp_core(); + TrexStateless::get_instance().launch_on_dp_core(phy_id); } return (0); diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 872fdd92..20e001c9 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -63,6 +63,9 @@ void TrexStateless::configure(const TrexStatelessCfg &cfg) { /* cores */ instance.m_dp_core_count = cfg.m_dp_core_count; + for (int i = 0; i < instance.m_dp_core_count; i++) { + instance.m_dp_cores.push_back(new TrexStatelessDpCore(i)); + } /* done */ instance.m_is_configured = true; @@ -90,12 +93,8 @@ TrexStateless::launch_control_plane() { } void -TrexStateless::launch_on_dp_core() { - //std::cout << "\n on DP core \n"; - - while (true) { - sleep(1); - } +TrexStateless::launch_on_dp_core(uint8_t core_id) { + m_dp_cores[core_id - 1]->run(); } /** diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 5c674fd6..ef612e84 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -26,6 +26,8 @@ limitations under the License. #include #include +#include +#include #include /** @@ -141,7 +143,7 @@ public: * launch on a single DP core * */ - void launch_on_dp_core(); + void launch_on_dp_core(uint8_t core_id); TrexStatelessPort * get_port_by_id(uint8_t port_id); uint8_t get_port_count(); @@ -181,11 +183,12 @@ protected: TrexRpcServer *m_rpc_server; /* ports */ - std::vector m_ports; - uint8_t m_port_count; + std::vector m_ports; + uint8_t m_port_count; /* cores */ - uint8_t m_dp_core_count; + std::vector m_dp_cores; + uint8_t m_dp_core_count; /* stats */ TrexStatelessStats m_stats; diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 031efb58..240b7582 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -22,6 +22,13 @@ limitations under the License. #include #include +// DPDK c++ issue +#define UINT8_MAX 255 +#define UINT16_MAX 0xFFFF +// DPDK c++ issue + +#include + using namespace std; /*************************** @@ -143,7 +150,11 @@ TrexStatelessPort::update_stats() { #else /* real update work */ - #endif + struct rte_eth_stats stats; + rte_eth_stats_get(m_port_id, &stats); + printf("ipackets is %u\n", stats.ipackets); + printf("opackets is %u\n", stats.opackets); + #endif } const TrexPortStats & 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..4e9309ab --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -0,0 +1,37 @@ +/* + 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 + +TrexStatelessDpCore::TrexStatelessDpCore(uint8_t core_id) : m_core_id(core_id) { +} + +void +TrexStatelessDpCore::run() { + printf("On DP core %d\n", m_core_id); + while (true) { + sleep(1); + TrexStateless::get_instance().get_port_by_id(0)->update_stats(); + } +} 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..d428bac2 --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -0,0 +1,42 @@ +/* + 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: + uint8_t m_core_id; +}; + +#endif /* __TREX_STATELESS_DP_CORE_H__ */ -- cgit 1.2.3-korg From 6c7880b9881ed6690954f0c29259dd0b584b3970 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 11 Oct 2015 14:42:24 +0200 Subject: DP cores now inject a single packet as a dummy to see stats --- linux/ws_main.py | 17 +++-- src/bp_sim.h | 13 +++- src/main_dpdk.cpp | 35 +++++----- src/mock/rte_ethdev.h | 44 ++++++++++++ src/mock/trex_rpc_server_mock.cpp | 92 +++++++++++++++++++++++++ src/rpc-server/trex_rpc_async_server.cpp | 12 +++- src/rpc-server/trex_rpc_async_server.h | 2 +- src/rpc-server/trex_rpc_req_resp_server.cpp | 12 +++- src/rpc-server/trex_rpc_req_resp_server.h | 2 +- src/rpc-server/trex_rpc_server.cpp | 9 +-- src/rpc-server/trex_rpc_server_api.h | 7 +- src/rpc-server/trex_rpc_server_mock.cpp | 92 ------------------------- src/stateless/cp/trex_stateless.cpp | 14 ++-- src/stateless/cp/trex_stateless.h | 4 ++ src/stateless/cp/trex_stateless_port.cpp | 77 ++++++++++++++++----- src/stateless/cp/trex_stateless_port.h | 34 ++++++++++ src/stateless/dp/trex_stateless_dp_core.cpp | 101 +++++++++++++++++++++++++++- src/stateless/dp/trex_stateless_dp_core.h | 1 + src/tuple_gen.h | 5 +- 19 files changed, 419 insertions(+), 154 deletions(-) create mode 100644 src/mock/rte_ethdev.h create mode 100644 src/mock/trex_rpc_server_mock.cpp delete mode 100644 src/rpc-server/trex_rpc_server_mock.cpp (limited to 'src/stateless/cp/trex_stateless.cpp') diff --git a/linux/ws_main.py b/linux/ws_main.py index 6dd0a813..eac46ac7 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -141,11 +141,12 @@ net_src = SrcGroup(dir='src/common/Network/Packet', 'VLANHeader.cpp']); # stateless code -stateless_src = SrcGroup(dir='src/stateless/cp/', - src_list=['trex_stream.cpp', - 'trex_stream_vm.cpp', - 'trex_stateless.cpp', - 'trex_stateless_port.cpp' +stateless_src = SrcGroup(dir='src/stateless/', + src_list=['cp/trex_stream.cpp', + 'cp/trex_stream_vm.cpp', + 'cp/trex_stateless.cpp', + 'cp/trex_stateless_port.cpp', + 'dp/trex_stateless_dp_core.cpp' ]) # RPC code rpc_server_src = SrcGroup(dir='src/rpc-server/', @@ -164,10 +165,12 @@ rpc_server_src = SrcGroup(dir='src/rpc-server/', ]) # RPC mock server (test) -rpc_server_mock_src = SrcGroup(dir='src/rpc-server/', +rpc_server_mock_src = SrcGroup(dir='src/mock/', src_list=[ 'trex_rpc_server_mock.cpp', '../gtest/rpc_test.cpp', + '../pal/linux/mbuf.cpp', + '../os_time.cpp', ]) # JSON package @@ -235,8 +238,10 @@ cxxflags_base =['-DWIN_UCODE_SIM', includes_path =''' ../src/pal/linux/ ../src/ + ../src/mock/ ../src/rpc-server/ ../src/stateless/cp/ + ../src/stateless/dp/ ../external_libs/json/ ../external_libs/zmq/include/ ../external_libs/yaml-cpp/include/ diff --git a/src/bp_sim.h b/src/bp_sim.h index 2f445cb7..18cd9b97 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -221,7 +221,9 @@ private: memset(m_pyload_mbuf_ptr+len+m_new_pkt_size,0xa,(-m_new_pkt_size)); } + return (0); } + public: int16_t m_new_pkt_size; /* New packet size after transform by plugin */ CFlowPktInfo * m_pkt_info; @@ -302,7 +304,7 @@ public: void CVirtualIFPerSideStats::Dump(FILE *fd){ - #define DP_B(f) if (f) printf(" %-40s : %llu \n",#f,f) + #define DP_B(f) if (f) printf(" %-40s : %lu \n",#f,f) DP_B(m_tx_pkt); DP_B(m_tx_rx_check_pkt); DP_B(m_tx_bytes); @@ -1440,7 +1442,7 @@ public: inline bool is_eligible_from_server_side(){ - return ( (m_src_ip&1==1)?true:false); + return ( ( (m_src_ip&1) == 1)?true:false); } @@ -1647,7 +1649,7 @@ public: */ inline int check_objects_sizes(void){ if ( sizeof(CGenNodeDeferPort) != sizeof(CGenNode) ) { - printf("ERROR sizeof(CGenNodeDeferPort) %d != sizeof(CGenNode) %d must be the same size \n",sizeof(CGenNodeDeferPort),sizeof(CGenNode)); + printf("ERROR sizeof(CGenNodeDeferPort) %lu != sizeof(CGenNode) %lu must be the same size \n",sizeof(CGenNodeDeferPort),sizeof(CGenNode)); assert(0); } if ( (int)offsetof(struct CGenNodeDeferPort,m_type)!=offsetof(struct CGenNode,m_type) ){ @@ -2587,6 +2589,8 @@ inline void CFlowPktInfo::update_pkt_info2(char *p, EthernetHeader * et = (EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset()); + (void)et; + if ( unlikely (m_pkt_indication.is_ipv6())) { IPv6Header *ipv6= (IPv6Header *)ipv4; @@ -2669,6 +2673,8 @@ inline void CFlowPktInfo::update_pkt_info(char *p, EthernetHeader * et = (EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset()); + (void)et; + uint16_t src_port = node->m_src_port; pkt_dir_t ip_dir = node->cur_pkt_ip_addr_dir(); @@ -2869,6 +2875,7 @@ inline rte_mbuf_t * CFlowPktInfo::do_generate_new_mbuf_ex_vm(CGenNode * node, /* need to update the mbuf size here .., this is not must but needed for accuracy */ uint16_t buf_adjust = len - vm.m_new_pkt_size; int rc = rte_pktmbuf_trim(m, buf_adjust); + (void)rc; /* update IP length , and TCP checksum , we can accelerate this using hardware ! */ uint16_t pkt_adjust = vm.m_new_pkt_size - m_packet->pkt_len; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 36d5052e..fe972d2f 100755 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -2735,7 +2735,7 @@ public: } public: - bool Create(); + bool Create(bool is_stateless); void Delete(); int ixgbe_prob_init(); @@ -3409,18 +3409,22 @@ int CGlobalPortCfg::ixgbe_start(void){ } -bool CGlobalPortCfg::Create(){ - - if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port, - !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){ - return (false); - } +bool CGlobalPortCfg::Create(bool is_stateless){ + /* hack - need to refactor */ + if (!is_stateless) { + if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port, + !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){ + return (false); + } + } /* We load the YAML twice, this is the first time. to update global flags */ CFlowsYamlInfo pre_yaml_info; - pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file); + if (!is_stateless) { + pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file); + } if ( pre_yaml_info.m_vlan_info.m_enable ){ CGlobalInfo::m_options.preview.set_vlan_mode_enable(true); @@ -4513,12 +4517,6 @@ int main_test(int argc , char * argv[]){ rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); } - /* patch here */ - if (CGlobalInfo::m_options.m_run_mode == CParserOption::RUN_MODE_INTERACTIVE) { - return launch_stateless_trex(); - } - - time_init(); /* check if we are in simulation mode */ @@ -4527,11 +4525,18 @@ int main_test(int argc , char * argv[]){ return ( sim_load_list_of_cap_files(&CGlobalInfo::m_options) ); } + bool is_stateless = (CGlobalInfo::m_options.m_run_mode == CParserOption::RUN_MODE_INTERACTIVE); - if ( !ports_cfg.Create() ){ + if ( !ports_cfg.Create(is_stateless) ){ exit(1); } + /* patch here */ + if (is_stateless) { + return launch_stateless_trex(); + } + + if (po->preview.get_is_rx_check_enable() && (po->m_rx_check_sampe< get_min_sample_rate()) ) { po->m_rx_check_sampe = get_min_sample_rate(); printf("Warning rx check sample rate should be lower than %d setting it to %d\n",get_min_sample_rate(),get_min_sample_rate()); diff --git a/src/mock/rte_ethdev.h b/src/mock/rte_ethdev.h new file mode 100644 index 00000000..046d8366 --- /dev/null +++ b/src/mock/rte_ethdev.h @@ -0,0 +1,44 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __MOCK_FILE_RTE_ETHDEV_H__ +#define __MOCK_FILE_RTE_ETHDEV_H__ + +#include + +struct rte_eth_stats { + uint64_t obytes; + uint64_t ibytes; + uint64_t opackets; + uint64_t ipackets; +}; + +static inline void +rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats) { + memset(stats, 0, sizeof(rte_eth_stats)); +} + +static inline uint16_t +rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, + struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { + return (0); +} + +#endif /* __MOCK_FILE_RTE_ETHDEV_H__ */ diff --git a/src/mock/trex_rpc_server_mock.cpp b/src/mock/trex_rpc_server_mock.cpp new file mode 100644 index 00000000..de43f92f --- /dev/null +++ b/src/mock/trex_rpc_server_mock.cpp @@ -0,0 +1,92 @@ +/* + 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 + +using namespace std; + +/** + * on simulation this is not rebuild every version + * (improved stub) + * + */ +extern "C" const char * get_build_date(void){ + return (__DATE__); +} + +extern "C" const char * get_build_time(void){ + return (__TIME__ ); +} + +int gtest_main(int argc, char **argv); + +int main(int argc, char *argv[]) { + + bool is_gtest = false; + + // gtest ? + if (argc > 1) { + if (string(argv[1]) != "--ut") { + cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n"; + exit(-1); + } + is_gtest = true; + } + + /* configure the stateless object with 4 ports */ + TrexStatelessCfg cfg; + + TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); + TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); + + cfg.m_port_count = 4; + cfg.m_dp_core_count = 2; + cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg; + cfg.m_rpc_async_cfg = &rpc_async_cfg; + cfg.m_rpc_server_verbose = (is_gtest ? false : true); + + TrexStateless::configure(cfg); + + TrexStateless::get_instance().launch_control_plane(); + + /* gtest handling */ + if (is_gtest) { + int rc = gtest_main(argc, argv); + TrexStateless::destroy(); + return rc; + } + + cout << "\n-= Starting RPC Server Mock =-\n\n"; + cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; + + cout << "Server Started\n\n"; + + while (true) { + sleep(1); + } + + TrexStateless::destroy(); +} + diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp index 3313e42e..f4d21f2f 100644 --- a/src/rpc-server/trex_rpc_async_server.cpp +++ b/src/rpc-server/trex_rpc_async_server.cpp @@ -36,7 +36,7 @@ limitations under the License. * ZMQ based publisher server * */ -TrexRpcServerAsync::TrexRpcServerAsync(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg, "publisher") { +TrexRpcServerAsync::TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "publisher", lock) { /* ZMQ is not thread safe - this should be outside */ m_context = zmq_ctx_new(); } @@ -73,9 +73,19 @@ TrexRpcServerAsync::_rpc_thread_cb() { Json::Value snapshot; Json::FastWriter writer; + /* if lock was provided - take it */ + if (m_lock) { + m_lock->lock(); + } + /* trigger a full update for stats */ TrexStateless::get_instance().update_stats(); + /* done with the lock */ + if (m_lock) { + m_lock->unlock(); + } + /* encode them to JSON */ TrexStateless::get_instance().encode_stats(snapshot); diff --git a/src/rpc-server/trex_rpc_async_server.h b/src/rpc-server/trex_rpc_async_server.h index 13525c01..02d1490e 100644 --- a/src/rpc-server/trex_rpc_async_server.h +++ b/src/rpc-server/trex_rpc_async_server.h @@ -33,7 +33,7 @@ limitations under the License. class TrexRpcServerAsync : public TrexRpcServerInterface { public: - TrexRpcServerAsync(const TrexRpcServerConfig &cfg); + TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL); protected: void _rpc_thread_cb(); diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp index 3d52686c..9147f75d 100644 --- a/src/rpc-server/trex_rpc_req_resp_server.cpp +++ b/src/rpc-server/trex_rpc_req_resp_server.cpp @@ -34,7 +34,7 @@ limitations under the License. * ZMQ based request-response server * */ -TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg, "req resp") { +TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "req resp", lock) { /* ZMQ is not thread safe - this should be outside */ m_context = zmq_ctx_new(); } @@ -127,6 +127,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) { int index = 0; + /* if lock was provided, take it */ + if (m_lock) { + m_lock->lock(); + } + /* for every command parsed - launch it */ for (auto command : commands) { Json::Value single_response; @@ -138,6 +143,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) { } + /* done with the lock */ + if (m_lock) { + m_lock->unlock(); + } + /* write the JSON to string and sever on ZMQ */ std::string response_str; diff --git a/src/rpc-server/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h index 7c1d66d1..1f638adf 100644 --- a/src/rpc-server/trex_rpc_req_resp_server.h +++ b/src/rpc-server/trex_rpc_req_resp_server.h @@ -32,7 +32,7 @@ limitations under the License. class TrexRpcServerReqRes : public TrexRpcServerInterface { public: - TrexRpcServerReqRes(const TrexRpcServerConfig &cfg); + TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL); protected: void _rpc_thread_cb(); diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index 8749c9b4..a14e6f97 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -30,7 +30,7 @@ limitations under the License. /************** RPC server interface ***************/ -TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name) : m_cfg(cfg), m_name(name) { +TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *lock) : m_cfg(cfg), m_name(name), m_lock(lock) { m_is_running = false; m_is_verbose = false; } @@ -114,16 +114,17 @@ get_current_date_time() { const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg, - const TrexRpcServerConfig *async_cfg) { + const TrexRpcServerConfig *async_cfg, + std::mutex *lock) { /* add the request response server */ if (req_resp_cfg) { - m_servers.push_back(new TrexRpcServerReqRes(*req_resp_cfg)); + m_servers.push_back(new TrexRpcServerReqRes(*req_resp_cfg, lock)); } /* add async publisher */ if (async_cfg) { - m_servers.push_back(new TrexRpcServerAsync(*async_cfg)); + m_servers.push_back(new TrexRpcServerAsync(*async_cfg, lock)); } } diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index 327c6eaa..ff876ac4 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -24,6 +24,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -68,7 +69,7 @@ private: class TrexRpcServerInterface { public: - TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name); + TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *m_lock = NULL); virtual ~TrexRpcServerInterface(); /** @@ -127,6 +128,7 @@ protected: bool m_is_verbose; std::thread *m_thread; std::string m_name; + std::mutex *m_lock; }; /** @@ -141,7 +143,8 @@ public: /* creates the collection of servers using configurations */ TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg, - const TrexRpcServerConfig *async_cfg); + const TrexRpcServerConfig *async_cfg, + std::mutex *m_lock = NULL); ~TrexRpcServer(); diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp deleted file mode 100644 index de43f92f..00000000 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ /dev/null @@ -1,92 +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 - -using namespace std; - -/** - * on simulation this is not rebuild every version - * (improved stub) - * - */ -extern "C" const char * get_build_date(void){ - return (__DATE__); -} - -extern "C" const char * get_build_time(void){ - return (__TIME__ ); -} - -int gtest_main(int argc, char **argv); - -int main(int argc, char *argv[]) { - - bool is_gtest = false; - - // gtest ? - if (argc > 1) { - if (string(argv[1]) != "--ut") { - cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n"; - exit(-1); - } - is_gtest = true; - } - - /* configure the stateless object with 4 ports */ - TrexStatelessCfg cfg; - - TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); - TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); - - cfg.m_port_count = 4; - cfg.m_dp_core_count = 2; - cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg; - cfg.m_rpc_async_cfg = &rpc_async_cfg; - cfg.m_rpc_server_verbose = (is_gtest ? false : true); - - TrexStateless::configure(cfg); - - TrexStateless::get_instance().launch_control_plane(); - - /* gtest handling */ - if (is_gtest) { - int rc = gtest_main(argc, argv); - TrexStateless::destroy(); - return rc; - } - - cout << "\n-= Starting RPC Server Mock =-\n\n"; - cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; - - cout << "Server Started\n\n"; - - while (true) { - sleep(1); - } - - TrexStateless::destroy(); -} - diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 20e001c9..72762e26 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -50,7 +50,9 @@ void TrexStateless::configure(const TrexStatelessCfg &cfg) { } /* create RPC servers */ - instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg); + + /* set both servers to mutex each other */ + instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &instance.m_global_cp_lock); instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); /* configure ports */ @@ -152,12 +154,10 @@ TrexStateless::get_dp_core_count() { void TrexStateless::update_stats() { - /* update CPU util. */ - #ifdef TREX_RPC_MOCK_SERVER - m_stats.m_stats.m_cpu_util = 0; - #else - m_stats.m_stats.m_cpu_util = 0; - #endif + /* 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++) { diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index ef612e84..649b25dd 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -25,6 +25,8 @@ limitations under the License. #include #include +#include + #include #include #include @@ -192,6 +194,8 @@ protected: /* stats */ TrexStatelessStats m_stats; + + std::mutex m_global_cp_lock; }; #endif /* __TREX_STATELESS_H__ */ diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 240b7582..f745bee9 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -28,6 +28,7 @@ limitations under the License. // DPDK c++ issue #include +#include using namespace std; @@ -133,28 +134,23 @@ TrexStatelessPort::generate_handler() { */ void TrexStatelessPort::update_stats() { - #ifdef TREX_RPC_MOCK_SERVER - /* do lies - its a mock */ - m_stats.m_stats.m_tx_bps = rand() % 10000; - m_stats.m_stats.m_rx_bps = rand() % 10000; + struct rte_eth_stats stats; + rte_eth_stats_get(m_port_id, &stats); - m_stats.m_stats.m_tx_pps = m_stats.m_stats.m_tx_bps / (64 + rand() % 1000); - m_stats.m_stats.m_rx_pps = m_stats.m_stats.m_rx_bps / (64 + rand() % 1000); + /* 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; - m_stats.m_stats.m_total_tx_bytes += m_stats.m_stats.m_tx_bps; - m_stats.m_stats.m_total_rx_bytes += m_stats.m_stats.m_rx_bps; + /* 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_total_tx_pkts += m_stats.m_stats.m_tx_pps; - m_stats.m_stats.m_total_rx_pkts += m_stats.m_stats.m_rx_pps; + 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); - #else - /* real update work */ - struct rte_eth_stats stats; - rte_eth_stats_get(m_port_id, &stats); - printf("ipackets is %u\n", stats.ipackets); - printf("opackets is %u\n", stats.opackets); - #endif } const TrexPortStats & @@ -181,3 +177,50 @@ TrexStatelessPort::encode_stats(Json::Value &port) { } + +/*************************** + * BW measurement + * + **************************/ +/* TODO: move this to a common place */ +BWMeasure::BWMeasure() { + reset(); +} + +void BWMeasure::reset(void) { + m_start=false; + m_last_time_msec=0; + m_last_bytes=0; + m_last_result=0.0; +}; + +double BWMeasure::calc_MBsec(uint32_t dtime_msec, + uint64_t dbytes){ + double rate=0.000008*( ( (double)dbytes*(double)os_get_time_freq())/((double)dtime_msec) ); + return(rate); +} + +double BWMeasure::add(uint64_t size) { + if ( false == m_start ) { + m_start=true; + m_last_time_msec = os_get_time_msec() ; + m_last_bytes=size; + return(0.0); + } + + uint32_t ctime=os_get_time_msec(); + if ((ctime - m_last_time_msec) +/** + * 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 * @@ -33,9 +54,22 @@ 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; diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 4e9309ab..1c96487d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -24,14 +24,109 @@ limitations under the License. #include #include +#include + +// DPDK c++ issue +#define UINT8_MAX 255 +#define UINT16_MAX 0xFFFF +// DPDK c++ issue + +#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("On DP core %d\n", m_core_id); + printf("\nOn DP core %d\n", m_core_id); while (true) { - sleep(1); - TrexStateless::get_instance().get_port_by_id(0)->update_stats(); + 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 index d428bac2..4b09b752 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -36,6 +36,7 @@ public: void run(); private: + void test_inject_dummy_pkt(); uint8_t m_core_id; }; diff --git a/src/tuple_gen.h b/src/tuple_gen.h index fb856538..c0add0be 100755 --- a/src/tuple_gen.h +++ b/src/tuple_gen.h @@ -113,6 +113,9 @@ class CIpInfoBase { void set_ip(uint32_t ip) { m_ip = ip; } + + virtual ~CIpInfoBase() {} + public: uint32_t m_ip; }; @@ -388,7 +391,7 @@ class CIpPool { (ip<=ip_back->get_ip())) { return(true); } - printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%x\n", + printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%p\n", ip, ip_front->get_ip(), ip_back->get_ip(),this); return(false); -- cgit 1.2.3-korg