summaryrefslogtreecommitdiffstats
path: root/src/stateless
diff options
context:
space:
mode:
Diffstat (limited to 'src/stateless')
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp33
-rw-r--r--src/stateless/cp/trex_stateless_port.h2
-rw-r--r--src/stateless/cp/trex_stream.cpp2
-rw-r--r--src/stateless/cp/trex_stream.h11
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp186
-rw-r--r--src/stateless/cp/trex_streams_compiler.h80
6 files changed, 305 insertions, 9 deletions
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index fbc5f7c7..7dc217a3 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -111,9 +111,12 @@ TrexStatelessPort::start_traffic(double mul, double duration) {
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;
- TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, mul);
+ TrexStreamsCompiledObj *compiled_obj = new TrexStreamsCompiledObj(m_port_id, per_core_mul);
bool rc = compiler.compile(streams, *compiled_obj);
if (!rc) {
@@ -133,6 +136,34 @@ TrexStatelessPort::start_traffic(double mul, double duration) {
}
+void
+TrexStatelessPort::start_traffic_max_bps(double max_bps, double duration) {
+ /* fetch all the streams from the table */
+ vector<TrexStream *> streams;
+ get_object_list(streams);
+
+ TrexStreamsGraph graph;
+ const TrexStreamsGraphObj &obj = graph.generate(streams);
+ double m = (max_bps / obj.get_max_bps());
+
+ /* call the main function */
+ start_traffic(m, duration);
+}
+
+void
+TrexStatelessPort::start_traffic_max_pps(double max_pps, double duration) {
+ /* fetch all the streams from the table */
+ vector<TrexStream *> streams;
+ get_object_list(streams);
+
+ TrexStreamsGraph graph;
+ const TrexStreamsGraphObj &obj = graph.generate(streams);
+ double m = (max_pps / obj.get_max_pps());
+
+ /* call the main function */
+ start_traffic(m, duration);
+}
+
/**
* stop traffic on port
*
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index 73157c15..9b74741c 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -77,6 +77,8 @@ public:
* throws TrexException in case of an error
*/
void start_traffic(double mul, double duration = -1);
+ void start_traffic_max_bps(double max_bps, double duration = -1);
+ void start_traffic_max_pps(double max_pps, double duration = -1);
/**
* stop traffic
diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp
index 5203b2a2..cad603e2 100644
--- a/src/stateless/cp/trex_stream.cpp
+++ b/src/stateless/cp/trex_stream.cpp
@@ -21,6 +21,7 @@ limitations under the License.
#include <trex_stream.h>
#include <cstddef>
#include <string.h>
+#include <assert.h>
/**************************************
* stream
@@ -129,6 +130,7 @@ TrexStream::get_stream_json() {
return m_stream_json;
}
+
/**************************************
* stream table
*************************************/
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index 0634829e..5baba840 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -90,7 +90,7 @@ public:
m_next_stream_id = next_stream_id;
}
- double get_pps() {
+ double get_pps() const {
return m_pps;
}
@@ -150,6 +150,15 @@ public:
return (dp);
}
+
+ double get_burst_length_usec() const {
+ return ( (m_burst_total_pkts / m_pps) * 1000 );
+ }
+
+ double get_bps() const {
+ return (m_pps * m_pkt.len * 8);
+ }
+
void Dump(FILE *fd);
public:
/* basic */
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index bdfc3c01..f36de1b4 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -34,19 +34,25 @@ limitations under the License.
*/
class GraphNode {
public:
- GraphNode(TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) {
- marked = false;
+ GraphNode(const TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) {
+ m_marked = false;
m_compressed_stream_id=-1;
+
}
uint32_t get_stream_id() const {
return m_stream->m_stream_id;
}
+ uint32_t get_next_stream_id() const {
+ return m_stream->m_next_stream_id;
+
+ }
+
const TrexStream *m_stream;
GraphNode *m_next;
std::vector<const GraphNode *> m_parents;
- bool marked;
+ bool m_marked;
int m_compressed_stream_id;
};
@@ -97,13 +103,13 @@ public:
void clear_marks() {
for (auto node : m_nodes) {
- node.second->marked = false;
+ node.second->m_marked = false;
}
}
void get_unmarked(std::vector <GraphNode *> &unmarked) {
for (auto node : m_nodes) {
- if (!node.second->marked) {
+ if (!node.second->m_marked) {
unmarked.push_back(node.second);
}
}
@@ -132,6 +138,7 @@ private:
GraphNode m_dead_end;
};
+
/**************************************
* stream compiled object
*************************************/
@@ -316,11 +323,11 @@ TrexStreamsCompiler::check_for_unreachable_streams(GraphNodeMap *nodes) {
/* pull one */
GraphNode *node = next_nodes.back();
next_nodes.pop_back();
- if (node->marked) {
+ if (node->m_marked) {
continue;
}
- node->marked = true;
+ node->m_marked = true;
if (node->m_next != NULL) {
next_nodes.push_back(node->m_next);
@@ -422,9 +429,174 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams,
my_stream_id,
my_next_stream_id
);
+
}
return true;
}
+/**************************************
+ * streams graph
+ *************************************/
+
+void
+TrexStreamsGraph::add_rate_events_for_stream(double &offset_usec, const TrexStream *stream) {
+ TrexStreamsGraphObj::rate_event_st start_event;
+ TrexStreamsGraphObj::rate_event_st stop_event;
+
+ switch (stream->get_type()) {
+ case TrexStream::stCONTINUOUS:
+
+ 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);
+
+ /* no more events after this stream */
+ offset_usec = -1;
+
+ break;
+
+ case TrexStream::stSINGLE_BURST:
+
+ /* start event */
+ 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);
+
+ /* 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);
+
+ /* next stream starts from here */
+ offset_usec = stop_event.time;
+
+ break;
+
+ case TrexStream::stMULTI_BURST:
+
+ double delay = stream->m_isg_usec;
+
+ start_event.diff_pps = stream->get_pps();
+ start_event.diff_bps = stream->get_bps();
+
+ stop_event.diff_pps = -(start_event.diff_pps);
+ stop_event.diff_bps = -(start_event.diff_bps);
+
+ for (int i = 0; i < stream->m_num_bursts; i++) {
+
+ start_event.time = offset_usec + delay;
+ 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);
+
+ delay = stream->m_ibg_usec;
+
+ offset_usec = stop_event.time;
+ }
+
+ break;
+ }
+}
+
+void
+TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) {
+
+
+ std::unordered_map<uint32_t, bool> loop_hash;
+
+
+ uint32_t stream_id = root_stream_id;
+ double offset = 0;
+
+ while (true) {
+
+ const TrexStream *stream = m_streams_hash.at(stream_id);
+ /* add the node to the hash for loop detection */
+ loop_hash[stream_id] = true;
+
+ add_rate_events_for_stream(offset, stream);
+
+ /* do we have a next stream ? */
+ if (stream->m_next_stream_id == -1) {
+ break;
+ }
+
+ /* loop detection */
+
+ auto search = loop_hash.find(stream->m_next_stream_id);
+ if (search != loop_hash.end()) {
+ break;
+ }
+
+ /* handle the next one */
+ stream_id = stream->m_next_stream_id;
+ }
+}
+
+const TrexStreamsGraphObj &
+TrexStreamsGraph::generate(const std::vector<TrexStream *> &streams) {
+ std::vector <uint32_t> root_streams;
+
+
+ for (TrexStream *stream : streams) {
+
+ /* for fast search we populate all the streams in a hash */
+ m_streams_hash[stream->m_stream_id] = stream;
+
+ /* hold all the self start nodes in a vector */
+ if (stream->m_self_start) {
+ root_streams.push_back(stream->m_stream_id);
+ }
+ }
+
+ /* for each node - scan until done or loop */
+ for (uint32_t root_id : root_streams) {
+ generate_graph_for_one_root(root_id);
+ }
+
+
+ m_graph_obj.generate();
+
+ return m_graph_obj;
+}
+
+/**************************************
+ * streams graph object
+ *************************************/
+void
+TrexStreamsGraphObj::find_max_rate() {
+ double max_rate_pps = 0;
+ double current_rate_pps = 0;
+
+ double max_rate_bps = 0;
+ double current_rate_bps = 0;
+
+ /* 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 += ev.diff_bps;
+
+ max_rate_pps = std::max(max_rate_pps, current_rate_pps);
+ max_rate_bps = std::max(max_rate_bps, current_rate_bps);
+ }
+
+ m_max_pps = max_rate_pps;
+ m_max_bps = max_rate_bps;
+}
+
+static
+bool event_compare (const TrexStreamsGraphObj::rate_event_st &first, const TrexStreamsGraphObj::rate_event_st &second) {
+ return (first.time < second.time);
+}
+
+void
+TrexStreamsGraphObj::generate() {
+ m_rate_events.sort(event_compare);
+ find_max_rate();
+}
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index 200f7ce9..28a9bd10 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -23,7 +23,9 @@ limitations under the License.
#include <stdint.h>
#include <vector>
+#include <list>
#include <string>
+#include <unordered_map>
class TrexStreamsCompiler;
class TrexStream;
@@ -109,6 +111,84 @@ private:
void err(const std::string &err);
std::vector<std::string> m_warnings;
+
+};
+
+class TrexStreamsGraph;
+
+/**************************************
+ * streams graph object
+ *
+ * holds the step graph for bandwidth
+ *************************************/
+class TrexStreamsGraphObj {
+ friend class TrexStreamsGraph;
+
+public:
+
+ /**
+ * rate event is defined by those:
+ * time - the time of the event on the timeline
+ * diff - what is the nature of the change ?
+ *
+ * @author imarom (23-Nov-15)
+ */
+ struct rate_event_st {
+ double time;
+ double diff_pps;
+ double diff_bps;
+ };
+
+ double get_max_pps() const {
+ return m_max_pps;
+ }
+
+ double get_max_bps() const {
+ return m_max_bps;
+ }
+
+
+private:
+
+ void add_rate_event(const rate_event_st &ev) {
+ m_rate_events.push_back(ev);
+ }
+
+ void generate();
+ void find_max_rate();
+
+ double m_max_pps;
+ double m_max_bps;
+
+ /* list of rate events */
+ std::list<rate_event_st> m_rate_events;
+};
+
+/**
+ * graph creator
+ *
+ * @author imarom (23-Nov-15)
+ */
+class TrexStreamsGraph {
+public:
+
+ /**
+ * generate a sequence graph for streams
+ *
+ */
+ const TrexStreamsGraphObj & generate(const std::vector<TrexStream *> &streams);
+
+private:
+
+ void generate_graph_for_one_root(uint32_t root_stream_id);
+
+ void add_rate_events_for_stream(double &offset, const TrexStream *stream);
+
+ /* for fast processing of streams */
+ std::unordered_map<uint32_t, const TrexStream *> m_streams_hash;
+
+ /* main object to hold the graph - returned to the user */
+ TrexStreamsGraphObj m_graph_obj;
};
#endif /* __TREX_STREAMS_COMPILER_H__ */