summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-02-16 16:08:23 +0200
committerHanoh Haim <hhaim@cisco.com>2016-02-16 16:08:23 +0200
commit47c865838678444c0075aab94267972a3a3cbfff (patch)
tree3551714c2b6e2f3c71374754732ab0e01c7d83f1
parent75c84998813a359cb8619e80507e04f21d71de89 (diff)
step instruction support
-rw-r--r--scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py4
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py9
-rw-r--r--scripts/exp/udp_1pkt_mac_step.pcapbin0 -> 1544 bytes
-rw-r--r--scripts/stl/udp_1pkt_mac_step.py35
-rw-r--r--scripts/stl/yaml/burst_1pkt_vm.yaml1
-rw-r--r--scripts/stl/yaml/imix_1pkt_vm.yaml1
-rw-r--r--scripts/stl/yaml/imix_3pkt_vm.yaml3
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp11
-rw-r--r--src/stateless/cp/trex_stream_vm.cpp321
-rw-r--r--src/stateless/cp/trex_stream_vm.h195
-rw-r--r--src/stateless/cp/trex_vm_splitter.cpp5
11 files changed, 500 insertions, 85 deletions
diff --git a/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py b/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py
index f4b67f05..1f07b6e4 100644
--- a/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py
+++ b/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py
@@ -139,7 +139,7 @@ class CStlBasic_Test(functional_general_test.CGeneralFunctional_Test):
def test_stl_profiles (self):
- p = [
+ p1 = [
["udp_1pkt_1mac_override.py","-m 1 -l 50",True],
["syn_attack.py","-m 1 -l 50",False], # can't compare random now
["udp_1pkt_1mac.py","-m 1 -l 50",True],
@@ -180,7 +180,7 @@ class CStlBasic_Test(functional_general_test.CGeneralFunctional_Test):
];
- p1 = [ ["burst_3st_loop_x_times.py","-m 1 -l 20 ",True] ]
+ p = [ ["udp_1pkt_mac_step.py","-m 1 -l 20 ",True] ]
for obj in p:
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
index 88efe265..c788e277 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
@@ -207,7 +207,7 @@ class CTRexVmInsFlowVar(CTRexVmInsBase):
OPERATIONS =['inc', 'dec', 'random']
VALID_SIZES =[1, 2, 4, 8]
- def __init__(self, fv_name, size, op, init_value, min_value, max_value):
+ def __init__(self, fv_name, size, op, init_value, min_value, max_value,step):
super(CTRexVmInsFlowVar, self).__init__("flow_var")
self.name = fv_name;
assert type(fv_name)==str, 'type of fv_name is not str'
@@ -219,6 +219,8 @@ class CTRexVmInsFlowVar(CTRexVmInsBase):
assert type(min_value)==int, 'type of min_value is not int'
self.max_value=max_value
assert type(max_value)==int, 'type of min_value is not int'
+ self.step=step
+ assert type(step)==int, 'type of step should be int'
class CTRexVmInsWrFlowVar(CTRexVmInsBase):
def __init__(self, fv_name, pkt_offset, add_value=0, is_big_endian=True):
@@ -496,7 +498,7 @@ def check_for_int (val):
class CTRexVmDescFlowVar(CTRexVmDescBase):
- def __init__(self, name, init_value=None, min_value=0, max_value=255, size=4, op="inc"):
+ def __init__(self, name, init_value=None, min_value=0, max_value=255, size=4, step=1,op="inc"):
super(CTRexVmDescFlowVar, self).__init__()
self.name = name;
assert type(name)==str, 'type of name is not str'
@@ -512,12 +514,13 @@ class CTRexVmDescFlowVar(CTRexVmDescBase):
self.init_value = convert_val (init_value)
self.min_value = convert_val (min_value);
self.max_value = convert_val (max_value)
+ self.step = convert_val (step)
if self.min_value > self.max_value :
raise CTRexPacketBuildException(-11,("max %d is lower than min %d ") % (self.max_value,self.min_value) );
def get_obj (self):
- return CTRexVmInsFlowVar(self.name,self.size,self.op,self.init_value,self.min_value,self.max_value);
+ return CTRexVmInsFlowVar(self.name,self.size,self.op,self.init_value,self.min_value,self.max_value,self.step);
def get_var_name(self):
return [self.name]
diff --git a/scripts/exp/udp_1pkt_mac_step.pcap b/scripts/exp/udp_1pkt_mac_step.pcap
new file mode 100644
index 00000000..0377567b
--- /dev/null
+++ b/scripts/exp/udp_1pkt_mac_step.pcap
Binary files differ
diff --git a/scripts/stl/udp_1pkt_mac_step.py b/scripts/stl/udp_1pkt_mac_step.py
new file mode 100644
index 00000000..077a162b
--- /dev/null
+++ b/scripts/stl/udp_1pkt_mac_step.py
@@ -0,0 +1,35 @@
+from trex_stl_lib.api import *
+
+
+# step is not 1.
+class STLS1(object):
+
+ def __init__ (self):
+ self.fsize =64; # the size of the packet
+
+ def create_stream (self):
+
+ # create a base packet and pad it to size
+ size = self.fsize - 4; # no FCS
+ base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
+ pad = max(0, size - len(base_pkt)) * 'x'
+
+ vm = CTRexScRaw( [ STLVmFlowVar(name="mac_src", min_value=1, max_value=100, size=1,step=2, op="inc"),
+ STLVmWrFlowVar(fv_name="mac_src", pkt_offset= 11) # write it to LSB of SRC offset it 11
+ ]
+ )
+
+ return STLStream(packet = STLPktBuilder(pkt = base_pkt/pad,vm = vm),
+ mode = STLTXCont( pps=10 ))
+
+ def get_streams (self, direction = 0):
+ # create 1 stream
+ return [ self.create_stream() ]
+
+
+# dynamic load - used for trex console or simulator
+def register():
+ return STLS1()
+
+
+
diff --git a/scripts/stl/yaml/burst_1pkt_vm.yaml b/scripts/stl/yaml/burst_1pkt_vm.yaml
index 246b8813..fed39488 100644
--- a/scripts/stl/yaml/burst_1pkt_vm.yaml
+++ b/scripts/stl/yaml/burst_1pkt_vm.yaml
@@ -19,6 +19,7 @@
"name" : "l3_src",
"op" : "inc",
"size" : 2,
+ "step" : 1,
"type" : "flow_var"
},
{
diff --git a/scripts/stl/yaml/imix_1pkt_vm.yaml b/scripts/stl/yaml/imix_1pkt_vm.yaml
index 05443a6c..698d3e60 100644
--- a/scripts/stl/yaml/imix_1pkt_vm.yaml
+++ b/scripts/stl/yaml/imix_1pkt_vm.yaml
@@ -19,6 +19,7 @@
"name" : "l3_src",
"op" : "inc",
"size" : 4,
+ "step" : 1,
"type" : "flow_var"
},
{
diff --git a/scripts/stl/yaml/imix_3pkt_vm.yaml b/scripts/stl/yaml/imix_3pkt_vm.yaml
index 6ba2c40c..3e7cd0ed 100644
--- a/scripts/stl/yaml/imix_3pkt_vm.yaml
+++ b/scripts/stl/yaml/imix_3pkt_vm.yaml
@@ -19,6 +19,7 @@
"name" : "l3_src",
"op" : "inc",
"size" : 2,
+ "step" : 1,
"type" : "flow_var"
},
{
@@ -49,6 +50,7 @@
"name" : "l3_src",
"op" : "inc",
"size" : 2,
+ "step" : 1,
"type" : "flow_var"
},
{
@@ -80,6 +82,7 @@
"name" : "l3_src",
"op" : "inc",
"size" : 2,
+ "step" : 1,
"type" : "flow_var"
},
{
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index 0262fd7c..508967b9 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -249,6 +249,7 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
uint64_t init_value = parse_uint64(inst, "init_value", result);
uint64_t min_value = parse_uint64(inst, "min_value", result);
uint64_t max_value = parse_uint64(inst, "max_value", result);
+ uint64_t step = parse_uint64(inst, "step", result);
if (max_value < min_value ) {
std::stringstream ss;
@@ -257,7 +258,7 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
}
if (flow_var_size == 1 ) {
- if ( (init_value > UINT8_MAX) || (min_value > UINT8_MAX) || (max_value > UINT8_MAX)) {
+ if ( (init_value > UINT8_MAX) || (min_value > UINT8_MAX) || (max_value > UINT8_MAX) || (step >UINT8_MAX) ) {
std::stringstream ss;
ss << "VM: request val is bigger than " << UINT8_MAX;
generate_parse_err(result, ss.str());
@@ -265,7 +266,7 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
}
if (flow_var_size == 2 ) {
- if ( (init_value > UINT16_MAX) || (min_value > UINT16_MAX) || (max_value > UINT16_MAX)) {
+ if ( (init_value > UINT16_MAX) || (min_value > UINT16_MAX) || (max_value > UINT16_MAX) || (step > UINT16_MAX) ) {
std::stringstream ss;
ss << "VM: request val is bigger than " << UINT16_MAX;
generate_parse_err(result, ss.str());
@@ -273,7 +274,7 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
}
if (flow_var_size == 4 ) {
- if ( (init_value > UINT32_MAX) || (min_value > UINT32_MAX) || (max_value > UINT32_MAX)) {
+ if ( (init_value > UINT32_MAX) || (min_value > UINT32_MAX) || (max_value > UINT32_MAX) || (step > UINT32_MAX) ) {
std::stringstream ss;
ss << "VM: request val is bigger than " << UINT32_MAX;
generate_parse_err(result, ss.str());
@@ -286,7 +287,9 @@ TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream
op_type,
init_value,
min_value,
- max_value));
+ max_value,
+ step)
+ );
}
void
diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp
index b91f0fb5..f99c3c9c 100644
--- a/src/stateless/cp/trex_stream_vm.cpp
+++ b/src/stateless/cp/trex_stream_vm.cpp
@@ -102,7 +102,7 @@ void StreamVmInstructionFlowMan::Dump(FILE *fd){
break;
};
- fprintf(fd," (%lu:%lu:%lu) \n",m_init_value,m_min_value,m_max_value);
+ fprintf(fd," (%lu:%lu:%lu:%lu) \n",m_init_value,m_min_value,m_max_value,m_step);
}
@@ -412,31 +412,52 @@ void StreamVm::build_program(){
if (lpMan->m_size_bytes == 1 ){
-
- uint8_t op=StreamDPVmInstructions::ditINC8;
-
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
- op = StreamDPVmInstructions::ditINC8 ;
- }
-
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
- op = StreamDPVmInstructions::ditDEC8 ;
+ if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){
+ uint8_t op=StreamDPVmInstructions::ditINC8;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC8 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC8 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
+ op = StreamDPVmInstructions::ditRANDOM8 ;
+ }
+
+ StreamDPOpFlowVar8 fv8;
+ fv8.m_op = op;
+ fv8.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv8.m_min_val = (uint8_t)lpMan->m_min_value;
+ fv8.m_max_val = (uint8_t)lpMan->m_max_value;
+ m_instructions.add_command(&fv8,sizeof(fv8));
+ }else{
+ uint8_t op=StreamDPVmInstructions::ditINC8_STEP;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC8_STEP ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC8_STEP ;
+ }
+
+ StreamDPOpFlowVar8Step fv8;
+ fv8.m_op = op;
+ fv8.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv8.m_min_val = (uint8_t)lpMan->m_min_value;
+ fv8.m_max_val = (uint8_t)lpMan->m_max_value;
+ fv8.m_step = (uint8_t)lpMan->m_step;
+ m_instructions.add_command(&fv8,sizeof(fv8));
}
-
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
- op = StreamDPVmInstructions::ditRANDOM8 ;
- }
-
- StreamDPOpFlowVar8 fv8;
- fv8.m_op = op;
- fv8.m_flow_offset = get_var_offset(lpMan->m_var_name);
- fv8.m_min_val = (uint8_t)lpMan->m_min_value;
- fv8.m_max_val = (uint8_t)lpMan->m_max_value;
- m_instructions.add_command(&fv8,sizeof(fv8));
}
if (lpMan->m_size_bytes == 2 ){
uint8_t op;
+ if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){
+
op = StreamDPVmInstructions::ditINC16;
@@ -458,56 +479,119 @@ void StreamVm::build_program(){
fv16.m_min_val = (uint16_t)lpMan->m_min_value;
fv16.m_max_val = (uint16_t)lpMan->m_max_value;
m_instructions.add_command(&fv16,sizeof(fv16));
- }
+ }else{
- if (lpMan->m_size_bytes == 4 ){
- uint8_t op;
+ op = StreamDPVmInstructions::ditINC16_STEP;
- op = StreamDPVmInstructions::ditINC32;
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC16_STEP ;
+ }
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
- op = StreamDPVmInstructions::ditINC32 ;
- }
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC16_STEP ;
+ }
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
- op = StreamDPVmInstructions::ditDEC32 ;
- }
+ StreamDPOpFlowVar16Step fv16;
+ fv16.m_op = op;
+ fv16.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv16.m_min_val = (uint16_t)lpMan->m_min_value;
+ fv16.m_max_val = (uint16_t)lpMan->m_max_value;
+ fv16.m_step = (uint16_t)lpMan->m_step;
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
- op = StreamDPVmInstructions::ditRANDOM32 ;
- }
-
- StreamDPOpFlowVar32 fv32;
- fv32.m_op = op;
- fv32.m_flow_offset = get_var_offset(lpMan->m_var_name);
- fv32.m_min_val = (uint32_t)lpMan->m_min_value;
- fv32.m_max_val = (uint32_t)lpMan->m_max_value;
- m_instructions.add_command(&fv32,sizeof(fv32));
+ m_instructions.add_command(&fv16,sizeof(fv16));
+ }
}
- if (lpMan->m_size_bytes == 8 ){
+ if (lpMan->m_size_bytes == 4 ){
uint8_t op;
+ if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){
+ op = StreamDPVmInstructions::ditINC32;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC32 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC32 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
+ op = StreamDPVmInstructions::ditRANDOM32 ;
+ }
+
+ StreamDPOpFlowVar32 fv32;
+ fv32.m_op = op;
+ fv32.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv32.m_min_val = (uint32_t)lpMan->m_min_value;
+ fv32.m_max_val = (uint32_t)lpMan->m_max_value;
+ m_instructions.add_command(&fv32,sizeof(fv32));
+ }else{
+ op = StreamDPVmInstructions::ditINC32_STEP;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC32_STEP ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC32_STEP ;
+ }
+
+ StreamDPOpFlowVar32Step fv32;
+ fv32.m_op = op;
+ fv32.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv32.m_min_val = (uint32_t)lpMan->m_min_value;
+ fv32.m_max_val = (uint32_t)lpMan->m_max_value;
+ fv32.m_step = (uint32_t)lpMan->m_step;
+ m_instructions.add_command(&fv32,sizeof(fv32));
+ }
+ }
- op = StreamDPVmInstructions::ditINC64;
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
- op = StreamDPVmInstructions::ditINC64 ;
- }
+ if (lpMan->m_size_bytes == 8 ){
+ uint8_t op;
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
- op = StreamDPVmInstructions::ditDEC64 ;
- }
+ if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){
- if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
- op = StreamDPVmInstructions::ditRANDOM64 ;
+ op = StreamDPVmInstructions::ditINC64;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC64 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC64 ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){
+ op = StreamDPVmInstructions::ditRANDOM64 ;
+ }
+
+ StreamDPOpFlowVar64 fv64;
+ fv64.m_op = op;
+ fv64.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv64.m_min_val = (uint64_t)lpMan->m_min_value;
+ fv64.m_max_val = (uint64_t)lpMan->m_max_value;
+ m_instructions.add_command(&fv64,sizeof(fv64));
+ }else{
+
+ op = StreamDPVmInstructions::ditINC64_STEP;
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){
+ op = StreamDPVmInstructions::ditINC64_STEP ;
+ }
+
+ if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){
+ op = StreamDPVmInstructions::ditDEC64_STEP ;
+ }
+
+ StreamDPOpFlowVar64Step fv64;
+ fv64.m_op = op;
+ fv64.m_flow_offset = get_var_offset(lpMan->m_var_name);
+ fv64.m_min_val = (uint64_t)lpMan->m_min_value;
+ fv64.m_max_val = (uint64_t)lpMan->m_max_value;
+ fv64.m_step = (uint64_t)lpMan->m_step;
+ m_instructions.add_command(&fv64,sizeof(fv64));
}
-
- StreamDPOpFlowVar64 fv64;
- fv64.m_op = op;
- fv64.m_flow_offset = get_var_offset(lpMan->m_var_name);
- fv64.m_min_val = (uint64_t)lpMan->m_min_value;
- fv64.m_max_val = (uint64_t)lpMan->m_max_value;
- m_instructions.add_command(&fv64,sizeof(fv64));
}
}
@@ -890,6 +974,12 @@ void StreamDPVmInstructions::Dump(FILE *fd){
StreamDPOpFlowVar16 *lpv16;
StreamDPOpFlowVar32 *lpv32;
StreamDPOpFlowVar64 *lpv64;
+
+ StreamDPOpFlowVar8Step *lpv8s;
+ StreamDPOpFlowVar16Step *lpv16s;
+ StreamDPOpFlowVar32Step *lpv32s;
+ StreamDPOpFlowVar64Step *lpv64s;
+
StreamDPOpIpv4Fix *lpIpv4Fix;
StreamDPOpPktWr8 *lpw8;
StreamDPOpPktWr16 *lpw16;
@@ -1016,6 +1106,47 @@ void StreamDPVmInstructions::Dump(FILE *fd){
p+=sizeof(StreamDPOpPktSizeChange);
break;
+ case ditINC8_STEP :
+ lpv8s =(StreamDPOpFlowVar8Step *)p;
+ lpv8s->dump(fd,"INC8_STEP");
+ p+=sizeof(StreamDPOpFlowVar8Step);
+ break;
+ case ditINC16_STEP :
+ lpv16s =(StreamDPOpFlowVar16Step *)p;
+ lpv16s->dump(fd,"INC16_STEP");
+ p+=sizeof(StreamDPOpFlowVar16Step);
+ break;
+ case ditINC32_STEP :
+ lpv32s =(StreamDPOpFlowVar32Step *)p;
+ lpv32s->dump(fd,"INC32_STEP");
+ p+=sizeof(StreamDPOpFlowVar32Step);
+ break;
+ case ditINC64_STEP :
+ lpv64s =(StreamDPOpFlowVar64Step *)p;
+ lpv64s->dump(fd,"INC64_STEP");
+ p+=sizeof(StreamDPOpFlowVar64Step);
+ break;
+
+ case ditDEC8_STEP :
+ lpv8s =(StreamDPOpFlowVar8Step *)p;
+ lpv8s->dump(fd,"DEC8_DEC");
+ p+=sizeof(StreamDPOpFlowVar8Step);
+ break;
+ case ditDEC16_STEP :
+ lpv16s =(StreamDPOpFlowVar16Step *)p;
+ lpv16s->dump(fd,"DEC16_STEP");
+ p+=sizeof(StreamDPOpFlowVar16Step);
+ break;
+ case ditDEC32_STEP :
+ lpv32s =(StreamDPOpFlowVar32Step *)p;
+ lpv32s->dump(fd,"DEC32_STEP");
+ p+=sizeof(StreamDPOpFlowVar32Step);
+ break;
+ case ditDEC64_STEP :
+ lpv64s =(StreamDPOpFlowVar64Step *)p;
+ lpv64s->dump(fd,"DEC64_STEP");
+ p+=sizeof(StreamDPOpFlowVar64Step);
+ break;
default:
assert(0);
@@ -1024,6 +1155,23 @@ void StreamDPVmInstructions::Dump(FILE *fd){
}
+void StreamDPOpFlowVar8Step::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s op:%lu, of:%lu, (%lu-%lu-%lu) \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val,(ulong)m_step);
+}
+
+void StreamDPOpFlowVar16Step::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s op:%lu, of:%lu, (%lu-%lu-%lu) \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val,(ulong)m_step);
+}
+
+void StreamDPOpFlowVar32Step::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s op:%lu, of:%lu, (%lu-%lu-%lu) \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val,(ulong)m_step);
+}
+
+void StreamDPOpFlowVar64Step::dump(FILE *fd,std::string opt){
+ fprintf(fd," %10s op:%lu, of:%lu, (%lu-%lu-%lu) \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val,(ulong)m_step);
+}
+
+
void StreamDPOpFlowVar8::dump(FILE *fd,std::string opt){
fprintf(fd," %10s op:%lu, of:%lu, (%lu- %lu) \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset,(ulong)m_min_val,(ulong)m_max_val);
}
@@ -1074,3 +1222,60 @@ void StreamDPOpPktSizeChange::dump(FILE *fd,std::string opt){
fprintf(fd," %10s op:%lu, flow_offset: %lu \n", opt.c_str(),(ulong)m_op,(ulong)m_flow_offset);
}
+
+
+void StreamDPVmInstructionsRunner::slow_commands(uint8_t op_code,
+ uint8_t * flow_var, /* flow var */
+ uint8_t * pkt,
+ uint8_t * & p){
+ ua_t ua;
+
+ switch (op_code) {
+
+ case StreamDPVmInstructions::ditINC8_STEP :
+ ua.lpv8s =(StreamDPOpFlowVar8Step *)p;
+ ua.lpv8s->run_inc(flow_var);
+ p+=sizeof(StreamDPOpFlowVar8Step);
+ break;
+
+ case StreamDPVmInstructions::ditINC16_STEP :
+ ua.lpv16s =(StreamDPOpFlowVar16Step *)p;
+ ua.lpv16s->run_inc(flow_var);
+ p+=sizeof(StreamDPOpFlowVar16Step);
+ break;
+ case StreamDPVmInstructions::ditINC32_STEP :
+ ua.lpv32s =(StreamDPOpFlowVar32Step *)p;
+ ua.lpv32s->run_inc(flow_var);
+ p+=sizeof(StreamDPOpFlowVar32Step);
+ break;
+ case StreamDPVmInstructions::ditINC64_STEP :
+ ua.lpv64s =(StreamDPOpFlowVar64Step *)p;
+ ua.lpv64s->run_inc(flow_var);
+ p+=sizeof(StreamDPOpFlowVar64Step);
+ break;
+
+ case StreamDPVmInstructions::ditDEC8_STEP :
+ ua.lpv8s =(StreamDPOpFlowVar8Step *)p;
+ ua.lpv8s->run_dec(flow_var);
+ p+=sizeof(StreamDPOpFlowVar8Step);
+ break;
+ case StreamDPVmInstructions::ditDEC16_STEP :
+ ua.lpv16s =(StreamDPOpFlowVar16Step *)p;
+ ua.lpv16s->run_dec(flow_var);
+ p+=sizeof(StreamDPOpFlowVar16Step);
+ break;
+ case StreamDPVmInstructions::ditDEC32_STEP :
+ ua.lpv32s =(StreamDPOpFlowVar32Step *)p;
+ ua.lpv32s->run_dec(flow_var);
+ p+=sizeof(StreamDPOpFlowVar32Step);
+ break;
+ case StreamDPVmInstructions::ditDEC64_STEP :
+ ua.lpv64s =(StreamDPOpFlowVar64Step *)p;
+ ua.lpv64s->run_dec(flow_var);
+ p+=sizeof(StreamDPOpFlowVar64Step);
+ break;
+ default:
+ assert(0);
+ }
+}
+
diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index dabc502c..fd685b24 100644
--- a/src/stateless/cp/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
@@ -215,6 +215,128 @@ public:
} __attribute__((packed)) ;
+
+struct StreamDPOpFlowVar8Step {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint8_t m_min_val;
+ uint8_t m_max_val;
+ uint8_t m_step;
+public:
+ void dump(FILE *fd,std::string opt);
+
+ inline void run_inc(uint8_t * flow_var) {
+ uint8_t *p = (flow_var + m_flow_offset);
+ if (*p >= (m_max_val-m_step)) {
+ *p = m_min_val;
+ } else {
+ *p = *p + m_step;
+ }
+ }
+
+ inline void run_dec(uint8_t * flow_var) {
+ uint8_t *p = (flow_var + m_flow_offset);
+ if (*p <= (m_min_val+m_step)) {
+ *p = m_max_val;
+ } else {
+ *p = *p - m_step;
+ }
+ }
+
+} __attribute__((packed)) ;
+
+struct StreamDPOpFlowVar16Step {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint16_t m_min_val;
+ uint16_t m_max_val;
+ uint16_t m_step;
+
+public:
+ void dump(FILE *fd,std::string opt);
+
+ inline void run_inc(uint8_t * flow_var) {
+ uint16_t *p = (uint16_t *)(flow_var + m_flow_offset);
+ if (*p >= (m_max_val-m_step)) {
+ *p = m_min_val;
+ } else {
+ *p = *p + m_step;
+ }
+ }
+
+ inline void run_dec(uint8_t * flow_var) {
+ uint16_t *p = (uint16_t *)(flow_var + m_flow_offset);
+ if (*p <= (m_min_val+m_step)) {
+ *p = m_max_val;
+ } else {
+ *p = *p - m_step;
+ }
+ }
+
+} __attribute__((packed)) ;
+
+struct StreamDPOpFlowVar32Step {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint32_t m_min_val;
+ uint32_t m_max_val;
+ uint32_t m_step;
+public:
+ void dump(FILE *fd,std::string opt);
+
+ inline void run_inc(uint8_t * flow_var) {
+ uint32_t *p = (uint32_t *)(flow_var + m_flow_offset);
+ if (*p >= (m_max_val-m_step)) {
+ *p = m_min_val;
+ } else {
+ *p = *p + m_step;
+ }
+ }
+
+ inline void run_dec(uint8_t * flow_var) {
+ uint32_t *p = (uint32_t *)(flow_var + m_flow_offset);
+ if (*p <= (m_min_val+m_step)) {
+ *p = m_max_val;
+ } else {
+ *p = *p - m_step;
+ }
+ }
+
+} __attribute__((packed)) ;
+
+struct StreamDPOpFlowVar64Step {
+ uint8_t m_op;
+ uint8_t m_flow_offset;
+ uint64_t m_min_val;
+ uint64_t m_max_val;
+ uint64_t m_step;
+public:
+ void dump(FILE *fd,std::string opt);
+
+ inline void run_inc(uint8_t * flow_var) {
+ uint64_t *p = (uint64_t *)(flow_var + m_flow_offset);
+ if (*p >= (m_max_val-m_step) ) {
+ *p = m_min_val;
+ } else {
+ *p = *p + m_step;
+ }
+ }
+
+ inline void run_dec(uint8_t * flow_var) {
+ uint64_t *p = (uint64_t *)(flow_var + m_flow_offset);
+ if (*p <= m_min_val+m_step) {
+ *p = m_max_val;
+ } else {
+ *p = *p - m_step;
+ }
+ }
+
+
+} __attribute__((packed)) ;
+
+///////////////////////////////////////////////////////////////////////
+
+
struct StreamDPOpPktWrBase {
enum {
PKT_WR_IS_BIG = 1
@@ -440,6 +562,18 @@ public:
itCLIENT_VAR_UNLIMIT ,
itPKT_SIZE_CHANGE ,
+ /* inc/dec with step*/
+ ditINC8_STEP ,
+ ditINC16_STEP ,
+ ditINC32_STEP ,
+ ditINC64_STEP ,
+
+ ditDEC8_STEP ,
+ ditDEC16_STEP ,
+ ditDEC32_STEP ,
+ ditDEC64_STEP ,
+
+
};
@@ -462,7 +596,14 @@ class StreamDPVmInstructionsRunner {
public:
StreamDPVmInstructionsRunner(){
m_new_pkt_size=0;;
+
}
+
+ void slow_commands(uint8_t op_code,
+ uint8_t * flow_var, /* flow var */
+ uint8_t * pkt,
+ uint8_t * & p);
+
inline void run(uint32_t * per_thread_random,
uint32_t program_size,
uint8_t * program, /* program */
@@ -477,19 +618,7 @@ private:
};
-inline void StreamDPVmInstructionsRunner::run(uint32_t * per_thread_random,
- uint32_t program_size,
- uint8_t * program, /* program */
- uint8_t * flow_var, /* flow var */
- uint8_t * pkt
- ){
-
-
- uint8_t * p=program;
- uint8_t * p_end=p+program_size;
-
-
- union ua_ {
+typedef union ua_ {
StreamDPOpFlowVar8 *lpv8;
StreamDPOpFlowVar16 *lpv16;
StreamDPOpFlowVar32 *lpv32;
@@ -503,7 +632,26 @@ inline void StreamDPVmInstructionsRunner::run(uint32_t * per_thread_random,
StreamDPOpClientsLimit *lpcl;
StreamDPOpClientsUnLimit *lpclu;
- } ua ;
+
+ StreamDPOpFlowVar8Step *lpv8s;
+ StreamDPOpFlowVar16Step *lpv16s;
+ StreamDPOpFlowVar32Step *lpv32s;
+ StreamDPOpFlowVar64Step *lpv64s;
+} ua_t ;
+
+
+
+inline void StreamDPVmInstructionsRunner::run(uint32_t * per_thread_random,
+ uint32_t program_size,
+ uint8_t * program, /* program */
+ uint8_t * flow_var, /* flow var */
+ uint8_t * pkt
+ ){
+
+ uint8_t * p=program;
+ uint8_t * p_end=p+program_size;
+
+ ua_t ua;
while ( p < p_end) {
uint8_t op_code=*p;
@@ -620,9 +768,10 @@ inline void StreamDPVmInstructionsRunner::run(uint32_t * per_thread_random,
ua.lpw_pkt_size->run(flow_var,m_new_pkt_size);
p+=sizeof(StreamDPOpPktSizeChange);
break;
-
+
default:
- assert(0);
+ slow_commands(op_code,flow_var,pkt,p);
+ break;
}
};
};
@@ -736,6 +885,11 @@ public:
return ( StreamVmInstruction::itFLOW_MAN);
}
+ virtual bool is_valid_for_split() const {
+ return (m_step==1?true:false);
+ }
+
+
virtual uint64_t get_splitable_range() const {
return (m_max_value - m_min_value + 1);
}
@@ -777,13 +931,16 @@ public:
flow_var_op_e op,
uint64_t init_value,
uint64_t min_value,
- uint64_t max_value) : StreamVmInstructionVar(var_name) {
+ uint64_t max_value,
+ uint64_t step=1) : 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;
+ m_step = step;
+
}
virtual void Dump(FILE *fd);
@@ -796,7 +953,8 @@ public:
m_op,
m_init_value,
m_min_value,
- m_max_value);
+ m_max_value,
+ m_step);
}
private:
@@ -817,6 +975,7 @@ public:
uint64_t m_min_value;
uint64_t m_max_value;
+ uint64_t m_step;
};
diff --git a/src/stateless/cp/trex_vm_splitter.cpp b/src/stateless/cp/trex_vm_splitter.cpp
index 9465718f..5e6d4fbd 100644
--- a/src/stateless/cp/trex_vm_splitter.cpp
+++ b/src/stateless/cp/trex_vm_splitter.cpp
@@ -101,6 +101,11 @@ TrexVmSplitter::split_by_flow_var(const StreamVmInstructionFlowMan *instr) {
return false;
}
+ /* split only step of 1 */
+ if (!instr->is_valid_for_split() ){
+ return false;
+ }
+
/* we need to split - duplicate VM now */
duplicate_vm();