4 :email: trex.tgen@gmail.com
8 :web_server_url: https://trex-tgn.cisco.com/trex
9 :local_web_server_url: csi-wiki-01:8181/trex
10 :github_stl_path: https://github.com/cisco-system-traffic-generator/trex-core/tree/master/scripts/stl
11 :github_stl_examples_path: https://github.com/cisco-system-traffic-generator/trex-core/tree/master/scripts/automation/trex_control_plane/stl/examples
14 include::trex_ga.asciidoc[]
16 // PDF version - image width variable
17 ifdef::backend-docbook[]
23 endif::backend-docbook[]
25 // HTML version - image width variable
26 ifdef::backend-xhtml11[]
32 endif::backend-xhtml11[]
38 This document assumes basic knowledge of TRex, and assumes that TRex is installed and configured.
39 For information, see the link:trex_manual.html[manual], especially the material up to the link:trex_manual.html#_basic_usage[Basic Usage] section.
43 === High level functionality
44 // maybe Feature overview
46 * Large scale - Supports about 10-22 million packets per second (mpps) per core, scalable with the number of cores
47 * Support for 1, 10, 25, 40, and 100 Gb/sec interfaces
48 * Support for multiple traffic profiles per interface
49 * Profile can support multiple streams, scalable to 10K parallel streams
50 * Supported for each stream:
51 ** Packet template - ability to build any packet (including malformed) using link:https://en.wikipedia.org/wiki/Scapy[Scapy] (example: MPLS/IPv4/Ipv6/GRE/VXLAN/NSH)
52 ** Field engine program
53 *** Ability to change any field inside the packet (example: src_ip = 10.0.0.1-10.0.0.255)
54 *** Ability to change the packet size (example: random packet size 64-9K)
55 ** Mode - Continuous/Burst/Multi-burst support
56 ** Rate can be specified as:
57 *** Packets per second (example: 14MPPS)
58 *** L1 bandwidth (example: 500Mb/sec)
59 *** L2 bandwidth (example: 500Mb/sec)
60 *** Interface link percentage (example: 10%)
61 ** Support for HLTAPI-like profile definition
62 ** Action - stream can trigger a stream
63 * Interactive support - Fast Console, GUI
64 * Statistics per interface
65 * Statistics per stream done in hardware
66 * Latency and Jitter per stream
67 * Blazingly fast automation support
68 ** Python 2.7/3.0 Client API
69 ** Python HLTAPI Client API
70 * Multi-user support - multiple users can interact with the same TRex instance simultaneously
73 ==== Traffic profile example
75 The following example shows three streams configured for Continuous, Burst, and Multi-burst traffic.
77 image::images/stl_streams_example_02.png[title="Example of multiple streams",align="left",width={p_width}, link="images/stl_streams_example_02.png"]
80 ==== High level functionality - Roadmap for future development
82 * Add emulation support
86 === IXIA IXExplorer vs TRex
88 TRex has limited functionality compared to IXIA, but has some advantages. The following table summarizes the differences:
91 [cols="1^,3^,3^,5^", options="header"]
93 | Feature | IXExplorer |TRex | Description
94 | Line rate | Yes | 10-24MPPS/core, depends on the use case |
95 | Multi stream | 255 | [green]*Unlimited* |
96 | Packet build flexibility | Limited | [green]*Scapy - Unlimited* | Example: GRE/VXLAN/NSH is supported. Can be extended to future protocols
97 | Packet Field engine | limited | [green]*Unlimited* |
98 | Tx Mode | Continuous/Burst/Multi-burst | Continuous/Burst/Multi-burst|
99 | ARP Emulation | Yes | Not yet - workaround |
100 | Automation | TCL/Python wrapper to TCL | [green]*native Python/Scapy* |
101 | Automation speed sec| 30 sec | [green]*1 msec* | Test of load/start/stop/get counters
102 | HLTAPI | Full support. 2000 pages of documentation | Limited. 20 pages of documentation|
103 | Per Stream statistics | 255 streams with 4 global masks | 128 rules for XL710/X710 hardware and software impl for 82599/I350/X550| Some packet type restrictions apply to XL710/X710.
104 | Latency Jitter | Yes,Resolution of nsec (hardware) | Yes,Resolution of usec (software) |
105 | Multi-user support | Yes | Yes |
106 | GUI | very good | WIP, packet build is scapy-based. Not the same as IXIA. Done by Exalt |
107 | Cisco pyATS support | Yes | Yes - Python 2.7/Python 3.4 |
108 | Emulation | Yes | Not yet |
109 | Port IDs | Based on IXIA numebrs | Depends on PCI enumeration
115 A JSON-RPC2 thread in the TRex control plane core provides support for interactive mode.
117 // RPC = Remote Procedure Call, alternative to REST? --YES, no change
119 image::images/trex_architecture_01.png[title="RPC Server Components",align="left",width={p_width}, link="images/trex_architecture_01.png"]
121 // OBSOLETE: image::images/trex_2_stateless.png[title="RPC Server Components",align="left",width={p_width}, link="images/trex_2_stateless.png"]
123 // Is there a big picture that would help to make the next 11 bullet points flow with clear logic? --explanation of the figure
126 * Control transport protocol: ZMQ working in REQ/RES mode.
127 // change all ZMQ to "link:http://rfc.zeromq.org/spec:37[ZeroMQ] Message Transport Protocol (ZMTP)"? not sure what REQ/RES mode is
128 * RPC protocol on top of the control transport protocol: JSON-RPC2.
129 * Asynchronous transport: ZMQ working in SUB/PUB mode (used for asynchronous events such as interface change mode, counters, and so on).
131 // TBD: rendering problem with bullet indentation
132 // Maybe Layers, Interfaces, and Control of Interfaces should each be level 4 headings instead of complex bulleted lists.
137 * Automation API: Python is the first client to implement the Python automation API.
138 * User interface: The console uses the Python API to implement a user interface for TRex.
139 * GUI : The GUI works on top of the JSON-RPC2 layer.
141 *Control of TRex interfaces*::
142 * Numerous users can control a single TRex server together, from different interfaces.
143 * Users acquire individual TRex interfaces exclusively. *Example*: Two users control a 4-port TRex server. User A acquires interfaces 0 and 1; User B acquires interfaces 3 and 4.
144 * Only one user interface (console or GUI) can have read/write control of a specific interface. This enables caching the TRex server interface information in the client core. *Example*: User A, with two acquired interfaces, can have only one read/write control session at a time.
145 * A user can set up numerous read-only clients on a single interface - for example, for monitoring traffic statistics on the interface.
146 * A client in read-write mode can acquire a statistic in real time (with ASYNC ZMQ). This enables viewing statistics through numerous user interfaces (console and GUI) simultaneously.
149 * A client syncs with the TRex server to get the state in connection time, and caches the server information locally after the state has changed.
150 * If a client crashes or exits, it syncs again after reconnecting.
152 image::images/trex_stateless_multi_user_02.png[title="Multiple users, per interface",align="left",width={p_width}, link="images/trex_stateless_multi_user_02.png"]
154 For details about the TRex RPC server, see the link:trex_rpc_server_spec.html[RPC specification].
156 ==== RPC architecture highlights
158 This Architecture provides the following advantages:
160 * Fast interaction with TRex server. Loading, starting, and stopping a profile for an interface is very fast - about 2000 cycles/sec.
161 * Leverages Python/Scapy for building a packet/field engine.
162 * HLTAPI compiler complexity is handled in Python.
166 // maybe call it "Objects" in title and figure caption
168 image::images/stateless_objects_02.png[title="TRex Objects",align="left",width={p_width_1}, link="images/stateless_objects_02.png"]
170 * *TRex*: Each TRex instance supports numerous interfaces.
172 * *Interface*: Each interface supports one or more traffic profiles.
173 * *Traffic profile*: Each traffic profile supports one or more streams.
174 * *Stream*: Each stream includes:
175 ** *Packet*: Packet template up to 9 KB
176 // ok to standardize to KB?
177 ** *Field Engine*: Which field to change, do we want to change packet size
179 ** *Mode*: Specifies how to send packets: Continuous/Burst/Multi-burst
180 ** *Rx Stats*: Statistics to collect for each stream
181 ** *Rate*: Rate (packets per second or bandwidth)
182 ** *Action*: Specifies stream to follow when the current stream is complete (valid for Continuous or Burst modes).
185 === Stateful vs Stateless
187 TRex Stateless support enables basic L2/L3 testing, relevant mostly for a switch or router. Using Statelss mode, it is possible to define a stream with a *one* packet template, define a program to change any fields in the packet, and run the stream in continuous, burst, or multi-burst mode.
188 With Stateless, you *cannot* learn NAT translation; there is no context of flow/client/server.
190 * In Stateful mode, the basic building block is a flow/application (composed of many packets).
191 * Stateless mode is much more flexible, enabling you to define any type of packet, and build a simple program.
193 .Stateful vs Stateless features
194 [cols="1^,3^,3^", options="header"]
196 | Feature | Stateless |Stateful
197 | Flow base | No | Yes
199 | Tunnel | Yes | Some are supported
200 | L7 App emulation | No | Yes
201 | Any type of packet | Yes | No
202 | Latency Jitter | Per Stream | Global/Per flow
205 ==== Using Stateless mode to mimic Stateful mode
207 Stateless mode can mimic some, but not all functionality of Stateful mode.
208 For example, you can load a pcap with the number of packets as a link of streams:
209 a->b->c->d-> back to a
210 You can then create a program for each stream to change src_ip=10. 0.0.1-10.0.0.254. This creates traffic similar to that of Stateful mode, but with a completely different basis.
212 If you are confused you probably need Stateless. :-)
214 === TRex package folders
216 [cols="5,5", options="header",width="100%"]
217 |=============================
218 | Location | Description
219 | / | t-rex-64/dpdk_set_ports/stl-sim
220 | /stl | Stateless native (py) profiles
221 | /stl/yaml | Stateless YAML profiles
222 | /stl/hlt | Stateless HLT profiles
223 | /ko | Kernel modules for DPDK
224 | /external_libs | Python external libs used by server/clients
225 | /exp | Golden pcap file for unit-tests
226 | /cfg | Examples of config files
227 | /cap2 | Stateful profiles
228 | /avl | Stateful profiles - SFR profile
229 | /automation | Python client/server code for both Stateful and Stateless
230 | /automation/regression | Regression for Stateless and Stateful
231 | /automation/config | Regression setups config files
232 | /automation/trex_control_plane/stl | Stateless lib and Console
233 | /automation/trex_control_plane/stl/trex_stl_lib | Stateless lib
234 | /automation/trex_control_plane/stl/examples | Stateless Examples
235 |=============================
237 === Port Layer Mode Configuration
239 TRex ports can operate in two different mutual exclusive modes:
241 * *Layer 2 mode* - MAC level configuration
242 * *Layer 3 mode* - IPv4/IPv6 configuration
244 When configuring a port for L2 mode, it is only required to provide
245 the destination MAC address for the port (Legacy mode previous to v2.12 version).
247 When configuring a port for L3, it is required to provide both
248 source IPv4/IPv6 address and a IPv4/IPv6 destination address.
250 As an intergral part of configuring L3, the client will try to ARP resolve the
251 destination address and automatically configure the correct destination MAC.
252 (instead of sending ARP request when starting traffic)
255 While in L3 mode, TRex server will generate *gratuitous ARP* packets to make sure
256 that no ARP timeout on the DUT/router will result in a faliure of the test.
258 .*Example of configuring L2 mode*
265 usage: port [-h] --port PORT --dst DST_MAC
267 Configures a port in L2 mode
270 -h, --help show this help message and exit
271 --port PORT, -p PORT source port for the action
272 --dst DST_MAC Configure destination MAC address
275 trex(service)>l2 -p 0 --dst 6A:A7:B5:3A:4E:FF
277 Setting port 0 in L2 mode: [SUCCESS]
284 .*Example of configuring L2 mode- Python API*
287 client.set_service_mode(port = 0, enabled = True)
289 client.set_l2_mode(port = 0, dst_mac = "6A:A7:B5:3A:4E:FF")
291 client.set_service_mode(port = 0, enabled = False)
296 .*Example of configuring L3 mode- Console*
303 trex(service)>l3 --help
304 usage: port [-h] --port PORT --src SRC_IPV4 --dst DST_IPV4
306 Configures a port in L3 mode
309 -h, --help show this help message and exit
310 --port PORT, -p PORT source port for the action
311 --src SRC_IPV4 Configure source IPv4 address
312 --dst DST_IPV4 Configure destination IPv4 address
314 trex(service)>l3 -p 0 --src 1.1.1.2 --dst 1.1.1.1
316 Setting port 0 in L3 mode: [SUCCESS]
319 ARP resolving address '1.1.1.1': [SUCCESS]
326 .*Example of configuring L3 mode - Python API*
330 client.set_service_mode(port = 0, enabled = True)
332 client.set_l3_mode(port = 0, src_ipv4 = '1.1.1.2', dst_ipv4 = '1.1.1.1')
334 client.set_service_mode(port = 0, enabled = False)
338 === Port Service Mode
340 In 'normal operation mode', to preserve high speed processing of packets,
341 TRex ignores most of the RX traffic, with the exception of counting/statistic and handling
345 In the following diagram it is illustrated how RX packets are handled.
346 Only a portion is forwarded to the RX handling module and none of forward back
347 to the Python client.
349 image::images/port_normal_mode.png[title="Port Under Normal Mode",align="left",width={p_width}, link="images/port_normal_mode.png"]
353 We provide another mode called 'service mode' in which a port will respond to ping, ARP requests
354 and also provide a capabality in this mode to forward packets to the Python control plane for
355 applying full duplex protocols (DCHP, IPv6 neighboring and etc.)
357 The following diagram illustrates of packets can be forwarded back to the Python client
359 image::images/port_service_mode.png[title="Port Under Service Mode",align="left",width={p_width}, link="images/port_service_mode.png"]
361 In this mode, it is possible to write python plugins for emulation (e.g. IPV6 ND/DHCP) to prepare the setup and then move to normal mode for high speed testing
364 *Example Of Switcing Between 'Service' And 'Normal' Mode*
368 trex(service)>service --help
369 usage: service [-h] [--port PORTS [PORTS ...] | -a] [--off]
371 Configures port for service mode. In service mode ports will reply to ARP,
375 -h, --help show this help message and exit
376 --port PORTS [PORTS ...], -p PORTS [PORTS ...]
377 A list of ports on which to apply the command
378 -a Set this flag to apply the command on all available
380 --off Deactivates services on port(s)
385 Enabling service mode on port(s) [0, 1]: [SUCCESS]
387 trex(service)>service --off
389 Disabling service mode on port(s) [0, 1]: [SUCCESS]
393 .*Example Of Switcing Between 'Service' And 'Normal' Mode-API*
397 client.set_service_mode(ports = [0, 1], enabled = True)
399 client.set_service_mode(ports = [0, 1], enabled = False)
403 ==== ARP / ICMP response
405 Only while in service mode, ports will reply to ICMP echo requests and ARP requests.
408 === Neighboring Protocols
409 As mentioned, in order to preserve high speed traffic generation,
410 TRex handles neighboring protocols in pre test phase.
412 A test that requires running a neighboring protocol should first move
413 to 'service mode', execute the required steps in Python, switch back to 'normal mode'
414 and start the actual test.
417 A basic neighboring protocol that is provided as part of TRex is ARP.
419 For example, let's take a look at the following setup:
421 image::images/router_arp.png[title="Router ARP",align="left",width={p_width}, link="images/router_arp.png"]
428 Enabling service mode on port(s) [0, 1]: [SUCCESS]
430 trex(service)>portattr --port 0
433 ------------------------------------------
434 driver | rte_ixgbe_pmd |
435 description | 82599EB 10-Gigabit |
437 link speed | 10 Gb/s |
443 src MAC | 00:00:00:01:00:00 |
445 Destination | 00:00:00:01:00:00 |
448 PCI Address | 0000:03:00.0 |
451 RX Filter Mode | hardware match |
457 trex(service)>l3 -p -s 1.1.1.1 -d 1.1.1.2 #<2>
459 trex(service)>arp -p 0 1 #<3>
461 Resolving destination on port(s) [0, 1]: [SUCCESS]
464 Port 0 - Recieved ARP reply from: 1.1.1.1, hw: d0:d0:fd:a8:a1:01
465 Port 1 - Recieved ARP reply from: 1.1.2.1, hw: d0:d0:fd:a8:a1:02
467 trex(service)>service --off #<4>
470 <1> Enable service mode
471 <2> Set IPv4/default gateway. it will resolve the arp
472 <3> repeat ARP resolution
473 <4> exist from service mode
477 to revert back to MAC address mode (without ARP resolution) you do the following
483 trex>l2 -p 0 --dst 00:00:00:01:00:00 #<1>
485 trex>portattr --port 0
488 ------------------------------------------
489 driver | rte_ixgbe_pmd |
490 description | 82599EB 10-Gigabit |
492 link speed | 10 Gb/s |
498 src MAC | 00:00:00:01:00:00 |
500 Destination | 00:00:00:01:00:00 |
503 PCI Address | 0000:03:00.0 |
506 RX Filter Mode | hardware match |
512 <1> disable service mode
520 client.set_service_mode(ports = [0, 1], enabled = True) <1>
522 # configure port 0, 1 to Layer 3 mode
523 client.set_l3_mode(port = 0, src_ipv4 = '1.1.1.2', dst_ipv4 = '1.1.1.2') <2>
524 client.set_l3_mode(port = 1, src_ipv4 = '1.1.2.2', dst_ipv4 = '1.1.2.1')
526 # ARP resolve ports 0, 1
527 c.resolve(ports = [0, 1])
529 client.set_service_mode(ports = [0, 1], enabled = False) <3>
532 <1> Enable service mode
533 <2> configure IPv4 and Default Gateway
534 <3> Disable service mode
538 Another basic protocol provided with TRex is ICMP.
539 It is possible, under service mode to ping the DUT or even a TRex port
540 from the console / API.
546 trex(service)>ping --help
547 usage: ping [-h] --port PORT -d PING_IPV4 [-s PKT_SIZE] [-n COUNT]
549 pings the server / specific IP
552 -h, --help show this help message and exit
553 --port PORT, -p PORT source port for the action
554 -d PING_IPV4 which IPv4 to ping
555 -s PKT_SIZE packet size to use
556 -n COUNT, --count COUNT
557 How many times to ping [default is 5]
559 trex(service)>ping -p 0 -d 1.1.2.2
561 Pinging 1.1.2.2 from port 0 with 64 bytes of data:
562 Reply from 1.1.2.2: bytes=64, time=27.72ms, TTL=127
563 Reply from 1.1.2.2: bytes=64, time=1.40ms, TTL=127
564 Reply from 1.1.2.2: bytes=64, time=1.31ms, TTL=127
565 Reply from 1.1.2.2: bytes=64, time=1.78ms, TTL=127
566 Reply from 1.1.2.2: bytes=64, time=1.95ms, TTL=127
576 # move to service mode
577 client.set_service_mode(ports = ports, enabled = True)
579 # configure port 0, 1 to Layer 3 mode
580 client.set_l3_mode(port = 0, src_ipv4 = '1.1.1.2', dst_ipv4 = '1.1.1.1')
581 client.set_l3_mode(port = 1, src_ipv4 = '1.1.2.2', dst_ipv4 = '1.1.2.1')
583 # ping port 1 from port 0 through the router
584 client.ping_ip(src_port = 0, dst_ipv4 = '1.1.2.2', pkt_size = 64) <1>
586 # disable service mode
587 client.set_service_mode(enabled = False)
590 <1> Check connectivity
593 ==== IPv6 ND/DHCP client
600 The tutorials in this section demonstrate basic TRex *stateless* use cases. Examples include common and moderately advanced TRex concepts.
602 ==== Tutorial: Simple IPv4/UDP packet - TRex
606 Send a simple UDP packet from all ports of a TRex server.
610 The following profile defines one stream, with an IP/UDP packet template with 10 bytes of 'x'(0x78) of payload. For more examples of defining packets using Scapy see the link:http://www.secdev.org/projects/scapy/doc/[Scapy documentation].
614 link:{github_stl_path}/udp_1pkt_simple.py[stl/udp_1pkt_simple.py]
618 from trex_stl_lib.api import *
622 def create_stream (self):
627 pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
628 UDP(dport=12,sport=1025)/(10*'x') <1>
630 mode = STLTXCont()) <2>
633 def get_streams (self, direction = 0, **kwargs): <3>
635 return [ self.create_stream() ]
638 # dynamic load - used for TRex console or simulator
642 <1> Defines the packet. In this case, the packet is IP/UDP with 10 bytes of 'x'. For more information, see the link:http://www.secdev.org/projects/scapy/doc/[Scapy documentation].
643 <2> Mode: Continuous. Rate: 1 PPS (default rate is 1 PPS)
644 <3> The `get_streams` function is mandatory
645 <4> Each traffic profile module requires a `register` function.
648 =====================================================================
649 The SRC/DST MAC addresses are taken from /etc/trex_cfg.yaml. To change them, add Ether(dst="00:00:dd:dd:00:01") with the desired destination.
650 =====================================================================
653 *Start TRex as a server*::
656 =====================================================================
657 The TRex package includes all required packages. It is unnecessary to install any python packages (including Scapy).
658 =====================================================================
665 * Wait until the server is up and running.
666 * (Optional) Use `-c` to add more cores.
667 * (Optional) Use `--cfg` to specify a different configuration file. The default is link:trex_manual.html#_create_minimum_configuration_file[/etc/trex_cfg.yaml].
669 // IGNORE: this line helps rendering of next line
671 *Connect with console*::
673 On the same machine, in a new terminal window (open a new window using `xterm`, or `ssh` again), connect to TRex using `trex-console`.
679 Connecting to RPC server on localhost:4501 [SUCCESS]
680 connecting to publisher server on localhost:4500 [SUCCESS]
681 Acquiring ports [0, 1, 2, 3]: [SUCCESS]
685 trex>start -f stl/udp_1pkt_simple.py -m 10mbps -a #<2>
687 Removing all streams from port(s) [0, 1, 2, 3]: [SUCCESS]
688 Attaching 1 streams to port(s) [0, 1, 2, 3]: [SUCCESS]
689 Starting traffic on port(s) [0, 1, 2, 3]: [SUCCESS]
691 # pause the traffic on all port
694 # resume the traffic on all port
697 # stop traffic on all port
700 # show dynamic statistic
703 <1> Connects to the TRex server from the local machine.
704 <2> Start the traffic on all ports at 10 mbps. Can also specify as MPPS. Example: 14 MPPS (`-m 14mpps`).
705 <3> Pauses the traffic.
707 <5> Stops traffic on all the ports.
711 =====================================================================
712 If you have a connection *error*, open the /etc/trex_cfg.yaml file and remove keywords such as `enable_zmq_pub : true` and `zmq_pub_port : 4501` from the file.
713 =====================================================================
717 To display stream data for all ports, use `streams -a`.
725 ID | packet type | length | mode | rate | next stream
726 -----------------------------------------------------------------------------------
727 1 | Ethernet:IP:UDP:Raw | 56 | Continuous | 1.00 pps | -1
731 ID | packet type | length | mode | rate | next stream
732 -----------------------------------------------------------------------------------
733 1 | Ethernet:IP:UDP:Raw | 56 | Continuous | 1.00 pps | -1
737 ID | packet type | length | mode | rate | next stream
738 -----------------------------------------------------------------------------------
739 1 | Ethernet:IP:UDP:Raw | 56 | Continuous | 1.00 pps | -1
743 ID | packet type | length | mode | rate | next stream
744 -----------------------------------------------------------------------------------
745 1 | Ethernet:IP:UDP:Raw | 56 | Continuous | 1.00 pps | -1
749 *Viewing command help*::
752 To view help for a command, use `<command> --help`.
754 *Viewing general statistics*::
756 To view general statistics, open a "textual user interface" with `tui`.
763 Connection : localhost, Port 4501
764 Version : v1.93, UUID: N/A
767 Total Tx L2 : 40.01 Mb/sec
768 Total Tx L1 : 52.51 Mb/sec
769 Total Rx : 40.01 Mb/sec
770 Total Pps : 78.14 Kpkt/sec
772 Drop Rate : 0.00 b/sec
778 --------------------------------------------------------
779 owner | hhaim | hhaim |
780 state | ACTIVE | ACTIVE |
782 Tx bps L2 | 10.00 Mbps | 10.00 Mbps |
783 Tx bps L1 | 13.13 Mbps | 13.13 Mbps |
784 Tx pps | 19.54 Kpps | 19.54 Kpps |
785 Line Util. | 0.13 % | 0.13 % |
787 Rx bps | 10.00 Mbps | 10.00 Mbps |
788 Rx pps | 19.54 Kpps | 19.54 Kpps |
790 opackets | 1725794 | 1725794 |
791 ipackets | 1725794 | 1725794 |
792 obytes | 110450816 | 110450816 |
793 ibytes | 110450816 | 110450816 |
794 tx-bytes | 110.45 MB | 110.45 MB |
795 rx-bytes | 110.45 MB | 110.45 MB |
796 tx-pkts | 1.73 Mpkts | 1.73 Mpkts |
797 rx-pkts | 1.73 Mpkts | 1.73 Mpkts |
804 browse: 'q' - quit, 'g' - dashboard, '0-3' - port display
805 dashboard: 'p' - pause, 'c' - clear, '-' - low 5%, '+' - up 5%,
811 In this example TRex sends the *same* packet from all ports. If your setup is connected with loopback, you will see Tx packets from port 0 in Rx port 1 and vice versa. If you have DUT with static route, you might see all the packets going to specific port.
816 interface TenGigabitEthernet0/0/0
818 ip address 1.1.9.1 255.255.255.0
820 interface TenGigabitEthernet0/1/0
822 ip address 1.1.10.1 255.255.255.0
825 ip route 16.0.0.0 255.0.0.0 1.1.9.2
826 ip route 48.0.0.0 255.0.0.0 1.1.10.2
829 // this is good info, but it isn't organized into specific tasks or explanations of specific goals. so comes across as useful but somewhat random. for example in the Static route example above, we should explain at the beginning that this will route all packets to one port, and that the next example will demonstrate how to route the packets to different ports.
831 In this example all the packets will be routed to `TenGigabitEthernet0/1/0` port. The following example uses the `direction` flag to change this.
833 *File*:: link:{github_stl_path}/udp_1pkt_simple_bdir.py[stl/udp_1pkt_simple_bdir.py]
840 def create_stream (self):
844 pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
845 UDP(dport=12,sport=1025)/(10*'x')
849 def get_streams (self, direction = 0, **kwargs):
859 pkt = Ether()/IP(src=src_ip,dst=dst_ip)/
860 UDP(dport=12,sport=1025)/(10*'x') )
862 return [ STLStream( packet = pkt,mode = STLTXCont()) ]
864 <1> This use of the `direction` flag causes a different packet to be sent for each direction.
867 ==== Tutorial: Connect from a remote server
869 *Goal*:: Connect by console from remote machine to a TRex server
871 *Check that TRex server is operational*::
873 Ensure that the TRex server is running. If not, run TRex in interactive mode.
874 // again, this is a bit vague. the tutorial should provide simple steps for using interactive mode or not. too many conditions.
881 *Connect with Console*::
883 From a remote machine, use `trex-console` to connect. Include the `-s` flag, as shown below, to specify the server.
887 $trex-console -s csi-kiwi-02 #<1>
889 <1> TRex server is csi-kiwi-02.
891 The TRex client requires Python versions 2.7.x or 3.4.x. To change the Python version, set the *PYTHON* environment variable as follows:
896 setenv PYTHON /bin/python #tcsh
902 extern PYTHON=/bin/mypython #bash
906 =====================================================================
907 The client machine should run Python 2.7.x or 3.4.x. Cisco CEL/ADS is supported. The TRex package includes the required link:cp_stl_docs/[client archive].
908 =====================================================================
910 ==== Tutorial: Source and Destination MAC addresses
912 *Goal*:: Change the source/destination MAC address
914 Each TRex port has a source and destination MAC (DUT) configured in the /etc/trex_cfg.yaml configuration file. The source MAC is not necessarily the hardware MAC address configured in EEPROM. By default, the hardware-specified MAC addresses (source and destination) are used. If a source or destination MAC address is configured explicitly, that address takes precedence over the hardware-specified default.
917 [format="csv",cols="2^,2^,2^", options="header",width="100%"]
919 Scapy , Source MAC,Destination MAC
920 Ether() , trex_cfg (src),trex_cfg(dst)
921 Ether(src="00:bb:12:34:56:01"),"00:bb:12:34:56:01",trex_cfg(dst)
922 Ether(dst="00:bb:12:34:56:01"),trex_cfg(src),"00:bb:12:34:56:01"
926 *File*:: link:{github_stl_path}/udp_1pkt_1mac_override.py[stl/udp_1pkt_1mac_override.py]
930 def create_stream (self):
932 base_pkt = Ether(src="00:bb:12:34:56:01")/ <1>
933 IP(src="16.0.0.1",dst="48.0.0.1")/
934 UDP(dport=12,sport=1025)
936 <1> Specifying the source interface MAC replaces the default specified in the configuration YAML file.
940 =====================================
941 TRex port will receive a packet only if the packet's destination MAC matches the HW Src MAC defined for that port in the `/etc/trex_cfg.yaml` configuration file. Alternatively, a port can be put into link:https://en.wikipedia.org/wiki/Promiscuous_mode[promiscuous mode], allowing the port to receive all packets on the line. The port can be configured to promiscuous mode by API or by the following command at the console: `portattr -a --prom`.
942 =====================================
944 To set ports to link:https://en.wikipedia.org/wiki/Promiscuous_mode[promiscuous mode] and show the port status:
948 trex>portattr -a --prom on #<1>
953 ---------------------------------------------------------------
954 driver | rte_ixgbe_pmd | rte_ixgbe_pmd |
955 maximum | 10 Gb/s | 10 Gb/s |
956 status | IDLE | IDLE |
957 promiscuous | on | on | #<2>
959 HW src mac | 90:e2:ba:36:33:c0 | 90:e2:ba:36:33:c1 |
960 SW src mac | 00:00:00:01:00:00 | 00:00:00:01:00:00 |
961 SW dst mac | 00:00:00:01:00:00 | 00:00:00:01:00:00 |
963 PCI Address | 0000:03:00.0 | 0000:03:00.1 |
966 <1> Configures all ports to promiscuous mode.
967 <2> Indicates port promiscuous mode status.
969 To change ports to promiscuous mode by Python API:
971 .Python API to change ports to promiscuous mode
974 c = STLClient(verbose_level = LoggerApi.VERBOSE_REGULAR)
981 c.reset(ports = my_ports)
983 # port info, mac-addr info, speed
984 print c.get_port_info(my_ports) <1>
986 c.set_port_attr(my_ports, promiscuous = True) <2>
988 <1> Get port info for all ports.
989 <2> Change the port attribute to `promiscuous = True`.
991 For more information see the link:cp_stl_docs/api/client_code.html[Python Client API].
995 =====================================================================
996 An interface is not set to promiscuous mode by default. Typically, after changing the port to promiscuous mode for a specific test, it is advisable to change it back to non-promiscuous mode.
997 =====================================================================
999 ==== Tutorial: Python automation
1001 *Goal*:: Simple automation test using Python from a local or remote machine
1005 Python API examples: `automation/trex_control_plane/stl/examples`.
1007 Python API library: `automation/trex_control_plane/stl/trex_stl_lib`.
1009 The TRex console uses the Python API library to interact with the TRex server using the JSON-RPC2 protocol over ZMQ.
1011 image::images/trex_architecture_01.png[title="RPC Server Components",align="left",width={p_width}, link="images/trex_architecture_01.png"]
1013 // OBSOLETE: image::images/trex_2_stateless.png[title="RPC Server Components",align="left",width={p_width}, link="images/trex_2_stateless.png"]
1015 *File*:: link:{github_stl_examples_path}/stl_bi_dir_flows.py[stl_bi_dir_flows.py]
1021 from trex_stl_lib.api import * <2>
1026 # simple packet creation <3>
1027 def create_pkt (size, direction):
1029 ip_range = {'src': {'start': "10.0.0.1", 'end': "10.0.0.254"},
1030 'dst': {'start': "8.0.0.1", 'end': "8.0.0.254"}}
1032 if (direction == 0):
1033 src = ip_range['src']
1034 dst = ip_range['dst']
1036 src = ip_range['dst']
1037 dst = ip_range['src']
1041 STLVmFlowVar(name="src",
1042 min_value=src['start'],
1043 max_value=src['end'],
1045 STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"),
1048 STLVmFlowVar(name="dst",
1049 min_value=dst['start'],
1050 max_value=dst['end'],
1052 STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
1055 STLVmFixIpv4(offset = "IP")
1059 base = Ether()/IP()/UDP()
1060 pad = max(0, len(base)) * 'x'
1062 return STLPktBuilder(pkt = base/pad,
1066 def simple_burst ():
1070 # username/server can be changed those are the default
1071 # username = common.get_current_user(),
1072 # server = "localhost"
1073 # STLClient(server = "my_server",username ="trex_client") for example
1077 # turn this on for some information
1078 #c.set_verbose("high")
1080 # create two streams
1081 s1 = STLStream(packet = create_pkt(200, 0),
1082 mode = STLTXCont(pps = 100))
1084 # second stream with a phase of 1ms (inter stream gap)
1085 s2 = STLStream(packet = create_pkt(200, 1),
1087 mode = STLTXCont(pps = 100))
1093 # prepare our ports (my machine has 0 <--> 1 with static route)
1094 c.reset(ports = [0, 1]) # Acquire port 0,1 for $USER <6>
1096 # add both streams to ports
1097 c.add_streams(s1, ports = [0])
1098 c.add_streams(s2, ports = [1])
1100 # clear the stats before injecting
1103 # choose rate and start traffic for 10 seconds on 5 mpps
1104 print "Running 5 Mpps on ports 0, 1 for 10 seconds..."
1105 c.start(ports = [0, 1], mult = "5mpps", duration = 10) <7>
1108 c.wait_on_traffic(ports = [0, 1]) <8>
1110 # read the stats after the test
1111 stats = c.get_stats() <9>
1113 print json.dumps(stats[0], indent = 4, separators=(',', ': '), sort_keys = True)
1114 print json.dumps(stats[1], indent = 4, separators=(',', ': '), sort_keys = True)
1116 lost_a = stats[0]["opackets"] - stats[1]["ipackets"]
1117 lost_b = stats[1]["opackets"] - stats[0]["ipackets"]
1119 print "\npackets lost from 0 --> 1: {0} pkts".format(lost_a)
1120 print "packets lost from 1 --> 0: {0} pkts".format(lost_b)
1122 if (lost_a == 0) and (lost_b == 0):
1127 except STLError as e:
1135 print "\nTest has passed :-)\n"
1137 print "\nTest has failed :-(\n"
1143 <1> Imports the stl_path. The path here is specific to this example. When configuring, provide the path to your stl_trex library.
1144 <2> Imports TRex Stateless library. When configuring, provide the path to your TRex Stateless library.
1145 <3> Creates packet per direction using Scapy.
1146 <4> See the Field Engine section for information.
1147 <5> Connects to the local TRex. Username and server can be added.
1148 <6> Acquires the ports.
1149 <7> Loads the traffic profile and start generating traffic.
1150 <8> Waits for the traffic to be finished. There is a polling function so you can test do something while waiting.
1151 <9> Get port statistics.
1154 See link:cp_stl_docs/index.html[TRex Stateless Python API] for details about using the Python APIs.
1157 ==== Tutorial: HLT Python API
1159 HLT Python API is a layer on top of the native layer. It supports the standard Cisco traffic generator API. For more information, see Cisco/IXIA/Spirent documentation.
1160 TRex supports limited number of HLTAPI arguments and the recommendation is to use the native API due to the flexibility and simplicity.
1162 Supported HLT Python API classes:
1173 ** traffic_config - not all arguments are supported
1177 // IGNORE: This line simply ends the bulletted section so that the next line will be formatted correctly.
1179 For details, see link:#_hlt_supported_arguments_a_id_altapi_support_a[Appendix]
1180 // confirm link above
1182 *File*:: link:{github_stl_examples_path}/hlt_udp_simple.py[hlt_udp_simple.py]
1191 from trex_stl_lib.api import * <1>
1192 from trex_stl_lib.trex_stl_hltapi import * <2>
1195 if __name__ == "__main__":
1196 parser = argparse.ArgumentParser(usage="""
1197 Connect to TRex and send burst of packets
1201 hlt_udp_simple.py -s 9000 -d 30
1203 hlt_udp_simple.py -s 9000 -d 30 -rate_percent 10
1205 hlt_udp_simple.py -s 300 -d 30 -rate_pps 5000000
1207 hlt_udp_simple.py -s 800 -d 30 -rate_bps 500000000 --debug
1209 then run the simulator on the output
1210 ./stl-sim -f example.yaml -o a.pcap ==> a.pcap include the packet
1213 description="Example for TRex HLTAPI",
1214 epilog=" based on hhaim's stl_run_udp_simple example")
1216 parser.add_argument("--ip",
1218 help='Remote trex ip',
1219 default="127.0.0.1",
1222 parser.add_argument("-s", "--frame-size",
1224 help='L2 frame size in bytes without FCS',
1228 parser.add_argument('-d','--duration',
1230 help='duration in second ',
1234 parser.add_argument('--rate-pps',
1236 help='speed in pps',
1239 parser.add_argument('--src',
1242 default='00:50:56:b9:de:75')
1244 parser.add_argument('--dst',
1247 default='00:50:56:b9:34:f3')
1249 args = parser.parse_args()
1251 hltapi = CTRexHltApi()
1252 print 'Connecting to TRex'
1253 res = hltapi.connect(device = args.ip, port_list = [0, 1], reset = True, break_locks = True)
1255 ports = res['port_handle']
1257 error('Should have at least 2 ports for this test')
1258 print 'Connected, acquired ports: %s' % ports
1260 print 'Creating traffic'
1262 res = hltapi.traffic_config(mode = 'create', bidirectional = True,
1263 port_handle = ports[0], port_handle2 = ports[1],
1264 frame_size = args.frame_size,
1265 mac_src = args.src_mac, mac_dst = args.dst_mac,
1266 mac_src2 = args.dst_mac, mac_dst2 = args.src_mac,
1267 l3_protocol = 'ipv4',
1268 ip_src_addr = '10.0.0.1', ip_src_mode = 'increment', ip_src_count = 254,
1269 ip_dst_addr = '8.0.0.1', ip_dst_mode = 'increment', ip_dst_count = 254,
1270 l4_protocol = 'udp',
1271 udp_dst_port = 12, udp_src_port = 1025,
1272 stream_id = 1, # temporary workaround, add_stream does not return stream_id
1273 rate_pps = args.rate_pps,
1277 print 'Starting traffic'
1278 res = hltapi.traffic_control(action = 'run', port_handle = ports[:2])
1280 wait_with_progress(args.duration)
1282 print 'Stopping traffic'
1283 res = hltapi.traffic_control(action = 'stop', port_handle = ports[:2])
1286 res = hltapi.traffic_stats(mode = 'aggregate', port_handle = ports[:2])
1288 print_brief_stats(res)
1290 res = hltapi.cleanup_session(port_handle = 'all')
1295 <1> Imports the native TRex API.
1296 <2> Imports the HLT API.
1299 ==== Tutorial: Simple IPv4/UDP packet - Simulator
1301 *Goal*:: Use the TRex Stateless simulator.
1303 Demonstrates the most basic use case using TRex simulator.
1305 The TRex package includes a simulator tool, `stl-sim`. The simulator operates as a Python script that calls an executable. The platform requirements for the simulator tool are the same as for TRex.
1307 The TRex simulator can:
1309 * Test your traffic profiles before running them on TRex.
1310 * Generate an output pcap file.
1311 * Simulate a number of threads.
1312 * Convert from one type of profile to another.
1313 * Convert any profile to JSON (API). For information, see: link:trex_rpc_server_spec.html#_add_stream[TRex stream specification]
1315 Example traffic profile:
1317 *File*:: link:{github_stl_path}/udp_1pkt_simple.py[stl/udp_1pkt_simple.py]
1321 from trex_stl_lib.api import *
1323 class STLS1(object):
1325 def create_stream (self):
1330 pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
1331 UDP(dport=12,sport=1025)/(10*'x') <1>
1333 mode = STLTXCont()) <2>
1336 def get_streams (self, direction = 0, **kwargs):
1338 return [ self.create_stream() ]
1341 # dynamic load - used for TRex console or simulator
1345 <1> Defines the packet - in this case, IP/UDP with 10 bytes of 'x'.
1346 <2> Mode is Continuous, with a rate of 1 PPS. (Default rate: 1 PPS)
1347 <3> Each traffic profile module requires a `register` function.
1349 The following runs the traffic profile through the TRex simulator, limiting the number of packets to 10, and storing the output in a pcap file.
1353 $ ./stl-sim -f stl/udp_1pkt_simple.py -o b.pcap -l 10
1354 executing command: 'bp-sim-64-debug --pcap --sl --cores 1 --limit 5000 -f /tmp/tmpq94Tfx -o b.pcap'
1362 core recording: merge all
1375 max BPS L1 : 672.00 bps
1376 max BPS L2 : 512.00 bps
1380 Starting simulation...
1386 simulated 10 packets
1387 written 10 packets to 'b.pcap'
1390 Contents of the output pcap file produced by the simulator in the previous step:
1392 image::images/stl_tut_1.png[title="TRex simulator output stored in pcap file",align="left",width={p_width}, link="images/stl_tut_1.png"]
1394 Adding `--json` displays the details of the JSON command for adding a stream:
1398 $./stl-sim -f stl/udp_1pkt_simple.py --json
1403 "method": "add_stream",
1417 "type": "continuous"
1419 "next_stream_id": -1,
1421 "binary": "AAAAAQAAAAAAAgAACABFAAAmAA",
1439 "method": "start_traffic",
1455 For more information about stream definition, see the link:trex_rpc_server_spec.html#_add_stream[RPC specification].
1457 To convert the profile to YAML format:
1460 $./stl-sim -f stl/udp_1pkt_simple.py --yaml
1470 binary: AAAAAQAAAAAAAgAACABFAAAmAAEAAEARO
1480 To display packet details, use the `--pkt` option (using Scapy).
1484 $./stl-sim -f stl/udp_1pkt_simple.py --pkt
1485 =======================
1487 =======================
1489 dst = 00:00:00:01:00:00
1490 src = 00:00:00:02:00:00
1513 0000 00 00 00 01 00 00 00 00 00 02 00 00 08 00 45 00 ..............E.
1514 0010 00 26 00 01 00 00 40 11 3A C5 10 00 00 01 30 00 .&....@.:.....0.
1515 0020 00 01 04 01 00 0C 00 12 61 61 78 78 78 78 78 78 ........aaxxxxxx
1516 0030 78 78 78 78 xxxx
1519 To convert any profile type to native again, use the `--native` option:
1524 $more stl/yaml/imix_1pkt.yaml
1529 pcap: udp_64B_no_crc.pcap # pcap should not include CRC
1535 To convert to native:
1539 $./stl-sim -f stl/yaml/imix_1pkt.yaml --native
1546 # !!! Auto-generated code !!!
1547 from trex_stl_lib.api import *
1549 class STLS1(object):
1550 def get_streams(self):
1553 packet = (Ether(src='00:de:01:0a:01:00', dst='00:50:56:80:0d:28', type=2048) /
1554 IP(src='101.0.0.1', proto=17, dst='102.0.0.1', chksum=28605, len=46, flags=2L, ihl=5L, id=0) /
1555 UDP(dport=2001, sport=2001, len=26, chksum=1176) /
1556 Raw(load='\xde\xad\xbe\xef\x00\x01\x06\x07\x08\x09\x0a\x0b\x00\x9b\xe7\xdb\x82M'))
1557 vm = STLScVmRaw([], split_by_field = '')
1558 stream = STLStream(packet = CScapyTRexPktBuilder(pkt = packet, vm = vm),
1560 mac_src_override_by_pkt = 0,
1561 mac_dst_override_mode = 0,
1562 mode = STLTXCont(pps = 100))
1563 streams.append(stream)
1573 The following are the main traffic profile formats. Native is the preferred format. There is a separation between how the traffic is defined and how to control/activate it. The API/Console/GUI can load a traffic profile and start/stop/get a statistic. Due to this separation it is possible to share traffic profiles.
1575 .Traffic profile formats
1576 [cols="1^,1^,10<", options="header",width="80%"]
1578 | Profile Type | Format | Description
1579 | Native | Python | Most flexibile. Any format can be converted to native using the `stl-sim` command with the `--native` option.
1580 | HLT | Python | Uses HLT arguments.
1581 | YAML | YAML | The common denominator traffic profile. Information is shared between console, GUI, and simulator in YAML format. This format is difficult to use for defining packets; primarily for machine use. YAML can be converted to native using the `stl-sim` command with the `--native` option.
1585 === Traffic profile Tutorials
1587 ==== Tutorial: Simple Interleaving streams
1589 *Goal*:: Demonstrate interleaving of multiple streams.
1591 The following example demonstrates 3 streams with different rates (10, 20, 40 PPS) and different start times, based on an inter-stream gap (ISG) of 0, 25 msec, or 50 msec.
1593 *File*:: link:{github_stl_path}/simple_3pkt.py[stl/simple_3pkt.py]
1595 // inserted this comment to fix rendering problem - otherwise the next several lines are not rendered
1596 // there's still a problem with the rendering. the image is not displayed.
1599 .Interleaving multiple streams
1602 def create_stream (self):
1604 # create a base packet and pad it to size
1605 size = self.fsize - 4 # no FCS
1606 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025) <1>
1607 base_pkt1 = Ether()/IP(src="16.0.0.2",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1608 base_pkt2 = Ether()/IP(src="16.0.0.3",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1609 pad = max(0, size - len(base_pkt)) * 'x'
1612 return STLProfile( [ STLStream( isg = 0.0,
1613 packet = STLPktBuilder(pkt = base_pkt/pad),
1614 mode = STLTXCont( pps = 10), <2>
1617 STLStream( isg = 25000.0, #defined in usec, 25 msec
1618 packet = STLPktBuilder(pkt = base_pkt1/pad),
1619 mode = STLTXCont( pps = 20), <3>
1622 STLStream( isg = 50000.0,#defined in usec, 50 msec
1623 packet = STLPktBuilder(pkt = base_pkt2/pad),
1624 mode = STLTXCont( pps = 40) <4>
1629 <1> Defines template packets using Scapy.
1630 <2> Defines streams with rate of 10 PPS.
1631 <3> Defines streams with rate of 20 PPS.
1632 <4> Defines streams with rate of 40 PPS.
1636 The folowing figure presents the output.
1638 image::images/stl_interleaving_01.png[title="Interleaving of streams",align="left",width={p_width}, link="images/stl_interleaving_01.png"]
1642 ** Schedules a packet each 100 msec
1644 ** Schedules a packet each 50 msec
1645 ** Starts 25 msec after stream #1
1647 ** Schedules a packet each 25 msec
1648 ** Starts 50 msec after stream #1
1650 You can run the traffic profile in the TRex simulator and view the details in the pcap file containing the simulation output.
1654 $./stl-sim -f stl/simple_3pkt.py -o b.pcap -l 200
1657 To run the traffic profile from console in TRex, use the following command.
1661 trex>start -f stl/simple_3pkt.py -m 10mbps -a
1664 ==== Tutorial: Multi burst streams - action next stream
1666 *Goal*:: Create a profile with a stream that trigger another stream
1668 The following example demonstrates:
1670 1. More than one stream
1671 2. Burst of 10 packets
1672 3. One stream activating another stream (see `self_start=False` in the traffic profile)
1674 *File*:: link:{github_stl_path}/burst_3pkt_60pkt.py[stl/burst_3pkt_60pkt.py]
1679 def create_stream (self):
1681 # create a base packet and pad it to size
1682 size = self.fsize - 4 # no FCS
1683 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1684 base_pkt1 = Ether()/IP(src="16.0.0.2",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1685 base_pkt2 = Ether()/IP(src="16.0.0.3",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1686 pad = max(0, size - len(base_pkt)) * 'x'
1689 return STLProfile( [ STLStream( isg = 10.0, # star in delay
1691 packet = STLPktBuilder(pkt = base_pkt/pad),
1692 mode = STLTXSingleBurst( pps = 10, total_pkts = 10), <1>
1693 next = 'S1'), # point to next stream
1695 STLStream( self_start = False, # stream is disabled enable trow S0 <2>
1697 packet = STLPktBuilder(pkt = base_pkt1/pad),
1698 mode = STLTXSingleBurst( pps = 10, total_pkts = 20),
1701 STLStream( self_start = False, # stream is disabled enable trow S0 <3>
1703 packet = STLPktBuilder(pkt = base_pkt2/pad),
1704 mode = STLTXSingleBurst( pps = 10, total_pkts = 30 )
1709 <1> Stream S0 is configured to `self_start=True`, starts after 10 sec.
1710 <2> S1 is configured to `self_start=False`, activated by stream S0.
1711 <3> S2 is activated by S1.
1713 To run the simulation, use this command.
1717 $ ./stl-sim -f stl/stl/burst_3pkt_60pkt.py -o b.pcap
1720 The generated pcap file has 60 packets. The first 10 packets have src_ip=16.0.0.1. The next 20 packets has src_ip=16.0.0.2. The next 30 packets has src_ip=16.0.0.3.
1722 This run the profile from console use this command.
1726 TRex>start -f stl/stl/burst_3pkt_60pkt.py --port 0
1729 ==== Tutorial: Multi-burst mode
1731 *Goal* : Use Multi-burst transmit mode
1733 *File*:: link:{github_stl_path}/multi_burst_2st_1000pkt.py[stl/multi_burst_2st_1000pkt.py]
1738 def create_stream (self):
1740 # create a base packet and pad it to size
1741 size = self.fsize - 4 # no FCS
1742 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1743 base_pkt1 = Ether()/IP(src="16.0.0.2",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1744 pad = max(0, size - len(base_pkt)) * 'x'
1747 return STLProfile( [ STLStream( isg = 10.0, # start in delay <1>
1749 packet = STLPktBuilder(pkt = base_pkt/pad),
1750 mode = STLTXSingleBurst( pps = 10, total_pkts = 10),
1751 next = 'S1'), # point to next stream
1753 STLStream( self_start = False, # stream is disabled. Enabled by S0 <2>
1755 packet = STLPktBuilder(pkt = base_pkt1/pad),
1756 mode = STLTXMultiBurst( pps = 1000,
1765 <1> Stream S0 waits 10 usec (inter-stream gap, ISG) and then sends a burst of 10 packets at 10 PPS.
1766 <2> Multi-burst of 5 bursts of 4 packets with an inter-burst gap of 1 second.
1769 The following illustration does not fully match the Python example cited above. It has been simplified, such as using a 0.5 second ISG, for illustration purposes.
1771 image::images/stl_multiple_streams_01.png[title="Example of multiple streams",align="left",width={p_width_lge}, link="images/stl_multiple_streams_01.png"]
1775 ==== Tutorial: Loops of streams
1777 *Goal* : Demonstrate a limited loop of streams
1779 *File*:: link:{github_stl_path}/burst_3st_loop_x_times.py[stl/burst_3st_loop_x_times.py]
1783 def create_stream (self):
1785 # create a base packet and pad it to size
1786 size = self.fsize - 4 # no FCS
1787 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1788 base_pkt1 = Ether()/IP(src="16.0.0.2",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1789 base_pkt2 = Ether()/IP(src="16.0.0.3",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1790 pad = max(0, size - len(base_pkt)) * 'x'
1793 return STLProfile( [ STLStream( isg = 10.0, # start in delay
1795 packet = STLPktBuilder(pkt = base_pkt/pad),
1796 mode = STLTXSingleBurst( pps = 10, total_pkts = 1),
1797 next = 'S1'), # point to next stream
1799 STLStream( self_start = False, # stream is disabled. Enabled by S0
1801 packet = STLPktBuilder(pkt = base_pkt1/pad),
1802 mode = STLTXSingleBurst( pps = 10, total_pkts = 2),
1805 STLStream( self_start = False, # stream is disabled. Enabled by S1
1807 packet = STLPktBuilder(pkt = base_pkt2/pad),
1808 mode = STLTXSingleBurst( pps = 10, total_pkts = 3 ),
1809 action_count = 2, # loop 2 times <1>
1810 next = 'S0' # loop back to S0
1815 <1> go back to S0 but limit it to 2 loops
1818 ==== Tutorial: IMIX with UDP packets, bi-directional
1820 *Goal* : Demonstrate how to create an IMIX traffic profile.
1822 This profile defines 3 streams, with packets of different sizes. The rate is different for each stream/size. See the link:https://en.wikipedia.org/wiki/Internet_Mix[Wikipedia article on Internet Mix].
1824 *File*:: link:{github_stl_path}/imix.py[stl/imix.py]
1828 def __init__ (self):
1830 self.ip_range = {'src': {'start': "10.0.0.1", 'end': "10.0.0.254"},
1831 'dst': {'start': "8.0.0.1", 'end': "8.0.0.254"}}
1833 # default IMIX properties
1834 self.imix_table = [ {'size': 60, 'pps': 28, 'isg':0 },
1835 {'size': 590, 'pps': 16, 'isg':0.1 },
1836 {'size': 1514, 'pps': 4, 'isg':0.2 } ]
1839 def create_stream (self, size, pps, isg, vm ):
1840 # create a base packet and pad it to size
1841 base_pkt = Ether()/IP()/UDP()
1842 pad = max(0, size - len(base_pkt)) * 'x'
1844 pkt = STLPktBuilder(pkt = base_pkt/pad,
1847 return STLStream(isg = isg,
1849 mode = STLTXCont(pps = pps))
1852 def get_streams (self, direction = 0, **kwargs): <1>
1854 if direction == 0: <2>
1855 src = self.ip_range['src']
1856 dst = self.ip_range['dst']
1858 src = self.ip_range['dst']
1859 dst = self.ip_range['src']
1861 # construct the base packet for the profile
1865 STLVmFlowVar(name="src",
1866 min_value=src['start'],
1867 max_value=src['end'],
1869 STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"),
1872 STLVmFlowVar(name="dst",
1873 min_value=dst['start'],
1874 max_value=dst['end'],
1877 STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
1880 STLVmFixIpv4(offset = "IP")
1884 # create imix streams
1885 return [self.create_stream(x['size'], x['pps'],x['isg'] , vm) for x in self.imix_table]
1887 <1> Constructs a diffrent stream for each direction (replaces src and dest).
1888 <2> Even port id has direction==0 and odd has direction==1.
1889 // direction==1 not shown explicitly in the code?
1890 <3> Field Engine program to change fields within the packets.
1891 // we can link "Field Engine" to an appropriate location for for more info.
1893 ==== Tutorial: Field Engine, Syn attack
1895 The following example demonstrates changing packet fields. The Field Engine (FE) has a limited number of instructions/operation, which support most use cases.
1898 * Allocate stream variables in a stream context
1899 * Write a stream variable to a packet offset
1900 * Change packet size
1902 * There is a plan to add LuaJIT to be more flexible at the cost of performance.
1905 * Change ipv4.tos value (1 to 10)
1906 * Change packet size to a random value in the range 64 to 9K
1907 * Create a range of flows (change src_ip, dest_ip, src_port, dest_port)
1908 * Update the IPv4 checksum
1910 For more information, see link:trex_rpc_server_spec.html#_object_type_em_vm_em_a_id_vm_obj_a[here]
1911 // add link to Python API: http://trex-tgn.cisco.com/trex/doc/cp_stl_docs/api/field_engine.html
1913 The following example demonstrates creating a SYN attack from many src addresses to one server.
1915 *File*:: link:{github_stl_path}/syn_attack.py[stl/syn_attack.py]
1919 def create_stream (self):
1922 base_pkt = Ether()/IP(dst="48.0.0.1")/TCP(dport=80,flags="S") <1>
1926 vm = STLScVmRaw( [ STLVmFlowVar(name="ip_src",
1927 min_value="16.0.0.0",
1928 max_value="18.0.0.254",
1929 size=4, op="random"), <2>
1931 STLVmFlowVar(name="src_port",
1934 size=2, op="random"), <3>
1936 STLVmWrFlowVar(fv_name="ip_src", pkt_offset= "IP.src" ), <4>
1938 STLVmFixIpv4(offset = "IP"), # fix checksum <5>
1940 STLVmWrFlowVar(fv_name="src_port", <6>
1941 pkt_offset= "TCP.sport") # U
1946 pkt = STLPktBuilder(pkt = base_pkt,
1949 return STLStream(packet = pkt,
1950 random_seed = 0x1234,# can be removed. will give the same random value any run
1953 <1> Creates SYN packet using Scapy .
1954 <2> Defines a stream variable `name=ip_src`, size 4 bytes, for IPv4.
1955 <3> Defines a stream variable `name=src_port`, size 2 bytes, for port.
1956 <4> Writes `ip_src` stream var into `IP.src` packet offset. Scapy calculates the offset. Can specify `IP:1.src` for a second IP header in the packet.
1957 <5> Fixes IPv4 checksum. Provides the header name `IP`. Can specify `IP:1` for a second IP.
1958 <6> Writes `src_port` stream var into `TCP.sport` packet offset. TCP checksum is not updated here.
1960 WARNING: Original Scapy cannot calculate offset for a header/field by name. This offset capability will not work for all cases. In some complex cases, Scapy may rebuild the header. In such cases, specify the offset as a number.
1965 [format="csv",cols="1^,2<,2<", options="header",width="40%"]
1967 pkt,Client IPv4,Client Port
1968 1 , 17.152.71.218 , 5814
1969 2 , 17.7.6.30 , 26810
1970 3 , 17.3.32.200 , 1810
1971 4 , 17.135.236.168 , 55810
1972 5 , 17.46.240.12 , 1078
1973 6 , 16.133.91.247 , 2323
1977 ==== Tutorial: Field Engine, Tuple Generator
1979 The following example creates multiple flows from the same packet template. The Tuple Generator instructions are used to create two stream variables for IP and port. See link:trex_rpc_server_spec.html#_object_type_em_vm_em_a_id_vm_obj_a[here]
1982 *File*:: link:{github_stl_path}/udp_1pkt_tuple_gen.py[stl/udp_1pkt_tuple_gen.py]
1986 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
1988 pad = max(0, size - len(base_pkt)) * 'x'
1990 vm = STLScVmRaw( [ STLVmTupleGen ( ip_min="16.0.0.1", <1>
1994 name="tuple"), # define tuple gen
1996 STLVmWrFlowVar (fv_name="tuple.ip", pkt_offset= "IP.src" ), <2>
1997 STLVmFixIpv4(offset = "IP"),
1998 STLVmWrFlowVar (fv_name="tuple.port", pkt_offset= "UDP.sport" ) <3>
2002 pkt = STLPktBuilder(pkt = base_pkt/pad,
2005 <1> Defines a struct with two dependent variables: tuple.ip, tuple.port
2006 <2> Writes the tuple.ip variable to `IPv4.src` field offset.
2007 <3> Writes the tuple.port variable to `UDP.sport` field offset. Set `UDP.checksum` to 0.
2008 // Hanoch: add how to set UDP.checksum to 0
2012 [format="csv",cols="1^,2^,1^", options="header",width="40%"]
2014 pkt,Client IPv4,Client Port
2023 * Number of clients: 2: 16.0.0.1 and 16.0.0.2
2024 * Number of flows is limited to 129020: (2 * (65535-1025))
2025 * The stream variable size should match the size of the FlowVarWr instruction.
2027 ==== Tutorial: Field Engine, write to a bit-field packet
2029 The following example writes a stream variable to a bit field packet variable. In this example, an MPLS label field is changed.
2032 [cols="32", halign="center",width="50%"]
2034 20+<|Label 3+<|TC 1+<|S 8+<|TTL|
2035 0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
2038 *File*:: link:{github_stl_path}/udp_1pkt_mpls_vm.py[stl/udp_1pkt_mpls_vm.py]
2043 def create_stream (self):
2044 # 2 MPLS label the internal with s=1 (last one)
2046 MPLS(label=17,cos=1,s=0,ttl=255)/
2047 MPLS(label=0,cos=1,s=1,ttl=12)/
2048 IP(src="16.0.0.1",dst="48.0.0.1")/
2049 UDP(dport=12,sport=1025)/('x'*20)
2051 vm = STLScVmRaw( [ STLVmFlowVar(name="mlabel", <1>
2054 size=2, op="inc"), # 2 bytes var <2>
2055 STLVmWrMaskFlowVar(fv_name="mlabel",
2056 pkt_offset= "MPLS:1.label", <3>
2058 mask=0xFFFFF000,shift=12) # write to 20bit MSB
2062 # burst of 100 packets
2063 return STLStream(packet = STLPktBuilder(pkt = pkt ,vm = vm),
2064 mode = STLTXSingleBurst( pps = 1, total_pkts = 100) )
2067 <1> Defines a variable size of 2 bytes.
2068 <2> Writes the stream variable label with a shift of 12 bits, with a 20-bit MSB mask. Cast the stream variables of 2 bytes to 4 bytes.
2069 <3> Change the second MPLS header.
2072 ==== Tutorial: Field Engine, Random packet size
2074 The following example demonstrates varies the packet size randomly, as follows:
2076 1. Defines the template packet with maximum size.
2077 2. Trims the packet to the size you want.
2078 3. Updates the packet fields according to the new size.
2080 *File*:: link:{github_stl_path}/udp_rand_len_9k.py[stl/udp_rand_len_9k.py]
2085 def create_stream (self):
2088 p_l3 = IP(src="16.0.0.1",dst="48.0.0.1")
2089 p_l4 = UDP(dport=12,sport=1025)
2090 pyld_size = max(0, self.max_pkt_size_l3 - len(p_l3/p_l4))
2091 base_pkt = p_l2/p_l3/p_l4/('\x55'*(pyld_size))
2093 l3_len_fix =-(len(p_l2))
2094 l4_len_fix =-(len(p_l2/p_l3))
2098 vm = STLScVmRaw( [ STLVmFlowVar(name="fv_rand", <1>
2100 max_value=len(base_pkt),
2104 STLVmTrimPktSize("fv_rand"), # total packet size <2>
2106 STLVmWrFlowVar(fv_name="fv_rand", <3>
2107 pkt_offset= "IP.len",
2108 add_val=l3_len_fix), # fix ip len
2110 STLVmFixIpv4(offset = "IP"),
2112 STLVmWrFlowVar(fv_name="fv_rand", <4>
2113 pkt_offset= "UDP.len",
2114 add_val=l4_len_fix) # fix udp len
2118 <1> Defines a random stream variable with the maximum size of the packet.
2119 <2> Trims the packet size to the `fv_rand` value.
2120 <3> Fixes ip.len to reflect the packet size.
2121 <4> Fixes udp.len to reflect the packet size.
2124 ==== Tutorial: Field Engine, Significantly improve performance
2126 anchor:trex_cache_mbuf[]
2128 The following example demonstrates a way to significantly improve Field Engine performance in case it is needed.
2130 Field Engine has a cost of CPU instructions and CPU memory bandwidth. There is a way to significantly improve performance by caching the packets and run the Field Engine offline(before sending the packets).
2131 The limitation is that you can have only a limited number of packets that can be cached (order or 10K depends how much memory you have).
2132 For example a program that change the src_ip to a random value can't be utilized this technique and still have random src_ip.
2133 Usually this is done with small packets (64bytes) where performance is an issue. This method can improve long packets senario with a complex Field Engine program.
2135 *File*:: link:{github_stl_path}/udp_1pkt_src_ip_split.py[stl/udp_1pkt_src_ip_split.py]
2140 def create_stream (self):
2141 # create a base packet and pad it to size
2142 size = self.fsize - 4; # no FCS
2144 base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
2146 pad = max(0, size - len(base_pkt)) * 'x'
2148 vm = STLScVmRaw( [ STLVmFlowVar ( "ip_src",
2149 min_value="10.0.0.1",
2150 max_value="10.0.0.255",
2151 size=4, step=1,op="inc"),
2153 STLVmWrFlowVar (fv_name="ip_src",
2154 pkt_offset= "IP.src" ),
2156 STLVmFixIpv4(offset = "IP")
2158 split_by_field = "ip_src",
2159 cache_size =255 # the cache size <1>
2162 pkt = STLPktBuilder(pkt = base_pkt/pad,
2165 stream = STLStream(packet = pkt,
2170 <1> Cache 255 packets. The range is the same as `ip_src` stream variable
2172 This FE program will run *x2-5 faster* compared to native (without cache).
2173 In this specific example the output will be *exactly* the same.
2175 Again the limitations of this method are:
2177 1. The total number of cache packets for all the streams all the ports in limited by the memory pool (range of ~10-40K)
2178 2. There could be cases that the cache options won't be exactly the same as the normal program, for example, in case of a program that step in prime numbers or with a random variable
2181 ==== Tutorial: New Scapy header
2183 The following example uses a header that is not supported by Scapy by default. The example demonstrates VXLAN support.
2185 *File*:: link:{github_stl_path}/udp_1pkt_vxlan.py[stl/udp_1pkt_vxlan.py]
2190 # Adding header that does not exists yet in Scapy
2191 # This was taken from pull request of Scapy
2195 # RFC 7348 - Virtual eXtensible Local Area Network (VXLAN): <1>
2196 # A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks
2197 # http://tools.ietf.org/html/rfc7348
2198 _VXLAN_FLAGS = ['R' for i in range(0, 24)] + ['R', 'R', 'R', 'I', 'R', 'R', 'R', 'R', 'R']
2200 class VXLAN(Packet):
2202 fields_desc = [FlagsField("flags", 0x08000000, 32, _VXLAN_FLAGS),
2203 ThreeBytesField("vni", 0),
2204 XByteField("reserved", 0x00)]
2206 def mysummary(self):
2207 return self.sprintf("VXLAN (vni=%VXLAN.vni%)")
2209 bind_layers(UDP, VXLAN, dport=4789)
2210 bind_layers(VXLAN, Ether)
2213 class STLS1(object):
2215 def __init__ (self):
2218 def create_stream (self):
2219 pkt = Ether()/IP()/UDP(sport=1337,dport=4789)/VXLAN(vni=42)/Ether()/IP()/('x'*20) <2>
2223 # burst of 17 packets
2224 return STLStream(packet = STLPktBuilder(pkt = pkt ,vm = []),
2225 mode = STLTXSingleBurst( pps = 1, total_pkts = 17) )
2229 <1> Downloads and adds a Scapy header from the specified location. Alternatively, write a Scapy header.
2230 <2> Apply the header.
2232 For more information how to define headers see link:http://www.secdev.org/projects/scapy/doc/build_dissect.html[Adding new protocols] in the Scapy documentation.
2235 ==== Tutorial: Field Engine, Multiple Clients
2237 The following example generates traffic from many clients with different IP/MAC addresses to one server.
2239 // Please leave this comment - helping rendition of image below.
2241 image::images/stl_multiple_clients_01b.png[title="Multiple clients to single server",align="left",width="80%", link="images/stl_multiple_clients_01b.png"]
2243 // OBSOLETEimage::images/stl_tut_12.png[title="client->server",align="left",width={p_width}, link="images/stl_tut_12.png"]
2245 1. Send a gratuitous ARP from B->D with server IP/MAC (58.55.1.1).
2246 2. DUT learns the ARP of server IP/MAC (58.55.1.1).
2247 3. Send traffic from A->C with many client IP/MAC addresses.
2251 Base source IPv4 : 55.55.1.1
2252 Destination IPv4: 58.55.1.1
2254 Increment src ipt portion starting at 55.55.1.1 for 'n' number of clients (55.55.1.1, 55.55.1.2)
2255 Src MAC: start with 0000.dddd.0001, increment mac in steps of 1
2256 Dst MAC: Fixed - 58.55.1.1
2258 The following sends a link:https://wiki.wireshark.org/Gratuitous_ARP[gratuitous ARP] from the TRex server port for this server (58.0.0.1).
2262 def create_stream (self):
2263 # create a base packet and pad it to size
2264 base_pkt = Ether(src="00:00:dd:dd:01:01",
2265 dst="ff:ff:ff:ff:ff:ff")/
2266 ARP(psrc="58.55.1.1",
2267 hwsrc="00:00:dd:dd:01:01",
2268 hwdst="00:00:dd:dd:01:01",
2272 Then traffic can be sent from client side: A->C
2274 *File*:: link:{github_stl_path}/udp_1pkt_range_clients_split.py[stl/udp_1pkt_range_clients_split.py]
2278 class STLS1(object):
2280 def __init__ (self):
2281 self.num_clients =30000 # max is 16bit
2284 def create_stream (self):
2286 # create a base packet and pad it to size
2287 size = self.fsize - 4 # no FCS
2288 base_pkt = Ether(src="00:00:dd:dd:00:01")/
2289 IP(src="55.55.1.1",dst="58.55.1.1")/UDP(dport=12,sport=1025)
2290 pad = max(0, size - len(base_pkt)) * 'x'
2292 vm = STLScVmRaw( [ STLVmFlowVar(name="mac_src",
2294 max_value=self.num_clients,
2295 size=2, op="inc"), # 1 byte varible, range 1-10
2297 STLVmWrFlowVar(fv_name="mac_src", pkt_offset= 10), <1>
2298 STLVmWrFlowVar(fv_name="mac_src" ,
2299 pkt_offset="IP.src",
2300 offset_fixup=2), <2>
2301 STLVmFixIpv4(offset = "IP")
2303 ,split_by_field = "mac_src" # split
2306 return STLStream(packet = STLPktBuilder(pkt = base_pkt/pad,vm = vm),
2307 mode = STLTXCont( pps=10 ))
2309 <1> Writes the stream variable `mac_src` with an offset of 10 (last 2 bytes of `src_mac` field). The offset is specified explicitly as 10 bytes from the beginning of the packet.
2310 <2> Writes the stream variable `mac_src` with an offset determined by the offset of `IP.src` plus the `offset_fixup` of 2.
2313 ==== Tutorial: Field Engine, many clients with ARP
2315 In the following example, there are two Switchs SW1 and SW2.
2316 TRex port 0 is connected to SW1 and TRex port 1 is connected to SW2.
2317 There are 253 hosts connected to SW1 and SW2 with two network ports.
2319 .Client side the network of the hosts
2320 [cols="3<,3<", options="header",width="50%"]
2322 | Name | Description
2323 | TRex port 0 MAC | 00:00:01:00:00:01
2324 | TRex port 0 IPv4 | 16.0.0.1
2325 | IPv4 host client side range | 16.0.0.2-16.0.0.254
2326 | MAC host client side range | 00:00:01:00:00:02-00:00:01:00:00:FE
2330 .Server side the network of the hosts
2331 [cols="3<,3<", options="header",width="50%"]
2333 | Name | Description
2334 | TRex port 1 MAC | 00:00:02:00:00:01
2335 | TRex port 1 IPv4 | 48.0.0.1
2336 | IPv4 host server side range | 48.0.0.2-48.0.0.254
2337 | MAC host server side range | 00:00:02:00:00:02-00:00:02:00:00:FE
2340 image::images/stl_arp.png[title="arp/nd",align="left",width={p_width}, link="images/stl_arp.png"]
2342 In the following example, there are two Switchs SW1 and SW2.
2343 TRex port 0 is connected to SW1 and TRex port 1 is connected to SW2
2344 In this example, because there are many hosts connected to the same network using SW1 and not as a next hope, we would like to teach SW1 the MAC addresses of the hosts and not to send the traffic directly to the hosts MAC (as it is unknown)
2345 For that we would send an ARP to all the hosts (16.0.0.2-16.0.0.254) from TRex port 0 and gratuitous ARP from server side (48.0.0.1) TRex port 1 as the first stage of the test
2347 So the step would be like that:
2349 1. Send a gratuitous ARP from TRex port 1 with server IP/MAC (48.0.0.1) after this stage SW2 will know that 48.0.0.1 is located after this port of SW2.
2350 2. Send ARP request for all hosts from port 0 with a range of 16.0.0.2-16.0.0.254 after this stage all switch ports will learn the PORT/MAC locations. Without this stage the first packets from TRex port 0 will be flooded to all Switch ports.
2351 3. send traffic from TRex0->clients, port 1->servers
2354 .ARP traffic profile
2358 base_pkt = Ether(dst="ff:ff:ff:ff:ff:ff")/
2359 ARP(psrc="16.0.0.1",hwsrc="00:00:01:00:00:01", pdst="16.0.0.2") <1>
2361 vm = STLScVmRaw( [ STLVmFlowVar(name="mac_src", min_value=2, max_value=254, size=2, op="inc"), <2>
2362 STLVmWrFlowVar(fv_name="mac_src" ,pkt_offset="ARP.pdst",offset_fixup=2),
2364 ,split_by_field = "mac_src" # split
2369 <1> ARP packet with TRex port 0 MAC and IP and pdst as variable.
2370 <2> Write it to `ARP.pdst`.
2373 .Gratuitous ARP traffic profile
2377 base_pkt = Ether(src="00:00:02:00:00:01",dst="ff:ff:ff:ff:ff:ff")/
2378 ARP(psrc="48.0.0.1",hwsrc="00:00:02:00:00:01",
2379 hwdst="00:00:02:00:00:01", pdst="48.0.0.1") <1>
2382 <1> G ARP packet with TRex port 1 MAC and IP no need a VM.
2385 =====================================================================
2386 This principal can be done for IPv6 too. ARP could be replaced with Neighbor Solicitation IPv6 packet.
2387 =====================================================================
2389 ==== Tutorial: Field Engine, split to core
2391 Post v2.08 version split to core directive was deprecated and was kept for backward compatibility.
2392 The new implementation is always to split as if the profile was sent from one core.
2393 The user of TRex is oblivious to the number of cores.
2398 def create_stream (self):
2401 base_pkt = Ether()/IP(dst="48.0.0.1")/TCP(dport=80,flags="S")
2405 vm = STLScVmRaw( [ STLVmFlowVar(name="ip_src",
2406 min_value="16.0.0.0",
2407 max_value="16.0.0.254",
2411 STLVmWrFlowVar(fv_name="ip_src", pkt_offset= "IP.src" ),
2413 STLVmFixIpv4(offset = "IP"), # fix checksum
2415 ,split_by_field = "ip_src" <1>
2419 <1> Deprecated split by field. not used any more (post v2.08)
2422 *Some rules regarding split stream variables and burst/multi-burst*::
2424 * When using burst/multi-burst, the number of packets are split to the defualt number of threads specified in the YAML cofiguraiton file, without any need to explicitly split the threads.
2425 * When the number of packets in a burst is smaller than the number of threads, one thread handles the burst.
2426 * In the case of a stream with a burst of *1* packet, only the first DP thread handles the stream.
2428 ==== Tutorial: Field Engine, Null stream
2430 The following example creates a stream with no packets. The example uses the inter-stream gap (ISG) of the Null stream, and then starts a new stream. Essentially, this uses one property of the stream (ISG) without actually including packets in the stream.
2432 This method can create loops like the following:
2434 image::images/stl_null_stream_02.png[title="Null stream",align="left",width={p_width_1}, link="images/stl_null_stream_02.png"]
2436 1. S1 - Sends a burst of packets, then proceed to stream NULL.
2437 2. NULL - Waits the inter-stream gap (ISG) time, then proceed to S1.
2439 Null stream configuration:
2442 2. Number of packets: 0
2445 ==== Tutorial: Field Engine, Stream Barrier (Split)
2447 *(Future Feature - not yet implemented)*
2449 In some situations, it is necessary to split streams into threads in such a way that specific streams will continue only after all the threads have passed the same path. In the figure below, a barrier ensures that stream S3 starts only after all threads of S2 are complete.
2451 image::images/stl_barrier_03.png[title="Stream Barrier",align="left",width={p_width}, link="images/stl_barrier_03.png"]
2453 ==== Tutorial: PCAP file to one stream
2455 *Goal*:: Load a stream template packet from a pcap file instead of Scapy.
2457 Assumption: The pcap file contains only one packet. If the pcap file contains more than one packet, this procedure loads only the first packet.
2459 *File*:: link:{github_stl_path}/udp_1pkt_pcap.py[stl/udp_1pkt_pcap.py]
2464 def get_streams (self, direction = 0, **kwargs):
2465 return [STLStream(packet =
2466 STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"), # path relative to pwd <1>
2467 mode = STLTXCont(pps=10)) ]
2470 <1> Takes the packet from the pcap file, relative to the directory in which you are running the script.
2473 *File*:: link:{github_stl_path}/udp_1pkt_pcap_relative_path.py[udp_1pkt_pcap_relative_path.py]
2479 def get_streams (self, direction = 0, **kwargs):
2480 return [STLStream(packet = STLPktBuilder(pkt ="yaml/udp_64B_no_crc.pcap",
2481 path_relative_to_profile = True), <1>
2482 mode = STLTXCont(pps=10)) ]
2485 <1> Takes the packet from the pcap file, relative to the directory of the *profile* file location.
2489 ==== Tutorial: Teredo tunnel (IPv6 over IPv4)
2491 The following example demonstrates creating an IPv6 packet within an IPv4 packet, and creating a range of IP addresses.
2493 *File*:: link:{github_stl_path}/udp_1pkt_ipv6_in_ipv4.py[stl/udp_1pkt_ipv6_in_ipv4.py]
2497 def create_stream (self):
2498 # Teredo Ipv6 over Ipv4
2499 pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
2500 UDP(dport=3797,sport=3544)/
2501 IPv6(dst="2001:0:4137:9350:8000:f12a:b9c8:2815",
2502 src="2001:4860:0:2001::68")/
2503 UDP(dport=12,sport=1025)/ICMPv6Unknown()
2506 # tuple gen for inner Ipv6
2507 STLVmTupleGen ( ip_min="16.0.0.1", ip_max="16.0.0.2",
2508 port_min=1025, port_max=65535,
2511 STLVmWrFlowVar (fv_name="tuple.ip",
2512 pkt_offset= "IPv6.src",
2513 offset_fixup=12 ), <2>
2514 STLVmWrFlowVar (fv_name="tuple.port",
2515 pkt_offset= "UDP:1.sport" ) <3>
2519 <1> Defines a stream struct called tuple with the following variables: `tuple.ip`, `tuple.port`
2520 <2> Writes a stream `tuple.ip` variable with an offset determined by the `IPv6.src` offset plus the `offset_fixup` of 12 bytes (only 4 LSB).
2521 <3> Writes a stream `tuple.port` variable into the second UDP header.
2524 ==== Tutorial: Mask instruction
2526 STLVmWrMaskFlowVar is single-instruction-multiple-data Field Engine instruction. The pseudocode is as follows:
2531 uint32_t val=(cast_to_size)rd_from_variable("name") # read flow-var
2532 val+=m_add_value # add value
2534 if (m_shift>0) { # shift
2542 pkt_val=rd_from_pkt(pkt_offset) # RMW
2543 pkt_val = (pkt_val & ~m_mask) | (val & m_mask)
2544 wr_to_pkt(pkt_offset,pkt_val)
2550 In this example, STLVmWrMaskFlowVar casts a stream variable with 2 bytes to be 1 byte.
2554 vm = STLScVmRaw( [ STLVmFlowVar(name="mac_src",
2557 size=2, op="dec",step=1),
2558 STLVmWrMaskFlowVar(fv_name="mac_src",
2561 mask=0xff) # mask command ->write it as one byte
2570 In this example, STLVmWrMaskFlowVar shifts a variable by 8, which effectively multiplies by 256.
2575 vm = STLScVmRaw( [ STLVmFlowVar(name="mac_src",
2578 size=2, op="dec",step=1),
2579 STLVmWrMaskFlowVar(fv_name="mac_src",
2583 shift=8) # take the var shift it 8 (x256) write only to LSB
2590 [format="csv",cols="1^", options="header",width="20%"]
2600 In this example, STLVmWrMaskFlowVar instruction to generate the values shown in the table below as offset values for `pkt_offset`.
2604 vm = STLScVmRaw( [ STLVmFlowVar(name="mac_src",
2609 STLVmWrMaskFlowVar(fv_name="mac_src",
2618 <1> Divides the value of `mac_src` by 2, and writes the LSB. For every two packets, the value written is changed.
2621 [format="csv",cols="1^", options="header",width="20%"]
2634 ==== Tutorial: Advanced traffic profile
2638 * Define a different profile to operate in each traffic direction.
2639 * Define a different profile for each port.
2640 * Tune a profile tune by the arguments of tunables.
2642 Every traffic profile must define the following function:
2646 def get_streams (self, direction = 0, **kwargs)
2649 `direction` is a mandatory field, required for any profile being loaded.
2651 A profile can be given any key-value pairs which can be used to customize this profile. These are called "tunables".
2653 The profile defines which tunables can be input to customize output.
2655 *Usage notes for defining parameters*::
2657 * All parameters require default values.
2658 * A profile must be loadable with no parameters specified.
2659 * **kwargs (see Python documentation for information about keyworded arguments) contain all of the automatically provided values which are not tunables.
2660 * Every tuanble must be expressed as key-value pair with default value.
2663 For example, for the profile below, 'pcap_with_vm.py':
2665 * The profile receives 'direction' as a tunable and mandatory field.
2666 * The profile defines 4 additional tunables.
2667 * Automatic values such as 'port_id' which are not tunables will be provided on kwargs.
2670 *File*:: link:{github_stl_path}/pcap_with_vm.py[stl/pcap_with_vm.py]
2674 def get_streams (self,
2678 ip_src_range = None,
2679 ip_dst_range = {'start' : '10.0.0.1', 'end': '10.0.0.254'},
2684 `direction` is a tunable that is always provided by the API/console when loading a profile, but it can be overridden by the user. It is used to make the traffic profile more usable - for example, as a bi-directional profile. However, the profile can ignore this parameter.
2686 By default, `direction` is equal to port_id % 2, so *even* numbered ports are provided with ''0'' and the *odd* numbered ports with ''1''.
2690 def get_streams (self, direction = 0,**kwargs):
2695 return [STLHltStream(tcp_src_port_mode = 'decrement',
2696 tcp_src_port_count = 10,
2697 tcp_src_port = 1234,
2698 tcp_dst_port_mode = 'increment',
2699 tcp_dst_port_count = 10,
2700 tcp_dst_port = 1234,
2701 name = 'test_tcp_ranges',
2702 direction = direction,
2707 <1> Specifies different rates (100 and 200) based on direction.
2716 * Interfaces 0 and 2: direction 0
2717 * Interfaces 1 and 3: direction 1
2719 The rate changes accordingly.
2721 *Customzing Profiles Using ''port_id''*::
2723 Keyworded arguments (**kwargs) provide default values that are passed along to the profile.
2725 In the following, 'port_id' (port ID for the profile) is a **kwarg. Using port_id, you can define a complex profile based on different ID of ports, providing a different profile for each port.
2731 def create_streams (self, direction = 0, **args):
2733 port_id = args.get('port_id')
2736 return [STLHltStream(tcp_src_port_mode = 'decrement',
2737 tcp_src_port_count = 10,
2738 tcp_src_port = 1234,
2739 tcp_dst_port_mode = 'increment',
2740 tcp_dst_port_count = 10,
2741 tcp_dst_port = 1234,
2742 name = 'test_tcp_ranges',
2743 direction = direction,
2749 return STLHltStream(
2750 #enable_auto_detect_instrumentation = '1', # not supported yet
2751 ip_dst_addr = '192.168.1.3',
2753 ip_dst_mode = 'increment',
2754 ip_dst_step = '0.0.0.1',
2755 ip_src_addr = '192.168.0.3',
2757 ip_src_mode = 'increment',
2758 ip_src_step = '0.0.0.1',
2762 l3_imix2_size = 570,
2764 l3_imix3_size = 1518,
2765 l3_protocol = 'ipv4',
2766 length_mode = 'imix',
2767 #mac_dst_mode = 'discovery', # not supported yet
2768 mac_src = '00.00.c0.a8.00.03',
2769 mac_src2 = '00.00.c0.a8.01.03',
2770 pkts_per_burst = '200000',
2771 rate_percent = '0.4',
2772 transmit_mode = 'continuous',
2774 direction = direction,
2781 *Full example using the TRex Console*::
2783 The following command displays information about tunables for the pcap_with_vm.py traffic profile.
2787 -=TRex Console v1.1=-
2789 Type 'help' or '?' for supported actions
2791 trex>profile -f stl/pcap_with_vm.py
2793 Profile Information:
2796 General Information:
2797 Filename: stl/pcap_with_vm.py
2800 Specific Information:
2802 Tunables: ['direction = 0', 'ip_src_range = None', 'loop_count = 5', 'ipg_usec = 10.0',
2803 "ip_dst_range = {'start': '10.0.0.1', 'end': '10.0.0.254'}"]
2808 One can provide tunables on all those fields. The following command changes some:
2812 trex>start -f stl/pcap_with_vm.py -t ipg_usec=15.0,loop_count=25
2814 Removing all streams from port(s) [0, 1, 2, 3]: [SUCCESS]
2817 Attaching 5 streams to port(s) [0]: [SUCCESS]
2820 Attaching 5 streams to port(s) [1]: [SUCCESS]
2823 Attaching 5 streams to port(s) [2]: [SUCCESS]
2826 Attaching 5 streams to port(s) [3]: [SUCCESS]
2829 Starting traffic on port(s) [0, 1, 2, 3]: [SUCCESS]
2837 The following command customizes these to different ports:
2842 trex>start -f stl/pcap_with_vm.py --port 0 1 -t ipg_usec=15.0,loop_count=25#ipg_usec=100,loop_count=300
2844 Removing all streams from port(s) [0, 1]: [SUCCESS]
2847 Attaching 5 streams to port(s) [0]: [SUCCESS]
2850 Attaching 5 streams to port(s) [1]: [SUCCESS]
2853 Starting traffic on port(s) [0, 1]: [SUCCESS]
2861 ==== Tutorial: Per stream statistics
2863 * Per stream statistics are implemented using hardware assist when possible (examples: Intel X710/XL710 NIC flow director rules).
2864 * With other NICs (examples: Intel I350, 82599), per stream statistics are implemented in software.
2866 ** User chooses 32-bit packet group ID (pg_id) for each stream that need statistic reporting. Same pg_id can be used for more than one stream. In this case, statistics for all streams with the same pg_id will be combined.
2867 ** The IPv4 identification (or IPv6 flow label in case of IPv6 packet) field of the stream is changed to a value within the reserved range 0xff00 to 0xffff (0xff00 to 0xfffff in case of IPv6). Note that if a stream for which no statistics are needed has an IPv4 Id (or IPv6 flow label) in the reserved range, it is changed (the left bit becomes 0).
2868 ** Software implementation: Hardware rules are used to direct packets from relevant streams to rx thread, where they are counted.
2869 ** Hardware implementation: Hardware rules are inserted to count packets from relevant streams.
2870 * Summed up statistics (per stream, per port) is sent using a link:http://zguide.zeromq.org/[ZMQ] async channel to clients.
2874 * The feature supports following packet types:
2875 ** IPv4 over Ethernet
2876 ** IPv4 with one VLAN tag (except 82599 which does not support this type of packet)
2877 ** IPv6 over Ethernet (except 82599 which does not support this type of packet)
2878 ** IPv6 with one VLAN tag (except 82599 which does not support this type of packet)
2880 * Maximum number of concurrent streams (with different pg_id) on which statistics may be collected: 127
2882 Two examples follow, one using the console and the other using the Python API.
2886 The following simple traffic profile defines 2 streams and configures them with 2 different PG IDs.
2888 *File*:: link:{github_stl_path}/flow_stats.py[stl/flow_stats.py]
2893 class STLS1(object):
2895 def get_streams (self, direction = 0):
2896 return [STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"),
2897 mode = STLTXCont(pps = 1000),
2898 flow_stats = STLFlowStats(pg_id = 7)), <1>
2900 STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_594B_no_crc.pcap"),
2901 mode = STLTXCont(pps = 5000),
2902 flow_stats = STLFlowStats(pg_id = 12)) <2>
2907 <1> Assigned to PG ID 7
2908 <2> Assigned to PG ID 12
2910 The following command injects this to the console and uses the textual user interface (TUI) to display the TRex activity:
2914 trex>start -f stl/flow_stats.py --port 0
2916 Removing all streams from port(s) [0]: [SUCCESS]
2919 Attaching 2 streams to port(s) [0]: [SUCCESS]
2922 Starting traffic on port(s) [0]: [SUCCESS]
2931 --------------------------------------------------
2932 Tx pps | 5.00 Kpps | 999.29 pps #<1>
2933 Tx bps L2 | 23.60 Mbps | 479.66 Kbps
2934 Tx bps L1 | 24.40 Mbps | 639.55 Kbps
2936 Rx pps | 5.00 Kpps | 999.29 pps #<2>
2937 Rx bps | N/A | N/A #<3>
2939 opackets | 222496 | 44500
2940 ipackets | 222496 | 44500
2941 obytes | 131272640 | 2670000
2942 ibytes | N/A | N/A #<3>
2944 tx_pkts | 222.50 Kpkts | 44.50 Kpkts
2945 rx_pkts | 222.50 Kpkts | 44.50 Kpkts
2946 tx_bytes | 131.27 MB | 2.67 MB
2947 rx_bytes | N/A | N/A #<3>
2950 <1> Tx bandwidth of the streams matches the configured values.
2951 <2> Rx bandwidth (999.29 pps) matches the Tx bandwidth (999.29 pps), indicating that there were no drops.
2952 <3> RX BPS is not supported on this platform (no hardware support for BPS), so TRex displays N/A.
2955 *Flow Stats Using The Python API*::
2957 The Python API example uses the following traffic profile:
2961 def rx_example (tx_port, rx_port, burst_size):
2967 pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/
2968 UDP(dport=12,sport=1025)/IP()/'a_payload_example')
2970 s1 = STLStream(name = 'rx',
2972 flow_stats = STLFlowStats(pg_id = 5), <1>
2973 mode = STLTXSingleBurst(total_pkts = 5000,
2980 # prepare our ports - TX/RX
2981 c.reset(ports = [tx_port, rx_port])
2983 # add the stream to the TX port
2984 c.add_streams([s1], ports = [tx_port])
2986 # start and wait for completion
2987 c.start(ports = [tx_port])
2988 c.wait_on_traffic(ports = [tx_port])
2990 # fetch stats for PG ID 5
2991 flow_stats = c.get_stats()['flow_stats'].get(5) <2>
2993 tx_pkts = flow_stats['tx_pkts'].get(tx_port, 0) <2>
2994 tx_bytes = flow_stats['tx_bytes'].get(tx_port, 0) <2>
2995 rx_pkts = flow_stats['rx_pkts'].get(rx_port, 0) <2>
2998 <1> Configures the stream to use PG ID 5.
2999 <2> The structure of the object ''flow_stats'' is described below.
3001 ==== Tutorial: flow_stats object structure
3003 The flow_stats object is a dictionary whose keys are the configured PG IDs. The next level is a dictionary containing 'tx_pkts', 'tx_bytes', 'rx_pkts', and 'rx_bytes' (on supported HW). Each of these keys contains a dictionary of per port values.
3005 The following shows a flow_stats object for 3 PG IDs after a specific run:
3010 5: {'rx_pkts' : {0: 0, 1: 0, 2: 500000, 3: 0, 'total': 500000},
3011 'tx_bytes' : {0: 0, 1: 39500000, 2: 0, 3: 0, 'total': 39500000},
3012 'tx_pkts' : {0: 0, 1: 500000, 2: 0, 3: 0, 'total': 500000}},
3014 7: {'rx_pkts' : {0: 0, 1: 0, 2: 0, 3: 288, 'total': 288},
3015 'tx_bytes' : {0: 17280, 1: 0, 2: 0, 3: 0, 'total': 17280},
3016 'tx_pkts' : {0: 288, 1: 0, 2: 0, 3: 0, 'total': 288}},
3018 12: {'rx_pkts' : {0: 0, 1: 0, 2: 0, 3: 1439, 'total': 1439},
3019 'tx_bytes': {0: 849600, 1: 0, 2: 0, 3: 0, 'total': 849600},
3020 'tx_pkts' : {0: 1440, 1: 0, 2: 0, 3: 0, 'total': 1440}}
3025 ==== Tutorial: Per stream latency/jitter/packet errors
3027 * Per stream latency/jitter is implemented by software. This is an extension of the per stream statistics. Meaning, whenever you choose to get latency info for a stream, the statistics described
3028 in the "Per stream statistics" section is also available.
3030 ** User chooses 32-bit packet group ID (pg_id) for each stream that need latency reporting. pg_id should be unique per stream.
3031 ** The IPv4 identification field (or IPv6 flow label in case of IPv6 packet) of the stream is changed to some defined constant value (in the reserved range described in the "per stream statistics" section), in order to signal the hardware to pass the stream to software.
3032 ** Last 16 bytes of the packet payload is used to pass needed information. Information contains ID of the stream, packet sequence number (per stream), timestamp of packet transmission.
3034 * Gathered info (per stream) is sent using a link:http://zguide.zeromq.org/[ZMQ] async channel to clients.
3038 * The feature supports following packet types:
3039 ** IPv4 over Ethernet
3040 ** IPv4 with one VLAN tag (except 82599 which does not support this type of packet)
3041 ** IPv6 over Ethernet (except 82599 which does not support this type of packet)
3042 ** IPv6 with one VLAN tag (except 82599 which does not support this type of packet)
3043 * Packets must contain at least 16 bytes of payload.
3044 * Each stream must have unique pg_id number. This also means that a given "latency collecting" stream can't be transmitted from two interfaces in parallel (internally it means that there are two streams).
3045 * Maximum number of concurrent streams (with different pg_id) on which latency info may be collected: 128 (This is in addition to the streams which collect per stream statistics).
3046 * Global multiplier does not apply to this type of stream. The reason is that latency streams are processed by software, so multiplying them might accidently overwhelm the RX core.
3047 This means that if you have profile with 1 latency stream, and 1 non latency stream, and you change the traffic multipler, latency stream keeps the same rate. If you want to change
3048 the rate of a latency stream, you need to manually edit your profile file. Usually this is not necessary, since normally you stress the system using non latency stream, and (in parallel) measure latency
3049 using constant rate latency stream.
3052 =====================================
3053 Latency streams are not supported in full line rate like normal streams. Both from, transmit and receive point of view. This is a design consideration to keep the latency measurement accurate and preserve CPU resource. One of the reason for doing so that in most cases it is enough to have a latency stream not in full rate. For example, if the required latency resolution is 10usec there is no need to send a latency stream in speed higher than 100KPPS- usually queues are built over time, so it is not possible that one packet will have a latency and another packet in the same path will not have the same latency. The none latency stream could be in full line rate (e.g. 100MPPS) to load the DUT while the low speed latency stream will measure this path latency.
3054 Don't expect the total latency streams rate to be higher than 1-5MPPS
3055 =====================================
3057 Two examples follow. One using the console and the other using the Python API.
3061 The following simple traffic profile defines 2 streams and configures them with 2 different PG IDs.
3063 *File*:: link:{github_stl_path}/flow_stats_latency.py[stl/flow_stats_latency.py]
3068 class STLS1(object):
3070 def get_streams (self, direction = 0):
3071 return [STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap"),
3072 mode = STLTXCont(pps = 1000),
3073 flow_stats = STLFlowLatencyStats(pg_id = 7)), <1>
3075 STLStream(packet = STLPktBuilder(pkt ="stl/yaml/udp_594B_no_crc.pcap"),
3076 mode = STLTXCont(pps = 5000),
3077 flow_stats = STLFlowLatencyStats(pg_id = 12)) <2>
3082 <1> Assigned to PG ID 7 , PPS would be *1000* regardless of the multplier
3083 <2> Assigned to PG ID 12, PPS would be *5000* regardless of the multplier
3085 The following command injects this to the console and uses the textual user interface (TUI) to display the TRex activity:
3089 trex>start -f stl/flow_stats.py --port 0
3093 Latency Statistics (usec)
3096 ----------------------------------------------
3097 Max latency | 0 | 0 #<1>
3098 Avg latency | 5 | 5 #<2>
3100 Last (max) | 3 | 4 #<3>
3116 <1> Maximum latency measured over the stream lifetime (in usec).
3117 <2> Average latency over the stream lifetime (usec).
3118 <3> Maximum latency measured between last two data reads from server (We currently read every 0.5 second).
3119 Numbers below are maximum latency for previous measuring periods, so we get latency history for last few seconds.
3120 <4> Jitter of latency measurements.
3121 <5> Indication of number of errors (it is the sum of seq_too_high and seq_too_low. You can see description in Python API doc below). In the future it will be possible to 'zoom in', to see specific counters.
3122 For now, if you need to see specific counters, you can use the Python API.
3125 An example of API usage is as follows
3127 *Example File*:: link:{github_stl_examples_path}/stl_flow_latency_stats.py[stl_flow_latency_stats.py]
3132 stats = c.get_stats()
3134 flow_stats = stats['flow_stats'].get(5)
3135 lat_stats = stats['latency'].get(5) <1>
3138 tx_pkts = flow_stats['tx_pkts'].get(tx_port, 0)
3139 tx_bytes = flow_stats['tx_bytes'].get(tx_port, 0)
3140 rx_pkts = flow_stats['rx_pkts'].get(rx_port, 0)
3141 drops = lat_stats['err_cntrs']['dropped']
3142 ooo = lat_stats['err_cntrs']['out_of_order']
3143 dup = lat_stats['err_cntrs']['dup']
3144 sth = lat_stats['err_cntrs']['seq_too_high']
3145 stl = lat_stats['err_cntrs']['seq_too_low']
3146 lat = lat_stats['latency']
3147 jitter = lat['jitter']
3148 avg = lat['average']
3149 tot_max = lat['total_max']
3150 last_max = lat['last_max']
3151 hist = lat ['histogram']
3153 # lat_stats will be in this format
3156 'err_cntrs':{ # error counters <2>
3157 u'dup':0, # Same sequence number was received twice in a row
3158 u'out_of_order':0, # Packets received with sequence number too low (We assume it is reorder)
3159 u'dropped':0 # Estimate of number of packets that were dropped (using seq number)
3160 u'seq_too_high':0, # seq number too high events
3161 u'seq_too_low':0, # seq number too low events
3164 'jitter':0, # in usec
3165 'average':15.2, # average latency (usec)
3166 'last_max':0, # last 0.5 sec window maximum latency (usec)
3167 'total_max':44, # maximum latency (usec)
3168 'histogram':[ # histogram of latency
3170 u'key':20, # bucket counting packets with latency in the range 20 to 30 usec
3171 u'val':489342 # number of samples that hit this bucket's range
3182 'key':0, # bucket counting packets with latency in the range 0 to 10 usec
3191 <1> Get the Latency dictionary
3192 <2> For calculating packet error events, we add sequence number to each packet's payload. We decide what went wrong only according to sequence number
3193 of last packet received and that of the previous packet. 'seq_too_low' and 'seq_too_high' count events we see. 'dup', 'out_of_order' and 'dropped'
3194 are heuristics we apply to try and understand what happened. They will be accurate in common error scenarios.
3195 We describe few scenarios below to help understand this. +
3197 *Error counters scenarios*::
3198 Scenario 1: Received packet with seq num 10, and another one with seq num 10. We increment 'dup' and 'seq_too_low' by 1. +
3199 Scenario 2: Received pacekt with seq num 10 and then packet with seq num 15. We assume 4 packets were dropped, and increment 'dropped' by 4, and 'seq_too_high' by 1.
3200 We expect next packet to arrive with sequence number 16. +
3201 Scenario 2 continue: Received packet with seq num 11. We increment 'seq_too_low' by 1. We increment 'out_of_order' by 1. We *decrement* 'dropped' by 1.
3202 (We assume here that one of the packets we considered as dropped before, actually arrived out of order).
3204 ==== Tutorial: HLT traffic profile
3206 The traffic_config API has set of arguments for specifying streams - in particular, the packet template, which field, and how to send it.
3207 // clarify "which field"
3208 It is possible to define a traffic profile using HTTAPI arguments.
3209 // clarify names: "HLT traffic profile", "traffic_config API", "HTTAP"
3210 The API creates native Scapy/Field Engine instructions.
3211 For limitations see xref:altapi-support[here].
3213 *File*:: link:{github_stl_path}/hlt/hlt_udp_inc_dec_len_9k.py[stl/hlt/hlt_udp_inc_dec_len_9k.py]
3218 class STLS1(object):
3220 Create 2 Eth/IP/UDP streams with different packet size:
3221 First stream will start from 64 bytes (default) and will increase until max_size (9,216)
3222 Seconds stream will decrease the packet size in reverse way
3225 def create_streams (self):
3227 return [STLHltStream(length_mode = 'increment',
3228 frame_size_max = max_size,
3229 l3_protocol = 'ipv4',
3230 ip_src_addr = '16.0.0.1',
3231 ip_dst_addr = '48.0.0.1',
3232 l4_protocol = 'udp',
3233 udp_src_port = 1025,
3237 STLHltStream(length_mode = 'decrement',
3238 frame_size_max = max_size,
3239 l3_protocol = 'ipv4',
3240 ip_src_addr = '16.0.0.1',
3241 ip_dst_addr = '48.0.0.1',
3242 l4_protocol = 'udp',
3243 udp_src_port = 1025,
3249 def get_streams (self, direction = 0, **kwargs):
3250 return self.create_streams()
3253 The following command, within a bash window, runs the traffic profile with the simulator to generate pcap file.
3257 $ ./stl-sim -f stl/hlt/hlt_udp_inc_dec_len_9k.py -o b.pcap -l 10
3260 The following commands, within a bash window, convert to native JSON or YAML.
3264 $ ./stl-sim -f stl/hlt/hlt_udp_inc_dec_len_9k.py --json
3269 $ ./stl-sim -f stl/hlt/hlt_udp_inc_dec_len_9k.py --yaml
3272 Alternatively, use the following command to convert to a native Python profile.
3276 $ ./stl-sim -f stl/hlt/hlt_udp_inc_dec_len_9k.py --native
3279 .Auto-generated code
3282 # !!! Auto-generated code !!!
3283 from trex_stl_lib.api import *
3285 class STLS1(object):
3286 def get_streams(self):
3289 packet = (Ether(src='00:00:01:00:00:01', dst='00:00:00:00:00:00', type=2048) /
3290 IP(proto=17, chksum=5882, len=9202, ihl=5L, id=0) /
3291 UDP(dport=12, sport=1025, len=9182, chksum=55174) /
3292 Raw(load='!' * 9174))
3293 vm = STLScVmRaw([CTRexVmDescFlowVar(name='pkt_len', size=2, op='inc',
3294 init_value=64, min_value=64, max_value=9216, step=1),
3295 CTRexVmDescTrimPktSize(fv_name='pkt_len'),
3296 CTRexVmDescWrFlowVar(fv_name='pkt_len',
3297 pkt_offset=16, add_val=-14, is_big=True),
3298 CTRexVmDescWrFlowVar(fv_name='pkt_len',
3299 pkt_offset=38, add_val=-34, is_big=True),
3300 CTRexVmDescFixIpv4(offset=14)], split_by_field = 'pkt_len')
3301 stream = STLStream(packet = CScapyTRexPktBuilder(pkt = packet, vm = vm),
3302 mode = STLTXCont(pps = 1.0))
3303 streams.append(stream)
3305 packet = (Ether(src='00:00:01:00:00:01', dst='00:00:00:00:00:00', type=2048) /
3306 IP(proto=17, chksum=5882, len=9202, ihl=5L, id=0) /
3307 UDP(dport=12, sport=1025, len=9182, chksum=55174) /
3308 Raw(load='!' * 9174))
3309 vm = STLScVmRaw([CTRexVmDescFlowVar(name='pkt_len', size=2, op='dec',
3310 init_value=9216, min_value=64,
3311 max_value=9216, step=1),
3312 CTRexVmDescTrimPktSize(fv_name='pkt_len'),
3313 CTRexVmDescWrFlowVar(fv_name='pkt_len', pkt_offset=16,
3314 add_val=-14, is_big=True),
3315 CTRexVmDescWrFlowVar(fv_name='pkt_len',
3316 pkt_offset=38, add_val=-34, is_big=True),
3317 CTRexVmDescFixIpv4(offset=14)], split_by_field = 'pkt_len')
3318 stream = STLStream(packet = CScapyTRexPktBuilder(pkt = packet, vm = vm),
3319 mode = STLTXCont(pps = 1.0))
3320 streams.append(stream)
3328 Use the following command within the TRex console to run the profile.
3332 TRex>start -f stl/hlt/hlt_udp_inc_dec_len_9k.py -m 10mbps -a
3336 === PCAP Based Traffic Tutorials
3338 ==== PCAP Based Traffic
3340 TRex provides a method of using a pre-recorded traffic as a profile template.
3342 There are two main distinct ways of creating a profile or a test based on a PCAP.
3347 ===== Local PCAP push
3349 On this mode, the PCAP file is loaded locally by the Python client,
3350 transformed to a list of streams which each one contains a single packet
3351 and points to the next one.
3353 This allows of a very flexible structure which can basically provide every
3354 functionality that a regular list of streams allow.
3356 However, due to the overhead of processing and
3357 sending a list of streams this method is limited to a file size (on default 1MB)
3362 * supports most CAP file formats
3363 * supports field engine
3364 * provides a way of locally manipulating packets as streams
3365 * supports same rate as regular streams
3369 * limited in file size
3370 * high configuration time due to transmitting the CAP file as streams
3373 ===== Server based push
3375 To provide also a way of injecting a much larger PCAP files, TRex also provides
3376 a server based push.
3378 The mechansim is much different and it simply providing a server a PCAP file which
3379 in turn is loaded to the server and injected packet after packet.
3381 This method provides an unlimited file size to be injected, and the overhead of
3382 setting up the server with the required configuration is much lower.
3387 * no limitation of PCAP file size
3388 * no overhead in sending any size of PCAP to the server
3392 * does not support field engine
3393 * support only PCAP and ERF formats
3394 * requires the file path to be accessible from the server
3395 * rate of transmition is usually limited by I/O performance and buffering (HDD)
3398 ==== Tutorial: Simple PCAP file - Profile
3400 *Goal*:: Load a pcap file with a *number* of packets, creating a stream with a burst value of 1 for each packet. The inter-stream gap (ISG) for each stream is equal to the inter-packet gap (IPG).
3402 *File*:: link:{github_stl_path}/pcap.py[pcap.py]
3406 def get_streams (self,
3407 ipg_usec = 10.0, <1>
3408 loop_count = 1): <2>
3410 profile = STLProfile.load_pcap(self.pcap_file, <3>
3411 ipg_usec = ipg_usec,
3412 loop_count = loop_count)
3414 <1> The inter-stream gap in microseconds.
3416 <3> Input pcap file.
3418 // Please leave this comment - helping rendition.
3420 image::images/stl_loop_count_01b.png[title="Example of multiple streams",align="left",width="80%", link="images/stl_loop_count_01b.png"]
3422 // OBSOLETE: image::images/stl_loop_count_01b.png[title="Streams, loop_count",align="left",width={p_width_1a}, link="images/stl_loop_count_01b.png"]
3424 The figure shows the streams for a pcap file with 3 packets, with a loop configured.
3426 * Each stream is configured to Burst mode with 1 packet.
3427 * Each stream triggers the next stream.
3428 * The last stream triggers the first with `action_loop=loop_count` if `loop_count` > 1.
3430 The profile runs on one DP thread because it has a burst with 1 packet. (Split cannot work in this case).
3432 To run this example, enter:
3436 ./stl-sim -f stl/pcap.py --yaml
3439 The following output appears:
3443 $./stl-sim -f stl/pcap.py --yaml
3535 self_start: false <4>
3540 <1> Each stream triggers the next stream.
3541 <2> The last stream triggers the first.
3542 <3> The current loop count is given in: `action_count: 1`
3543 <4> `Self_start` is enabled for the first stream, disabled for all other streams.
3546 ==== Tutorial: Simple PCAP file - API
3548 For this case we can use the local push:
3552 c = STLClient(server = "localhost")
3557 c.reset(ports = [0])
3559 d = c.push_pcap(pcap_file = "my_file.pcap", # our local PCAP file
3560 ports = 0, # use port 0
3561 ipg_usec = 100, # IPG
3562 count = 1) # inject only once
3567 stats = c.get_stats()
3568 opackets = stats[port]['opackets']
3569 print("{0} packets were Tx on port {1}\n".format(opackets, port))
3571 except STLError as e:
3580 ==== Tutorial: PCAP file iterating over dest IP
3582 For this case we can use the local push:
3586 c = STLClient(server = "localhost")
3592 c.reset(ports = [port])
3594 vm = STLIPRange(dst = {'start': '10.0.0.1', 'end': '10.0.0.254', 'step' : 1})
3596 c.push_pcap(pcap_file = "my_file.pcap", # our local PCAP file
3597 ports = port, # use 'port'
3598 ipg_usec = 100, # IPG
3599 count = 1, # inject only once
3600 vm = vm # provide VM object
3605 stats = c.get_stats()
3606 opackets = stats[port]['opackets']
3607 print("{0} packets were Tx on port {1}\n".format(opackets, port))
3609 except STLError as e:
3618 ==== Tutorial: PCAP file with VLAN
3620 This is a more intresting case where we can provide the push API a function hook.
3621 The hook will be called for each packet that is loaded from the PCAP file.
3625 # generate a packet hook function with a VLAN ID
3626 def packet_hook_generator (vlan_id):
3628 # this function will be called for each packet and will expect
3629 # the new packet as a return value
3630 def packet_hook (packet):
3631 packet = Ether(packet)
3633 if vlan_id >= 0 and vlan_id <= 4096:
3634 packet_l3 = packet.payload
3635 packet = Ether() / Dot1Q(vlan = vlan_id) / packet_l3
3641 c = STLClient(server = "localhost")
3647 c.reset(ports = [port])
3649 vm = STLIPRange(dst = {'start': '10.0.0.1', 'end': '10.0.0.254', 'step' : 1})
3651 d = c.push_pcap(pcap_file = "my_file.pcap",
3655 packet_hook = packet_hook_generator(vlan_id = 1)
3660 stats = c.get_stats()
3661 opackets = stats[port]['opackets']
3662 print("{0} packets were Tx on port {1}\n".format(opackets, port))
3664 except STLError as e:
3673 ==== Tutorial: PCAP file and Field Engine - Profile
3675 The following example loads a pcap file to many streams, and attaches Field Engine program to each stream. For example, the Field Engine can change the `IP.src` of all the streams to a random IP address.
3677 *File*:: link:{github_stl_path}/pcap_with_vm.py[stl/pcap_with_vm.py]
3682 def create_vm (self, ip_src_range, ip_dst_range):
3683 if not ip_src_range and not ip_dst_range:
3686 # until the feature of offsets will be fixed for PCAP use hard coded offsets
3691 vm += [STLVmFlowVar(name="src",
3692 min_value = ip_src_range['start'],
3693 max_value = ip_src_range['end'],
3694 size = 4, op = "inc"),
3695 #STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src")
3696 STLVmWrFlowVar(fv_name="src",pkt_offset = 26)
3700 vm += [STLVmFlowVar(name="dst",
3701 min_value = ip_dst_range['start'],
3702 max_value = ip_dst_range['end'],
3703 size = 4, op = "inc"),
3705 #STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst")
3706 STLVmWrFlowVar(fv_name="dst",pkt_offset = 30)
3709 vm += [#STLVmFixIpv4(offset = "IP")
3710 STLVmFixIpv4(offset = 14)
3716 def get_streams (self,
3719 ip_src_range = None,
3720 ip_dst_range = {'start' : '10.0.0.1',
3721 'end': '10.0.0.254'}):
3723 vm = self.create_vm(ip_src_range, ip_dst_range) <1>
3724 profile = STLProfile.load_pcap(self.pcap_file,
3725 ipg_usec = ipg_usec,
3726 loop_count = loop_count,
3729 return profile.get_streams()
3731 <1> Creates Field Engine program.
3732 <2> Applies the Field Engine to all packets -> converts to streams.
3735 [format="csv",cols="1^,2^,1^", options="header",width="40%"]
3753 ==== Tutorial: Huge server side PCAP file
3755 Now we would like to use the remote push API.
3756 This will require the file path to be visible to the server.
3760 c = STLClient(server = "localhost")
3765 c.reset(ports = [0])
3767 # use an absolute path so the server can reach this
3768 pcap_file = os.path.abspath(pcap_file)
3770 c.push_remote(pcap_file = pcap_file,
3778 stats = c.get_stats()
3779 opackets = stats[port]['opackets']
3780 print("{0} packets were Tx on port {1}\n".format(opackets, port))
3782 except STLError as e:
3791 ==== Tutorial: A long list of PCAP files of varied sizes
3793 This is also a good candidate for the remote push API.
3794 The total overhead for sending the PCAP files will be high if the list is long,
3795 so we would prefer to inject them with remote API and to save the transmition of the packets.
3799 c = STLClient(server = "localhost")
3804 c.reset(ports = [0])
3806 # iterate over the list and send each file to the server
3807 for pcap_file in pcap_file_list:
3808 pcap_file = os.path.abspath(pcap_file)
3810 c.push_remote(pcap_file = pcap_file,
3818 stats = c.get_stats()
3819 opackets = stats[port]['opackets']
3820 print("{0} packets were Tx on port {1}\n".format(opackets, port))
3822 except STLError as e:
3831 === Performance Tweaking
3832 In this section we provide some advanced features to help get the most of TRex performance.
3833 The reason that those features are not active out of the box because they might have
3834 some impact on other areas and in general, might sacrafice one or more properties
3835 that requires the user to explicitly give up on those.
3840 see xref:trex_cache_mbuf[here]
3843 ==== Core masking per interface
3844 By default, TRex will regard any TX command with a **greedy approach**:
3845 All the DP cores associated with this port will be assigned in order to produce the maximum
3848 image::images/core_mask_split.png[title="Greedy Approach - Splitting",align="left",width={p_width}, link="images/core_mask_split.png"]
3850 However, in some cases it might be beneficial to provide a port with a subset of the cores to use.
3853 For example, when injecting traffic on two ports and the following conditions are met:
3855 * the two ports are adjacent
3856 * the profile is symmetric
3858 Due to TRex architecture, adjacent ports (e.g. port 0 & port 1) shares the same cores,
3859 and using the greedy approach will cause all the cores to transmit on both port 0 and port 1.
3861 When the profile is *symmetric* it will be wiser to pin half the cores to port 0 and half
3862 the cores to port 1 and thus avoid cache trashing and bouncing.
3863 If the profile is not symmetric, the static pinning may deny CPU cycles from the more congested port.
3865 image::images/core_mask_pin.png[title="Pinning Cores To Ports",align="left",width={p_width}, link="images/core_mask_pin.png"]
3867 TRex provides this in two ways:
3870 ==== Predefind modes
3872 As said above, the default mode is 'split' mode, but you can provide a predefined mode called 'pin'.
3873 This can be done by both API and from the console:
3878 trex>start -f stl/syn_attack.py -m 40mpps --total -p 0 1 --pin <-- provide '--pin' to the command
3880 Removing all streams from port(s) [0, 1]: [SUCCESS]
3883 Attaching 1 streams to port(s) [0]: [SUCCESS]
3886 Attaching 1 streams to port(s) [1]: [SUCCESS]
3889 Starting traffic on port(s) [0, 1]: [SUCCESS]
3898 .API example to PIN cores
3901 c.start(ports = [port_a, port_b], mult = rate,core_mask=STLClient.CORE_MASK_PIN) <1>
3903 <1> core_mask = STLClient.CORE_MASK_PIN
3905 .API example to MASK cores
3908 c.start(ports = [port_a, port_b], mult = rate, core_mask=[0x1,0x2])<1>
3910 <1> DP Core 0 (mask==1) is assign to port 1 and DP core 1 (mask==2) is for port 2
3916 We can see in the CPU util. available from the TUI window,
3917 that each core was reserverd for an interface:
3921 Total Tx L2 : 20.49 Gb/sec
3922 Total Tx L1 : 26.89 Gb/sec
3923 Total Rx : 20.49 Gb/sec
3924 Total Pps : 40.01 Mpkt/sec <-- performance meets the requested rate
3925 Drop Rate : 0.00 b/sec
3931 Thread | Avg | Latest | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8
3933 0 (0) | 92 | 92 | 92 | 91 | 91 | 92 | 91 | 92 | 93 | 94
3934 1 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3935 2 (1) | 96 | 95 | 95 | 96 | 96 | 96 | 96 | 95 | 94 | 95
3936 3 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3937 4 (0) | 92 | 93 | 93 | 91 | 91 | 93 | 93 | 93 | 93 | 93
3938 5 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3939 6 (1) | 88 | 88 | 88 | 88 | 88 | 88 | 88 | 88 | 87 | 87
3940 7 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3945 If we had used the *default mode*, the table should have looked like this, and yield
3946 much worse performance:
3953 Total Tx L2 : 12.34 Gb/sec
3954 Total Tx L1 : 16.19 Gb/sec
3955 Total Rx : 12.34 Gb/sec
3956 Total Pps : 24.09 Mpkt/sec <-- performance is quite low than requested
3957 Drop Rate : 0.00 b/sec
3962 Thread | Avg | Latest | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8
3964 0 (0,1) | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100
3965 1 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3966 2 (0,1) | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100
3967 3 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3968 4 (0,1) | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100
3969 5 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3970 6 (0,1) | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100 | 100
3971 7 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
3975 This feature is also available from the Python API by providing:
3976 *CORE_MASK_SPLIT* or *CORE_MASK_PIN* to the start API.
3980 Sometimes for debug purposes or for a more advanced core scheduling you might want
3981 to provide a manual masking that will guide the server on which cores to use.
3983 For example, let's assume we have a profile that utilize 95% of the traffic on one side,
3984 and in the other direction it provides 5% of the traffic.
3985 Let's assume also we have 8 cores assigned to the two interfaces.
3987 We want to assign 3 cores to interface 0 and 1 core only to interface 1.
3989 We can provide this line to the console (or for the API by providing a list of masks to the start
3994 trex>start -f stl/syn_attack.py -m 10mpps --total -p 0 1 --core_mask 0xE 0x1
3996 Removing all streams from port(s) [0, 1]: [SUCCESS]
3999 Attaching 1 streams to port(s) [0]: [SUCCESS]
4002 Attaching 1 streams to port(s) [1]: [SUCCESS]
4005 Starting traffic on port(s) [0, 1]: [SUCCESS]
4014 c.start(ports = [port_a, port_b], mult = rate,core_mask=[0x0xe,0x1]) <1>
4016 <1> mask of cores per port
4020 The following output is received on the TUI CPU util window:
4025 Total Tx L2 : 5.12 Gb/sec
4026 Total Tx L1 : 6.72 Gb/sec
4027 Total Rx : 5.12 Gb/sec
4028 Total Pps : 10.00 Mpkt/sec
4029 Drop Rate : 0.00 b/sec
4034 Thread | Avg | Latest | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8
4036 0 (1) | 45 | 45 | 45 | 45 | 45 | 45 | 46 | 45 | 46 | 45
4037 1 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
4038 2 (0) | 15 | 15 | 14 | 15 | 15 | 14 | 14 | 14 | 14 | 14
4039 3 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
4040 4 (0) | 14 | 14 | 14 | 14 | 14 | 14 | 14 | 14 | 15 | 14
4041 5 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
4042 6 (0) | 15 | 15 | 15 | 15 | 15 | 15 | 15 | 15 | 15 | 15
4043 7 (IDLE) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
4049 Additional profiles and examples are available in the `stl/hlt` folder.
4051 For information about the Python client API, see the link:cp_stl_docs/index.html[Python Client API documentation].
4053 === Console commands
4057 The console uses TRex client API to control TRex.
4059 *Important information about console usage*::
4061 // it seems that all of these provide background info, not guidelines for use. the use of "should" is unclear.
4063 * The console does not save its own state. It caches the server state. It is assumed that there is only one console with R/W permission at any given time, so once connected as R/W console (per user/interface), it can read the server state and then cache all operations.
4064 * Many read-only clients can exist for the same user interface.
4065 * The console syncs with the server to get the state during connection stage, and caches the server information locally.
4066 * In case of crash or exit of the console, it will sync again at startup.
4067 * Command line parameters order is not important.
4068 * The console can display TRex stats in real time. You can open two consoles simultaneously - one for commands (R/W) and one for displaying statistics (read only).
4072 [options="header",cols="^1,3a"]
4076 | STREAMS | Has streams. Not transmitting (did not start transmission, or it was stopped).
4077 | WORK | Has streams. Transmitting.
4078 | PAUSE | Has streams. Transmission paused.
4085 IDLE -> (add streams) -> STREAMS (start) -> WORK (stop) -> STREAMS (start)
4086 | WORK (pause) -> PAUSE (resume )---
4089 --------------------------------------
4092 ==== Common Arguments
4094 Following command line arguments are common to many commands.
4097 You can specify -h or --help after each command to get full description of its purpose and arguments.
4108 Port mask enables selecting range, or set of ports.
4114 $<command> [-a] [--port 1 2 3] [--port 0xff] [--port clients/servers]
4118 [--port 1 2 3] : port 1,2 3
4119 [--port 0xff] : port by mask 0x1 for port 0 0x3 for port 0 and 1
4124 Duration is expressed in seconds, minutes, or hours.
4130 $<command> [-d 100] [-d 10m] [-d 1h]
4141 The traffic profile defines default bandwidth for each stream. Using the multiplier command line argument, it is possible to set different bandwidth. It is possible to specify either packets or bytes per second, percentage of total port rate, or just factor to multiply the original rate by.
4147 $<command> [-m 100] [-m 10gb] [-m 10kpps] [-m 40%]
4151 -m 100 : Multiply original rate by given factor.
4152 -m 10gbps : From graph calculate the maximum rate as this bandwidth for all streams( for each port )
4153 -m 10kpps : From graph calculate the maximum rate as this pps for all streams ( for each port )
4154 -m 40% : From graph calculate the maximum rate as this precent from total port rate ( for each port )
4156 // What does it mean from graph???
4163 Attempts to connet to the server you were connected to. Can be used in case server was restarted. Can not be used
4164 in order to connect to different server. In addition:
4166 * Syncs the port info and stream info state.
4167 * Reads all counter statistics for reference.
4169 // IGNORE: this line helps rendering of next line
4180 Resets the server and client to a known state. Not used in normal scenarios.
4182 - Forces acquire on all ports
4183 - Stops all traffic on all ports
4184 - Removes all streams from all ports
4196 Configures port attributes.
4203 usage: port_attr [-h] [--port PORTS [PORTS ...] | -a] [--prom {on,off}]
4204 [--link {up,down}] [--led {on,off}] [--fc {none,tx,rx,full}]
4207 Sets port attributes
4210 -h, --help show this help message and exit
4211 --port PORTS [PORTS ...], -p PORTS [PORTS ...]
4212 A list of ports on which to apply the command
4213 -a Set this flag to apply the command on all available
4215 --prom {on,off} Set port promiscuous on/off
4216 --link {up,down} Set link status up/down
4217 --led {on,off} Set LED status on/off
4218 --fc {none,tx,rx,full}
4219 Set Flow Control type
4220 --supp Show which attributes are supported by current NICs
4223 image::images/console_link_down.png[title="Setting link down on port 0 affects port 1 at loopback"]
4228 Clears all port stats counters.
4240 Can be used to show global/port/stream statistics. +
4241 Also, can be used to retrieve extended stats from port (xstats)
4251 *Xstats error example*::
4256 trex>stats -x --port 0 2
4259 Name: | Port 0: | Port 2:
4260 \------------------------------------------------------------------
4261 rx_good_packets | 154612905 | 153744994
4262 tx_good_packets | 154612819 | 153745136
4263 rx_good_bytes | 9895225920 | 9839679168
4264 tx_good_bytes | 9276768500 | 9224707392
4265 rx_unicast_packets | 154611873 | 153743952
4266 rx_unknown_protocol_packets | 154611896 | 153743991
4267 tx_unicast_packets | 154612229 | 153744562
4268 mac_remote_errors | 1 | 0 #<1>
4269 rx_size_64_packets | 154612170 | 153744295
4270 tx_size_64_packets | 154612595 | 153744902
4274 <1> Error that can be seen only with this command
4276 // IGNORE - this line helps rendering
4280 Shows info about configured streams on each port, from the client cache.
4290 ID | packet type | length | mode | rate | next stream
4292 1 | Ethernet:IP:UDP:Raw | 64 | continuous | 1 pps | -1
4293 2 | Ethernet:IP:UDP:Raw | 64 | continuous | 1.00 Kpps | -1
4297 ID | packet type | length | mode | rate | next stream
4299 1 | Ethernet:IP:UDP:Raw | 64 | continuous | 1 pps | -1
4300 2 | Ethernet:IP:UDP:Raw | 64 | continuous | 1.00 Kpps | -1
4307 Use this command to show only ports 1 and 2.
4319 Use this command to show full information for stream 0 and port 0, output in JSON format.
4323 $streams --port 0 --streams 0
4330 Start transmitting traffic on set of ports
4332 * Removes all streams
4334 * Starts traffic (can set multiplier, duration and other parameters)
4335 * Acts only on ports in "stopped: mode. If `--force` is specified, port(s) are first stopped.
4336 * Note: If any ports are not in "stopped" mode, and `--force` is not used the command fails.
4338 // IGNORE: this line helps rendering of next line
4342 Use this command to start a profile on all ports, with a maximum bandwidth of 10 GB.
4346 $start -a -f stl/imix.py -m 10gb
4351 Use this command to start a profile on ports 1 and 2, and multiply the bandwidth specified in the traffic profile by 100.
4355 $start -port 1 2 -f stl/imix.py -m 100
4361 * Operates on a set of ports
4362 * Changes the mode of the port(s) to "stopped"
4363 * Does not remove streams
4365 // IGNORE: this line helps rendering of next line
4369 Use this command to stop the specified ports.
4380 * Operates on a set of ports
4381 * Changes a working set of ports to "pause" (no traffic transmission) state.
4394 * Operates on a set of ports
4395 * Changes a working set of port(s) to "resume" state (transmitting traffic again).
4396 * All ports should be in "paused" status. If any of the ports is not paused, the command fails.
4398 // IGNORE: this line helps rendering of next line
4411 Update the bandwidth multiplier for a set of ports.
4413 * All ports must be in "work" state. If any ports are not in "work" state, the command fails
4415 // IGNORE: this line helps rendering of next line
4419 Multiplly traffic on all ports by a factor of 5.
4428 =====================================
4429 We might add in the future the ability to disable/enable specific stream, load a new stream dynamically, and so on.
4430 =====================================
4432 // clarify note above
4436 The textual user interface (TUI) displays constantly updated TRex statistics in a textual window.
4445 Enters a Stats mode and displays three types of TRex statistics:
4446 * Global/port stats/version/connected etc
4451 The followig keyboard commands operate in the TUI window: +
4452 q - Quit the TUI window (get back to console) +
4453 c - Clear all counters +
4454 d, s, l - change display between dashboard (d), streams (s) and l (latency) info. +
4456 === Benchmarks of 40G NICs
4458 link:trex_stateless_bench.html[TRex stateless benchmarks]
4462 ==== Scapy packet examples
4468 Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
4471 Ether()/Dot1Q(vlan=12)/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
4474 Ether()/Dot1Q(vlan=12)/Dot1Q(vlan=12)/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
4476 #TCP over IP over VLAN
4477 Ether()/Dot1Q(vlan=12)/IP(src="16.0.0.1",dst="48.0.0.1")/TCP(dport=12,sport=1025)
4480 Ether()/Dot1Q(vlan=12)/IPv6(src="::5")/TCP(dport=12,sport=1025)
4482 #Ipv6 over UDP over IP
4483 Ether()/IP()/UDP()/IPv6(src="::5")/TCP(dport=12,sport=1025)
4486 Ether()/IP()/UDP()/DNS()
4489 Ether()/IP()/TCP()/"GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"
4493 ==== HLT supported Arguments anchor:altapi-support[]
4495 include::build/hlt_args.asciidoc[]
4497 ==== FD.IO open source project using TRex
4499 link:https://gerrit.fd.io/r/gitweb?p=csit.git;a=tree;f=resources/tools/t-rex[here]
4502 ==== Using Stateless client via JSON-RPC
4504 For functions that do not require complex objects and can use JSON-serializable input/output, you can use Stateless API via JSON-RPC proxy server. +
4505 Thus, you can use Stateless TRex *from any language* supporting JSON-RPC.
4507 ===== How to run TRex side:
4509 * Run the Stateless TRex server in one of 2 ways:
4511 ** Either run TRex directly in shell:
4518 ** Or run it via JSON-RPC command to trex_daemon_server:
4522 start_trex(trex_cmd_options, user, block_to_success = True, timeout = 40, stateless = True)
4525 * Run the RPC "proxy" to stateless, here are also 2 ways:
4531 cd automation/trex_control_plane/stl/examples
4532 python rpc_proxy_server.py
4535 ** Send JSON-RPC command to master_daemon:
4539 if not master_daemon.is_stl_rpc_proxy_running():
4540 master_daemon.start_stl_rpc_proxy()
4545 Now you can send requests to the rpc_proxy_server and get results as array of 2 values:
4547 * If fail, result will be: [False, <traceback log with error>]
4548 * If success, result will be: [True, <return value of called function>]
4550 In same directory of rpc_proxy_server.py, there is python example of usage: using_rpc_proxy.py
4552 ===== Native Stateless API functions:
4563 ...can be called directly as server.push_remote(\'udp_traffic.pcap'). +
4564 If you need any other function of stateless client, you can either add it to rpc_proxy_server.py, or use this method: +
4565 server.*native_method*(<string of function name>, <args of the function>) +
4567 ===== HLTAPI Methods can be called here as well:
4577 =====================================================================
4578 In case of names collision with native functions (such as connect), for HLTAPI, function will change to have "hlt_" prefix.
4579 =====================================================================
4581 ===== Example of running from Java:
4585 package com.cisco.trex_example;
4587 import java.net.URL;
4588 import java.util.ArrayList;
4589 import java.util.Arrays;
4590 import java.util.Map;
4591 import java.util.HashMap;
4593 import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
4595 public class TrexMain {
4597 @SuppressWarnings("rawtypes")
4598 public static Object verify(ArrayList response) {
4599 if ((boolean) response.get(0)) {
4600 return response.get(1);
4602 System.out.println("Error: " + response.get(1));
4607 @SuppressWarnings("rawtypes")
4608 public static void main(String[] args) throws Throwable {
4610 String trex_host = "csi-trex-11";
4611 int rpc_proxy_port = 8095;
4612 Map<String, Object> kwargs = new HashMap<>();
4613 ArrayList<Integer> ports = new ArrayList<Integer>();
4614 HashMap res_dict = new HashMap<>();
4615 ArrayList res_list = new ArrayList();
4616 JsonRpcHttpClient rpcConnection = new JsonRpcHttpClient(new URL("http://" + trex_host + ":" + rpc_proxy_port));
4618 System.out.println("Initializing Native Client");
4619 kwargs.put("server", trex_host);
4620 kwargs.put("force", true);
4621 verify(rpcConnection.invoke("native_proxy_init", kwargs, ArrayList.class));
4624 System.out.println("Connecting to TRex server");
4625 verify(rpcConnection.invoke("connect", kwargs, ArrayList.class));
4627 System.out.println("Resetting all ports");
4628 verify(rpcConnection.invoke("reset", kwargs, ArrayList.class));
4630 System.out.println("Getting ports info");
4631 kwargs.put("func_name", "get_port_info"); // some "custom" function
4632 res_list = (ArrayList) verify(rpcConnection.invoke("native_method", kwargs, ArrayList.class));
4633 System.out.println("Ports info is: " + Arrays.toString(res_list.toArray()));
4635 for (int i = 0; i < res_list.size(); i++) {
4636 Map port = (Map) res_list.get(i);
4637 ports.add((int)port.get("index"));
4640 System.out.println("Sending pcap to ports: " + Arrays.toString(ports.toArray()));
4641 kwargs.put("pcap_filename", "stl/sample.pcap");
4642 verify(rpcConnection.invoke("push_remote", kwargs, ArrayList.class));
4644 verify(rpcConnection.invoke("wait_on_traffic", kwargs, ArrayList.class));
4646 System.out.println("Getting stats");
4647 res_dict = (HashMap) verify(rpcConnection.invoke("get_stats", kwargs, ArrayList.class));
4648 System.out.println("Stats: " + res_dict.toString());
4650 System.out.println("Deleting Native Client instance");
4651 verify(rpcConnection.invoke("native_proxy_del", kwargs, ArrayList.class));
4653 } catch (Throwable e) {
4654 e.printStackTrace();