more stateless doc
authorHanoh Haim <[email protected]>
Wed, 2 Mar 2016 06:12:45 +0000 (08:12 +0200)
committerHanoh Haim <[email protected]>
Wed, 2 Mar 2016 06:12:45 +0000 (08:12 +0200)
draft_trex_stateless.asciidoc
images/Thumbs.db
images/stl_tut_pcap_file1.png [new file with mode: 0644]

index a9195d4..7a202c3 100644 (file)
@@ -7,7 +7,7 @@ TRex
 :numbered:
 :web_server_url: http://trex-tgn.cisco.com/trex
 :local_web_server_url: csi-wiki-01:8181/trex
-:toclevels: 4
+:toclevels: 6
 
 
 == Stateless support  
@@ -19,7 +19,7 @@ TRex
 * Interface can configured with multi traffic profiles 
 * Profile can support multi streams. Scale to 10K streams in parallel 
 * Each Stream
-** Packet template - ability to build any packet using Scapy (e.g. MPLS/Ipv4/Ipv6/GRE/VXLAN/NSH)
+** Packet template - ability to build any packet using Scapy (e.g. MPLS/IPv4/Ipv6/GRE/VXLAN/NSH)
 ** Field engine program
 *** Ability to change any field inside the packet, for example src_ip = 10.0.0.1-10.0.0.255
 *** Ability to change the packet size (e.g. Random packet size 64-9K)
@@ -97,7 +97,7 @@ image::images/stateless_objects.png[title="TRex Objects ",align="left",width=600
 
 This tutorial will walk you through basic but complete TRex Stateless use cases that will show you common concepts as well as slightly more advanced ones.
                 
-==== Tutorial 1: Simple Ipv4/UDP packet - Simulator 
+==== Tutorial 1: Simple IPv4/UDP packet - Simulator 
 
 The following example demonstrates the most basic use case using our simulator.  
 
@@ -305,7 +305,7 @@ $./stl-sim -f stl/udp_1pkt_simple.py --pkt
 0030   78 78 78 78                                        xxxx
 ----
 
-==== Tutorial 2: Simple Ipv4/UDP packet - TRex 
+==== Tutorial 2: Simple IPv4/UDP packet - TRex 
 
 =====  Run TRex as a server mode 
 
@@ -446,7 +446,7 @@ Port Statistics
 ----
 
 
-==== Tutorial 3: Simple Ipv4/UDP packet 
+==== Tutorial 3: Simple IPv4/UDP packet 
 
 The following example demonstrates 
 
@@ -666,14 +666,14 @@ file: `stl/imix.py`
 
 The following example demonstrates changing packet fields. 
 The Field Engine (FE) has limited number of instructions/operation for supporting most use cases. There is a plan to add LuaJIT to get 100% flexiable in the cost of performance.
-The FE can allocate variable in Stream context. Write a variable to a packet offset, change packet size etc.
+The FE can allocate stream variable in Stream context. Write a stream variable to a packet offset, change packet size etc.
 
 *Some examples for what can be done:*
 
 * Change ipv4.tos 1-10
 * Change packet size to be random in range 64-9K
 * Create range of flows (change src_ip,dest_ip,src_port,dest_port) 
-* Update Ipv4 checksum 
+* Update IPv4 checksum 
 
 for more info see link:trex_rpc_server_spec.html#_object_type_em_vm_em_a_id_vm_obj_a[here]
 
@@ -718,10 +718,10 @@ file: `stl/syn_attack.py`
                          mode = STLTXCont())
 ----
 <1> Create SYN packet using Scapy 
