summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-11-26 06:26:27 -0500
committerimarom <imarom@cisco.com>2015-11-26 06:26:27 -0500
commit59548ae8f65f8aa387900a321b437b8501046fde (patch)
tree6f6406331b7e2f7bc49192a7b240768ea5c88a1e /src
parentd9a11302236095e055247295021bdfce6c988802 (diff)
Hanoch's review - changed update model to differential
also, graph is calculated on demand and once for each update
Diffstat (limited to 'src')
-rw-r--r--src/gtest/trex_stateless_gtest.cpp16
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp44
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp103
-rw-r--r--src/stateless/cp/trex_stateless_port.h59
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp18
-rw-r--r--src/stateless/cp/trex_streams_compiler.h9
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp11
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h2
-rw-r--r--src/stateless/dp/trex_stream_node.h8
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.cpp4
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.h6
11 files changed, 184 insertions, 96 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 5b298023..ea54a935 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -1713,13 +1713,15 @@ TEST_F(basic_stl, graph_generator1) {
streams.push_back(stream);
- const TrexStreamsGraphObj &obj = graph.generate(streams);
- EXPECT_EQ(obj.get_max_bps(), 405120);
- EXPECT_EQ(obj.get_max_pps(), 50);
+ const TrexStreamsGraphObj *obj = graph.generate(streams);
+ EXPECT_EQ(obj->get_max_bps(), 405120);
+ EXPECT_EQ(obj->get_max_pps(), 50);
for (auto stream : streams) {
delete stream;
}
+
+ delete obj;
}
@@ -1761,15 +1763,17 @@ TEST_F(basic_stl, graph_generator2) {
streams.push_back(stream);
- const TrexStreamsGraphObj &obj = graph.generate(streams);
- EXPECT_EQ(obj.get_max_pps(), 1000.0);
+ const TrexStreamsGraphObj *obj = graph.generate(streams);
+ EXPECT_EQ(obj->get_max_pps(), 1000.0);
- EXPECT_EQ(obj.get_max_bps(), (1000 * (128 + 4) * 8));
+ EXPECT_EQ(obj->get_max_bps(), (1000 * (128 + 4) * 8));
for (auto stream : streams) {
delete stream;
}
+
+ delete obj;
}
/* stress test */
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index 96224d4e..a5bf0d16 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -473,32 +473,32 @@ TrexRpcCmdStartTraffic::_run(const Json::Value &params, Json::Value &result) {
TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
+ /* multiplier */
+ const Json::Value &mul_obj = parse_object(params, "mul", result);
+ std::string mul_type = parse_string(mul_obj, "type", result);
+ double mul_value = parse_double(mul_obj, "max", result);
- const Json::Value &mul = parse_object(params, "mul", result);
-
- std::string mul_type = parse_string(mul, "type", result);
- double max_rate = parse_double(mul, "max", result);
-
-
- double m = 0;
+ /* now create an object for multiplier */
+ TrexStatelessPort::mul_st mul;
+
+ mul.value = mul_value;
/* dispatch according to type of multiplier */
if (mul_type == "raw") {
- m = max_rate;
+ mul.type = TrexStatelessPort::MUL_FACTOR;
} else if (mul_type == "max_bps") {
- m = port->calculate_m_from_bps(max_rate);
+ mul.type = TrexStatelessPort::MUL_MAX_BPS;
} else if (mul_type == "max_pps") {
- m = port->calculate_m_from_pps(max_rate);
+ mul.type = TrexStatelessPort::MUL_MAX_PPS;
} else {
generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'");
}
-
try {
- port->start_traffic(m, duration);
+ port->start_traffic(mul, duration);
} catch (const TrexRpcException &ex) {
generate_execute_err(result, ex.what());
@@ -651,29 +651,31 @@ TrexRpcCmdUpdateTraffic::_run(const Json::Value &params, Json::Value &result) {
TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
/* multiplier */
- const Json::Value &mul = parse_object(params, "mul", result);
+ const Json::Value &mul_obj = parse_object(params, "mul", result);
+ std::string mul_type = parse_string(mul_obj, "type", result);
+ double mul_value = parse_double(mul_obj, "max", result);
- std::string mul_type = parse_string(mul, "type", result);
- double max_rate = parse_double(mul, "max", result);
-
- double m = 0;
+ /* now create an object for multiplier */
+ TrexStatelessPort::mul_st mul;
+
+ mul.value = mul_value;
/* dispatch according to type of multiplier */
if (mul_type == "raw") {
- m = max_rate;
+ mul.type = TrexStatelessPort::MUL_FACTOR;
} else if (mul_type == "max_bps") {
- m = port->calculate_m_from_bps(max_rate);
+ mul.type = TrexStatelessPort::MUL_MAX_BPS;
} else if (mul_type == "max_pps") {
- m = port->calculate_m_from_pps(max_rate);
+ mul.type = TrexStatelessPort::MUL_MAX_PPS;
} else {
generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'");
}
try {
- port->update_traffic(m);
+ port->update_traffic(mul);
} catch (const TrexRpcException &ex) {
generate_execute_err(result, ex.what());
}
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 8e18a5bf..8346b61d 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -104,17 +104,21 @@ TrexStatelessPort::release(void) {
*
*/
void
-TrexStatelessPort::start_traffic(double mul, double duration) {
+TrexStatelessPort::start_traffic(const TrexStatelessPort::mul_st &mul, double duration) {
/* command allowed only on state stream */
verify_state(PORT_STATE_STREAMS);
+ /* just making sure no leftovers... */
+ delete_streams_graph();
+
+ /* calculate the effective M */
+ double per_core_mul = calculate_effective_mul(mul);
+
/* fetch all the streams from the table */
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;
@@ -127,6 +131,7 @@ TrexStatelessPort::start_traffic(double mul, double duration) {
/* generate a message to all the relevant DP cores to start transmitting */
int event_id = m_dp_events.generate_event_id();
+
/* mark that DP event of stoppped is possible */
m_dp_events.wait_for_event(TrexDpPortEvent::EVENT_STOP, event_id);
@@ -142,32 +147,11 @@ TrexStatelessPort::start_traffic(double mul, double duration) {
Json::Value data;
data["port_id"] = m_port_id;
get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data);
-}
-
-double
-TrexStatelessPort::calculate_m_from_bps(double max_bps) {
- /* fetch all the streams from the table */
- vector<TrexStream *> streams;
- get_object_list(streams);
-
- TrexStreamsGraph graph;
- const TrexStreamsGraphObj &obj = graph.generate(streams);
-
- return (max_bps / obj.get_max_bps());
+ /* save the per core multiplier for update messages */
+ m_current_per_core_m = per_core_mul;
}
-double
-TrexStatelessPort::calculate_m_from_pps(double max_pps) {
- /* fetch all the streams from the table */
- vector<TrexStream *> streams;
- get_object_list(streams);
-
- TrexStreamsGraph graph;
- const TrexStreamsGraphObj &obj = graph.generate(streams);
-
- return (max_pps / obj.get_max_pps());
-}
/**
* stop traffic on port
@@ -180,10 +164,13 @@ void
TrexStatelessPort::stop_traffic(void) {
if (!( (m_port_state == PORT_STATE_TX)
- || (m_port_state ==PORT_STATE_PAUSE) )) {
+ || (m_port_state == PORT_STATE_PAUSE) )) {
return;
}
+ /* delete any previous graphs */
+ delete_streams_graph();
+
/* mask out the DP stop event */
m_dp_events.disable(TrexDpPortEvent::EVENT_STOP);
@@ -234,16 +221,20 @@ TrexStatelessPort::resume_traffic(void) {
}
void
-TrexStatelessPort::update_traffic(double mul) {
+TrexStatelessPort::update_traffic(const TrexStatelessPort::mul_st &mul) {
verify_state(PORT_STATE_TX | PORT_STATE_PAUSE);
/* generate a message to all the relevant DP cores to start transmitting */
- double per_core_mul = mul / m_cores_id_list.size();
- TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, per_core_mul);
+ double new_per_core_m = calculate_effective_mul(mul);
+ double factor = new_per_core_m / m_current_per_core_m;
+
+ TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, factor);
send_message_to_dp(update_msg);
+ m_current_per_core_m = new_per_core_m;
+
}
std::string
@@ -376,3 +367,55 @@ TrexStatelessPort::on_dp_event_occured(TrexDpPortEvent::event_e event_type) {
}
}
+
+/**
+ * calculate an effective M based on requirments
+ *
+ */
+double
+TrexStatelessPort::calculate_effective_mul(const mul_st &mul) {
+
+ /* for a simple factor request - calculate the multiplier per core */
+ if (mul.type == MUL_FACTOR) {
+ return (mul.value / m_cores_id_list.size());
+ }
+
+ /* we now need the graph - generate it if we don't have it (happens once) */
+ if (!m_graph_obj) {
+ generate_streams_graph();
+ }
+
+ /* now we can calculate the effective M */
+ if (mul.type == MUL_MAX_BPS) {
+ return ( (mul.value / m_graph_obj->get_max_bps()) / m_cores_id_list.size());
+ } else if (mul.type == MUL_MAX_PPS) {
+ return ( (mul.value / m_graph_obj->get_max_pps()) / m_cores_id_list.size());
+ } else {
+ assert(0);
+ }
+}
+
+void
+TrexStatelessPort::generate_streams_graph() {
+
+ /* dispose of the old one */
+ if (m_graph_obj) {
+ delete_streams_graph();
+ }
+
+ /* fetch all the streams from the table */
+ vector<TrexStream *> streams;
+ get_object_list(streams);
+
+ TrexStreamsGraph graph;
+ m_graph_obj = graph.generate(streams);
+}
+
+void
+TrexStatelessPort::delete_streams_graph() {
+ if (m_graph_obj) {
+ delete m_graph_obj;
+ m_graph_obj = NULL;
+ }
+}
+
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index b061a414..7d20f338 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -26,6 +26,7 @@ limitations under the License.
#include <internal_api/trex_platform_api.h>
class TrexStatelessCpToDpMsgBase;
+class TrexStreamsGraphObj;
/**
* describes a stateless port
@@ -58,6 +59,24 @@ public:
RC_ERR_FAILED_TO_COMPILE_STREAMS
};
+ /**
+ * defines the type of multipler passed to start
+ */
+ enum mul_type_e {
+ MUL_FACTOR,
+ MUL_MAX_BPS,
+ MUL_MAX_PPS
+ };
+
+ /**
+ * multiplier object
+ */
+ typedef struct {
+ mul_type_e type;
+ double value;
+ } mul_st;
+
+
TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api);
/**
@@ -76,19 +95,7 @@ public:
* start traffic
* throws TrexException in case of an error
*/
- void start_traffic(double mul, double duration = -1);
-
- /**
- * given a BPS rate calculate ther correct M for this port
- *
- */
- double calculate_m_from_bps(double max_bps);
-
- /**
- * given a PPS rate calculate the correct M for this port
- *
- */
- double calculate_m_from_pps(double max_pps);
+ void start_traffic(const mul_st &mul, double duration = -1);
/**
* stop traffic
@@ -112,7 +119,7 @@ public:
* update current traffic on port
*
*/
- void update_traffic(double mul);
+ void update_traffic(const mul_st &mul);
/**
* get the port state
@@ -265,6 +272,26 @@ private:
void on_dp_event_occured(TrexDpPortEvent::event_e event_type);
+ /**
+ * calculate effective M per core
+ *
+ */
+ double calculate_effective_mul(const mul_st &mul);
+
+ /**
+ * generates a graph of streams graph
+ *
+ */
+ void generate_streams_graph();
+
+ /**
+ * dispose of it
+ *
+ * @author imarom (26-Nov-15)
+ */
+ void delete_streams_graph();
+
+
TrexStreamTable m_stream_table;
uint8_t m_port_id;
port_state_e m_port_state;
@@ -279,8 +306,12 @@ private:
bool m_last_all_streams_continues;
double m_last_duration;
+ double m_current_per_core_m;
TrexDpPortEvents m_dp_events;
+
+ /* holds a graph of streams rate*/
+ const TrexStreamsGraphObj *m_graph_obj;
};
#endif /* __TREX_STATELESS_PORT_H__ */
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index b28989be..c8aa1e40 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -486,7 +486,7 @@ TrexStreamsGraph::add_rate_events_for_stream_cont(double &offset_usec, const Tre
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);
+ m_graph_obj->add_rate_event(start_event);
/* no more events after this stream */
offset_usec = -1;
@@ -510,13 +510,13 @@ TrexStreamsGraph::add_rate_events_for_stream_single_burst(double &offset_usec, c
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);
+ 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);
+ m_graph_obj->add_rate_event(stop_event);
/* next stream starts from here */
offset_usec = stop_event.time;
@@ -549,10 +549,10 @@ TrexStreamsGraph::add_rate_events_for_stream_multi_burst(double &offset_usec, co
for (int i = 0; i < stream->m_num_bursts; i++) {
start_event.time = offset_usec + delay;
- m_graph_obj.add_rate_event(start_event);
+ 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);
+ m_graph_obj->add_rate_event(stop_event);
/* after the first burst, the delay is inter burst gap */
delay = stream->m_ibg_usec;
@@ -615,8 +615,12 @@ TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) {
* see graph object for more details
*
*/
-const TrexStreamsGraphObj &
+const TrexStreamsGraphObj *
TrexStreamsGraph::generate(const std::vector<TrexStream *> &streams) {
+
+ /* main object to hold the graph - returned to the user */
+ m_graph_obj = new TrexStreamsGraphObj();
+
std::vector <uint32_t> root_streams;
/* before anything we create a hash streams ID
@@ -644,7 +648,7 @@ TrexStreamsGraph::generate(const std::vector<TrexStream *> &streams) {
}
- m_graph_obj.generate();
+ m_graph_obj->generate();
return m_graph_obj;
}
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index 70a31c5e..a4c12f8d 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -171,6 +171,7 @@ private:
/* list of rate events */
std::list<rate_event_st> m_rate_events;
+
};
/**
@@ -181,11 +182,15 @@ private:
class TrexStreamsGraph {
public:
+ TrexStreamsGraph() {
+ m_graph_obj = NULL;
+ }
+
/**
* generate a sequence graph for streams
*
*/
- const TrexStreamsGraphObj & generate(const std::vector<TrexStream *> &streams);
+ const TrexStreamsGraphObj * generate(const std::vector<TrexStream *> &streams);
private:
@@ -200,7 +205,7 @@ private:
std::unordered_map<uint32_t, const TrexStream *> m_streams_hash;
/* main object to hold the graph - returned to the user */
- TrexStreamsGraphObj m_graph_obj;
+ TrexStreamsGraphObj *m_graph_obj;
};
#endif /* __TREX_STREAMS_COMPILER_H__ */
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index dd4937cd..9b62fabd 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -139,7 +139,7 @@ bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){
return (true);
}
-bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) {
+bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double factor) {
assert( (m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING ||
(m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE)) );
@@ -148,7 +148,7 @@ bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) {
CGenNodeStateless * node = dp_stream.m_node;
assert(node->get_port_id() == port_id);
- node->set_multiplier(mul);
+ node->update_rate(factor);
}
return (true);
@@ -453,8 +453,7 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port,
node->m_pause =0;
node->m_stream_type = stream->m_type;
- node->m_base_pps = stream->get_pps();
- node->set_multiplier(comp->get_multiplier());
+ node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier());
/* stateless specific fields */
switch ( stream->m_type ) {
@@ -597,11 +596,11 @@ TrexStatelessDpCore::pause_traffic(uint8_t port_id){
}
void
-TrexStatelessDpCore::update_traffic(uint8_t port_id, double mul) {
+TrexStatelessDpCore::update_traffic(uint8_t port_id, double factor) {
TrexStatelessDpPerPort * lp_port = get_port_db(port_id);
- lp_port->update_traffic(port_id, mul);
+ lp_port->update_traffic(port_id, factor);
}
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
index 563159b2..7dc4a2b2 100644
--- a/src/stateless/dp/trex_stateless_dp_core.h
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -68,7 +68,7 @@ public:
bool resume_traffic(uint8_t port_id);
- bool update_traffic(uint8_t port_id, double mul);
+ bool update_traffic(uint8_t port_id, double factor);
bool stop_traffic(uint8_t port_id,
bool stop_on_id,
diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h
index 5997376f..111af845 100644
--- a/src/stateless/dp/trex_stream_node.h
+++ b/src/stateless/dp/trex_stream_node.h
@@ -86,9 +86,8 @@ private:
TrexStream * m_ref_stream_info; /* the stream info */
CGenNodeStateless * m_next_stream;
- double m_base_pps;
/* pad to match the size of CGenNode */
- uint8_t m_pad_end[48];
+ uint8_t m_pad_end[56];
@@ -105,8 +104,9 @@ public:
* on the PPS and multiplier
*
*/
- void set_multiplier(double mul) {
- m_next_time_offset = 1.0 / (m_base_pps * mul) ;
+ void update_rate(double factor) {
+ /* update the inter packet gap */
+ m_next_time_offset = m_next_time_offset / factor;
}
/* we restart the stream, schedule it using stream isg */
diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp
index 3210f29a..257de168 100644
--- a/src/stateless/messaging/trex_stateless_messaging.cpp
+++ b/src/stateless/messaging/trex_stateless_messaging.cpp
@@ -168,14 +168,14 @@ TrexStatelessDpCanQuit::clone(){
************************/
bool
TrexStatelessDpUpdate::handle(TrexStatelessDpCore *dp_core) {
- dp_core->update_traffic(m_port_id, m_mul);
+ dp_core->update_traffic(m_port_id, m_factor);
return true;
}
TrexStatelessCpToDpMsgBase *
TrexStatelessDpUpdate::clone() {
- TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_mul);
+ TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_factor);
return new_msg;
}
diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h
index 7390be60..d56596bf 100644
--- a/src/stateless/messaging/trex_stateless_messaging.h
+++ b/src/stateless/messaging/trex_stateless_messaging.h
@@ -231,9 +231,9 @@ public:
class TrexStatelessDpUpdate : public TrexStatelessCpToDpMsgBase {
public:
- TrexStatelessDpUpdate(uint8_t port_id, double mul) {
+ TrexStatelessDpUpdate(uint8_t port_id, double factor) {
m_port_id = port_id;
- m_mul = mul;
+ m_factor = factor;
}
virtual bool handle(TrexStatelessDpCore *dp_core);
@@ -242,7 +242,7 @@ public:
private:
uint8_t m_port_id;
- double m_mul;
+ double m_factor;
};