summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/automation/trex_control_plane')
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py31
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py271
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py86
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py38
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py1
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py84
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)