diff options
-rw-r--r-- | draft_trex_stateless.asciidoc | 509 | ||||
-rwxr-xr-x | images/Thumbs.db | bin | 518144 -> 552960 bytes | |||
-rw-r--r-- | images/stl_tut_pcap_file1.png | bin | 0 -> 3800 bytes |
3 files changed, 479 insertions, 30 deletions
diff --git a/draft_trex_stateless.asciidoc b/draft_trex_stateless.asciidoc index a9195d46..7a202c34 100644 --- a/draft_trex_stateless.asciidoc +++ b/draft_trex_stateless.asciidoc @@ -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 diff --git a/images/Thumbs.db b/images/Thumbs.db Binary files differindex 309dd91e..175b366f 100755 --- a/images/Thumbs.db +++ b/images/Thumbs.db diff --git a/images/stl_tut_pcap_file1.png b/images/stl_tut_pcap_file1.png Binary files differnew file mode 100644 index 00000000..1e4be64e --- /dev/null +++ b/images/stl_tut_pcap_file1.png |