summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py2
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp6
-rw-r--r--src/stateless/cp/trex_stream.h19
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp45
-rw-r--r--src/stateless/cp/trex_streams_compiler.h103
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 */