diff options
-rw-r--r-- | src/gtest/trex_stateless_gtest.cpp | 16 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 44 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 103 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 59 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 18 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.h | 9 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 11 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 2 | ||||
-rw-r--r-- | src/stateless/dp/trex_stream_node.h | 8 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.cpp | 4 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.h | 6 |
11 files changed, 184 insertions, 96 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp index 5b298023..ea54a935 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -1713,13 +1713,15 @@ TEST_F(basic_stl, graph_generator1) { streams.push_back(stream); - const TrexStreamsGraphObj &obj = graph.generate(streams); - EXPECT_EQ(obj.get_max_bps(), 405120); - EXPECT_EQ(obj.get_max_pps(), 50); + const TrexStreamsGraphObj *obj = graph.generate(streams); + EXPECT_EQ(obj->get_max_bps(), 405120); + EXPECT_EQ(obj->get_max_pps(), 50); for (auto stream : streams) { delete stream; } + + delete obj; } @@ -1761,15 +1763,17 @@ TEST_F(basic_stl, graph_generator2) { streams.push_back(stream); - const TrexStreamsGraphObj &obj = graph.generate(streams); - EXPECT_EQ(obj.get_max_pps(), 1000.0); + const TrexStreamsGraphObj *obj = graph.generate(streams); + EXPECT_EQ(obj->get_max_pps(), 1000.0); - EXPECT_EQ(obj.get_max_bps(), (1000 * (128 + 4) * 8)); + EXPECT_EQ(obj->get_max_bps(), (1000 * (128 + 4) * 8)); for (auto stream : streams) { delete stream; } + + delete obj; } /* stress test */ diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 96224d4e..a5bf0d16 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -473,32 +473,32 @@ TrexRpcCmdStartTraffic::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); + /* multiplier */ + const Json::Value &mul_obj = parse_object(params, "mul", result); + std::string mul_type = parse_string(mul_obj, "type", result); + double mul_value = parse_double(mul_obj, "max", result); - const Json::Value &mul = parse_object(params, "mul", result); - - std::string mul_type = parse_string(mul, "type", result); - double max_rate = parse_double(mul, "max", result); - - - double m = 0; + /* now create an object for multiplier */ + TrexStatelessPort::mul_st mul; + + mul.value = mul_value; /* dispatch according to type of multiplier */ if (mul_type == "raw") { - m = max_rate; + mul.type = TrexStatelessPort::MUL_FACTOR; } else if (mul_type == "max_bps") { - m = port->calculate_m_from_bps(max_rate); + mul.type = TrexStatelessPort::MUL_MAX_BPS; } else if (mul_type == "max_pps") { - m = port->calculate_m_from_pps(max_rate); + mul.type = TrexStatelessPort::MUL_MAX_PPS; } else { generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'"); } - try { - port->start_traffic(m, duration); + port->start_traffic(mul, duration); } catch (const TrexRpcException &ex) { generate_execute_err(result, ex.what()); @@ -651,29 +651,31 @@ TrexRpcCmdUpdateTraffic::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); /* multiplier */ - const Json::Value &mul = parse_object(params, "mul", result); + const Json::Value &mul_obj = parse_object(params, "mul", result); + std::string mul_type = parse_string(mul_obj, "type", result); + double mul_value = parse_double(mul_obj, "max", result); - std::string mul_type = parse_string(mul, "type", result); - double max_rate = parse_double(mul, "max", result); - - double m = 0; + /* now create an object for multiplier */ + TrexStatelessPort::mul_st mul; + + mul.value = mul_value; /* dispatch according to type of multiplier */ if (mul_type == "raw") { - m = max_rate; + mul.type = TrexStatelessPort::MUL_FACTOR; } else if (mul_type == "max_bps") { - m = port->calculate_m_from_bps(max_rate); + mul.type = TrexStatelessPort::MUL_MAX_BPS; } else if (mul_type == "max_pps") { - m = port->calculate_m_from_pps(max_rate); + mul.type = TrexStatelessPort::MUL_MAX_PPS; } else { generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'"); } try { - port->update_traffic(m); + port->update_traffic(mul); } catch (const TrexRpcException &ex) { generate_execute_err(result, ex.what()); } 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<TrexStream *> 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<TrexStream *> 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<TrexStream *> 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<TrexStream *> 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 <internal_api/trex_platform_api.h> 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<TrexStream *> &streams) { + + /* main object to hold the graph - returned to the user */ + m_graph_obj = new TrexStreamsGraphObj(); + std::vector <uint32_t> root_streams; /* before anything we create a hash streams ID @@ -644,7 +648,7 @@ TrexStreamsGraph::generate(const std::vector<TrexStream *> &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<rate_event_st> 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<TrexStream *> &streams); + const TrexStreamsGraphObj * generate(const std::vector<TrexStream *> &streams); private: @@ -200,7 +205,7 @@ private: std::unordered_map<uint32_t, const TrexStream *> 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; }; |