diff options
Diffstat (limited to 'scripts/automation')
7 files changed, 123 insertions, 68 deletions
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 5096e33d..46d33e3e 100644 --- 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 @@ -2006,6 +2006,7 @@ class STLClient(object): try: # pcap injection removes all previous streams from the ports self.remove_all_streams(ports = opts.ports) + profile = STLProfile.load_pcap(opts.file[0], opts.ipg_usec, opts.speedup, @@ -2018,4 +2019,5 @@ class STLClient(object): print e.brief() return + return True 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 ab3c7282..96d1854d 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 @@ -3,10 +3,12 @@ import zmq import json import re -from time import sleep from collections import namedtuple from trex_stl_types import * from utils.common import random_id_gen +import zlib +import struct + class bcolors: BLUE = '\033[94m' @@ -35,12 +37,15 @@ class BatchMessage(object): msg = json.dumps(self.batch_list) - return self.rpc_client.send_raw_msg(msg) + return self.rpc_client.send_msg(msg) # JSON RPC v2.0 client class JsonRpcClient(object): + MSG_COMPRESS_THRESHOLD = 4096 + MSG_COMPRESS_HEADER_MAGIC = 0xABE85CEA + def __init__ (self, default_server, default_port, logger): self.logger = logger self.connected = False @@ -109,14 +114,64 @@ class JsonRpcClient(object): id, msg = self.create_jsonrpc_v2(method_name, params) - return self.send_raw_msg(msg) + return self.send_msg(msg) + + + def compress_msg (self, msg): + # compress + compressed = zlib.compress(msg) + new_msg = struct.pack(">II", self.MSG_COMPRESS_HEADER_MAGIC, len(msg)) + compressed + return new_msg + + + def decompress_msg (self, msg): + if len(msg) < 8: + return None + + t = struct.unpack(">II", msg[:8]) + if (t[0] != self.MSG_COMPRESS_HEADER_MAGIC): + return None + + x = zlib.decompress(msg[8:]) + if len(x) != t[1]: + return None + + return x + + def send_msg (self, msg): + # 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") + + if len(msg) > self.MSG_COMPRESS_THRESHOLD: + response = self.send_raw_msg(self.compress_msg(msg)) + if response: + response = self.decompress_msg(response) + else: + response = self.send_raw_msg(msg) + + if response == None: + return RC_ERR("*** [RPC] - Failed to decode response from server") + + + # print after + if self.logger.check_verbose(self.logger.VERBOSE_HIGH): + self.verbose_msg("Server Response:\n\n" + self.pretty_json(response) + "\n") + + # process response (batch and regular) + + response_json = json.loads(response) + + if isinstance(response_json, list): + return self.process_batch_response(response_json) + else: + return self.process_single_response(response_json) + # low level send of string message def send_raw_msg (self, msg): - self.verbose_msg("Sending Request To Server:\n\n" + self.pretty_json(msg) + "\n") - tries = 0 while True: try: @@ -141,26 +196,11 @@ class JsonRpcClient(object): return RC_ERR("*** [RPC] - Failed to get server response at {0}".format(self.transport)) - self.verbose_msg("Server Response:\n\n" + self.pretty_json(response) + "\n") - - # decode - - # batch ? - response_json = json.loads(response) - - if isinstance(response_json, list): - rc_batch = RC() - - for single_response in response_json: - rc = self.process_single_response(single_response) - rc_batch.add(rc) - - return rc_batch - - else: - return self.process_single_response(response_json) - + return response + + + # processs a single response from server def process_single_response (self, response_json): if (response_json.get("jsonrpc") != "2.0"): @@ -182,6 +222,17 @@ class JsonRpcClient(object): + # process a batch response + def process_batch_response (self, response_json): + rc_batch = RC() + + for single_response in response_json: + rc = self.process_single_response(single_response) + rc_batch.add(rc) + + return rc_batch + + def disconnect (self): if self.connected: self.socket.close(linger = 0) 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 56657e22..c3fa70ec 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 @@ -3,6 +3,7 @@ from collections import namedtuple, OrderedDict import trex_stl_stats from trex_stl_types import * +import time StreamOnPort = namedtuple('StreamOnPort', ['compiled_stream', 'metadata']) @@ -198,15 +199,12 @@ class Port(object): cmd = RpcCmdData('add_stream', params) batch.append(cmd) - # meta data for show streams - self.streams[stream.get_id()] = StreamOnPort(stream.to_json(), - Port._generate_stream_metadata(stream)) + self.streams[stream.get_id()] = stream rc = self.transmit_batch(batch) if not rc: return self.err(rc.err()) - # the only valid state now self.state = self.STATE_STREAMS @@ -493,39 +491,22 @@ class Port(object): return self.port_stats.invalidate() ################# stream printout ###################### - def generate_loaded_streams_sum(self, stream_id_list): + def generate_loaded_streams_sum(self): if self.state == self.STATE_DOWN: return {} - streams_data = {} - - if not stream_id_list: - # if no mask has been provided, apply to all streams on port - stream_id_list = self.streams.keys() - - - streams_data = {stream_id: self.streams[stream_id].metadata.get('stream_sum', ["N/A"] * 6) - for stream_id in stream_id_list - if stream_id in self.streams} - - # sort the data - return {"streams" : OrderedDict(sorted(streams_data.items())) } - - @staticmethod - def _generate_stream_metadata(stream): - meta_dict = {} - - next = stream.get_next_id() - if next == -1: - next = "-" - - meta_dict['stream_sum'] = OrderedDict([("id", stream.get_id()), - ("packet_type", stream.get_pkt_type()), - ("L2 len", stream.get_pkt_len()), - ("mode", stream.get_mode()), - ("rate_pps", stream.get_pps()), - ("next_stream", next) - ]) - return meta_dict + + data = {} + for id, stream in self.streams.iteritems(): + data[id] = OrderedDict([ ('id', id), + ('packet_type', stream.get_pkt_type()), + ('L2 len', stream.get_pkt_len()), + ('mode' , stream.get_mode()), + ('rate_pps', stream.get_pps()), + ('next_stream', stream.get_next_id()) + ]) + + return {"streams" : OrderedDict(sorted(data.items())) } + ################# events handler ###################### def async_event_port_stopped (self): diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py index 4d720aac..380b7a39 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py @@ -27,7 +27,8 @@ from trex_stl_client import STLClient import re import json - +import zlib +import struct import argparse @@ -217,11 +218,19 @@ class STLSim(object): # internal run - def __run (self, cmds_json): + def __run (self, cmds_json, zipped = True): # write to temp file f = tempfile.NamedTemporaryFile(delete = False) - f.write(json.dumps(cmds_json)) + + msg = json.dumps(cmds_json) + + # stress the zip path + if zipped: + compressed = zlib.compress(msg) + new_msg = struct.pack(">II", 0xABE85CEA, len(msg)) + compressed + + f.write(new_msg) f.close() # launch bp-sim diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index 30f303a8..e5578564 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -208,7 +208,7 @@ class CTRexInfoGenerator(object): def _generate_single_port_streams_info(self, port_obj, stream_id_list): - return_streams_data = port_obj.generate_loaded_streams_sum(stream_id_list) + return_streams_data = port_obj.generate_loaded_streams_sum() if not return_streams_data.get("streams"): # we got no streams available @@ -219,13 +219,16 @@ class CTRexInfoGenerator(object): # because we mutate this - deep copy before return_streams_data = copy.deepcopy(return_streams_data) + p_type_field_len = 0 + for stream_id, stream_id_sum in return_streams_data['streams'].iteritems(): stream_id_sum['rate_pps'] = format_num(stream_id_sum['rate_pps'], suffix='pps') - stream_id_sum['packet_type'] = self._trim_packet_headers(stream_id_sum['packet_type'], 20) + stream_id_sum['packet_type'] = self._trim_packet_headers(stream_id_sum['packet_type'], 30) + p_type_field_len = max(p_type_field_len, len(stream_id_sum['packet_type'])) info_table = text_tables.TRexTextTable() info_table.set_cols_align(["c"] + ["l"] + ["r"] + ["c"] + ["r"] + ["c"]) - info_table.set_cols_width([10] + [20] + [8] + [16] + [10] + [12]) + info_table.set_cols_width([10] + [p_type_field_len] + [8] + [16] + [10] + [12]) info_table.set_cols_dtype(["t"] + ["t"] + ["t"] + ["t"] + ["t"] + ["t"]) info_table.add_rows([v.values() diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py index 1a46aae7..efeb5c8a 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py @@ -157,7 +157,10 @@ class STLStream(object): # packet and VM self.fields['packet'] = packet.dump_pkt() self.fields['vm'] = packet.get_vm_data() - self.packet_desc = packet.pkt_layers_desc() + + + # this is heavy, calculate lazy + self.packet_desc = None if not rx_stats: self.fields['rx_stats'] = {} @@ -194,6 +197,9 @@ class STLStream(object): return self.next def get_pkt_type (self): + if self.packet_desc == None: + self.packet_desc = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(base64.b64decode(self.fields['packet']['binary'])) + return self.packet_desc def get_pkt_len (self, count_crc = True): @@ -432,14 +438,17 @@ class STLProfile(object): else: next = i + 1 + streams.append(STLStream(name = i, packet = CScapyTRexPktBuilder(pkt_buffer = cap), mode = STLTXSingleBurst(total_pkts = 1), self_start = True if (i == 1) else False, isg = (ts_usec - last_ts_usec), # seconds to usec next = next)) + last_ts_usec = ts_usec + return STLProfile(streams) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py index d387ac9c..0a6e64fb 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py @@ -4,6 +4,7 @@ from utils.text_opts import * from trex_stl_exceptions import * RpcCmdData = namedtuple('RpcCmdData', ['method', 'params']) +TupleRC = namedtuple('RC', ['rc', 'data', 'is_warn']) class RpcResponseStatus(namedtuple('RpcResponseStatus', ['success', 'id', 'msg'])): __slots__ = () @@ -19,8 +20,7 @@ class RC(): self.rc_list = [] if (rc != None): - tuple_rc = namedtuple('RC', ['rc', 'data', 'is_warn']) - self.rc_list.append(tuple_rc(rc, data, is_warn)) + self.rc_list.append(TupleRC(rc, data, is_warn)) def __nonzero__ (self): return self.good() |