summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trex_rpc_server_spec.asciidoc209
1 files changed, 208 insertions, 1 deletions
diff --git a/trex_rpc_server_spec.asciidoc b/trex_rpc_server_spec.asciidoc
index 94a95bfb..e973aedc 100644
--- a/trex_rpc_server_spec.asciidoc
+++ b/trex_rpc_server_spec.asciidoc
@@ -2,12 +2,25 @@ The TRex RPC Server
===================
:author: Itay Marom
:email: <imarom@cisco.com>
-:revnumber: 1.70-0.0
+:revnumber: 1.01
:quotes.++:
:numbered:
:web_server_url: http://trex-tgn.cisco.com/trex
:local_web_server_url: csi-wiki-01:8181/trex
+== Change log
+
+[options="header",cols="^1,^h,3a"]
+|=================
+| Version | name | meaning
+| 1.00 | Itay Marom (imarom) |
+- first version
+| 1.01 | Dan Klein (danklei)
+|
+- added usage examples using Python code as Higher-level usage
+- added logic and explanation behind VM commands
+
+|=================
== RPC Support On TRex
@@ -1084,3 +1097,197 @@ Describes the log off from the machine
* *remove_all_streams* ['optional'] - if you want to clear all the previous streams - use this
* *release* - release the ownership over the device
+
+== Higher Level implementation examples
+The following examples represents common scenarios implemented by a higher layer, which uses the API described above.
+
+The examples are written in Python, however similar examples can be shown in any programming language.
+
+=== CTRexPktBuilder class description
+`CTRexPktBuilder` is a Python module designed to provide a progammer API for dynamic packet building.
+Since the packet is built to be used by TRex, a `CTRexVM` subclass has been created to describe how TRex should use the described packet in its transmission.
+
+While the entire `CTRexPktBuilder` class (which is initialized by specifying the total length of the packet) responsible to both building the packet layer by layer, the `CTRexVM` class is responsible for controlling the ranging of the values as desribed in the <<vm_obj,VM objects section>>, and other attributes being used by TRex data-plane once the server receives its streams.
+
+
+=== Creating an example packet
+The following conde snippet describes how an ICMP Echo packet is built.
+
+[source, python, numbered]
+----
+from packet_builder import CTRexPktBuilder
+import dpkt
+
+pkt_bld = CTRexPktBuilder() # <1>
+pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet())
+# set Ethernet layer attributes
+pkt_bld.set_eth_layer_addr("l2", "src", "00:15:17:a7:75:a3")
+pkt_bld.set_eth_layer_addr("l2", "dst", "e0:5f:b9:69:e9:22")
+pkt_bld.set_layer_attr("l2", "type", dpkt.ethernet.ETH_TYPE_IP)
+# set IP layer attributes
+pkt_bld.add_pkt_layer("l3_ip", dpkt.ip.IP())
+pkt_bld.set_ip_layer_addr("l3_ip", "src", "21.0.0.2")
+pkt_bld.set_ip_layer_addr("l3_ip", "dst", "22.0.0.12")
+pkt_bld.set_layer_attr("l3_ip", "p", dpkt.ip.IP_PROTO_ICMP)
+# set ICMP layer attributes
+pkt_bld.add_pkt_layer("icmp", dpkt.icmp.ICMP())
+pkt_bld.set_layer_attr("icmp", "type", dpkt.icmp.ICMP_ECHO)
+# set Echo(ICMP) layer attributes
+pkt_bld.add_pkt_layer("icmp_echo", dpkt.icmp.ICMP.Echo())
+pkt_bld.set_layer_attr("icmp_echo", "id", 24528)
+pkt_bld.set_layer_attr("icmp_echo", "seq", 11482)
+pkt_bld.set_pkt_payload('hello world')
+# finally, set IP header len with relation to payload data
+pkt_bld.set_layer_attr("l3_ip", "len", len(pkt_bld.get_layer('l3_ip')))
+----
+
+<1> Initialize the packet builder instance.
+
+This example created a packet without any ranging to it, so in this case TRex is expected to reply the same packet over and over without any changes to it.
+
+When adding sending this packet as part of the <<_add_stream, Add Stream>> command, the packet content specified under `packet` would look for the created ICMP packet like this:
+
+[source, python]
+----
+>>> print pkt_bld.dump_pkt()
+ [224, 95, 185, 105, 233, 34, 0, 21, 23, 167, 117, 163, 8, 0, 69, 0, 0, 39,
+ 0, 0, 0, 0, 64, 1, 79, 201, 21, 0, 0, 2, 22, 0, 0, 12, 8, 0, 217, 134, 95,
+ 208, 44, 218, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
+----
+
+Each of the array items representing a byte data-representation, hence ranging from 0 to 255.
+
+=== Create a packet with single ranging instruction
+The following example creates an HTTP GET packet, hence layering Ethernet/IP/TCP/HTTP.
+
+[source, python, numbered]
+----
+from packet_builder import CTRexPktBuilder
+import dpkt
+
+pkt_bld = CTRexPktBuilder()
+pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet())
+# set Ethernet layer attributes
+pkt_bld.set_eth_layer_addr("l2", "src", "00:15:17:a7:75:a3")
+pkt_bld.set_eth_layer_addr("l2", "dst", "e0:5f:b9:69:e9:22")
+pkt_bld.set_layer_attr("l2", "type", dpkt.ethernet.ETH_TYPE_IP)
+# set IP layer attributes
+pkt_bld.add_pkt_layer("l3_ip", dpkt.ip.IP())
+pkt_bld.set_ip_layer_addr("l3_ip", "src", "21.0.0.2")
+pkt_bld.set_ip_layer_addr("l3_ip", "dst", "22.0.0.12")
+pkt_bld.set_layer_attr("l3_ip", "p", dpkt.ip.IP_PROTO_TCP)
+# set TCP layer attributes
+pkt_bld.add_pkt_layer("l4_tcp", dpkt.tcp.TCP())
+pkt_bld.set_layer_attr("l4_tcp", "sport", 13311)
+pkt_bld.set_layer_attr("l4_tcp", "dport", 80)
+pkt_bld.set_layer_attr("l4_tcp", "flags", 0)
+pkt_bld.set_layer_attr("l4_tcp", "win", 32768)
+pkt_bld.set_layer_attr("l4_tcp", "seq", 0)
+# set packet payload, for example HTTP GET request
+pkt_bld.set_pkt_payload('GET /10k_60k HTTP/1.1\r\nHost: 22.0.0.3\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\nAccept: */*\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate, compress\r\n\r\n')
+
+# finally, set IP header len with relation to payload data
+pkt_bld.set_layer_attr("l3_ip", "len", len(pkt_bld.get_layer('l3_ip')))
+----
+
+Now, we extened the single packet created with three VM instructions, in order to range over the source IP of the packet.
+
+[source, python, numbered]
+----
+pkt_bld.set_vm_ip_range(ip_layer_name="l3_ip", # <1>
+ ip_field="src", # <2>
+ ip_init="10.0.0.1", ip_start="10.0.0.1", ip_end="10.0.0.255",
+ add_value=1,
+ operation="inc")
+----
+
+<1> `l3_ip` corresponds with the layer name given to the IP layer of the packet. This helps identifying and diffrenciate in packet containing more than one IP header.
+
+<2> the name of the field on which we want to range.
+
+Now, we added ranging for source IP starting from 10.0.0.1 to 10.0.0.255.
+This will generate the follwing VM instructions, which will be provided under `vm` field of the <<_add_stream, add_stream>> command:
+
+[source, python]
+----
+>>> print pkt_bld.vm.dump(),
+ [{'name': 'l3__src', 'ins_name': 'flow_var', 'max_value': '167772415', 'min_value': '167772161', 'init_value': '167772161', 'size': 4, 'op': 'inc'},
+ {'is_big_endian': False, 'pkt_offset': 26, 'type': 'write_flow_var', 'name': 'l3__src', 'add_value': 1},
+ {'pkt_offset': 14, 'type': 'fix_checksum_ipv4'}]
+----
+
+As we can see, three instructions has been generated for this ranging criteria:
+
+1. `flow_var` instruction - for defining the ranging parameters.
+
+2. `write_flow_var` instruction - for specifying where and how the modification should take place.
+
+3. `fix_checksum_ipv4` instruction - for updated the checksum field
+
+[WARNING]
+The order of the instruction **does matter**. In this example, if the `fix_checksum_ipv4` instruction would have been places prior to the `write_flow_var` instruction, the generated packet would have satyed with the old checksum values.
+
+[NOTE]
+By default, with each change to the IP header, a `fix_checksum_ipv4` instruction is added. This can be canceled by passing `add_checksum_inst=False` in functions which ranges over an IP field.
+
+
+=== Create a packet with multiple ranging instructions
+Now, we shall extend our ranging and add another field to range on, this time we'll pick the TOS field of the IP header.
+
+So, we'll add the following code snippet **ontop of the ranging method we already applied**:
+
+[source, python, numbered]
+----
+pkt_bld.set_vm_custom_range(layer_name="l3_ip",
+ hdr_field="tos",
+ init_val="10", start_val="10", end_val="200", add_val=2, val_size=1,
+ operation="inc")
+----
+
+So, in this case we chose to range the TOS field from 10 to 200 in steps of 2.
+
+Finally, let's see the expected JSON output of the VM instructions:
+
+[source, python]
+----
+>>> print pkt_bld.vm.dump()
+ [{ 'init_value': '167772161', # <1>
+ 'ins_name': 'flow_var',
+ 'max_value': '167772415',
+ 'min_value': '167772161',
+ 'name': 'l3__src',
+ 'op': 'inc',
+ 'size': 4},
+ { 'init_value': '10', # <2>
+ 'ins_name': 'flow_var',
+ 'max_value': '200',
+ 'min_value': '10',
+ 'name': 'l3__tos',
+ 'op': 'inc',
+ 'size': 1},
+ { 'add_value': 2, # <3>
+ 'is_big_endian': False,
+ 'name': 'l3__tos',
+ 'pkt_offset': 15,
+ 'type': 'write_flow_var'},
+ { 'add_value': 1, # <4>
+ 'is_big_endian': False,
+ 'name': 'l3__src',
+ 'pkt_offset': 26,
+ 'type': 'write_flow_var'},
+ { 'pkt_offset': 14, 'type': 'fix_checksum_ipv4'} # <5>
+ ]
+----
+
+<1> `flow_var` instruction for source IP.
+
+<2> `flow_var` instruction for TOS field
+
+<3> `write_flow_var` instruction for TOS.
+
+<4> `write_flow_var` instruction for source IP.
+
+<5> `fix_checksum_ipv4` instruction for both ranging options
+
+[NOTE]
+In this case only one checksum instruction has been generated, since both ranging options applies to the same IP header. \ No newline at end of file