diff options
author | 2015-11-23 18:02:14 +0200 | |
---|---|---|
committer | 2015-11-23 18:02:14 +0200 | |
commit | 1f6977d1e109acba69f1bf2230d6b9f5e4aae54e (patch) | |
tree | 21292c73ea16f456d4deee455dcb9e1f96397141 /src/stateless | |
parent | 903b855393acd411e85b25e6b2df1158d9fe2856 (diff) |
add stream graph + support for console to use any of the following
bps, kbps, mbps, gbps, pps, kpps, mbps
percentage is not working yet
Diffstat (limited to 'src/stateless')
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 33 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 2 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 2 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 11 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 186 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.h | 80 |
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__ */ |