-<2> Define variable name=ip_src, 4 bytes size for IPv4. 
-<3> Define variable name=src_port, 2 bytes size for port. 
+<2> Define stream variable name=ip_src, 4 bytes size for IPv4. 
+<3> Define stream variable name=src_port, 2 bytes size for port. 
 <4> Write ip_src var into `IP.src` packet offset. Scapy calculate the offset. We could gave `IP:1.src" for second IP header in the packet
-<5> Fix Ipv4 checksum. here we provide the header name `IP` we could gave `IP:1` for second IP
+<5> Fix IPv4 checksum. here we provide the header name `IP` we could gave `IP:1` for second IP
 <6> Update TCP src port- TCP checksum is not updated here
 
 WARNING: Original Scapy does not have the capability to calculate offset for a header/field by name. This offset capability won't work for all the cases because there could be complex cases that Scapy rebuild the header. In such cases put offset as a number
@@ -729,22 +729,22 @@ WARNING: Original Scapy does not have the capability to calculate offset for a h
 The output pcap file field can be seen here 
 
 .Pcap file output 
-[format="csv",cols="1^,2^,1^", options="header"]
+[format="csv",cols="1^,2^,2^", options="header",width="40%"]
 |=================
 pkt,Client IPv4,Client Port
- 1  , 17.152.71.218 , 5814
- 2  , 17.7.6.30 , 26810
- 3  , 17.3.32.200 , 1810 
+ 1  , 17.152.71.218  , 5814
+ 2  , 17.7.6.30      , 26810
+ 3  , 17.3.32.200    , 1810 
  4  , 17.135.236.168 , 55810 
- 5  , 17.46.240.12 , 1078  
- 6  , 16.133.91.247, 2323
+ 5  , 17.46.240.12   , 1078  
+ 6  , 16.133.91.247  , 2323
 |=================
 
 
 ==== Tutorial 8: Field Engine, Tuple Generator 
 
 The following example demonstrates creating multiply flow from the same packet template.
-The TupleGenerator instructions are used to create two variables with IP, port
+The TupleGenerator instructions are used to create two stream variables with IP, port
 
 file: `stl/udp_1pkt_tuple_gen.py`
 
@@ -770,12 +770,12 @@ file: `stl/udp_1pkt_tuple_gen.py`
                             vm = vm)
 ----
 <1> Define struct with two dependent varibles tuple.ip tuple.port 
-<2> Write tuple.ip to Ipv4 src field offset
+<2> Write tuple.ip to IPv4 src field offset
 <3> Write tuple.port to UDP header. You should set UDP.checksum to zero  
 
 
 .Pcap file output 
-[format="csv",cols="1^,2^,1^", options="header"]
+[format="csv",cols="1^,2^,1^", options="header",width="40%"]
 |=================
 pkt,Client IPv4,Client Port
  1  , 16.0.0.1 , 1025
@@ -788,11 +788,11 @@ pkt,Client IPv4,Client Port
 
 * Number of clients are two 16.0.0.1 and 16.0.0.2
 * Number of flows is limited to 129020 (2*65535-1025)
-* The variable size should match the size of the FlowVarWr instruction
+* The stream variable size should match the size of the FlowVarWr instruction
 
 ==== Tutorial 9: Field Engine, write to a bit-field packet  
 
-The following example demonstrates a way to write a variable to a bit field packet variables.
+The following example demonstrates a way to write a stream variable to a bit field packet variables.
 In this example MPLS label field will be changed.
 
 .MPLS header 
@@ -832,7 +832,7 @@ file: `stl/udp_1pkt_mpls_vm.py`
 
 ----
 <1> Define varible size of 2 bytes
-<2> Write the variable label with a shift of 12 bits and with 20bit MSB mask. Cast the variables of 2 bytes to 4 bytes
+<2> Write the stream variable label with a shift of 12 bits and with 20bit MSB mask. Cast the stream variables of 2 bytes to 4 bytes
 <3> Second MPLS header should be changed 
 
 
@@ -882,7 +882,7 @@ file: `stl/udp_rand_len_9k.py`
                           ]
                        )
 ----
-<1> Define a random variable with maximum size of the packet
+<1> Define a random stream variable with maximum size of the packet
 <2> Trim the packet size to the fv_rand value 
 <3> fix ip.len 
 <4> fix udp.len 
@@ -969,15 +969,17 @@ To send gratuitous ARP from TRex server side for this server (58.0.0.1)
 
 [source,python]
 ----
-
     def create_stream (self):
         # create a base packet and pad it to size
-        base_pkt =  Ether(src="00:00:dd:dd:00:01",dst="ff:ff:ff:ff:ff:ff")/ARP(psrc="58.0.0.1",hwsrc="00:00:dd:dd:00:01", hwdst="00:00:dd:dd:00:01", pdst="58.0.0.1")
-
+        base_pkt =  Ether(src="00:00:dd:dd:00:01",
+                          dst="ff:ff:ff:ff:ff:ff")/
+                    ARP(psrc="58.0.0.1",
+                        hwsrc="00:00:dd:dd:00:01", 
+                        hwdst="00:00:dd:dd:00:01", 
+                        pdst="58.0.0.1")
 ----
 
-Then we can send the clients traffic from A->C 
-
+Then traffic can be sent from client side  A->C 
 
 file: `stl/udp_1pkt_range_clients_split.py`
 
@@ -1014,8 +1016,455 @@ class STLS1(object):
         return STLStream(packet = STLPktBuilder(pkt = base_pkt/pad,vm = vm),
                          mode = STLTXCont( pps=10 ))
 ----
-<1> Write the variable mac_src with offset of 10 (last 2 bytes of src_mac field)
-<2> Write the variable mac_src with `offset_fixup` of 2. beacuse we write it with offset
+<1> Write the stream variable mac_src with offset of 10 (last 2 bytes of src_mac field)
+<2> Write the stream variable mac_src with `offset_fixup` of 2. beacuse we write it with offset
+
+
+==== Tutorial 12: Field Engine, Split to core 
+
+The following example demonstrates a way to split generated traffic to a number of threads.
+Using this feature, there is a way to specify by each field to split the traffic to threads.
+Without this feature the traffic is duplicated and all the threads transmits the same traffic.
+
+===== Without Split 
+
+Let's assume we have two transmitters DP threads
+
+[source,python]
+----
+    def create_stream (self):
+
+        # TCP SYN
+        base_pkt  = Ether()/IP(dst="48.0.0.1")/TCP(dport=80,flags="S")     
+
+
+        # vm
+        vm = CTRexScRaw( [ STLVmFlowVar(name="ip_src", 
+                                              min_value="16.0.0.0", 
+                                              max_value="16.0.0.254", 
+                                              size=4, op="inc"),                     <1>
+
+
+                           STLVmWrFlowVar(fv_name="ip_src", pkt_offset= "IP.src" ),  <2>
+
+                           STLVmFixIpv4(offset = "IP"), # fix checksum              
+                          ]
+
+                       )
+
+----
+<1> Stream variable 
+<2> write it to IPv4.src
+
+
+.Variable per thread 
+[format="csv",cols="1^,3^,3^", options="header",width="40%"]
+|=================
+pkt, thread-0 ip_src,thread-1 ip_src
+ 1  , 16.0.0.1 , 16.0.0.1
+ 2  , 16.0.0.2 , 16.0.0.2
+ 3  , 16.0.0.3 , 16.0.0.3
+ 4  , 16.0.0.4 , 16.0.0.4
+ 5  , 16.0.0.5 , 16.0.0.5
+ 6  , 16.0.0.6,  16.0.0.6
+|=================
+
+* In this case all the threads transmit the same packets
+
+
+===== With  Split feature  
+
+Let's assume we have two transmitters DP threads
+
+[source,python]
+----
+    def create_stream (self):
+
+        # TCP SYN
+        base_pkt  = Ether()/IP(dst="48.0.0.1")/TCP(dport=80,flags="S")     
+
+
+        # vm
+        vm = CTRexScRaw( [ STLVmFlowVar(name="ip_src", 
+                                              min_value="16.0.0.0", 
+                                              max_value="16.0.0.254", 
+                                              size=4, op="inc"),                     
+
+
+                           STLVmWrFlowVar(fv_name="ip_src", pkt_offset= "IP.src" ),  
+
+                           STLVmFixIpv4(offset = "IP"), # fix checksum              
+                          ]
+                         ,split_by_field = "ip_src"                                 <1>  
+                       )
+
+----
+<1> The same example but now we with split by `ip_src` stream variable
+
+.Variable per thread 
+[format="csv",cols="1^,3^,3^", options="header",width="40%"]
+|=================
+pkt, thread-0 ip_src ,thread-1 ip_src
+ 1  , 16.0.0.1 , 16.0.0.128
+ 2  , 16.0.0.2 , 16.0.0.129
+ 3  , 16.0.0.3 , 16.0.0.130
+ 4  , 16.0.0.4 , 16.0.0.131
+ 5  , 16.0.0.5 , 16.0.0.132
+ 6  , 16.0.0.6,  16.0.0.133
+|=================
+
+* In this case the stream variable is split 
+
+To simulate it you can run the following command, let's take the file `stl/udp_1pkt_range_clients_split.py` and simulate it
+
+[source,bash]
+----
+$./stl-sim -f stl/udp_1pkt_range_clients_split.py -o a.pcap -c 2 -l 10   #<1> 
+----
+<1> simulate 2 threads -c 2
+
+
+.Variable per thread 
+[format="csv",cols="1^,3^,3^", options="header",width="40%"]
+|=================
+pkt, thread-0 ip_src,thread-1 ip_src
+ 1  , 55.55.0.1 , 55.55.58.153
+ 2  , 55.55.0.2 , 55.55.58.154
+ 3  , 55.55.0.3 , 55.55.58.155
+ 4  , 55.55.0.4 , 55.55.58.156
+ 5  , 55.55.0.5 , 55.55.58.157
+ 6  , 55.55.0.6 , 55.55.58.158
+|=================
+
+
+
+===== Some rules about Split stream varibles and burst/multi-burst 
+
+* In case of burst/multi-burst the number of packets are split to number of threads in *default* there is no need an explict split 
+* When the number of packets in a burst is smaller than the number of threads only one thread will do the work.
+* In case there is stream with burst of *1* packet, only the first DP thread will do the work. 
+
+
+==== Tutorial 13: Pcap file to *one* stream 
+
+There is a way to load *one* packet data into a stream. There is an assumption  that this pcap. only the first packet from this pcap is taken.
+
+file: `stl/udp_1pkt_pcap.py`
+
+[source,python]
+----
+
+    def get_streams (self, direction = 0):
+        return [STLStream(packet = 
+                          STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"), # path relative to pwd   <1>
+                           mode = STLTXCont(pps=10)) ] 
+
+----
+<1> packet is taken from pcap file relative to pwd of the script you run
+
+
+file: `stl/udp_1pkt_pcap_relative_path.py`
+
+
+[source,python]
+----
+
+    def get_streams (self, direction = 0):
+        return [STLStream(packet = STLPktBuilder(pkt ="yaml/udp_64B_no_crc.pcap",
+                                                 path_relative_to_profile = True), <1>
+                         mode = STLTXCont(pps=10)) ] 
+
+----
+<1> packet is taken from pcap file relative to *profile* file location
+
+==== Tutorial 14: Pcap file to many streams 
+
+The following example demonstrates a way to load pcap with *number* of packets and for each packet create a stream with burst of 1. 
+
+file: `stl/pcap.py`
+
+[source,python]
+----
+    def get_streams (self,
+                     ipg_usec = 10.0,                           <1>
+                     loop_count = 1):                           <2>
+
+        profile = STLProfile.load_pcap(self.pcap_file,          <3>
+                                       ipg_usec = ipg_usec, 
+                                       loop_count = loop_count)
+----
+<1> The inter stream gap in usec
+<2> How many times to loop
+<3> the pcap file 
+
+
+image::images/stl_tut_pcap_file1.png[title="pcap file",align="left",width=300, link="images/stl_tut_pcap_file1.png"]
+
+This figure illustrates how the streams look like for pcap file with 3 packet.
+* Each stream is configured to burst with one packet 
+* Each stream point to the next stream. 
+* The last stream point to the first with action_loop=loop_count in case it was asked (>1)
+The profile will run on only one DP thread because it has burst with one packet (see Split example)
+
+Running this example
+
+[source,bash]
+----
+./stl-sim -f stl/pcap.py --yaml
+----
+
+will give this
+
+[source,python]
+----
+csi-kiwi-02]> ./stl-sim -f stl/pcap.py --yaml
+- name: 1
+  next: 2                      <1> 
+  stream:
+    action_count: 0
+    enabled: true
+    flags: 0
+    isg: 10.0
+    mode:
+      percentage: 100
+      total_pkts: 1
+      type: single_burst
+    packet:
+      meta: ''
+    rx_stats:
+      enabled: false
+    self_start: true
+    vm:
+      instructions: []
+      split_by_var: ''
+- name: 2
+  next: 3
+  stream:
+    action_count: 0
+    enabled: true
+    flags: 0
+    isg: 10.0
+    mode:
+      percentage: 100
+      total_pkts: 1
+      type: single_burst
+    packet:
+      meta: ''
+    rx_stats:
+      enabled: false
+    self_start: false
+    vm:
+      instructions: []
+      split_by_var: ''
+- name: 3
+  next: 4
+  stream:
+    action_count: 0
+    enabled: true
+    flags: 0
+    isg: 10.0
+    mode:
+      percentage: 100
+      total_pkts: 1
+      type: single_burst
+    packet:
+      meta: ''
+    rx_stats:
+      enabled: false
+    self_start: false
+    vm:
+      instructions: []
+      split_by_var: ''
+- name: 4
+  next: 5
+  stream:
+    action_count: 0
+    enabled: true
+    flags: 0
+    isg: 10.0
+    mode:
+      percentage: 100
+      total_pkts: 1
+      type: single_burst
+    packet:
+      meta: ''
+    rx_stats:
+      enabled: false
+    self_start: false
+    vm:
+      instructions: []
+      split_by_var: ''
+- name: 5
+  next: 1                   <2>
+  stream:
+    action_count: 1         <3>
+    enabled: true
+    flags: 0
+    isg: 10.0
+    mode:
+      percentage: 100
+      total_pkts: 1
+      type: single_burst
+    packet:
+      meta: ''
+    rx_stats:
+      enabled: false
+    self_start: false       <4>    
+    vm:
+      instructions: []
+      split_by_var: ''
+----
+<1> each stream point to the next stream
+<2> last point to the first 
+<3> the number of loop is given in `action_count: 1`
+<4> self_start is disabled for all the streams except the first one
+
+
+==== Tutorial 15: Pcap file to many streams and Field Engine 
+
+The following example demonstrates a way to load pcap file to many stream and attach to each stream a Field Engine program.
+For example change the IP.src of all the streams to a random number
+file: `stl/pcap_with_vm.py`
+
+[source,python]
+----
+
+    def create_vm (self, ip_src_range, ip_dst_range):
+        if not ip_src_range and not ip_dst_range:
+            return None
+
+        # until the feature of offsets will be fixed for PCAP use hard coded offsets
+
+        vm = []
+
+        if ip_src_range:
+            vm += [STLVmFlowVar(name="src", 
+                                min_value = ip_src_range['start'], 
+                                max_value = ip_src_range['end'], 
+                                size = 4, op = "inc"),
+                   #STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src")
+                   STLVmWrFlowVar(fv_name="src",pkt_offset = 26)
+                  ]
+
+        if ip_dst_range:
+            vm += [STLVmFlowVar(name="dst", 
+                                min_value = ip_dst_range['start'], 
+                                max_value = ip_dst_range['end'], 
+                                size = 4, op = "inc"),
+                   
+                   #STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst")
+                   STLVmWrFlowVar(fv_name="dst",pkt_offset = 30)
+                   ]
+
+        vm += [#STLVmFixIpv4(offset = "IP")
+              STLVmFixIpv4(offset = 14)
+              ]
+
+        return vm
+
+
+    def get_streams (self,
+                     ipg_usec = 10.0,
+                     loop_count = 5,
+                     ip_src_range = None,
+                     ip_dst_range = {'start' : '10.0.0.1', 
+                                        'end': '10.0.0.254'}):
+
+        vm = self.create_vm(ip_src_range, ip_dst_range)                 <1> 
+        profile = STLProfile.load_pcap(self.pcap_file, 
+                                      ipg_usec = ipg_usec, 
+                                      loop_count = loop_count, 
+                                      vm = vm)                          <2> 
+
+        return profile.get_streams()
+----
+<1> Create Field Engine program, 
+<2> Apply to all the packets -> convert to streams 
+
+.Output 
+[format="csv",cols="1^,2^,1^", options="header",width="40%"]
+|=================
+pkt, IPv4 , flow 
+ 1  , 10.0.0.1, 1 
+ 2  , 10.0.0.1, 1 
+ 3  , 10.0.0.1, 1 
+ 4  , 10.0.0.1, 1 
+ 5  , 10.0.0.1, 1 
+ 6  , 10.0.0.1, 1
+ 7  , 10.0.0.2, 2
+ 8  , 10.0.0.2, 2 
+ 9  , 10.0.0.2, 2 
+ 10  , 10.0.0.2,2  
+ 11  , 10.0.0.2,2  
+ 12  , 10.0.0.2,2 
+|=================
+
+
+==== Tutorial 16: Source and Destination MAC address
+
+Each TRex port has a source MAC configure and destination MAC (DUT) configured in /etc/trex_cfg.yaml
+By default those MAC (source and destination) is taken 
+In case a user configures a source or destination MAC explicitly this MAC will override
+
+
+.MAC addrees
+[format="csv",cols="2^,2^,2^", options="header",width="40%"]
+|=================
+Scapy , Source MAC,Destination MAC
+Ether() , trex_cfg,trex_cfg
+Ether(src="00:bb:12:34:56:01"),"00:bb:12:34:56:01",trex_cfg
+Ether(dst="00:bb:12:34:56:01"),trex_cfg,"00:bb:12:34:56:01"
+|=================
+
+For example 
+
+file: `stl/udp_1pkt_1mac_override.py`
+
+
+[source,python]
+----
+    def create_stream (self):
+
+        base_pkt =  Ether(src="00:bb:12:34:56:01")/      <1>
+                    IP(src="16.0.0.1",dst="48.0.0.1")/
+                    UDP(dport=12,sport=1025)  
+----
+<1> Don't take TRex port src interface MAC
+
+==== Tutorial 17: Teredo tunnel (IPv6 over IPv4)
+
+The following example demonstrates creating IPv6 packet inside IPv4 packet and create a range of IPs
+
+file: `stl/udp_1pkt_ipv6_in_ipv4.py`
+
+[source,python]
+----
+    def create_stream (self):
+        # Teredo Ipv6 over Ipv4 
+        pkt =  Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
+              UDP(dport=3797,sport=3544)/
+              IPv6(dst="2001:0:4137:9350:8000:f12a:b9c8:2815",
+                   src="2001:4860:0:2001::68")/
+              UDP(dport=12,sport=1025)/ICMPv6Unknown()
+
+        vm = CTRexScRaw( [ 
+                            # tuple gen for inner Ipv6 
+                            STLVmTupleGen ( ip_min="16.0.0.1", ip_max="16.0.0.2", 
+                                            port_min=1025, port_max=65535,
+                                            name="tuple"),                      <1>
+
+                             STLVmWrFlowVar (fv_name="tuple.ip", 
+                                             pkt_offset= "IPv6.src",
+                                             offset_fixup=12 ),                 <2>
+                             STLVmWrFlowVar (fv_name="tuple.port", 
+                                             pkt_offset= "UDP:1.sport" )        <3>
+                          ]
+                       )
+----
+<1> Define stream struct name tuple. it has tuple.ip, tuple.port variables
+<2> Write stream tuple.ip variable into IPv6.src offset and fixup with 12 bytes (only 4 LSB)
+<3> Write stream tuple.port variable into the second UDP header 
 
 
 
index 309dd91..175b366 100755 (executable)
Binary files a/images/Thumbs.db and b/images/Thumbs.db differ
diff --git a/images/stl_tut_pcap_file1.png b/images/stl_tut_pcap_file1.png
new file mode 100644 (file)
index 0000000..1e4be64
Binary files /dev/null and b/images/stl_tut_pcap_file1.png differ