diff options
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py')
-rwxr-xr-x | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py | 143 |
1 files changed, 125 insertions, 18 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 1b57218f..d75c554e 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 @@ -26,6 +26,7 @@ import random import json import traceback import os.path +import argparse ############################ logger ############################# ############################ ############################# @@ -2961,7 +2962,7 @@ class STLClient(object): Resolves ports (ARP resolution) :parameters: - ports - for which ports to apply a unique sniffer (each port gets a unique file) + ports - which ports to resolve retires - how many times to retry on each port (intervals of 100 milliseconds) verbose - log for each request the response :raises: @@ -3022,7 +3023,7 @@ class STLClient(object): self.logger.pre_cmd("Starting PCAP capturing up to {0} packets".format(limit)) - rc = self._transmit("start_capture", params = {'limit': limit, 'tx': tx_ports, 'rx': rx_ports}) + rc = self._transmit("capture", params = {'command': 'start', 'limit': limit, 'tx': tx_ports, 'rx': rx_ports}) self.logger.post_cmd(rc) @@ -3032,24 +3033,82 @@ class STLClient(object): @__api_check(True) - def stop_capture (self, ports = None): + def stop_capture (self, capture_id, output_filename): """ - Removes RX sniffer from port(s) + Stops an active capture + + :parameters: + capture_id - an active capture ID to stop + output_filename - output filename to save capture :raises: + :exe:'STLError' """ - ports = ports if ports is not None else self.get_acquired_ports() - ports = self._validate_port_list(ports) - self.logger.pre_cmd("Removing RX sniffers on port(s) {0}:".format(ports)) - rc = self.__remove_rx_sniffer(ports) + + + # stopping a capture requires: + # 1. stopping + # 2. fetching + # 3. saving to file + + # stop + + self.logger.pre_cmd("Stopping PCAP capture {0}".format(capture_id)) + rc = self._transmit("capture", params = {'command': 'stop', 'capture_id': capture_id}) self.logger.post_cmd(rc) + if not rc: + raise STLError(rc) + + # pkt count + pkt_count = rc.data()['pkt_count'] + + if not output_filename or pkt_count == 0: + return + + self.logger.pre_cmd("Writing {0} packets to '{1}'".format(pkt_count, output_filename)) + + # create a PCAP file + writer = RawPcapWriter(output_filename, linktype = 1) + writer._write_header(None) + + # fetch + while True: + rc = self._transmit("capture", params = {'command': 'fetch', 'capture_id': capture_id, 'pkt_limit': 50}) + if not rc: + self.logger.post_cmd(rc) + raise STLError(rc) + + pkts = rc.data()['pkts'] + for pkt in pkts: + ts = pkt['ts'] + pkt_bin = base64.b64decode(pkt['binary']) + writer._write_packet(pkt_bin, sec = 0, usec = 0) + + if rc.data()['pending'] == 0: + break + + self.logger.post_cmd(rc) + + + # get capture status + @__api_check(True) + def get_capture_status (self): + """ + returns a list of all active captures + each element in the list is an object containing + info about the capture + + """ + + rc = self._transmit("capture", params = {'command': 'status'}) if not rc: raise STLError(rc) + return rc.data() + @__api_check(True) def set_rx_queue (self, ports = None, size = 1000): @@ -3766,23 +3825,71 @@ class STLClient(object): @__console - def start_capture_line (self, line): - '''Starts PCAP recorder on port(s)''' + def capture_line (self, line): + '''Manage PCAP recorders''' - parser = parsing_opts.gen_parser(self, - "capture", - self.start_capture_line.__doc__, - parsing_opts.TX_PORT_LIST, - parsing_opts.RX_PORT_LIST, - parsing_opts.LIMIT) + # default + if not line: + line = "show" + + parser = parsing_opts.gen_parser(self, "capture", self.capture_line.__doc__) + subparsers = parser.add_subparsers(title = "commands", dest="commands") + + # start + start_parser = subparsers.add_parser('start', help = "starts a new capture") + start_parser.add_arg_list(parsing_opts.TX_PORT_LIST, + parsing_opts.RX_PORT_LIST, + parsing_opts.LIMIT) + + # stop + stop_parser = subparsers.add_parser('stop', help = "stops an active capture") + stop_parser.add_arg_list(parsing_opts.CAPTURE_ID, + parsing_opts.OUTPUT_FILENAME) + + # show + show_parser = subparsers.add_parser('show', help = "show all active captures") + + opts = parser.parse_args(line.split()) - opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) if not opts: return opts - self.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit) + # start + if opts.commands == 'start': + if not opts.tx_port_list and not opts.rx_port_list: + start_parser.formatted_error('please provide either --tx or --rx') + return + + self.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit) + + # stop + elif opts.commands == 'stop': + self.stop_capture(opts.capture_id, opts.output_filename) + + # show + else: + data = self.get_capture_status() + + stats_table = text_tables.TRexTextTable() + stats_table.set_cols_align(["c"] * 6) + stats_table.set_cols_width([15] * 6) + + for elem in data: + row = [elem['id'], + elem['state'], + '[{0}/{1}]'.format(elem['count'], elem['limit']), + format_num(elem['bytes'], suffix = 'B'), + bitfield_to_str(elem['filter']['tx']), + bitfield_to_str(elem['filter']['rx'])] + + stats_table.add_rows([row], header=False) + + stats_table.header(['ID', 'Status', 'Count', 'Bytes', 'TX Ports', 'RX Ports']) + text_tables.print_table_with_header(stats_table, "Captures") + return RC_OK() + @__console |