diff options
Diffstat (limited to 'scripts/automation/trex_control_plane')
6 files changed, 367 insertions, 144 deletions
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 b33b0447..627761ff 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -330,6 +330,23 @@ class TRexConsole(TRexGeneralCmd): self.do_portattr("-h") @verify_connected + def do_l2 (self, line): + '''Configures a port in L2 mode''' + self.stateless_client.set_l2_mode_line(line) + + def help_l2 (self): + self.do_l2("-h") + + @verify_connected + def do_l3 (self, line): + '''Configures a port in L3 mode''' + self.stateless_client.set_l3_mode_line(line) + + def help_l3 (self): + self.do_l3("-h") + + + @verify_connected def do_set_rx_sniffer (self, line): '''Sets a port sniffer on RX channel as PCAP recorder''' self.stateless_client.set_rx_sniffer_line(line) @@ -342,9 +359,12 @@ class TRexConsole(TRexGeneralCmd): '''Resolve ARP for ports''' self.stateless_client.resolve_line(line) - def help_sniffer (self): + def help_resolve (self): self.do_resolve("-h") + do_arp = do_resolve + help_arp = help_resolve + @verify_connected def do_map (self, line): '''Maps ports topology\n''' @@ -488,7 +508,7 @@ class TRexConsole(TRexGeneralCmd): ############# update @verify_connected def do_update(self, line): - '''update speed of port(s)currently transmitting traffic\n''' + '''update speed of port(s) currently transmitting traffic\n''' self.stateless_client.update_line(line) @@ -549,6 +569,13 @@ class TRexConsole(TRexGeneralCmd): '''Clear cached local statistics\n''' self.stateless_client.clear_stats_line(line) + @verify_connected + def do_service (self, line): + '''Sets port(s) service mode state''' + self.stateless_client.service_line(line) + + def help_service (self, line): + self.do_service("-h") def help_clear(self): self.do_clear("-h") 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 cc20e088..ee5db1f0 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 @@ -878,6 +878,15 @@ class STLClient(object): return rc + def __set_service_mode (self, port_id_list, enabled): + port_id_list = self.__ports(port_id_list) + rc = RC() + + for port_id in port_id_list: + rc.add(self.ports[port_id].set_service_mode(enabled)) + + return rc + # connect to server def __connect(self): @@ -1387,6 +1396,12 @@ class STLClient(object): if port_obj.is_acquired() and port_obj.get_dst_addr()['ipv4'] is not None] + def get_service_enabled_ports(self): + return [port_id + for port_id, port_obj in self.ports.items() + if port_obj.is_acquired() and port_obj.is_service_mode_on()] + + # get paused ports def get_paused_ports (self, owned = True): if owned: @@ -1829,6 +1844,72 @@ class STLClient(object): @__api_check(True) + def set_l2_mode (self, port, dst_mac): + """ + Sets the port mode to L2 + + :parameters: + port - the port to set the source address + dst_mac - destination MAC + :raises: + + :exc:`STLError` + """ + + validate_type('port', port, int) + if port not in self.get_all_ports(): + raise STLError("port {0} is not a valid port id".format(port)) + + if not is_valid_mac(dst_mac): + raise STLError("dest_mac is not a valid MAC address: '{0}'".format(dst_mac)) + + self.logger.pre_cmd("Setting port {0} in L2 mode: ".format(port)) + rc = self.ports[port].set_l2_mode(dst_mac) + self.logger.post_cmd(rc) + + if not rc: + raise STLError(rc) + + + @__api_check(True) + def set_l3_mode (self, port, src_ipv4, dst_ipv4): + """ + Sets the port mode to L3 + + :parameters: + port - the port to set the source address + src_ipv4 - IPv4 source address for the port + dst_ipv4 - IPv4 destination address + :raises: + + :exc:`STLError` + """ + + validate_type('port', port, int) + if port not in self.get_all_ports(): + raise STLError("port {0} is not a valid port id".format(port)) + + if not is_valid_ipv4(src_ipv4): + raise STLError("src_ipv4 is not a valid IPv4 address: '{0}'".format(src_ipv4)) + + if not is_valid_ipv4(dst_ipv4): + raise STLError("dst_ipv4 is not a valid IPv4 address: '{0}'".format(dst_ipv4)) + + self.logger.pre_cmd("Setting port {0} in L3 mode: ".format(port)) + rc = self.ports[port].set_l3_mode(src_ipv4, dst_ipv4) + self.logger.post_cmd(rc) + + if not rc: + raise STLError(rc) + + # try to resolve + with self.logger.supress(level = LoggerApi.VERBOSE_REGULAR_SYNC): + self.logger.pre_cmd("ARP resolving address '{0}': ".format(dst_ipv4)) + rc = self.ports[port].arp_resolve(0) + self.logger.post_cmd(rc) + if not rc: + raise STLError(rc) + + + @__api_check(True) def ping_ip (self, src_port, dst_ipv4, pkt_size = 64, count = 5): """ Pings an IP address through a port @@ -1854,9 +1935,7 @@ class STLClient(object): raise STLError("pkt_size should be a value between 64 and 9216: '{0}'".format(pkt_size)) validate_type('count', count, int) - - - + self.logger.pre_cmd("Pinging {0} from port {1} with {2} bytes of data:".format(dst_ipv4, src_port, pkt_size)) @@ -1997,8 +2076,8 @@ class STLClient(object): self.clear_stats(ports) self.set_port_attr(ports, promiscuous = False, - link_up = True if restart else None, - rxf = 'hw') + link_up = True if restart else None) + self.set_service_mode(ports, False) self.remove_rx_sniffer(ports) self.remove_rx_queue(ports) @@ -2164,7 +2243,10 @@ class STLClient(object): unresolved_ports = [port_id for port_id in ports if not self.ports[port_id].is_resolved()] if unresolved_ports and not force: raise STLError("Port(s) {0} have unresolved destination addresses - please resolve them or specify 'force'".format(unresolved_ports)) - + + if self.get_service_enabled_ports() and not force: + raise STLError("Port(s) {0} are under service mode - please disable service mode or specify 'force'".format(self.get_service_enabled_ports())) + @__api_check(True) def start (self, @@ -2797,9 +2879,6 @@ class STLClient(object): link_up = None, led_on = None, flow_ctrl = None, - rxf = None, - ipv4 = None, - dest = None, resolve = True): """ Set port attributes @@ -2809,9 +2888,6 @@ class STLClient(object): link_up - True or False led_on - True or False flow_ctrl - 0: disable all, 1: enable tx side, 2: enable rx side, 3: full enable - rxf - 'hw' for hardware rules matching packets only or 'all' all packets - ipv4 - configure IPv4 address for port(s). for multiple ports should be a list of IPv4 addresses in the same length of the ports array - dest - configure destination address for port(s) in either IPv4 or MAC format. for multiple ports should be a list in the same length of the ports array resolve - if true, in case a destination address is configured as IPv4 try to resolve it :raises: + :exe:'STLError' @@ -2826,8 +2902,7 @@ class STLClient(object): validate_type('link_up', link_up, (bool, type(None))) validate_type('led_on', led_on, (bool, type(None))) validate_type('flow_ctrl', flow_ctrl, (int, type(None))) - validate_choice('rxf', rxf, ['hw', 'all']) - + # common attributes for all ports cmn_attr_dict = {} @@ -2835,34 +2910,10 @@ class STLClient(object): cmn_attr_dict['link_status'] = link_up cmn_attr_dict['led_status'] = led_on cmn_attr_dict['flow_ctrl_mode'] = flow_ctrl - cmn_attr_dict['rx_filter_mode'] = rxf # each port starts with a set of the common attributes attr_dict = [dict(cmn_attr_dict) for _ in ports] - # default value for IPv4 / dest is none for all ports - if ipv4 is None: - ipv4 = [None] * len(ports) - if dest is None: - dest = [None] * len(ports) - - ipv4 = listify(ipv4) - if len(ipv4) != len(ports): - raise STLError("'ipv4' must be a list in the same length of ports - 'ports': {0}, 'ip': {1}".format(ports, ipv4)) - - dest = listify(dest) - if len(dest) != len(ports): - raise STLError("'dest' must be a list in the same length of ports - 'ports': {0}, 'dest': {1}".format(ports, dest)) - - # update each port attribute with ipv4 - for addr, port_attr in zip(ipv4, attr_dict): - port_attr['ipv4'] = addr - - # update each port attribute with dest - for addr, port_attr in zip(dest, attr_dict): - port_attr['dest'] = addr - - self.logger.pre_cmd("Applying attributes on port(s) {0}:".format(ports)) rc = self.__set_port_attr(ports, attr_dict) self.logger.post_cmd(rc) @@ -2870,26 +2921,47 @@ class STLClient(object): if not rc: raise STLError(rc) - - # automatic resolve - if resolve: - # find any port with a dest configured as IPv4 - resolve_ports = [port_id for port_id, port_dest in zip(ports, dest) if is_valid_ipv4(port_dest)] + - if resolve_ports: - self.resolve(ports = resolve_ports) + + @__api_check(True) + def set_service_mode (self, ports = None, enabled = True): + """ + Set service mode for port(s) + In service mode ports will respond to ARP, PING and etc. + + :parameters: + ports - for which ports to configure service mode on/off + enabled - True for activating service mode, False for disabling + :raises: + + :exe:'STLError' + + """ + # by default take all acquired ports + ports = ports if ports is not None else self.get_acquired_ports() + ports = self._validate_port_list(ports) + if enabled: + self.logger.pre_cmd('Enabling service mode on port(s) {0}:'.format(ports)) + else: + self.logger.pre_cmd('Disabling service mode on port(s) {0}:'.format(ports)) + rc = self.__set_service_mode(ports, enabled) + self.logger.post_cmd(rc) + if not rc: + raise STLError(rc) + @__api_check(True) - def resolve (self, ports = None, retries = 0): + def resolve (self, ports = None, retries = 0, verbose = True): """ Resolves ports (ARP resolution) :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) + verbose - log for each request the response :raises: + :exe:'STLError' @@ -2913,8 +2985,9 @@ class STLClient(object): raise STLError(rc) # print the ARP transaction - self.logger.log(rc) - self.logger.log('') + if verbose: + self.logger.log(rc) + self.logger.log('') @@ -3078,7 +3151,7 @@ class STLClient(object): try: rc = f(*args) except STLError as e: - client.logger.log("Log:\n" + format_text(e.brief() + "\n", 'bold')) + client.logger.log("\nAction has failed with the following error:\n" + format_text(e.brief() + "\n", 'bold')) return RC_ERR(e.brief()) # if got true - print time @@ -3102,7 +3175,7 @@ class STLClient(object): parser = parsing_opts.gen_parser(self, "ping", self.ping_line.__doc__, - parsing_opts.SOURCE_PORT, + parsing_opts.SINGLE_PORT, parsing_opts.PING_IPV4, parsing_opts.PKT_SIZE, parsing_opts.PING_COUNT) @@ -3112,7 +3185,8 @@ class STLClient(object): return opts # IP ping - self.ping_ip(opts.source_port, opts.ping_ipv4, opts.pkt_size, opts.count) + # source ports maps to ports as a single port + self.ping_ip(opts.ports[0], opts.ping_ipv4, opts.pkt_size, opts.count) @__console @@ -3647,9 +3721,6 @@ class STLClient(object): parsing_opts.LED_STATUS, parsing_opts.FLOW_CTRL, parsing_opts.SUPPORTED, - parsing_opts.RX_FILTER_MODE, - parsing_opts.IPV4, - parsing_opts.DEST ) opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) @@ -3662,7 +3733,7 @@ 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, opts.rx_filter_mode, opts.ipv4, opts.dest])): + 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))) return @@ -3680,10 +3751,7 @@ class STLClient(object): opts.prom, opts.link, opts.led, - opts.flow_ctrl, - opts.rx_filter_mode, - opts.ipv4, - opts.dest) + opts.flow_ctrl) @@ -3697,18 +3765,12 @@ class STLClient(object): self.set_rx_sniffer_line.__doc__, parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.OUTPUT_FILENAME, - parsing_opts.LIMIT, - parsing_opts.ALL_FILES) + parsing_opts.LIMIT) opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) if not opts: return opts - rxf = 'all' if opts.all else None - - if rxf: - self.set_port_attr(opts.ports, rxf = rxf) - self.set_rx_sniffer(opts.ports, opts.output_filename, opts.limit) return RC_OK() @@ -3744,6 +3806,51 @@ class STLClient(object): @__console + def set_l2_mode_line (self, line): + '''Configures a port in L2 mode''' + + parser = parsing_opts.gen_parser(self, + "port", + self.set_l2_mode_line.__doc__, + parsing_opts.SINGLE_PORT, + parsing_opts.DST_MAC, + ) + + opts = parser.parse_args(line.split()) + if not opts: + return opts + + + # source ports maps to ports as a single port + self.set_l2_mode(opts.ports[0], dst_mac = opts.dst_mac) + + return RC_OK() + + + @__console + def set_l3_mode_line (self, line): + '''Configures a port in L3 mode''' + + parser = parsing_opts.gen_parser(self, + "port", + self.set_l3_mode_line.__doc__, + parsing_opts.SINGLE_PORT, + parsing_opts.SRC_IPV4, + parsing_opts.DST_IPV4, + ) + + opts = parser.parse_args(line.split()) + if not opts: + return opts + + + # source ports maps to ports as a single port + self.set_l3_mode(opts.ports[0], src_ipv4 = opts.src_ipv4, dst_ipv4 = opts.dst_ipv4) + + return RC_OK() + + + @__console def show_profile_line (self, line): '''Shows profile information''' @@ -3840,10 +3947,38 @@ class STLClient(object): return "{0}(read-only)>".format(prefix) elif self.is_all_ports_acquired(): - return "{0}>".format(prefix) + + p = prefix + + if self.get_service_enabled_ports(): + if self.get_service_enabled_ports() == self.get_acquired_ports(): + p += '(service)' + else: + p += '(service: {0})'.format(', '.join(map(str, self.get_service_enabled_ports()))) + + return "{0}>".format(p) else: - return "{0} {1}>".format(prefix, self.get_acquired_ports()) + return "{0} (ports: {1})>".format(prefix, ', '.join(map(str, self.get_acquired_ports()))) + @__console + def service_line (self, line): + '''Configures port for service mode. + In service mode ports will reply to ARP, PING + and etc. + ''' + + parser = parsing_opts.gen_parser(self, + "service", + self.service_line.__doc__, + parsing_opts.PORT_LIST_WITH_ALL, + parsing_opts.SERVICE_OFF) + + opts = parser.parse_args(line.split()) + if not opts: + return opts + + self.set_service_mode(ports = opts.ports, enabled = opts.enabled) + 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 389a942b..487f3055 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 @@ -489,6 +489,9 @@ class Port(object): @owned def set_rx_sniffer (self, pcap_filename, limit): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for performing RX capturing. Please enable service mode') + params = {"handler": self.handler, "port_id": self.port_id, "type": "capture", @@ -516,22 +519,40 @@ class Port(object): return self.ok() - @owned - def set_arp_resolution (self, ipv4, mac): - + def set_l2_mode (self, dst_mac): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for configuring L2 mode. Please enable service mode') + params = {"handler": self.handler, "port_id": self.port_id, - "ipv4": ipv4, - "mac": mac} + "dst_mac": dst_mac} - rc = self.transmit("set_arp_resolution", params) + rc = self.transmit("set_l2", params) if rc.bad(): return self.err(rc.err()) - return self.ok() + return self.sync() + + + @owned + def set_l3_mode (self, src_addr, dest_addr, resolved_mac = None): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for configuring L3 mode. Please enable service mode') - + params = {"handler": self.handler, + "port_id": self.port_id, + "src_addr": src_addr, + "dst_addr": dest_addr} + + if resolved_mac: + params["resolved_mac"] = resolved_mac + + rc = self.transmit("set_l3", params) + if rc.bad(): + return self.err(rc.err()) + + return self.sync() @owned @@ -680,12 +701,6 @@ class Port(object): if kwargs.get('rx_filter_mode') is not None: json_attr['rx_filter_mode'] = {'mode': kwargs.get('rx_filter_mode')} - if kwargs.get('ipv4') is not None: - json_attr['ipv4'] = {'addr': kwargs.get('ipv4')} - - if kwargs.get('dest') is not None: - json_attr['dest'] = {'addr': kwargs.get('dest')} - params = {"handler": self.handler, "port_id": self.port_id, @@ -698,6 +713,26 @@ class Port(object): # update the dictionary from the server explicitly return self.sync() + + @owned + def set_service_mode (self, enabled): + rc = self.set_attr(rx_filter_mode = 'all' if enabled else 'hw') + if not rc: + return rc + + if not enabled: + rc = self.remove_rx_queue() + if not rc: + return rc + + rc = self.remove_rx_sniffer() + if not rc: + return rc + + return self.ok() + + def is_service_mode_on (self): + return self.get_rx_filter_mode() == 'all' @writeable def push_remote (self, pcap_filename, ipg_usec, speedup, count, duration, is_dual, slave_handler): @@ -836,7 +871,7 @@ class Port(object): info['src_ipv4'] = attr['src_ipv4'] if info['src_ipv4'] is None: - info['src_ipv4'] = 'Not Configured' + info['src_ipv4'] = '-' # dest dest = attr['dest'] @@ -865,6 +900,14 @@ class Port(object): queue = rx_info['queue'] info['rx_queue'] = '[{0} / {1}]'.format(queue['count'], queue['size']) if queue['is_active'] else 'off' + # Grat ARP + grat_arp = rx_info['grat_arp'] + if grat_arp['is_active']: + info['grat_arp'] = "every {0} seconds".format(grat_arp['interval_sec']) + else: + info['grat_arp'] = "off" + + return info @@ -877,6 +920,8 @@ class Port(object): return {'mac': src_mac, 'ipv4': src_ipv4} + def get_rx_filter_mode (self): + return self.__attr['rx_filter_mode'] def get_dst_addr (self): dest = self.__attr['dest'] @@ -904,10 +949,16 @@ class Port(object): @writeable def arp_resolve (self, retries): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for performing ARP resolution. Please enable service mode') + return ARPResolver(self).resolve(retries) @writeable def ping (self, ping_ipv4, pkt_size): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for performing ping. Please enable service mode') + return PingResolver(self, ping_ipv4, pkt_size).resolve() @@ -924,14 +975,14 @@ class Port(object): "src MAC": info['src_mac'], "src IPv4": info['src_ipv4'], "Destination": info['dest'], - "ARP Resolution": info['arp'], + "ARP Resolution": format_text("{0}".format(info['arp']), 'bold', 'red') if info['arp'] == 'unresolved' else info['arp'], "PCI Address": info['pci_addr'], "NUMA Node": info['numa'], "--": "", "---": "", "----": "", "-----": "", - "link speed": info['speed'], + "link speed": "%g Gb/s" % info['speed'], "port status": info['status'], "link status": info['link'], "promiscuous" : info['prom'], @@ -940,6 +991,7 @@ class Port(object): "RX Filter Mode": info['rx_filter_mode'], "RX Queueing": info['rx_queue'], "RX sniffer": info['rx_sniffer'], + "Grat ARP": info['grat_arp'], } diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py index 3754e608..ec83de5d 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py @@ -46,11 +46,6 @@ class Resolver(object): # add the stream(s) self.port.add_streams(self.generate_request()) - - rc = self.port.set_attr(rx_filter_mode = 'all') - if not rc: - return rc - rc = self.port.set_rx_queue(size = 100) if not rc: return rc @@ -59,7 +54,6 @@ class Resolver(object): finally: # best effort restore - self.port.set_attr(rx_filter_mode = 'hw') self.port.remove_rx_queue() self.port.remove_all_streams() @@ -170,7 +164,8 @@ class ARPResolver(Resolver): return None - rc = self.port.set_arp_resolution(arp.psrc, arp.hwsrc) + # update the port with L3 full configuration + rc = self.port.set_l3_mode(self.src['ipv4'], self.dst['ipv4'], arp.hwsrc) if not rc: return rc @@ -202,19 +197,13 @@ class PingResolver(Resolver): if self.dst['mac'] is None: return self.port.err('Ping - port has an unresolved destination, cannot determine next hop MAC address') - if self.ping_ip == self.src['ipv4']: - return self.port.err('Ping - cannot ping own IP') - return self.port.ok() # return a list of streams for request def generate_request (self): - src = self.port.get_src_addr() - dst = self.port.get_dst_addr() - - base_pkt = Ether(dst = dst['mac'])/IP(src = src['ipv4'], dst = self.ping_ip)/ICMP(type = 8) + base_pkt = Ether(dst = self.dst['mac'])/IP(src = self.src['ipv4'], dst = self.ping_ip)/ICMP(type = 8) pad = max(0, self.pkt_size - len(base_pkt)) base_pkt = base_pkt / (pad * 'x') @@ -222,6 +211,8 @@ class PingResolver(Resolver): #base_pkt.show2() s1 = STLStream( packet = STLPktBuilder(pkt = base_pkt), mode = STLTXSingleBurst(total_pkts = 1) ) + self.base_pkt = base_pkt + return [s1] # return None for more packets otherwise RC object @@ -230,23 +221,32 @@ class PingResolver(Resolver): if not 'ICMP' in scapy_pkt: return None - #scapy_pkt.show2() ip = scapy_pkt['IP'] - + if ip.dst != self.src['ipv4']: + return None + icmp = scapy_pkt['ICMP'] dt = pkt['ts'] - self.start_ts + # echo reply if icmp.type == 0: - # echo reply + # check seq + if icmp.seq != self.base_pkt['ICMP'].seq: + return None return self.port.ok('Reply from {0}: bytes={1}, time={2:.2f}ms, TTL={3}'.format(ip.src, len(pkt['binary']), dt * 1000, ip.ttl)) # unreachable elif icmp.type == 3: + # check seq + if icmp.payload.seq != self.base_pkt['ICMP'].seq: + return None return self.port.ok('Reply from {0}: Destination host unreachable'.format(icmp.src)) + else: - scapy_pkt.show2() - return self.port.err('unknown ICMP reply') + # skip any other types + #scapy_pkt.show2() + return None 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 6a59126f..c08a0af8 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 @@ -682,6 +682,7 @@ class CTRexInfoGenerator(object): ("RX Filter Mode", []), ("RX Queueing", []), ("RX sniffer", []), + ("Grat ARP", []), ] ) 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 7ae22e89..0a7b510f 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 @@ -46,20 +46,23 @@ SUPPORTED = 29 FILE_PATH_NO_CHECK = 30 OUTPUT_FILENAME = 31 -ALL_FILES = 32 LIMIT = 33 PORT_RESTART = 34 -IPV4 = 35 -DEST = 36 RETRIES = 37 -RX_FILTER_MODE = 38 -SOURCE_PORT = 39 +SINGLE_PORT = 38 +DST_MAC = 39 + PING_IPV4 = 40 PING_COUNT = 41 PKT_SIZE = 42 +SERVICE_OFF = 43 + +SRC_IPV4 = 44 +DST_IPV4 = 45 + GLOBAL_STATS = 50 PORT_STATS = 51 PORT_STATUS = 52 @@ -250,9 +253,9 @@ def check_pkt_size (pkt_size): return pkt_size -def check_dest_addr (addr): - if not (is_valid_ipv4(addr) or is_valid_mac(addr)): - raise argparse.ArgumentTypeError("not a valid IPv4 or MAC address: '{0}'".format(addr)) +def check_mac_addr (addr): + if not is_valid_mac(addr): + raise argparse.ArgumentTypeError("not a valid MAC address: '{0}'".format(addr)) return addr @@ -341,25 +344,24 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'dest': 'flow_ctrl', 'choices': FLOW_CTRL_DICT}), - RX_FILTER_MODE: ArgumentPack(['--rxf'], - {'help': 'Set RX filtering mode', - 'dest': 'rx_filter_mode', - 'choices': ['hw', 'all']}), - - - IPV4: ArgumentPack(['--ipv4'], - {'help': 'IPv4 address(s) for the port(s)', - 'dest': 'ipv4', - 'nargs': '+', - 'default': None, - 'type': check_ipv4_addr}), - - DEST: ArgumentPack(['--dest'], - {'help': 'Destination address(s) for the port(s) in either IPv4 or MAC format', - 'dest': 'dest', - 'nargs': '+', - 'default': None, - 'type': check_dest_addr}), + SRC_IPV4: ArgumentPack(['--src'], + {'help': 'Configure source IPv4 address', + 'dest': 'src_ipv4', + 'required': True, + 'type': check_ipv4_addr}), + + DST_IPV4: ArgumentPack(['--dst'], + {'help': 'Configure destination IPv4 address', + 'dest': 'dst_ipv4', + 'required': True, + 'type': check_ipv4_addr}), + + + DST_MAC: ArgumentPack(['--dst'], + {'help': 'Configure destination MAC address', + 'dest': 'dst_mac', + 'required': True, + 'type': check_mac_addr}), RETRIES: ArgumentPack(['-r', '--retries'], {'help': 'retries count [default is zero]', @@ -382,14 +384,6 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': False, 'action': 'store_true'}), - - 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', @@ -420,9 +414,10 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': []}), - SOURCE_PORT: ArgumentPack(['--port', '-p'], - {'dest':'source_port', + SINGLE_PORT: ArgumentPack(['--port', '-p'], + {'dest':'ports', 'type': int, + 'metavar': 'PORT', 'help': 'source port for the action', 'required': True}), @@ -575,6 +570,12 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': None, 'help': "Core mask - only cores responding to the bit mask will be active"}), + SERVICE_OFF: ArgumentPack(['--off'], + {'action': 'store_false', + 'dest': 'enabled', + 'default': True, + 'help': 'Deactivates services on port(s)'}), + # advanced options PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST, ALL_PORTS], @@ -644,6 +645,8 @@ class CCmdArgParser(argparse.ArgumentParser): if not self.has_ports_cfg(opts): return opts + opts.ports = listify(opts.ports) + # if all ports are marked or if (getattr(opts, "all_ports", None) == True) or (getattr(opts, "ports", None) == []): if default_ports is None: @@ -656,7 +659,12 @@ class CCmdArgParser(argparse.ArgumentParser): # so maybe we have ports configured invalid_ports = list_difference(opts.ports, self.stateless_client.get_all_ports()) if invalid_ports: - msg = "{0}: port(s) {1} are not valid port IDs".format(self.cmd_name, invalid_ports) + + if len(invalid_ports) > 1: + msg = "{0}: port(s) {1} are not valid port IDs".format(self.cmd_name, invalid_ports) + else: + msg = "{0}: port {1} is not a valid port ID".format(self.cmd_name, invalid_ports[0]) + self.stateless_client.logger.log(format_text(msg, 'bold')) return RC_ERR(msg) |