summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-12-23 09:48:38 -0500
committerimarom <imarom@cisco.com>2015-12-23 09:59:43 -0500
commitfb46a1735d7f723ddc791221563e365ad54ef5e0 (patch)
tree28c258c4f8cf327f3967b272fa5de1c98c8ca06e /src
parent0bde21ac82ff025939f73bbd1e4783345917e49a (diff)
connected control plane to split
Diffstat (limited to 'src')
-rw-r--r--src/gtest/trex_stateless_gtest.cpp26
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp20
-rw-r--r--src/stateless/cp/trex_stream_vm.cpp35
-rw-r--r--src/stateless/cp/trex_stream_vm.h93
-rw-r--r--src/stateless/cp/trex_vm_splitter.cpp6
5 files changed, 121 insertions, 59 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index dff2b4b0..dc1313f1 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -2659,12 +2659,12 @@ public:
assert(m_stream);
- StreamVmInstruction *split_instr = new StreamVmInstructionFlowMan("var1",
- 8,
- op,
- init,
- start,
- end);
+ StreamVmInstructionVar *split_instr = new StreamVmInstructionFlowMan("var1",
+ 8,
+ op,
+ init,
+ start,
+ end);
StreamVm &vm = m_stream->m_vm;
@@ -2686,13 +2686,13 @@ public:
assert(m_stream);
- StreamVmInstruction *split_instr = new StreamVmInstructionFlowClient("var1",
- client_min_value,
- client_max_value,
- port_min,
- port_max,
- 0,
- 0);
+ StreamVmInstructionVar *split_instr = new StreamVmInstructionFlowClient("var1",
+ client_min_value,
+ client_max_value,
+ port_min,
+ port_max,
+ 0,
+ 0);
StreamVm &vm = m_stream->m_vm;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index e0186493..51db0b20 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -82,7 +82,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
stream->m_pkt.meta = parse_string(pkt, "meta", result);
/* parse VM */
- const Json::Value &vm = parse_array(section ,"vm", result);
+ const Json::Value &vm = parse_object(section ,"vm", result);
parse_vm(vm, stream, result);
/* parse RX info */
@@ -248,9 +248,12 @@ TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, Trex
void
TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, TrexStream *stream, Json::Value &result) {
+
+ const Json::Value &instructions = parse_array(vm ,"instructions", result);
+
/* array of VM instructions on vm */
- for (int i = 0; i < vm.size(); i++) {
- const Json::Value & inst = parse_object(vm, i, result);
+ for (int i = 0; i < instructions.size(); i++) {
+ const Json::Value & inst = parse_object(instructions, i, result);
auto vm_types = {"fix_checksum_ipv4", "flow_var", "write_flow_var","tuple_flow_var"};
std::string vm_type = parse_choice(inst, "type", vm_types, result);
@@ -272,6 +275,17 @@ TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, TrexStream *stream, Json::V
throw TrexRpcException("internal error");
}
}
+
+ const std::string &var_name = parse_string(vm, "split_by_var", result);
+ if (var_name != "") {
+ StreamVmInstructionVar *instr = stream->m_vm.lookup_var_by_name(var_name);
+ if (!instr) {
+ std::stringstream ss;
+ ss << "VM: request to split by variable '" << var_name << "' but does not exists";
+ generate_parse_err(result, ss.str());
+ }
+ stream->m_vm.set_split_instruction(instr);
+ }
}
void
diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp
index cbd2ce7c..cccbfe88 100644
--- a/src/stateless/cp/trex_stream_vm.cpp
+++ b/src/stateless/cp/trex_stream_vm.cpp
@@ -600,12 +600,7 @@ void StreamVm::build_bss() {
*
*/
void
-StreamVm::set_split_instruction(StreamVmInstruction *instr) {
- if (!instr->is_splitable()) {
- throw TrexException("non splitable instruction");
- return;
- }
-
+StreamVm::set_split_instruction(StreamVmInstructionVar *instr) {
m_split_instr = instr;
}
@@ -631,7 +626,9 @@ StreamVm::copy_instructions(StreamVm &other) const {
/* for the split instruction - find the right one */
if (instr == m_split_instr) {
- other.m_split_instr = new_instr;
+ /* dynamic cast must succeed here */
+ other.m_split_instr = dynamic_cast<StreamVmInstructionVar *>(new_instr);
+ assert(other.m_split_instr);
}
}
@@ -677,6 +674,30 @@ StreamVm::~StreamVm() {
free_bss();
}
+/**
+* return a pointer to a flow var / client var
+* by name if exists, otherwise NULL
+*
+*/
+StreamVmInstructionVar *
+StreamVm::lookup_var_by_name(const std::string &var_name) {
+ for (StreamVmInstruction *inst : m_inst_list) {
+
+ /* try to cast up to a variable */
+ StreamVmInstructionVar *var = dynamic_cast<StreamVmInstructionVar *>(inst);
+ if (!var) {
+ continue;
+ }
+
+ if (var->get_var_name() == var_name) {
+ return var;
+ }
+
+ }
+
+ return NULL;
+}
+
void StreamVm::Dump(FILE *fd){
fprintf(fd," instructions \n");
diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index ce905655..f327267e 100644
--- a/src/stateless/cp/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
@@ -579,9 +579,7 @@ public:
virtual StreamVmInstruction * clone() = 0;
- /**
- * by default an instruction is not a splitable field
- */
+ /* by default an instruction is not splitable */
virtual bool is_splitable() const {
return false;
}
@@ -591,6 +589,39 @@ private:
};
/**
+ * abstract class that defines a flow var
+ *
+ * @author imarom (23-Dec-15)
+ */
+class StreamVmInstructionVar : public StreamVmInstruction {
+
+public:
+
+ StreamVmInstructionVar(const std::string &var_name) : m_var_name(var_name) {
+
+ }
+
+ const std::string & get_var_name() {
+ return m_var_name;
+ }
+
+ virtual bool is_splitable() const {
+ return true;
+ }
+
+ /**
+ * what is the split range for this var
+ *
+ */
+ virtual uint64_t get_splitable_range() const = 0;
+
+public:
+
+ /* flow var name */
+ const std::string m_var_name;
+};
+
+/**
* fix checksum for ipv4
*
*/
@@ -619,7 +650,7 @@ public:
*
* @author imarom (07-Sep-15)
*/
-class StreamVmInstructionFlowMan : public StreamVmInstruction {
+class StreamVmInstructionFlowMan : public StreamVmInstructionVar {
public:
@@ -627,14 +658,10 @@ public:
return ( StreamVmInstruction::itFLOW_MAN);
}
- uint64_t get_range() const {
+ virtual uint64_t get_splitable_range() const {
return (m_max_value - m_min_value + 1);
}
- virtual bool is_splitable() const {
- return true;
- }
-
/**
* different types of operations on the object
*/
@@ -672,14 +699,13 @@ public:
flow_var_op_e op,
uint64_t init_value,
uint64_t min_value,
- uint64_t max_value) :
- m_var_name(var_name),
- m_size_bytes(size),
- m_op(op),
- m_init_value(init_value),
- m_min_value(min_value),
- m_max_value(max_value) {
+ uint64_t max_value) : StreamVmInstructionVar(var_name) {
+ m_op = op;
+ m_size_bytes = size;
+ m_init_value = init_value;
+ m_min_value = min_value;
+ m_max_value = max_value;
}
virtual void Dump(FILE *fd);
@@ -702,10 +728,6 @@ private:
public:
-
- /* flow var name */
- std::string m_var_name;
-
/* flow var size */
uint8_t m_size_bytes;
@@ -725,7 +747,7 @@ public:
*
* @author hhaim
*/
-class StreamVmInstructionFlowClient : public StreamVmInstruction {
+class StreamVmInstructionFlowClient : public StreamVmInstructionVar {
public:
enum client_flags_e {
@@ -737,9 +759,6 @@ public:
return ( StreamVmInstruction::itFLOW_CLIENT);
}
- virtual bool is_splitable() const {
- return true;
- }
StreamVmInstructionFlowClient(const std::string &var_name,
uint32_t client_min_value,
@@ -748,8 +767,8 @@ public:
uint16_t port_max,
uint32_t limit_num_flows, /* zero means don't limit */
uint16_t flags
- ) {
- m_var_name = var_name;
+ ) : StreamVmInstructionVar(var_name) {
+
m_client_min = client_min_value;
m_client_max = client_max_value;
@@ -774,6 +793,10 @@ public:
return (m_port_max - m_port_min + 1);
}
+ virtual uint64_t get_splitable_range() const {
+ return get_ip_range();
+ }
+
bool is_unlimited_flows(){
return ( (m_flags & StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS ) ==
StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS );
@@ -791,10 +814,6 @@ public:
public:
-
- /* flow var name */
- std::string m_var_name;
-
uint32_t m_client_min; // min ip
uint32_t m_client_max; // max ip
uint16_t m_port_min; // start port
@@ -1014,9 +1033,9 @@ public:
}
- void set_split_instruction(StreamVmInstruction *instr);
+ void set_split_instruction(StreamVmInstructionVar *instr);
- StreamVmInstruction * get_split_instruction() {
+ StreamVmInstructionVar * get_split_instruction() {
return m_split_instr;
}
@@ -1098,6 +1117,14 @@ public:
/* raise exception */
void err(const std::string &err);
+
+ /**
+ * return a pointer to a flow var / client var
+ * by name if exists, otherwise NULL
+ *
+ */
+ StreamVmInstructionVar * lookup_var_by_name(const std::string &var_name);
+
private:
/* lookup for varible offset, */
@@ -1138,7 +1165,7 @@ private:
StreamDPVmInstructions m_instructions;
- StreamVmInstruction *m_split_instr;
+ StreamVmInstructionVar *m_split_instr;
};
diff --git a/src/stateless/cp/trex_vm_splitter.cpp b/src/stateless/cp/trex_vm_splitter.cpp
index 56776f7e..9465718f 100644
--- a/src/stateless/cp/trex_vm_splitter.cpp
+++ b/src/stateless/cp/trex_vm_splitter.cpp
@@ -61,7 +61,7 @@ TrexVmSplitter::split(TrexStream *stream, std::vector<TrexStream *> core_streams
bool
TrexVmSplitter::split_internal() {
- const StreamVmInstruction *split_instr = m_stream->m_vm.get_split_instruction();
+ const StreamVmInstructionVar *split_instr = m_stream->m_vm.get_split_instruction();
/* if no split instruction was specified - fall back*/
if (split_instr == NULL) {
@@ -97,7 +97,7 @@ TrexVmSplitter::split_by_flow_var(const StreamVmInstructionFlowMan *instr) {
}
/* if the range is too small - it is unsplitable */
- if (instr->get_range() < m_dp_core_count) {
+ if (instr->get_splitable_range() < m_dp_core_count) {
return false;
}
@@ -105,7 +105,7 @@ TrexVmSplitter::split_by_flow_var(const StreamVmInstructionFlowMan *instr) {
duplicate_vm();
/* calculate range splitting */
- uint64_t range = instr->get_range();
+ uint64_t range = instr->get_splitable_range();
uint64_t range_part = range / m_dp_core_count;
uint64_t leftover = range % m_dp_core_count;