From 04ecbc54655938241a5e753bdc770d20e1ec5289 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Tue, 3 Jan 2017 15:17:58 +0200 Subject: Stateless API: increase delay in remove rx filters to 100ms in case of virtual NICs. Regression: increase delay in remove rx filters in trex07 to 100ms in test_all_profiles test. Change-Id: Ia7dda25c94aeadcaae0b16023f6ea2957a99906f Signed-off-by: Yaroslav Brustinov --- .../stl/trex_stl_lib/trex_stl_client.py | 16 ++++++++++++++-- .../trex_control_plane/stl/trex_stl_lib/trex_stl_port.py | 5 ++++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index e163d516..e20de3da 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -2342,7 +2342,7 @@ class STLClient(object): @__api_check(True) - def stop (self, ports = None, rx_delay_ms = 10): + def stop (self, ports = None, rx_delay_ms = None): """ Stop port(s) @@ -2376,6 +2376,12 @@ class STLClient(object): if not rc: raise STLError(rc) + if rx_delay_ms is None: + if self.ports[ports[0]].is_virtual(): # assume all ports have same type + rx_delay_ms = 100 + else: + rx_delay_ms = 10 + # remove any RX filters rc = self._remove_rx_filters(ports, rx_delay_ms = rx_delay_ms) if not rc: @@ -2847,7 +2853,7 @@ class STLClient(object): @__api_check(True) - def wait_on_traffic (self, ports = None, timeout = None, rx_delay_ms = 10): + def wait_on_traffic (self, ports = None, timeout = None, rx_delay_ms = None): """ .. _wait_on_traffic: @@ -2891,6 +2897,12 @@ class STLClient(object): if timer.has_expired(): raise STLTimeoutError(timeout) + if rx_delay_ms is None: + if self.ports[ports[0]].is_virtual(): # assume all ports have same type + rx_delay_ms = 100 + else: + rx_delay_ms = 10 + # remove any RX filters rc = self._remove_rx_filters(ports, rx_delay_ms = rx_delay_ms) if not rc: diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 07587b9f..8b6b2e2e 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -930,7 +930,10 @@ class Port(object): def get_rx_filter_mode (self): return self.__attr['rx_filter_mode'] - + + def is_virtual(self): + return self.info.get('is_virtual') + def is_l3_mode (self): return self.get_layer_cfg()['ipv4']['state'] != 'none' -- cgit 1.2.3-korg From 69f6ba4c5dfd0848397da01436671e7c5a0551a9 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Tue, 3 Jan 2017 17:54:20 +0200 Subject: STL Console: fix crash in case of no supported speeds reported by DPDK Regression: update stl performance kiwi benchmark (was my typo) Change-Id: I0ea615d2511ea0339665e8fa5c8621eec9ebcb1e Signed-off-by: Yaroslav Brustinov --- scripts/automation/regression/setups/kiwi02/benchmark.yaml | 2 +- scripts/automation/trex_control_plane/stl/console/trex_console.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/regression/setups/kiwi02/benchmark.yaml b/scripts/automation/regression/setups/kiwi02/benchmark.yaml index 6e29d196..5337b878 100644 --- a/scripts/automation/regression/setups/kiwi02/benchmark.yaml +++ b/scripts/automation/regression/setups/kiwi02/benchmark.yaml @@ -254,7 +254,7 @@ test_performance_vm_single_cpu: cfg: mult : "90%" mpps_per_core_golden : - min: 11.5 + min: 11.2 max: 13.1 diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py index 7d47128b..cecdd72e 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -838,10 +838,10 @@ def show_intro (logger, c): # find out which NICs the server has port_types = {} for port in x['ports']: - if 'supp_speeds' in port: + if 'supp_speeds' in port and port['supp_speeds']: speed = max(port['supp_speeds']) // 1000 else: - speed = port['speed'] + speed = c.ports[port['index']].get_speed_gbps() key = (speed, port.get('description', port['driver'])) if key not in port_types: port_types[key] = 0 -- cgit 1.2.3-korg From f11d01a06951ae9e55f16f1982b08f4552408014 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Wed, 4 Jan 2017 17:38:21 +0200 Subject: console: move show_intro into try-finally to ensure release of ports Change-Id: Icfe30379a24560cf0807edd239d3eb07d81a492f Signed-off-by: Yaroslav Brustinov --- .../trex_control_plane/stl/console/trex_console.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py index cecdd72e..c9956472 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -906,17 +906,16 @@ def main(): if options.readonly: logger.log(format_text("\nRead only mode - only few commands will be available", 'bold')) - show_intro(logger, stateless_client) - - - # a script mode - if options.batch: - cont = run_script_file(options.batch[0], stateless_client) - if not cont: - return - # console try: + show_intro(logger, stateless_client) + + # a script mode + if options.batch: + cont = run_script_file(options.batch[0], stateless_client) + if not cont: + return + console = TRexConsole(stateless_client, options.verbose) logger.prompt_redraw = console.prompt_redraw -- cgit 1.2.3-korg From 3484a1699e36953d8c8dc95743b468eb026a09e1 Mon Sep 17 00:00:00 2001 From: Vyacheslav Ogai Date: Thu, 29 Dec 2016 14:49:39 +0700 Subject: Update docs with info about Field Engine and predefined templates. Change-Id: Ia9480a21c982d2d245aef75908e248ecf0573053 Signed-off-by: Vyacheslav Ogai --- doc/trex_scapy_rpc_server.asciidoc | 111 +++++++++++++++++++-- .../stl/services/scapy_server/scapy_service.py | 2 +- 2 files changed, 106 insertions(+), 7 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/doc/trex_scapy_rpc_server.asciidoc b/doc/trex_scapy_rpc_server.asciidoc index 65d9e7b2..431215e3 100755 --- a/doc/trex_scapy_rpc_server.asciidoc +++ b/doc/trex_scapy_rpc_server.asciidoc @@ -16,9 +16,9 @@ include::trex_ga.asciidoc[] [options="header",cols="^1,^h,3a"] |================= | Version | name | meaning -| 1.00 | Itamar Raviv (itraviv) | -- first version -| 2.00 | Anton (XORED) | update by xored software +| 1.00 | Itamar Raviv (itraviv) | first version +| 2.00 | Anton Kiselev (kisel) | Add description for updated compatibilities of packet creation and modification +| 3.00 | Vyacheslav Ogai (hedjuo) | Add description for supporting Filed Engine and predefined packet templates |================= @@ -56,7 +56,7 @@ Error codes are given according to this table: [also follows the JSON-RPC spec, == Data Bases and Data Structures used in Scapy Server -=== build_pkt, reconstruct_pkt packet model [[build_pkt_input]] +=== build_pkt, build_pkt_ex, reconstruct_pkt packet model [[build_pkt_input]] Following JSON represents a Scapy structure, which can be used to build packet from scratch(build_pkt) or to modify particular fields in the prococol(reconstruct_pkt). Most fields can be omitted, in this case default or calculated values will be used. For reconstruct_pkt default values will be taken from the original packet. @@ -79,6 +79,35 @@ Ether(src="de:ad:be:ef:de:ad")/Dot1Q()/Dot1Q(vtype=1)/IP(src="127.0.0.1", chksum ] ---- +Field Engine VM instruction model + +For more reference see link:https://trex-tgn.cisco.com/trex/doc/cp_stl_docs/api/field_engine.html[Field Engine modules spec] + +[source,python] +---- +{ + "field_engine":{ + "instructions":[ + { + "id":"STLVmFlowVar", + "parameters": { + "name": "Ether_dst", + "init_value": "00:00:00:01:00:00", #can be a string or an integer + "max_value": "0", #can be a string or an integer + "min_value": "0", #can be a string or an integer + "step": "1", + "size": "4", + "op": "inc" + } + }, + ... + ], + "global_parameters":{ + "cache_size":"1000" + } + } +} +---- + === Scapy server value types Most values can be passed as strings(including decimal numbers, hex numbers, enums, values), but for binary payload, value object should be used @@ -113,7 +142,7 @@ Ether()/IP()/TCP()/Raw(load=my_payload) ---- === Scapy packet result payload [[build_pkt_output]] -build_pkt and reconstruct pkt take packet model and produce result JSON, +build_pkt, build_pkt_ex and reconstruct pkt take packet model and produce result JSON, with the binary payload and field values and offsets defined [source,python] @@ -264,6 +293,44 @@ with the binary payload and field values and offsets defined ---- +=== Scapy packet result payload in extended mode [[build_pkt_ex_output]] +[source,python] +---- +{ + "binary": #same as in build_pkt + "data": #same as in build_pkt + "field_engine": { + "error": "", + "instructions": { + "cache": 1000, + "instructions": [ + ... + #FlowVar definition instruction + { + "name": "Ether_dst", + "max_value": 0, + "min_value": 0, + "init_value": 65536, + "step": 1, + "size": 4, + "type": "flow_var", + "op": "inc" + }, + #FlowVar write instruction + { + "name": "Ether_dst", + "is_big_endian": true, + "pkt_offset": 6, + "type": "write_flow_var", + "add_value": 0 + } + ... + ] + } + } +} +---- + === Scapy server field definitions [[get_definitions_model]] Scapy server can return metadata object, describing protocols and fields. Most values, including field types are optional in the definition. @@ -745,6 +812,12 @@ The following RPC commands are supported. Please refer to databases section for * *Return Value* - Returns xref:build_pkt_output[Scapy packet result payload]. * *Paramters* - JSON xref:build_pkt_input[packet definition model]. +=== Build Packet and VM instructions +* *Name* - 'build_pkt_ex' +* *Description* - Builds a new packet with VM instructions from the definition and returns binary data and json structure + +* *Return Value* - Returns xref:build_pkt_ex_output[Scapy packet result with VM instructions payload]. +* *Paramters* - JSON xref:build_pkt_input[Packet definition model]. + === Create packet from binary data and modify fields * *Name* - 'reconstruct_pkt' * *Description* - Builds a new packet from the binary data and returns binary data and json structure + @@ -794,9 +867,35 @@ User can still create non valid hierarchies. (such as Ether()/DNS()/IP()) } ---- +=== Get a list of predefined packet templates +* *Name* - 'get_templates' +* *Description* - returns a list of predefined templates. +* *Parameters* - none +* *Result* [array] - A list of predefined templates. + +*Example:* + +[source,python] +---- +[ + { + "id": "TCP-SYN", + "meta": { + "name": "TCP-SYN", + "description": "" + }, + } +] +---- +=== Get predefined packet template +* *Name* - 'get_template' +* *Description* - returns a JSON template encoded in Base64. +* *Parameters* - none +* *Result* [string] - String contains Base64 encoded JSON. + == Usage of Scapy RPC Server -Notice the existance of the following files: +Notice the existence of the following files: * scapy_service.py * scapy_zmq_server.py diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index 654b98f7..7ed03ec2 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -853,7 +853,7 @@ class Scapy_service(Scapy_service_api): for instruction_def in instructions_def: instruction_id = instruction_def['id'] instruction_class = self._vm_instructions[instruction_id] - parameters = {k: self._sanitize_value(k, v) for (k, v) in instruction_def['parameters'].iteritems()} + parameters = {k: self._sanitize_value(k, v) for (k, v) in instruction_def['parameters'].items()} instructions.append(instruction_class(**parameters)) fe_parameters = field_engine_model_descriptor['global_parameters'] -- cgit 1.2.3-korg From 10a1d2e33a110a091f539bdf3de5e5c69e5887f8 Mon Sep 17 00:00:00 2001 From: ichebyki Date: Tue, 20 Dec 2016 12:57:59 +0700 Subject: Add support for predefined packet templates. Change-Id: Ib2bdcbe6ea18933394527f06be001607344c75e4 Signed-off-by: Igor Chebykin --- .../stl/services/scapy_server/scapy_service.py | 91 +++++++++++++++++++++- .../scapy_server/templates/ICMP echo request.trp | 1 + .../services/scapy_server/templates/IPv4/ICMP.trp | 1 + .../services/scapy_server/templates/IPv4/TCP.trp | 1 + .../services/scapy_server/templates/IPv4/UDP.trp | 1 + .../services/scapy_server/templates/IPv6/ICMP.trp | 1 + .../services/scapy_server/templates/IPv6/TCP.trp | 1 + .../services/scapy_server/templates/IPv6/UDP.trp | 1 + .../services/scapy_server/templates/TCP-SYN.trp | 1 + .../services/scapy_server/unit_tests/basetest.py | 9 +++ .../scapy_server/unit_tests/test_scapy_service.py | 40 ++++++++++ 11 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/ICMP echo request.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/ICMP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/TCP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/UDP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/ICMP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/TCP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/UDP.trp create mode 100644 scripts/automation/trex_control_plane/stl/services/scapy_server/templates/TCP-SYN.trp (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py index 7ed03ec2..7b19896b 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_service.py @@ -264,6 +264,34 @@ class Scapy_service_api(): """ pass + def get_templates(self,client_v_handler): + """ get_templates(self,client_v_handler) + + Returns an array of templates, which normally can be used for creating packet + + Parameters + ---------- + + Returns + ------- + array of templates + """ + pass + + def get_template(self,client_v_handler,template): + """ get_template(self,client_v_handler,template) + + Returns a template, which normally can be used for creating packet + + Parameters + ---------- + + Returns + ------- + base64 of template content + """ + pass + def is_python(version): return version == sys.version_info[0] @@ -933,7 +961,7 @@ class Scapy_service(Scapy_service_api): else: return pkt_class() - + def _get_payload_classes(self, pkt_class): # tries to find, which subclasses allowed. # this can take long time, since it tries to build packets with all subclasses(O(N)) @@ -950,6 +978,61 @@ class Scapy_service(Scapy_service_api): pass return allowed_subclasses + + + def _get_templates(self): + # Make sure you understand the three return values of os.walk: + # + # for root, subdirs, files in os.walk(rootdir): + # has the following meaning: + # + # root: Current path which is "walked through" + # subdirs: Files in root of type directory + # files: Files in root (not in subdirs) of type other than directory + # And please use os.path.join instead of concatenating with a slash! + # Your problem is filePath = rootdir + '/' + file - you must concatenate the currently "walked" folder instead of the topmost folder. + # So that must be filePath = os.path.join(root, file). BTW "file" is a builtin, so you don't normally use it as variable name. + + templates = [] + for root, subdirs, files in os.walk("templates"): + for file in files: + if file.endswith('.trp'): + try: + f = os.path.join(root, file) + o = open(f) + c = json.loads(o.read()) + o.close() + id = f.replace("templates" + os.path.sep, "", 1) + id = id.split(os.path.sep) + id[-1] = id[-1].replace(".trp", "", 1) + id = "/".join(id) + t = { + "id": id, + "meta": { + "name": c["metadata"]["caption"], + "description": "" + } + } + templates.append(t) + except: + pass + return templates + + def _get_template(self,template): + id = template["id"] + f2 = "templates" + os.path.sep + os.path.sep.join(id.split("/")) + ".trp" + for c in r'[]\;,><&*:%=+@!#^()|?^': + id = id.replace(c,'') + id = id.replace("..", "") + id = id.split("/") + f = "templates" + os.path.sep + os.path.sep.join(id) + ".trp" + if f != f2: + return "" + with open(f, 'r') as content_file: + content = base64.b64encode(content_file.read()) + return content + + def _get_fields_definition(self, pkt_class, fieldsDef): # fieldsDef - array of field definitions(or empty array) fields = [] @@ -1010,6 +1093,12 @@ class Scapy_service(Scapy_service_api): return protocolDef['payload'] return [c.__name__ for c in self._get_payload_classes(pkt_class)] + def get_templates(self,client_v_handler): + return self._get_templates() + + def get_template(self,client_v_handler,template): + return self._get_template(template) + #input in string encoded base64 def check_update_of_dbs(self,client_v_handler,db_md5,field_md5): if not (self._verify_version_handler(client_v_handler)): diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/ICMP echo request.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/ICMP echo request.trp new file mode 100644 index 00000000..f8988a5f --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/ICMP echo request.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[]},{"id":"IP","fields":[]},{"id":"ICMP","fields":[{"id":"type","value":"8"}]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/ICMP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/ICMP.trp new file mode 100644 index 00000000..4ab1a1ae --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/ICMP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"2048"}]},{"id":"IP","fields":[]},{"id":"ICMP","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/TCP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/TCP.trp new file mode 100644 index 00000000..6c94592c --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/TCP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"2048"}]},{"id":"IP","fields":[]},{"id":"TCP","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/UDP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/UDP.trp new file mode 100644 index 00000000..bef92993 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv4/UDP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"2048"}]},{"id":"IP","fields":[]},{"id":"UDP","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/ICMP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/ICMP.trp new file mode 100644 index 00000000..c0387a0a --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/ICMP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"34525"}]},{"id":"IPv6","fields":[]},{"id":"ICMPv6ND_Redirect","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/TCP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/TCP.trp new file mode 100644 index 00000000..1cb9576f --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/TCP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"34525"}]},{"id":"IPv6","fields":[]},{"id":"TCP","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/UDP.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/UDP.trp new file mode 100644 index 00000000..da96ae89 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/IPv6/UDP.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"ICMP echo request"},"packet":[{"id":"Ether","fields":[{"id":"type","value":"34525"}]},{"id":"IPv6","fields":[]},{"id":"UDP","fields":[]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/TCP-SYN.trp b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/TCP-SYN.trp new file mode 100644 index 00000000..8d7668cc --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/templates/TCP-SYN.trp @@ -0,0 +1 @@ +{"fileType":"trex-packet-editor","version":"1.0.0","metadata":{"caption":"TCP-SYN"},"packet":[{"id":"Ether","fields":[]},{"id":"IP","fields":[]},{"id":"TCP","fields":[{"id":"flags","value":""}]}],"fePrarameters":{"cache_size":"1000"},"feInstructions":[]} \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/basetest.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/basetest.py index e48880e8..9836c794 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/basetest.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/basetest.py @@ -88,3 +88,12 @@ def adapt_json_protocol_fields(protocols_array): # change structure for easier if protocol.get("fields"): protocol["fields"] = fields_to_map(protocol["fields"]) + +def get_templates(): + return pass_result(service.get_templates(v_handler)) + + + +def get_template(t): + return pass_result(service.get_template(v_handler, t)) + diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py index e1094a79..1ece5d1e 100644 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/unit_tests/test_scapy_service.py @@ -289,3 +289,43 @@ def test_generate_vm_instructions(): ttl_instruction = res['field_engine']['instructions']['instructions'][2] assert(ttl_instruction['min_value'] == 32) assert(ttl_instruction['max_value'] == 64) + + +def test_get_templates(): + tt = get_templates() + assert(tt[0]['id']) + assert(tt[7]["meta"]['name']) + try: + assert(tt[9]['id']) + except: + pass + + +def test_get_template(): + tt = get_templates() + t = tt[0] + res = get_template(t) + res2 = base64.b64decode(res) + obj = json.loads(res2) + assert(obj['packet'][0]['id'] == 'Ether') + assert(obj['packet'][1]['id'] == 'IP') + assert(obj['packet'][2]['id'] == 'ICMP') + + +def test_get_template2(): + tt = get_templates() + t = tt[7] + res = get_template(t) + res2 = base64.b64decode(res) + obj = json.loads(res2) + assert(obj['packet'][0]['id'] == 'Ether') + assert(obj['packet'][1]['id'] == 'IPv6') + assert(obj['packet'][2]['id'] == 'UDP') + + +def test_get_template3(): + tt = get_templates() + t = tt[7] + t["id"] = "../../" + t["id"] + res = get_template(t) + assert(res == '') -- cgit 1.2.3-korg From b7fcb83a06ac4c6a75b4b6982418a36865e14440 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Wed, 11 Jan 2017 13:50:09 +0200 Subject: scapy_server: add try-catch on determining self IP Change-Id: Ibda7ba66a08385cfd8d73717e4c0fa257aa38436 Signed-off-by: Yaroslav Brustinov --- .../trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py index 6489b36a..0788229a 100755 --- a/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py +++ b/scripts/automation/trex_control_plane/stl/services/scapy_server/scapy_zmq_server.py @@ -103,7 +103,10 @@ class Scapy_server(): self.context = zmq.Context() self.socket = self.context.socket(zmq.REP) self.socket.bind("tcp://*:"+str(port)) - self.IP_address = socket.gethostbyname(socket.gethostname()) + try: + self.IP_address = socket.gethostbyname(socket.gethostname()) + except: + self.IP_address = '0.0.0.0' self.logger = logging.getLogger('scapy_logger') self.logger.setLevel(logging.INFO) console_h = logging.StreamHandler(sys.__stdout__) -- cgit 1.2.3-korg From 83861b490b5ce17212830a425d7c8cfd00090c40 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Thu, 12 Jan 2017 16:24:03 +0200 Subject: Add help message for --no-scapy-server flag Python API: fix arp resolve console message Python API: retry ZMQ send/recv only for push_pcap Console: portattr fix for readonly mode Change-Id: I69587987deb4edfbe192ee422ce6aad74b1ecaf3 Signed-off-by: Yaroslav Brustinov --- .../stl/trex_stl_lib/trex_stl_client.py | 31 ++++++++++++---------- .../stl/trex_stl_lib/trex_stl_jsonrpc_client.py | 28 +++++++++---------- .../stl/trex_stl_lib/trex_stl_port.py | 6 ++--- src/main_dpdk.cpp | 1 + 4 files changed, 35 insertions(+), 31 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl') diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index e20de3da..21ae42f1 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -449,16 +449,16 @@ class CCommLink(object): if not self.virtual: return self.rpc_link.disconnect() - def transmit(self, method_name, params = None, api_class = 'core'): + def transmit(self, method_name, params = None, api_class = 'core', retry = 0): if self.virtual: self._prompt_virtual_tx_msg() _, msg = self.rpc_link.create_jsonrpc_v2(method_name, params, api_class) print(msg) return else: - return self.rpc_link.invoke_rpc_method(method_name, params, api_class) + return self.rpc_link.invoke_rpc_method(method_name, params, api_class, retry = retry) - def transmit_batch(self, batch_list): + def transmit_batch(self, batch_list, retry = 0): if self.virtual: self._prompt_virtual_tx_msg() print([msg @@ -469,7 +469,7 @@ class CCommLink(object): for command in batch_list: batch.add(command.method, command.params, command.api_class) # invoke the batch - return batch.invoke() + return batch.invoke(retry = retry) def _prompt_virtual_tx_msg(self): print("Transmitting virtually over tcp://{server}:{port}".format(server=self.server, @@ -2997,7 +2997,7 @@ class STLClient(object): :parameters: ports - for which ports to apply a unique sniffer (each port gets a unique file) - retires - how many times to retry on each port (intervals of 100 milliseconds) + retries - how many times to retry on each port (intervals of 100 milliseconds) verbose - log for each request the response :raises: + :exe:'STLError' @@ -3015,7 +3015,7 @@ class STLClient(object): self.logger.post_cmd(rc) if verbose: - for x in filter(bool, rc.data()): + for x in filter(bool, listify(rc.data())): self.logger.log(format_text("{0}".format(x), 'bold')) if not rc: @@ -3757,7 +3757,7 @@ class STLClient(object): parsing_opts.SUPPORTED, ) - opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) + opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports()) if not opts: return opts @@ -3767,8 +3767,9 @@ class STLClient(object): opts.flow_ctrl = parsing_opts.FLOW_CTRL_DICT.get(opts.flow_ctrl) # if no attributes - fall back to printing the status - if not list(filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.supp])): - self.show_stats_line("--ps --port {0}".format(' '.join(str(port) for port in opts.ports))) + if not list(filter(lambda opt:opt[0] not in ('all_ports', 'ports') and opt[1] is not None, opts._get_kwargs())): + ports = opts.ports if opts.ports else self.get_all_ports() + self.show_stats_line("--ps --port {0}".format(' '.join(str(port) for port in ports))) return if opts.supp: @@ -3781,11 +3782,13 @@ class STLClient(object): print(' Flow control: %s' % info['fc_supported']) print('') else: - self.set_port_attr(opts.ports, - opts.prom, - opts.link, - opts.led, - opts.flow_ctrl) + if not opts.ports: + raise STLError('No acquired ports!') + self.set_port_attr(opts.ports, + opts.prom, + opts.link, + opts.led, + opts.flow_ctrl) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py index 72c9317a..db216532 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py @@ -32,7 +32,7 @@ class BatchMessage(object): id, msg = self.rpc_client.create_jsonrpc_v2(method_name, params, api_class, encode = False) self.batch_list.append(msg) - def invoke(self, block = False, chunk_size = 500000): + def invoke(self, block = False, chunk_size = 500000, retry = 0): if not self.rpc_client.connected: return RC_ERR("Not connected to server") @@ -54,7 +54,7 @@ class BatchMessage(object): return response_batch else: batch_json = json.dumps(self.batch_list) - return self.rpc_client.send_msg(batch_json) + return self.rpc_client.send_msg(batch_json, retry = retry) # JSON RPC v2.0 client @@ -127,16 +127,16 @@ class JsonRpcClient(object): return id, msg - def invoke_rpc_method (self, method_name, params = None, api_class = 'core'): + def invoke_rpc_method (self, method_name, params = None, api_class = 'core', retry = 0): if not self.connected: return RC_ERR("Not connected to server") id, msg = self.create_jsonrpc_v2(method_name, params, api_class) - return self.send_msg(msg) + return self.send_msg(msg, retry = retry) - def send_msg (self, msg): + def send_msg (self, msg, retry = 0): # print before if self.logger.check_verbose(self.logger.VERBOSE_HIGH): self.verbose_msg("Sending Request To Server:\n\n" + self.pretty_json(msg) + "\n") @@ -145,9 +145,9 @@ class JsonRpcClient(object): buffer = msg.encode() if self.zipper.check_threshold(buffer): - response = self.send_raw_msg(self.zipper.compress(buffer)) + response = self.send_raw_msg(self.zipper.compress(buffer), retry = retry) else: - response = self.send_raw_msg(buffer) + response = self.send_raw_msg(buffer, retry = retry) if not response: return response @@ -175,16 +175,16 @@ class JsonRpcClient(object): # low level send of string message - def send_raw_msg (self, msg): + def send_raw_msg (self, msg, retry = 0): - tries = 0 + retry_left = retry while True: try: self.socket.send(msg) break except zmq.Again: - tries += 1 - if tries > 5: + retry_left -= 1 + if retry_left < 0: self.disconnect() return RC_ERR("*** [RPC] - Failed to send message to server") @@ -193,14 +193,14 @@ class JsonRpcClient(object): self.reconnect() raise e - tries = 0 + retry_left = retry while True: try: response = self.socket.recv() break except zmq.Again: - tries += 1 - if tries > 5: + retry_left -= 1 + if retry_left < 0: self.disconnect() return RC_ERR("*** [RPC] - Failed to get server response from {0}".format(self.transport)) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 8b6b2e2e..a9509ee9 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -264,7 +264,7 @@ class Port(object): def add_streams (self, streams_list): # listify - streams_list = streams_list if isinstance(streams_list, list) else [streams_list] + streams_list = listify(streams_list) lookup = {} @@ -338,7 +338,7 @@ class Port(object): def remove_streams (self, stream_id_list): # single element to list - stream_id_list = stream_id_list if isinstance(stream_id_list, list) else [stream_id_list] + stream_id_list = listify(stream_id_list) # verify existance if not all([stream_id in self.streams for stream_id in stream_id_list]): @@ -751,7 +751,7 @@ class Port(object): "slave_handler": slave_handler, "min_ipg_usec": min_ipg_usec if min_ipg_usec else 0} - rc = self.transmit("push_remote", params) + rc = self.transmit("push_remote", params, retry = 4) if rc.bad(): return self.err(rc.err()) diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 3149bdb3..aa31cf0b 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -826,6 +826,7 @@ static int usage(){ printf(" --no-flow-control-change : By default TRex disables flow-control. If this option is given, it does not touch it \n"); printf(" --no-key : Daemon mode, don't get input from keyboard \n"); printf(" --no-ofed-check : Disable the check of OFED version \n"); + printf(" --no-scapy-server : Disable Scapy server implicit start at stateless \n"); printf(" --no-watchdog : Disable watchdog \n"); printf(" -p : Send all flow packets from the same interface (choosed randomly between client ad server ports) without changing their src/dst IP \n"); printf(" -pm : Platform factor. If you have splitter in the setup, you can multiply the total results by this factor \n"); -- cgit 1.2.3-korg