diff options
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py | 2 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 6 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 19 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 45 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.h | 103 |
5 files changed, 135 insertions, 40 deletions
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index 104befcd..e1100b17 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -31,7 +31,7 @@ LS_COMPAT = [GLOBAL_STATS, LATENCY_STATS] # latency stats ExportableStats = namedtuple('ExportableStats', ['raw_data', 'text_table']) def round_float (f): - return float("%.2f" % f) + return float("%.2f" % f) if type(f) is float else f # deep mrege of dicts dst = src + dst def deep_merge_dicts (dst, src): diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 360cc7d6..ec3907b1 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -626,17 +626,17 @@ TrexStatelessPort::calculate_effective_factor_internal(const TrexPortMultiplier return (mul.m_value); case TrexPortMultiplier::MUL_BPS: - return (mul.m_value / m_graph_obj->get_max_bps_l2()); + return m_graph_obj->get_factor_bps_l2(mul.m_value); case TrexPortMultiplier::MUL_PPS: - return (mul.m_value / m_graph_obj->get_max_pps()); + return m_graph_obj->get_factor_pps(mul.m_value); case TrexPortMultiplier::MUL_PERCENTAGE: /* if abs percentage is from the line speed - otherwise its from the current speed */ if (mul.m_op == TrexPortMultiplier::OP_ABS) { double required = (mul.m_value / 100.0) * get_port_speed_bps(); - return (required / m_graph_obj->get_max_bps_l1()); + return m_graph_obj->get_factor_bps_l1(required); } else { return (m_factor * (mul.m_value / 100.0)); } diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index b0bfba52..8ac5ebc8 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -351,7 +351,10 @@ public: } void update_rate_factor(double factor) { - m_rate.update_factor(factor); + /* fixed rate streams cannot be updated in rate */ + if (!is_fixed_rate_stream()) { + m_rate.update_factor(factor); + } } void set_type(uint8_t type){ @@ -366,20 +369,30 @@ public: return ( m_type ); } - bool is_dp_next_stream(){ + bool is_dp_next_stream() { if (m_next_stream_id<0) { return (false); }else{ return (true); } } + + bool is_latency_stream() const { + return (m_rx_check.m_enabled && (m_rx_check.m_rule_type == TrexPlatformApi::IF_STAT_PAYLOAD)); + } + + bool is_fixed_rate_stream() const { + return is_latency_stream(); + } + /* can this stream be split ? */ bool is_splitable(uint8_t dp_core_count) const { - if (m_rx_check.m_enabled && (m_rx_check.m_rule_type == TrexPlatformApi::IF_STAT_PAYLOAD)) { + if (is_latency_stream()) { // because of sequence number, can't split streams with payload rule to different cores return false; } + /* cont stream is always splitable */ if (m_type == stCONTINUOUS) { return true; diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index d1cffbb7..f2296aeb 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -688,6 +688,13 @@ TrexStreamsCompiler::compile_stream_on_single_core(TrexStream *stream, void TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, TrexStream *stream) { + /* for fixed rate streams such as latency - simply add a fix rate addition */ + if (stream->is_fixed_rate_stream()) { + BW bw(stream->get_pps(), stream->get_bps_L2(), stream->get_bps_L1()); + m_graph_obj->add_fixed_rate(bw); + return; + } + switch (stream->get_type()) { case TrexStream::stCONTINUOUS: @@ -716,10 +723,10 @@ TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, TrexStrea /* for debug purposes */ start_event.stream_id = stream->m_stream_id; - start_event.time = offset_usec + stream->m_isg_usec; - 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(); + start_event.time = offset_usec + stream->m_isg_usec; + 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); /* no more events after this stream */ @@ -900,25 +907,21 @@ TrexStreamsGraph::generate(const std::vector<TrexStream *> &streams) { *************************************/ void TrexStreamsGraphObj::find_max_rate() { - double max_rate_pps = 0; - double current_rate_pps = 0; - double max_rate_bps_l1 = 0; - double current_rate_bps_l1 = 0; - - double max_rate_bps_l2 = 0; - double current_rate_bps_l2 = 0; + BW max_bw; + BW current_bw; /* now we simply walk the list and hold the max */ for (auto &ev : m_rate_events) { - current_rate_pps += ev.diff_pps; - current_rate_bps_l2 += ev.diff_bps_l2; - current_rate_bps_l1 += ev.diff_bps_l1; + current_bw.m_pps += ev.diff_pps; + current_bw.m_bps_l2 += ev.diff_bps_l2; + current_bw.m_bps_l1 += ev.diff_bps_l1; + + max_bw.m_pps = std::max(max_bw.m_pps, current_bw.m_pps); + max_bw.m_bps_l2 = std::max(max_bw.m_bps_l2, current_bw.m_bps_l2); + max_bw.m_bps_l1 = std::max(max_bw.m_bps_l1, current_bw.m_bps_l1); - max_rate_pps = std::max(max_rate_pps, current_rate_pps); - max_rate_bps_l2 = std::max(max_rate_bps_l2, current_rate_bps_l2); - max_rate_bps_l1 = std::max(max_rate_bps_l1, current_rate_bps_l1); } /* if not mark as inifite - get the last event time */ @@ -926,9 +929,11 @@ TrexStreamsGraphObj::find_max_rate() { m_expected_duration = m_rate_events.back().time; } - m_max_pps = max_rate_pps; - m_max_bps_l2 = max_rate_bps_l2; - m_max_bps_l1 = max_rate_bps_l1; + /* save it to the class member */ + m_var = max_bw; + + /* for total - max and fixed */ + m_total = m_var + m_fixed; } static diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index 23b06d06..69b44c3d 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -26,6 +26,7 @@ limitations under the License. #include <list> #include <string> #include <unordered_map> +#include "trex_exception.h" class TrexStreamsCompiler; class TrexStream; @@ -163,6 +164,44 @@ private: class TrexStreamsGraph; +/* describes a bandwidth point */ +class BW { +public: + + BW() { + m_pps = 0; + m_bps_l2 = 0; + m_bps_l1 = 0; + } + + BW(double pps, double bps_l2, double bps_l1) { + m_pps = pps; + m_bps_l2 = bps_l2; + m_bps_l1 = bps_l1; + + } + + BW& operator+= (const BW &other) { + m_pps += other.m_pps; + m_bps_l1 += other.m_bps_l1; + m_bps_l2 += other.m_bps_l2; + + return *this; + } + + + double m_pps; + double m_bps_l1; + double m_bps_l2; + +}; + +/* there are two temp copies here - it is known... */ +static inline BW operator+ (BW lhs, const BW &rhs) { + lhs += rhs; + return lhs; +} + /************************************** * streams graph object * @@ -174,9 +213,6 @@ class TrexStreamsGraphObj { public: TrexStreamsGraphObj() { - m_max_pps = 0; - m_max_bps_l1 = 0; - m_max_bps_l2 = 0; m_expected_duration = 0; } @@ -188,23 +224,53 @@ public: * @author imarom (23-Nov-15) */ struct rate_event_st { - double time; - double diff_pps; - double diff_bps_l1; - double diff_bps_l2; + double time; + double diff_pps; + double diff_bps_l1; + double diff_bps_l2; uint32_t stream_id; }; double get_max_pps() const { - return m_max_pps; + return m_total.m_pps; } double get_max_bps_l1() const { - return m_max_bps_l1; + return m_total.m_bps_l1; } double get_max_bps_l2() const { - return m_max_bps_l2; + return m_total.m_bps_l2; + } + + double get_factor_pps(double req_pps) const { + if ( (req_pps - m_fixed.m_pps) <= 0 ) { + std::stringstream ss; + ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_pps << "' pps"; + throw TrexException(ss.str()); + } + + return ( (req_pps - m_fixed.m_pps) / m_var.m_pps ); + } + + double get_factor_bps_l1(double req_bps_l1) const { + if ( (req_bps_l1 - m_fixed.m_bps_l1) <= 0 ) { + std::stringstream ss; + ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_bps_l1 << "' BPS L1"; + throw TrexException(ss.str()); + } + + return ( (req_bps_l1 - m_fixed.m_bps_l1) / m_var.m_bps_l1 ); + } + + double get_factor_bps_l2(double req_bps_l2) const { + if ( (req_bps_l2 - m_fixed.m_bps_l2) <= 0 ) { + std::stringstream ss; + ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_bps_l2 << "' BPS L2"; + throw TrexException(ss.str()); + } + + return ( (req_bps_l2 - m_fixed.m_bps_l2) / m_var.m_bps_l2 ); } int get_duration() const { @@ -218,6 +284,7 @@ public: private: + void on_loop_detection() { m_expected_duration = -1; } @@ -226,12 +293,22 @@ private: m_rate_events.push_back(ev); } + void add_fixed_rate(const BW &bw) { + m_fixed += bw; + } + void generate(); void find_max_rate(); - double m_max_pps; - double m_max_bps_l1; - double m_max_bps_l2; + /* max variable BW in the graph */ + BW m_var; + + /* graph might contain fixed rate traffic (DC traffic such as latency) */ + BW m_fixed; + + /* total consists of fixed rate + variable rate*/ + BW m_total; + int m_expected_duration; /* list of rate events */ |