diff options
Diffstat (limited to 'scripts/automation/trex_control_plane')
18 files changed, 269 insertions, 51 deletions
diff --git a/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py b/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py index 0a72c9ac..8560a5db 100644 --- a/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py +++ b/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py @@ -14,8 +14,8 @@ def minimal_stateful_test(server,csv_file,a_active_flows): trex_client.start_trex( c = 7, m = 30000, -# f = 'cap2/cur_flow_single.yaml', - f = 'cap2/cur_flow.yaml', + f = 'cap2/cur_flow_single.yaml', +# f = 'cap2/cur_flow.yaml', d = 30, l = 1000, p=True, @@ -39,6 +39,7 @@ def minimal_stateful_test(server,csv_file,a_active_flows): print("WARNING QUEU WAS FULL"); tuple=(active_flows[-5],cpu_utl[-5],pps[-5],queue_full[-1]) + print(tuple) file_writer = csv.writer(test_file) file_writer.writerow(tuple); @@ -58,7 +59,7 @@ if __name__ == '__main__': max_flows = 8000000; min_flows = 100; active_flow = min_flows; - num_point = 10 + num_point = 40 factor = math.exp(math.log(max_flows/min_flows,math.e)/num_point); for i in range(num_point+1): print("<<=====================>>",i,math.floor(active_flow)) diff --git a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py index 0977d2eb..4e7deb93 100755 --- a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py +++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py @@ -154,8 +154,7 @@ class CTRexClient(object): raise ValueError('d parameter must be integer, specifying how long TRex run.') trex_cmd_options.update( {'f' : f, 'd' : d} ) - if not trex_cmd_options.get('l'): - self.result_obj.latency_checked = False + self.result_obj.latency_checked = 'l' in trex_cmd_options if 'k' in trex_cmd_options: timeout += int(trex_cmd_options['k']) # during 'k' seconds TRex stays in 'Starting' state @@ -1117,6 +1116,7 @@ class CTRexResult(object): "Done warmup? {arg}\n".format( arg = self.is_done_warmup() ) + "Expected tx rate: {arg}\n".format( arg = self.get_expected_tx_rate() ) + "Current tx rate: {arg}\n".format( arg = self.get_current_tx_rate() ) + + "Minimum latency: {arg}\n".format( arg = self.get_min_latency() ) + "Maximum latency: {arg}\n".format( arg = self.get_max_latency() ) + "Average latency: {arg}\n".format( arg = self.get_avg_latency() ) + "Average window latency: {arg}\n".format( arg = self.get_avg_window_latency() ) + @@ -1163,6 +1163,36 @@ class CTRexResult(object): """ return self._max_latency + def get_min_latency (self): + """ + Fetches the minimum latency measured on each of the interfaces + + :parameters: + None + + :return: + dictionary containing the maximum latency, where the key is the measurement interface (`c` indicates client), and the value is the measurement value. + + """ + return self._min_latency + + + + def get_jitter_latency (self): + """ + Fetches the jitter latency measured on each of the interfaces from the start of TRex run + + :parameters: + None + + :return: + dictionary containing the average latency, where the key is the measurement interface (`c` indicates client), and the value is the measurement value. + + The `all` key represents the average of all interfaces' average + + """ + return self._jitter_latency + def get_avg_latency (self): """ Fetches the average latency measured on each of the interfaces from the start of TRex run @@ -1398,8 +1428,11 @@ class CTRexResult(object): latency_per_port = self.get_last_value("trex-latency-v2.data", "port-") self._max_latency = self.__get_filtered_max_latency(latency_per_port, self.filtered_latency_amount) + self._min_latency = self.__get_filtered_min_latency(latency_per_port) avg_latency = self.get_last_value("trex-latency.data", "avg-") self._avg_latency = CTRexResult.__avg_all_and_rename_keys(avg_latency) + jitter_latency = self.get_last_value("trex-latency.data", "jitter-") + self._jitter_latency = CTRexResult.__avg_all_and_rename_keys(jitter_latency) avg_win_latency_list = self.get_value_list("trex-latency.data", "avg-") self._avg_window_latency = CTRexResult.__calc_latency_win_stats(avg_win_latency_list) @@ -1425,7 +1458,9 @@ class CTRexResult(object): self._expected_tx_rate = None self._current_tx_rate = None self._max_latency = None + self._min_latency = None self._avg_latency = None + self._jitter_latency = None self._avg_window_latency = None self._total_drops = None self._drop_rate = None @@ -1488,6 +1523,21 @@ class CTRexResult(object): return res @staticmethod + def __get_filtered_min_latency(src_dict): + result = {} + if src_dict: + for port, data in src_dict.items(): + if not port.startswith('port-'): + continue + res = data['hist']['min_usec'] + min_port = 'min-%s' % port[5:] + result[min_port] = int(res) + + return(result); + + + + @staticmethod def __get_filtered_max_latency (src_dict, filtered_latency_amount = 0.001): result = {} if src_dict: 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 270ef31c..83f36820 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -859,10 +859,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 @@ -927,17 +927,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 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..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] @@ -853,7 +881,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'] @@ -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/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__)
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 == '') 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 c82d77fb..f7432107 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 @@ -452,16 +452,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 @@ -472,7 +472,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, @@ -2322,7 +2322,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) @@ -2356,6 +2356,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: @@ -2827,7 +2833,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: @@ -2871,6 +2877,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: @@ -2965,7 +2977,7 @@ class STLClient(object): :parameters: ports - which ports to resolve - 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' @@ -3835,7 +3847,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 @@ -3845,8 +3857,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: @@ -3859,11 +3872,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 ff07b59a..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 > 0: + 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 > 0: + 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 654514cb..31d752af 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 @@ -267,7 +267,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 = {} @@ -341,7 +341,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]): @@ -736,7 +736,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()) @@ -908,6 +908,10 @@ class Port(object): def get_layer_cfg (self): return self.__attr['layer_cfg'] + + def is_virtual(self): + return self.info.get('is_virtual') + def is_l3_mode (self): return self.get_layer_cfg()['ipv4']['state'] != 'none' |