From bc7f0b85b85a8deb6bc58bcca32ff11d9289cd92 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 21 Feb 2016 08:34:28 -0500 Subject: rate per stream --- src/stateless/cp/trex_stream.cpp | 25 +++- src/stateless/cp/trex_stream.h | 209 +++++++++++++++++++++++++---- src/stateless/cp/trex_streams_compiler.cpp | 36 ++--- src/stateless/cp/trex_streams_compiler.h | 16 +-- 4 files changed, 227 insertions(+), 59 deletions(-) (limited to 'src/stateless/cp') diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index fb0b35d5..f4a8e800 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include /************************************** * stream @@ -91,20 +92,25 @@ void TrexStream::Dump(FILE *fd){ fprintf(fd," type : %s \n",get_stream_type_str(m_type).c_str()); if ( m_type == TrexStream::stCONTINUOUS ) { - fprintf(fd," pps : %f \n",m_pps); } if (m_type == TrexStream::stSINGLE_BURST) { - fprintf(fd," pps : %f \n",m_pps); fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); } if (m_type == TrexStream::stMULTI_BURST) { - fprintf(fd," pps : %f \n",m_pps); fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); fprintf(fd," mburst : %lu \n",(ulong)m_num_bursts); if (m_ibg_usec>0.0) { fprintf(fd," m_ibg_usec : %f \n",m_ibg_usec); } } + + fprintf(fd," rate :\n\n"); + + fprintf(fd," pps : %f\n", get_rate().get_pps()); + fprintf(fd," bps L1 : %f\n", get_rate().get_bps_L1()); + fprintf(fd," bps L2 : %f\n", get_rate().get_bps_L2()); + fprintf(fd," percentage : %f\n", get_rate().get_percentage()); + } @@ -125,7 +131,6 @@ TrexStream::TrexStream(uint8_t type, m_rx_check.m_enable = false; - m_pps=-1.0; m_burst_total_pkts=0; m_num_bursts=1; m_ibg_usec=0.0; @@ -155,6 +160,18 @@ TrexStream::get_stream_json() { return m_stream_json; } +TrexStreamRate & +TrexStream::get_rate() { + + /* lazy calculation of the rate */ + if (!m_rate.is_calculated()) { + TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_port_id); + double pkt_size = get_pkt_size(); + m_rate.calculate(pkt_size, port->get_port_speed_bps()); + } + + return m_rate; +} /************************************** * stream table diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 2ab90c99..f4739569 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -103,6 +103,151 @@ public: } }; +/** + * describes a stream rate + * + * @author imarom (18-Feb-16) + */ +class TrexStreamRate { + + +public: + + enum rate_type_e { + RATE_INVALID, + RATE_PPS, + RATE_BPS_L1, + RATE_BPS_L2, + RATE_PERCENTAGE + }; + + TrexStreamRate() { + m_base_rate_type = RATE_INVALID; + m_is_calculated = false; + } + + /** + * set the base rate + * other values will be dervied from this value + * + */ + void set_base_rate(rate_type_e type, double value) { + m_base_rate_type = type; + m_value = value; + m_is_calculated = false; + } + + + /** + * calculates all the rates from the base rate + * + */ + void calculate(uint16_t pkt_size, uint64_t line_bps) { + + switch (m_base_rate_type) { + + case RATE_PPS: + calculate_from_pps(m_value, pkt_size, line_bps); + break; + + case RATE_BPS_L1: + calculate_from_bps_L1(m_value, pkt_size, line_bps); + break; + + case RATE_BPS_L2: + calculate_from_bps_L2(m_value, pkt_size, line_bps); + break; + + case RATE_PERCENTAGE: + calculate_from_percentage(m_value, pkt_size, line_bps); + break; + + default: + assert(0); + } + + m_is_calculated = true; + } + + + bool is_calculated() const { + return m_is_calculated; + } + + + /* update the rate by a factor */ + void update_factor(double factor) { + assert(m_is_calculated); + + m_pps *= factor; + m_bps_L1 *= factor; + m_bps_L2 *= factor; + m_percentage *= factor; + } + + double get_pps() { + assert(m_is_calculated); + return (m_pps); + } + + double get_bps_L1() { + assert(m_is_calculated); + return (m_bps_L1); + } + + double get_bps_L2() { + assert(m_is_calculated); + return m_bps_L2; + } + + double get_percentage() { + assert(m_is_calculated); + return m_percentage; + } + +private: + + void calculate_from_pps(double pps, uint16_t pkt_size, uint64_t line_bps) { + m_pps = pps; + m_bps_L1 = m_pps * (pkt_size + 24) * 8; + m_bps_L2 = m_pps * (pkt_size + 4) * 8; + m_percentage = (m_bps_L1 / line_bps) * 100.0; + } + + + void calculate_from_bps_L1(double bps_L1, uint16_t pkt_size, uint64_t line_bps) { + m_bps_L1 = bps_L1; + m_bps_L2 = m_bps_L1 * ( (pkt_size + 4.0) / (pkt_size + 24.0) ); + m_pps = m_bps_L2 / (8 * (pkt_size + 4)); + m_percentage = (m_bps_L1 / line_bps) * 100.0; + } + + + void calculate_from_bps_L2(double bps_L2, uint16_t pkt_size, uint64_t line_bps) { + m_bps_L2 = bps_L2; + m_bps_L1 = m_bps_L2 * ( (pkt_size + 24.0) / (pkt_size + 4.0)); + m_pps = m_bps_L2 / (8 * (pkt_size + 4)); + m_percentage = (m_bps_L1 / line_bps) * 100.0; + } + + void calculate_from_percentage(double percentage, uint16_t pkt_size, uint64_t line_bps) { + m_percentage = percentage; + m_bps_L1 = (m_percentage / 100.0) * line_bps; + m_bps_L2 = m_bps_L1 * ( (pkt_size + 4.0) / (pkt_size + 24.0) ); + m_pps = m_bps_L2 / (8 * (pkt_size + 4)); + + } + + rate_type_e m_base_rate_type; + double m_value; + + bool m_is_calculated; + double m_pps; + double m_bps_L1; + double m_bps_L2; + double m_percentage; + +}; /** * Stateless Stream @@ -151,12 +296,29 @@ public: m_next_stream_id = next_stream_id; } - double get_pps() const { - return m_pps; + + double get_pps() { + return get_rate().get_pps(); + } + + double get_bps_L1() { + return get_rate().get_bps_L1(); + } + + double get_bps_L2() { + return get_rate().get_bps_L2(); + } + + double get_bw_percentage() { + return get_rate().get_percentage(); + } + + void set_rate(TrexStreamRate::rate_type_e type, double value) { + m_rate.set_base_rate(type, value); } - void set_pps(double pps){ - m_pps = pps; + void update_rate_factor(double factor) { + get_rate().update_factor(factor); } void set_type(uint8_t type){ @@ -223,13 +385,14 @@ public: dp->m_expected_pkt_len = m_expected_pkt_len; dp->m_rx_check = m_rx_check; - dp->m_pps = m_pps; dp->m_burst_total_pkts = m_burst_total_pkts; dp->m_num_bursts = m_num_bursts; dp->m_ibg_usec = m_ibg_usec; dp->m_flags = m_flags; dp->m_action_count = m_action_count; + dp->m_rate = m_rate; + return(dp); } @@ -241,19 +404,11 @@ public: } } - double get_burst_length_usec() const { - return ( (m_burst_total_pkts / m_pps) * 1000 * 1000); - } - - double get_bps_l2() { - return get_bps(false); - } - - double get_bps_l1() { - return get_bps(true); + double get_burst_length_usec() { + return ( (m_burst_total_pkts / get_pps()) * 1000 * 1000); } - + void Dump(FILE *fd); StreamVmDp * getDpVm(){ @@ -321,8 +476,6 @@ public: } m_rx_check; - double m_pps; - uint32_t m_burst_total_pkts; /* valid in case of burst stSINGLE_BURST,stMULTI_BURST*/ uint32_t m_num_bursts; /* valid in case of stMULTI_BURST */ @@ -334,8 +487,7 @@ public: private: - double get_bps(bool layer1) { - + double get_pkt_size() { /* lazy calculate the expected packet length */ if (m_expected_pkt_len == 0) { /* if we have a VM - it might have changed the packet (even random) */ @@ -345,17 +497,16 @@ private: m_expected_pkt_len = m_vm.calc_expected_pkt_size(m_pkt.len); } } - - /* packet length + 4 CRC bytes to bits and multiplied by PPS */ - - if (layer1) { - /* layer one includes preamble, frame delimiter and interpacket gap */ - return (m_pps * (m_expected_pkt_len + 4 + 8 + 12) * 8); - } else { - return (m_pps * (m_expected_pkt_len + 4) * 8); - } + return m_expected_pkt_len; } + + + /* get (and calculate if need) the rate of the stream */ + TrexStreamRate & get_rate(); + + /* no access to this without a lazy build method */ + TrexStreamRate m_rate; }; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 9d048dbd..aca74498 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -459,7 +459,7 @@ TrexStreamsCompiler::compile_internal(uint8_t por * */ void -TrexStreamsCompiler::compile_stream(const TrexStream *stream, +TrexStreamsCompiler::compile_stream(TrexStream *stream, double factor, uint8_t dp_core_count, std::vector &objs, @@ -500,7 +500,7 @@ TrexStreamsCompiler::compile_stream(const TrexStream *stream, * */ void -TrexStreamsCompiler::compile_stream_on_all_cores(const TrexStream *stream, +TrexStreamsCompiler::compile_stream_on_all_cores(TrexStream *stream, double factor, uint8_t dp_core_count, std::vector &objs, @@ -509,7 +509,7 @@ TrexStreamsCompiler::compile_stream_on_all_cores(const TrexStream *stream, std::vector core_streams(dp_core_count); - double per_core_rate = (stream->m_pps * (factor / dp_core_count)); + double per_core_factor = (factor / dp_core_count); int per_core_burst_total_pkts = (stream->m_burst_total_pkts / dp_core_count); /* for each core - creates its own version of the stream */ @@ -521,7 +521,7 @@ TrexStreamsCompiler::compile_stream_on_all_cores(const TrexStream *stream, /* adjust rate and packets count */ - dp_stream->m_pps = per_core_rate; + dp_stream->update_rate_factor(per_core_factor); dp_stream->m_burst_total_pkts = per_core_burst_total_pkts; core_streams[i] = dp_stream; @@ -547,7 +547,7 @@ TrexStreamsCompiler::compile_stream_on_all_cores(const TrexStream *stream, * */ void -TrexStreamsCompiler::compile_stream_on_single_core(const TrexStream *stream, +TrexStreamsCompiler::compile_stream_on_single_core(TrexStream *stream, double factor, TrexStreamsCompiledObj *obj, int new_id, @@ -560,7 +560,7 @@ TrexStreamsCompiler::compile_stream_on_single_core(const TrexStream *stream, /* compile the VM if exists */ if (!stream->m_vm.is_vm_empty()) { - ((TrexStream *)stream)->vm_compile(); + stream->vm_compile(); dp_stream->m_vm_dp = stream->m_vm_dp->clone(); } @@ -581,7 +581,7 @@ TrexStreamsCompiler::compile_stream_on_single_core(const TrexStream *stream, * @param stream */ void -TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, const TrexStream *stream) { +TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, TrexStream *stream) { switch (stream->get_type()) { @@ -604,7 +604,7 @@ TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, const TrexStre * */ void -TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const TrexStream *stream) { +TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, TrexStream *stream) { TrexStreamsGraphObj::rate_event_st start_event; @@ -613,8 +613,8 @@ 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_l2 = ((TrexStream *)stream)->get_bps_l2(); - start_event.diff_bps_l1 = ((TrexStream *)stream)->get_bps_l1(); + start_event.diff_bps_l2 = stream->get_bps_L2(); + start_event.diff_bps_l1 = stream->get_bps_L1(); m_graph_obj->add_rate_event(start_event); /* no more events after this stream */ @@ -629,7 +629,7 @@ TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const Tre * */ void -TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, const TrexStream *stream) { +TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, TrexStream *stream) { TrexStreamsGraphObj::rate_event_st start_event; TrexStreamsGraphObj::rate_event_st stop_event; @@ -640,9 +640,9 @@ TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, c /* start event */ start_event.time = offset_usec + stream->m_isg_usec; - start_event.diff_pps = stream->get_pps(); - start_event.diff_bps_l2 = ((TrexStream *)stream)->get_bps_l2(); - start_event.diff_bps_l1 = ((TrexStream *)stream)->get_bps_l1(); + start_event.diff_pps = stream->get_pps(); + start_event.diff_bps_l2 = stream->get_bps_L2(); + start_event.diff_bps_l1 = stream->get_bps_L1(); m_graph_obj->add_rate_event(start_event); /* stop event */ @@ -662,7 +662,7 @@ TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, c * */ void -TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, const TrexStream *stream) { +TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, TrexStream *stream) { TrexStreamsGraphObj::rate_event_st start_event; TrexStreamsGraphObj::rate_event_st stop_event; @@ -672,8 +672,8 @@ TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, co /* for debug purposes */ start_event.diff_pps = stream->get_pps(); - start_event.diff_bps_l2 = ((TrexStream *)stream)->get_bps_l2(); - start_event.diff_bps_l1 = ((TrexStream *)stream)->get_bps_l1(); + start_event.diff_bps_l2 = stream->get_bps_L2(); + start_event.diff_bps_l1 = stream->get_bps_L1(); start_event.stream_id = stream->m_stream_id; stop_event.diff_pps = -(start_event.diff_pps); @@ -714,7 +714,7 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { double offset = 0; while (true) { - const TrexStream *stream; + TrexStream *stream; /* fetch the stream from the hash - if it is not present, report an error */ try { diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index a3a1f8f7..b8b0be37 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -123,19 +123,19 @@ private: void add_warning(const std::string &warning); void err(const std::string &err); - void compile_stream(const TrexStream *stream, + void compile_stream(TrexStream *stream, double factor, uint8_t dp_core_count, std::vector &objs, GraphNodeMap &nodes); - void compile_stream_on_single_core(const TrexStream *stream, + void compile_stream_on_single_core(TrexStream *stream, double factor, TrexStreamsCompiledObj *obj, int new_id, int new_next_id); - void compile_stream_on_all_cores(const TrexStream *stream, + void compile_stream_on_all_cores(TrexStream *stream, double factor, uint8_t dp_core_count, std::vector &objs, @@ -245,13 +245,13 @@ private: void generate_graph_for_one_root(uint32_t root_stream_id); - void add_rate_events_for_stream(double &offset, const TrexStream *stream); - void add_rate_events_for_stream_cont(double &offset_usec, const TrexStream *stream); - void add_rate_events_for_stream_single_burst(double &offset_usec, const TrexStream *stream); - void add_rate_events_for_stream_multi_burst(double &offset_usec, const TrexStream *stream); + void add_rate_events_for_stream(double &offset, TrexStream *stream); + void add_rate_events_for_stream_cont(double &offset_usec, TrexStream *stream); + void add_rate_events_for_stream_single_burst(double &offset_usec, TrexStream *stream); + void add_rate_events_for_stream_multi_burst(double &offset_usec, TrexStream *stream); /* for fast processing of streams */ - std::unordered_map m_streams_hash; + std::unordered_map m_streams_hash; /* main object to hold the graph - returned to the user */ TrexStreamsGraphObj *m_graph_obj; -- cgit 1.2.3-korg