summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gtest/trex_stateless_gtest.cpp105
-rw-r--r--src/stateless/cp/trex_stream.h7
-rw-r--r--src/stateless/cp/trex_stream_vm.h8
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp1
-rw-r--r--src/stateless/cp/trex_vm_splitter.cpp50
-rw-r--r--src/stateless/cp/trex_vm_splitter.h8
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp2
7 files changed, 144 insertions, 37 deletions
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index cb02a80a..dff2b4b0 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -2633,19 +2633,9 @@ public:
pcap.load_pcap_file("cap2/udp_64B.pcap",0);
pcap.update_ip_src(0x10000001);
- m_split_instr = new StreamVmInstructionFlowMan("var1",
- 8,
- StreamVmInstructionFlowMan::FLOW_VAR_OP_INC,
- 0,
- 0,
- 1000
- );
}
~VmSplitTest() {
- if (m_split_instr) {
- delete m_split_instr;
- }
}
void set_stream(TrexStream *stream) {
@@ -2667,41 +2657,75 @@ public:
uint64_t end,
uint64_t init) {
- if (m_split_instr) {
- delete m_split_instr;
- m_split_instr = NULL;
- }
-
- m_split_instr = new StreamVmInstructionFlowMan("var1",
- 8,
- op,
- init,
- start,
- end);
- }
+ assert(m_stream);
- void run(uint8_t dp_core_count, uint8_t dp_core_to_check) {
- TrexStreamsCompiler compile;
- std::vector<TrexStreamsCompiledObj *> objs;
- std::vector<TrexStream *> streams;
+ StreamVmInstruction *split_instr = new StreamVmInstructionFlowMan("var1",
+ 8,
+ op,
+ init,
+ start,
+ end);
StreamVm &vm = m_stream->m_vm;
- vm.add_instruction(m_split_instr);
+ vm.add_instruction(split_instr);
vm.add_instruction(new StreamVmInstructionWriteToPkt( "var1", 60 - 8 - 4, 0,true));
vm.add_instruction(new StreamVmInstructionFixChecksumIpv4(14));
- vm.set_split_instruction(m_split_instr);
+ vm.set_split_instruction(split_instr);
+
+ }
+
+ void set_client_var_as_split(uint32_t client_min_value,
+ uint32_t client_max_value,
+ uint16_t port_min,
+ uint16_t port_max) {
+
+
+ assert(m_stream);
+
+ StreamVmInstruction *split_instr = new StreamVmInstructionFlowClient("var1",
+ client_min_value,
+ client_max_value,
+ port_min,
+ port_max,
+ 0,
+ 0);
+
+
+ StreamVm &vm = m_stream->m_vm;
+
+ vm.add_instruction(split_instr);
+
+ /* src ip */
+ vm.add_instruction(new StreamVmInstructionWriteToPkt( "var1.ip",26, 0,true));
+ vm.add_instruction(new StreamVmInstructionFixChecksumIpv4(14));
+
+ /* src port */
+ vm.add_instruction(new StreamVmInstructionWriteToPkt("var1.port",34, 0,true));
+
+ vm.set_split_instruction(split_instr);
+ }
+
+ void run(uint8_t dp_core_count, uint8_t dp_core_to_check) {
+ TrexStreamsCompiler compile;
+ std::vector<TrexStreamsCompiledObj *> objs;
+ std::vector<TrexStream *> streams;
+
+ if (m_stream->m_vm.is_vm_empty()) {
+ set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_INC,
+ 0,
+ 1000,
+ 0);
+ }
streams.push_back(m_stream);
/* compiling for 8 cores */
assert(compile.compile(0, streams, objs, dp_core_count));
- m_split_instr = NULL;
-
/* choose one DP object */
TrexStatelessDpStart *lpStartCmd = new TrexStatelessDpStart(0, 0, objs[dp_core_to_check], 1 /*sec */ );
objs[dp_core_to_check] = NULL;
@@ -2728,7 +2752,6 @@ public:
private:
const char *m_erf_filename;
TrexStream *m_stream;
- StreamVmInstruction *m_split_instr;
CPcapLoader pcap;
};
@@ -2753,20 +2776,36 @@ TEST_F(basic_stl, vm_split_flow_var_small_range) {
TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0);
stream.set_pps(1000);
- split.set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_INC, 0, 1, 0);
split.set_stream(&stream);
+ split.set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_INC, 0, 1, 0);
+
split.run(8, 4);
}
TEST_F(basic_stl, vm_split_flow_var_big_range) {
- VmSplitTest split("exp/stl_vm_split_flow_var_big_range.erf");
+ VmSplitTest split("exp/stl_vm_split_flow_var_big_range.erf");
TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0);
stream.set_pps(1000);
+ split.set_stream(&stream);
split.set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC, 1, 1000, 1000);
+
+ split.run(8, 7);
+
+
+}
+
+TEST_F(basic_stl, vm_split_client_var) {
+ VmSplitTest split("exp/stl_vm_split_client_var.erf");
+
+ TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0);
+ stream.set_pps(1000);
+
split.set_stream(&stream);
+ split.set_client_var_as_split(0x10000001, 0x100000fe, 5000, 5050);
+
split.run(8, 7);
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index 80368e4c..b4f19111 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -206,6 +206,13 @@ public:
return(dp);
}
+ /* release the DP object */
+ void release_dp_object() {
+ if (m_vm_dp) {
+ delete m_vm_dp;
+ m_vm_dp = NULL;
+ }
+ }
double get_burst_length_usec() const {
return ( (m_burst_total_pkts / m_pps) * 1000 * 1000);
diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index 136389c5..ce905655 100644
--- a/src/stateless/cp/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
@@ -766,6 +766,14 @@ public:
return (4+2+4);
}
+ uint32_t get_ip_range() const {
+ return (m_client_max - m_client_min + 1);
+ }
+
+ uint16_t get_port_range() const {
+ return (m_port_max - m_port_min + 1);
+ }
+
bool is_unlimited_flows(){
return ( (m_flags & StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS ) ==
StreamVmInstructionFlowClient::CLIENT_F_UNLIMITED_FLOWS );
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index 24b14469..6bcddc1d 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -184,7 +184,6 @@ TrexStreamsCompiledObj::clone() {
}
return new_compiled_obj;
-
}
void TrexStreamsCompiledObj::Dump(FILE *fd){
diff --git a/src/stateless/cp/trex_vm_splitter.cpp b/src/stateless/cp/trex_vm_splitter.cpp
index 8aae8c76..56776f7e 100644
--- a/src/stateless/cp/trex_vm_splitter.cpp
+++ b/src/stateless/cp/trex_vm_splitter.cpp
@@ -22,6 +22,11 @@ limitations under the License.
#include <trex_vm_splitter.h>
#include <trex_stateless.h>
+/**
+ * split a specific stream's VM to multiple cores
+ * number of cores is implied by the size of the vector
+ *
+ */
void
TrexVmSplitter::split(TrexStream *stream, std::vector<TrexStream *> core_streams) {
@@ -57,6 +62,8 @@ bool
TrexVmSplitter::split_internal() {
const StreamVmInstruction *split_instr = m_stream->m_vm.get_split_instruction();
+
+ /* if no split instruction was specified - fall back*/
if (split_instr == NULL) {
return false;
}
@@ -132,10 +139,48 @@ TrexVmSplitter::split_by_flow_var(const StreamVmInstructionFlowMan *instr) {
bool
TrexVmSplitter::split_by_flow_client_var(const StreamVmInstructionFlowClient *instr) {
- return false;
-}
+ /* if the range is too small - it is unsplitable */
+ if (instr->get_ip_range() < m_dp_core_count) {
+ return false;
+ }
+
+ /* we need to split - duplicate VM now */
+ duplicate_vm();
+
+ /* calculate range splitting */
+ uint64_t range = instr->get_ip_range();
+
+ uint64_t range_part = range / m_dp_core_count;
+ uint64_t leftover = range % m_dp_core_count;
+
+ /* first core handles a bit more */
+ uint64_t start = instr->m_client_min;
+ uint64_t end = start + range_part + leftover - 1;
+
+
+ /* do work */
+ for (TrexStream *core_stream : *m_core_streams) {
+
+ /* get the per-core instruction to split */
+ StreamVmInstructionFlowClient *per_core_instr = (StreamVmInstructionFlowClient *)core_stream->m_vm.get_split_instruction();
+
+ per_core_instr->m_client_min = start;
+ per_core_instr->m_client_max = end;
+ core_stream->vm_compile();
+
+ start = end + 1;
+ end = start + range_part - 1;
+ }
+
+ return true;
+}
+
+/**
+ * duplicate the VM instructions
+ * to all the cores
+ */
void
TrexVmSplitter::duplicate_vm() {
/* for each core - duplicate the instructions */
@@ -143,3 +188,4 @@ TrexVmSplitter::duplicate_vm() {
m_stream->m_vm.copy_instructions(core_stream->m_vm);
}
}
+
diff --git a/src/stateless/cp/trex_vm_splitter.h b/src/stateless/cp/trex_vm_splitter.h
index 37c61599..dac71c21 100644
--- a/src/stateless/cp/trex_vm_splitter.h
+++ b/src/stateless/cp/trex_vm_splitter.h
@@ -23,7 +23,13 @@ limitations under the License.
#include <trex_stream.h>
-
+/**
+ * TRex VM splitter is used to split
+ * VM instructions around cores
+ *
+ *
+ * @author imarom (23-Dec-15)
+ */
class TrexVmSplitter {
public:
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index e0378cfb..acbf1b88 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -472,6 +472,8 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port,
/* clone the stream from control plane memory to DP memory */
node->m_ref_stream_info = stream->clone();
+ /* no need for this memory anymore on the control plane memory */
+ stream->release_dp_object();
node->m_next_stream=0; /* will be fixed later */