step instruction support
authorHanoh Haim <[email protected]>
Tue, 16 Feb 2016 14:08:23 +0000 (16:08 +0200)
committerHanoh Haim <[email protected]>
Tue, 16 Feb 2016 14:08:23 +0000 (16:08 +0200)
scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
scripts/exp/udp_1pkt_mac_step.pcap [new file with mode: 0644]
scripts/stl/udp_1pkt_mac_step.py [new file with mode: 0644]
scripts/stl/yaml/burst_1pkt_vm.yaml
scripts/stl/yaml/imix_1pkt_vm.yaml
scripts/stl/yaml/imix_3pkt_vm.yaml
src/rpc-server/commands/trex_rpc_cmd_stream.cpp
src/stateless/cp/trex_stream_vm.cpp
src/stateless/cp/trex_stream_vm.h
src/stateless/cp/trex_vm_splitter.cpp

index f4b67f0..1f07b6e 100644 (file)
@@ -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:
index 88efe26..c788e27 100644 (file)
@@ -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 (file)
index 0000000..0377567
Binary files /dev/null and b/scripts/exp/udp_1pkt_mac_step.pcap differ
diff --git a/scripts/stl/udp_1pkt_mac_step.py b/scripts/stl/udp_1pkt_mac_step.py
new file mode 100644 (file)
index 0000000..077a162
--- /dev/null
@@ -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()
+
+
+
index 246b881..fed3948 100644 (file)
@@ -19,6 +19,7 @@
                   "name" : "l3_src",
                   "op" : "inc",
                   "size" : 2,
+                  "step" : 1,
                   "type" : "flow_var"
                },
                {
index 05443a6..698d3e6 100644 (file)
@@ -19,6 +19,7 @@
                   "name" : "l3_src",
                   "op" : "inc",
                   "size" : 4,
+                  "step" : 1,
                   "type" : "flow_var"
                },
                {
index 6ba2c40..3e7cd0e 100644 (file)
@@ -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"
                },
                {
index 0262fd7..508967b 100644 (file)
@@ -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 
index b91f0fb..f99c3c9 100644 (file)
@@ -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);
+    }
+}
+
index dabc502..fd685b2 100644 (file)
@@ -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;
 };
 
 
index 9465718..5e6d4fb 100644 (file)
@@ -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();