summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-11-24 11:52:33 +0200
committerimarom <imarom@cisco.com>2015-11-24 11:52:33 +0200
commit161a85c57c3d2a165e4fa94140d67db05714a7d3 (patch)
tree939451cf95e90b537d9505b87a7ced4151c897db
parent1f6977d1e109acba69f1bf2230d6b9f5e4aae54e (diff)
bug fixes for the graph
-rw-r--r--src/gtest/trex_stateless_gtest.cpp128
-rw-r--r--src/stateless/cp/trex_stream.h5
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp170
-rw-r--r--src/stateless/cp/trex_streams_compiler.h7
4 files changed, 260 insertions, 50 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 3aad2d41..72a99e93 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -1342,7 +1342,7 @@ TEST_F(basic_stl, dp_stop_event) {
}
-TEST_F(basic_stl, graph_generator) {
+TEST_F(basic_stl, graph_generator1) {
std::vector<TrexStream *> streams;
TrexStreamsGraph graph;
TrexStream *stream;
@@ -1388,12 +1388,134 @@ TEST_F(basic_stl, graph_generator) {
const TrexStreamsGraphObj &obj = graph.generate(streams);
- EXPECT_TRUE(obj.get_max_bps() == 403840.0);
- EXPECT_TRUE(obj.get_max_pps() == 50.0);
+ EXPECT_EQ(obj.get_max_bps(), 405120);
+ EXPECT_EQ(obj.get_max_pps(), 50);
for (auto stream : streams) {
delete stream;
}
}
+
+TEST_F(basic_stl, graph_generator2) {
+ std::vector<TrexStream *> streams;
+ TrexStreamsGraph graph;
+ TrexStream *stream;
+
+ /* add some multi burst streams */
+ stream = new TrexStream(TrexStream::stMULTI_BURST, 0, 1);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+
+
+ stream->set_pps(1000);
+
+ /* a burst of 2000 packets with a delay of 1 second */
+ stream->m_isg_usec = 0;
+ stream->set_multi_burst(1000, 500, 1000 * 1000);
+ stream->m_pkt.len = 64;
+
+ stream->m_next_stream_id = -1;
+
+ streams.push_back(stream);
+
+ /* another multi burst stream but with a shorter burst ( less 2 ms ) and
+ higher ibg (2 ms) , one milli for each side
+ */
+ stream = new TrexStream(TrexStream::stMULTI_BURST, 0, 2);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+
+ stream->set_pps(1000);
+ stream->m_isg_usec = 1000 * 1000 + 1000;
+ stream->set_multi_burst(1000 - 2, 1000, 1000 * 1000 + 2000);
+ stream->m_pkt.len = 128;
+
+ stream->m_next_stream_id = -1;
+
+ streams.push_back(stream);
+
+ const TrexStreamsGraphObj &obj = graph.generate(streams);
+ EXPECT_EQ(obj.get_max_pps(), 1000.0);
+
+ EXPECT_EQ(obj.get_max_bps(), (1000 * (128 + 4) * 8));
+
+
+ for (auto stream : streams) {
+ delete stream;
+ }
+}
+
+/* stress test */
+#if 0
+TEST_F(basic_stl, graph_generator2) {
+ std::vector<TrexStream *> streams;
+ TrexStreamsGraph graph;
+ TrexStream *stream;
+
+ /* add some multi burst streams */
+ stream = new TrexStream(TrexStream::stMULTI_BURST, 0, 1);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+ stream->m_isg_usec = 100;
+
+ stream->set_pps(20);
+ stream->set_multi_burst(4918, 321312, 15);
+ stream->m_next_stream_id = -1;
+ stream->m_pkt.len = 64;
+
+ streams.push_back(stream);
+
+ stream = new TrexStream(TrexStream::stMULTI_BURST, 0, 2);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+ stream->m_isg_usec = 59281;
+
+ stream->set_pps(30);
+ stream->set_multi_burst(4918, 51040, 27);
+ stream->m_next_stream_id = -1;
+ stream->m_pkt.len = 64;
+
+ streams.push_back(stream);
+
+ stream = new TrexStream(TrexStream::stMULTI_BURST, 0, 3);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+ stream->m_isg_usec = 59281492;
+
+ stream->set_pps(40);
+ stream->set_multi_burst(4918, 412312, 2917);
+ stream->m_next_stream_id = -1;
+ stream->m_pkt.len = 64;
+
+ streams.push_back(stream);
+
+
+ /* stream 3 */
+ stream = new TrexStream(TrexStream::stCONTINUOUS, 0, 4);
+ stream->m_enabled = true;
+ stream->m_self_start = true;
+
+ stream->m_isg_usec = 50;
+ stream->set_pps(30);
+ stream->m_next_stream_id = -1;
+ stream->m_pkt.len = 1512;
+
+ streams.push_back(stream);
+
+
+ const TrexStreamsGraphObj &obj = graph.generate(streams);
+ printf("event_count is: %lu, max BPS: %f, max PPS: %f\n", obj.get_events().size(), obj.get_max_bps(), obj.get_max_pps());
+
+// for (const TrexStreamsGraphObj::rate_event_st &ev : obj.get_events()) {
+// printf("time: %f, diff bps: %f, diff pps: %f\n", ev.time, ev.diff_bps, ev.diff_pps);
+// }
+
+ for (auto stream : streams) {
+ delete stream;
+ }
+}
+
+#endif
+
/********************************************* Itay Tests End *************************************/
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index 5baba840..3e48d7e4 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -152,11 +152,12 @@ public:
double get_burst_length_usec() const {
- return ( (m_burst_total_pkts / m_pps) * 1000 );
+ return ( (m_burst_total_pkts / m_pps) * 1000 * 1000);
}
double get_bps() const {
- return (m_pps * m_pkt.len * 8);
+ /* packet length + 4 CRC bytes to bits and multiplied by PPS */
+ return (m_pps * (m_pkt.len + 4) * 8);
}
void Dump(FILE *fd);
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index f36de1b4..f97b15b9 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -439,86 +439,154 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams,
* streams graph
*************************************/
+/**
+ * for each stream we create the right rate events (up/down)
+ *
+ * @author imarom (24-Nov-15)
+ *
+ * @param offset_usec
+ * @param stream
+ */
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:
+ add_rate_events_for_stream_cont(offset_usec, stream);
+ return;
+
+ case TrexStream::stSINGLE_BURST:
+ add_rate_events_for_stream_single_burst(offset_usec, stream);
+ return;
- 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);
+ case TrexStream::stMULTI_BURST:
+ add_rate_events_for_stream_multi_burst(offset_usec, stream);
+ return;
+ }
+}
- /* no more events after this stream */
- offset_usec = -1;
+/**
+ * continous stream
+ *
+ */
+void
+TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const TrexStream *stream) {
- break;
-
- case TrexStream::stSINGLE_BURST:
+ TrexStreamsGraphObj::rate_event_st start_event;
- /* 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);
+ /* for debug purposes */
+ start_event.stream_id = stream->m_stream_id;
- /* 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);
+ 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);
- /* next stream starts from here */
- offset_usec = stop_event.time;
+ /* no more events after this stream */
+ offset_usec = -1;
+}
+
+/**
+ * single burst stream
+ *
+ */
+void
+TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, const TrexStream *stream) {
+ TrexStreamsGraphObj::rate_event_st start_event;
+ TrexStreamsGraphObj::rate_event_st stop_event;
- break;
- case TrexStream::stMULTI_BURST:
+ /* for debug purposes */
+ start_event.stream_id = stream->m_stream_id;
+ stop_event.stream_id = stream->m_stream_id;
+
+ /* 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;
- double delay = stream->m_isg_usec;
+}
- start_event.diff_pps = stream->get_pps();
- start_event.diff_bps = stream->get_bps();
+/**
+ * multi burst stream
+ *
+ */
+void
+TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, const TrexStream *stream) {
+ TrexStreamsGraphObj::rate_event_st start_event;
+ TrexStreamsGraphObj::rate_event_st stop_event;
- stop_event.diff_pps = -(start_event.diff_pps);
- stop_event.diff_bps = -(start_event.diff_bps);
+ /* first the delay is the inter stream gap */
+ double delay = stream->m_isg_usec;
+
+ /* for debug purposes */
+
+ start_event.diff_pps = stream->get_pps();
+ start_event.diff_bps = stream->get_bps();
+ start_event.stream_id = stream->m_stream_id;
- for (int i = 0; i < stream->m_num_bursts; i++) {
+ stop_event.diff_pps = -(start_event.diff_pps);
+ stop_event.diff_bps = -(start_event.diff_bps);
+ stop_event.stream_id = stream->m_stream_id;
- start_event.time = offset_usec + delay;
- m_graph_obj.add_rate_event(start_event);
+ /* for each burst create up/down events */
+ for (int i = 0; i < stream->m_num_bursts; i++) {
- stop_event.time = start_event.time + stream->get_burst_length_usec();
- m_graph_obj.add_rate_event(stop_event);
+ start_event.time = offset_usec + delay;
+ m_graph_obj.add_rate_event(start_event);
- delay = stream->m_ibg_usec;
+ stop_event.time = start_event.time + stream->get_burst_length_usec();
+ m_graph_obj.add_rate_event(stop_event);
- offset_usec = stop_event.time;
- }
+ /* after the first burst, the delay is inter burst gap */
+ delay = stream->m_ibg_usec;
- break;
+ offset_usec = stop_event.time;
}
}
+/**
+ * for a single root we can until done or a loop detected
+ *
+ * @author imarom (24-Nov-15)
+ *
+ * @param root_stream_id
+ */
void
TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) {
-
std::unordered_map<uint32_t, bool> loop_hash;
-
+ std::stringstream ss;
uint32_t stream_id = root_stream_id;
double offset = 0;
while (true) {
+ const TrexStream *stream;
+
+ /* fetch the stream from the hash - if it is not present, report an error */
+ try {
+ stream = m_streams_hash.at(stream_id);
+ } catch (const std::out_of_range &e) {
+ ss << "stream id " << stream_id << " does not exists";
+ throw TrexException(ss.str());
+ }
- const TrexStream *stream = m_streams_hash.at(stream_id);
/* add the node to the hash for loop detection */
loop_hash[stream_id] = true;
+ /* create the right rate events for the stream */
add_rate_events_for_stream(offset, stream);
/* do we have a next stream ? */
@@ -527,7 +595,6 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) {
}
/* loop detection */
-
auto search = loop_hash.find(stream->m_next_stream_id);
if (search != loop_hash.end()) {
break;
@@ -538,13 +605,25 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) {
}
}
+/**
+ * for a vector of streams generate a graph of BW
+ * see graph object for more details
+ *
+ */
const TrexStreamsGraphObj &
TrexStreamsGraph::generate(const std::vector<TrexStream *> &streams) {
std::vector <uint32_t> root_streams;
-
+ /* before anything we create a hash streams ID
+ and grab the root nodes
+ */
for (TrexStream *stream : streams) {
-
+
+ /* skip non enabled streams */
+ if (!stream->m_enabled) {
+ continue;
+ }
+
/* for fast search we populate all the streams in a hash */
m_streams_hash[stream->m_stream_id] = stream;
@@ -578,6 +657,7 @@ TrexStreamsGraphObj::find_max_rate() {
/* 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;
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index 28a9bd10..9f0c1f8e 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -137,6 +137,7 @@ public:
double time;
double diff_pps;
double diff_bps;
+ uint32_t stream_id;
};
double get_max_pps() const {
@@ -147,6 +148,9 @@ public:
return m_max_bps;
}
+ const std::list<rate_event_st> & get_events() const {
+ return m_rate_events;
+ }
private:
@@ -183,6 +187,9 @@ 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);
/* for fast processing of streams */
std::unordered_map<uint32_t, const TrexStream *> m_streams_hash;