From a1ade6fd8e044b9866a8644db3519305539cfc61 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 6 Nov 2016 17:20:17 +0200 Subject: RX features - RX sniffer Signed-off-by: imarom --- .../stl/trex_stl_lib/trex_stl_client.py | 108 +++++++++++++++++---- .../stl/trex_stl_lib/trex_stl_port.py | 37 +++++-- .../stl/trex_stl_lib/trex_stl_stats.py | 2 + .../stl/trex_stl_lib/utils/parsing_opts.py | 28 ++++++ 4 files changed, 149 insertions(+), 26 deletions(-) (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib') 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 907e405a..b9143896 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 @@ -24,6 +24,8 @@ import re import random import json import traceback +import os.path + ############################ logger ############################# ############################ ############################# @@ -322,26 +324,28 @@ class EventsHandler(object): # port attr changed elif (event_type == 8): + return - port_id = int(data['port_id']) - - if data['attr'] == self.client.ports[port_id].attr: - return # false alarm - - old_info = self.client.ports[port_id].get_formatted_info() - self.__async_event_port_attr_changed(port_id, data['attr']) - - new_info = self.client.ports[port_id].get_formatted_info() - ev = "port {0} attributes changed".format(port_id) - for key, old_val in old_info.items(): - new_val = new_info[key] - if old_val != new_val: - ev += '\n {key}: {old} -> {new}'.format( - key = key, - old = old_val.lower() if type(old_val) is str else old_val, - new = new_val.lower() if type(new_val) is str else new_val) - show_event = True + # port_id = int(data['port_id']) + # + # if data['attr'] == self.client.ports[port_id].attr: + # return # false alarm + # + # old_info = self.client.ports[port_id].get_formatted_info() + # self.__async_event_port_attr_changed(port_id, data['attr']) + # + # new_info = self.client.ports[port_id].get_formatted_info() + # ev = "port {0} attributes changed".format(port_id) + # for key, old_val in old_info.items(): + # new_val = new_info[key] + # if old_val != new_val: + # ev += '\n {key}: {old} -> {new}'.format( + # key = key, + # old = old_val.lower() if type(old_val) is str else old_val, + # new = new_val.lower() if type(new_val) is str else new_val) + # show_event = True + # server stopped elif (event_type == 100): ev = "Server has stopped" @@ -814,6 +818,17 @@ class STLClient(object): return rc + def __set_rx_sniffer (self, port_id_list, base_filename, limit): + port_id_list = self.__ports(port_id_list) + rc = RC() + + for port_id in port_id_list: + head, tail = os.path.splitext(base_filename) + filename = "{0}-{1}{2}".format(head, port_id, tail) + rc.add(self.ports[port_id].set_rx_sniffer(filename, limit)) + + return rc + # connect to server def __connect(self): @@ -2685,6 +2700,39 @@ class STLClient(object): if not rc: raise STLError(rc) + + + @__api_check(True) + def set_rx_sniffer (self, ports = None, base_filename = 'rx_capture', limit = 1000): + """ + Sets RX sniffer for port(s) written to a PCAP file + + :parameters: + ports - for which ports to apply a unique sniffer (each port gets a unique file) + base_filename - filename will be appended with '-' + limit - limit how many packets will be written + :raises: + + :exe:'STLError' + + """ + ports = ports if ports is not None else self.get_acquired_ports() + ports = self._validate_port_list(ports) + + # check arguments + validate_type('base_filename', base_filename, basestring) + validate_type('limit', limit, (int)) + + + self.logger.pre_cmd("Setting RX sniffers on port(s) {0}:".format(ports)) + rc = self.__set_rx_sniffer(ports, base_filename, limit) + self.logger.post_cmd(rc) + + + if not rc: + raise STLError(rc) + + + def clear_events (self): """ Clear all events @@ -3281,7 +3329,29 @@ class STLClient(object): return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.rx_filter_mode) - + + @__console + def set_rx_sniffer_line (self, line): + '''Sets a port sniffer on RX channel in form of a PCAP file''' + + parser = parsing_opts.gen_parser(self, + "set_rx_sniffer", + self.set_rx_sniffer_line.__doc__, + parsing_opts.PORT_LIST_WITH_ALL, + parsing_opts.OUTPUT_FILENAME, + parsing_opts.LIMIT, + parsing_opts.ALL_FILES) + + opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) + if not opts: + return opts + + if parsing_opts.ALL_FILES: + self.set_port_attr(ports = opts.ports, rx_filter_mode = 'all') + + self.set_rx_sniffer(opts.ports, opts.output_filename, opts.limit) + + @__console def show_profile_line (self, line): '''Shows profile information''' 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 59793495..571a6e16 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 @@ -252,6 +252,10 @@ class Port(object): # attributes self.attr = rc.data()['attr'] + + # rx info + self.rx_info = rc.data()['rx_info'] + return self.ok() @@ -484,18 +488,15 @@ class Port(object): return self.ok() - # + @writeable - def start_rx_capture (self, pcap_filename, limit): - - prefix, suffix = pcap_filename.split('.') - filename = "{0}-{1}.{2}".format(prefix, self.port_id, suffix) + def set_rx_sniffer (self, pcap_filename, limit): params = {"handler": self.handler, "port_id": self.port_id, "type": "capture", "enabled": True, - "pcap_filename": filename, + "pcap_filename": pcap_filename, "limit": limit} rc = self.transmit("set_rx_feature", params) @@ -679,6 +680,10 @@ class Port(object): # generate formatted (console friendly) port info def get_formatted_info (self): + + # sync the attributes + self.sync() + info = dict(self.info) info['status'] = self.get_port_state_name() @@ -726,7 +731,22 @@ class Port(object): else: info['speed'] = 'N/A' - info['rx_filter_mode'] = self.attr.get('rx_filter_mode', 'N/A') + + # RX info + if 'rx_filter_mode' in self.attr: + info['rx_filter_mode'] = 'Hardware Match' if self.attr['rx_filter_mode'] == 'hw' else 'Fetch All' + else: + info['rx_filter_mode'] = 'N/A' + + if 'sniffer' in self.rx_info: + sniffer = self.rx_info['sniffer'] + if sniffer['is_active']: + info['rx_sniffer'] = '{0}\n[{1} / {2}]'.format(sniffer['pcap_filename'], sniffer['count'], sniffer['limit']) + else: + info['rx_sniffer'] = 'off' + else: + info['rx_sniffer'] = 'N/A' + return info @@ -759,6 +779,9 @@ class Port(object): "flow ctrl" : info['fc'], "RX Filter Mode": info['rx_filter_mode'], + "RX Queueing": 'off', + "RX sniffer": info['rx_sniffer'], + } def clear_stats(self): 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 7e47eb61..5e71b7f2 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 @@ -678,6 +678,8 @@ class CTRexInfoGenerator(object): ("NUMA Node", []), ("----", []), ("RX Filter Mode", []), + ("RX Queueing", []), + ("RX sniffer", []), ] ) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py index 0d316c9e..715a741e 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py @@ -45,6 +45,10 @@ FLOW_CTRL = 28 SUPPORTED = 29 RX_FILTER_MODE = 30 +OUTPUT_FILENAME = 31 +ALL_FILES = 32 +LIMIT = 33 + GLOBAL_STATS = 50 PORT_STATS = 51 PORT_STATUS = 52 @@ -310,6 +314,29 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'choices': ['hw', 'all']}), + OUTPUT_FILENAME: ArgumentPack(['-o', '--output'], + {'help': 'Output PCAP filename', + 'dest': 'output_filename', + 'default': None, + 'required': True, + 'type': str}), + + + + ALL_FILES: ArgumentPack(['--all'], + {'help': 'change RX port filter to fetch all packets', + 'dest': 'all', + 'default': False, + 'action': "store_true"}), + + + LIMIT: ArgumentPack(['-l', '--limit'], + {'help': 'Limit the packet count to be written to the file', + 'dest': 'limit', + 'default': 1000, + 'type': int}), + + SUPPORTED: ArgumentPack(['--supp'], {'help': 'Show which attributes are supported by current NICs', 'default': None, @@ -459,6 +486,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], ALL_PORTS], {'required': False}), + STREAM_FROM_PATH_OR_FILE: ArgumentGroup(MUTEX, [FILE_PATH, FILE_FROM_DB], {'required': True}), -- cgit 1.2.3-korg