""" Trex acts as traffic generation and vnf definitions based on IETS Spec """
from __future__ import absolute_import
-from __future__ import print_function
-
import logging
import os
import yaml
-from yardstick.common.utils import mac_address_to_hex_list
+from yardstick.common.utils import mac_address_to_hex_list, try_int
from yardstick.network_services.utils import get_nsb_option
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
ASYNC_PORT = 4500
SYNC_PORT = 4501
+ def __init__(self, setup_helper):
+ super(TrexResourceHelper, self).__init__(setup_helper)
+ self.port_map = {}
+ self.dpdk_to_trex_port_map = {}
+
def generate_cfg(self):
- ext_intf = self.vnfd_helper.interfaces
+ port_names = self.vnfd_helper.port_pairs.all_ports
vpci_list = []
port_list = []
- trex_cfg = {
- 'interfaces': vpci_list,
- 'port_info': port_list,
- "port_limit": len(ext_intf),
- "version": '2',
- }
- cfg_file = [trex_cfg]
+ self.port_map = {}
+ self.dpdk_to_trex_port_map = {}
- for interface in ext_intf:
+ sorted_ports = sorted((self.vnfd_helper.port_num(port_name), port_name) for port_name in
+ port_names)
+ for index, (port_num, port_name) in enumerate(sorted_ports):
+ interface = self.vnfd_helper.find_interface(name=port_name)
virtual_interface = interface['virtual-interface']
- vpci_list.append(virtual_interface["vpci"])
dst_mac = virtual_interface["dst_mac"]
+ # this is to check for unused ports, all ports in the topology
+ # will always have dst_mac
if not dst_mac:
continue
-
+ # TRex ports are in logical order roughly based on DPDK port number sorting
+ vpci_list.append(virtual_interface["vpci"])
local_mac = virtual_interface["local_mac"]
port_list.append({
"src_mac": mac_address_to_hex_list(local_mac),
"dest_mac": mac_address_to_hex_list(dst_mac),
})
+ self.port_map[port_name] = index
+ self.dpdk_to_trex_port_map[port_num] = index
+ trex_cfg = {
+ 'interfaces': vpci_list,
+ 'port_info': port_list,
+ "port_limit": len(port_names),
+ "version": '2',
+ }
+ cfg_file = [trex_cfg]
cfg_str = yaml.safe_dump(cfg_file, default_flow_style=False, explicit_start=True)
self.ssh_helper.upload_config_file(os.path.basename(self.CONF_FILE), cfg_str)
- self._vpci_ascending = sorted(vpci_list)
+
+ def _build_ports(self):
+ super(TrexResourceHelper, self)._build_ports()
+ # override with TRex logic port number
+ self.uplink_ports = [self.dpdk_to_trex_port_map[p] for p in self.uplink_ports]
+ self.downlink_ports = [self.dpdk_to_trex_port_map[p] for p in self.downlink_ports]
+ self.all_ports = [self.dpdk_to_trex_port_map[p] for p in self.all_ports]
+
+ def port_num(self, intf):
+ # return logical TRex port
+ return self.port_map[intf]
def check_status(self):
status, _, _ = self.ssh_helper.execute("sudo lsof -i:%s" % self.SYNC_PORT)
self.ssh_helper.execute("sudo pkill -9 rex > /dev/null 2>&1")
+ # We MUST default to 1 because TRex won't work on single-queue devices with
+ # more than one core per port
+ # We really should be trying to find the number of queues in the driver,
+ # but there doesn't seem to be a way to do this
+ # TRex Error: the number of cores should be 1 when the driver
+ # support only one tx queue and one rx queue. Please use -c 1
+ threads_per_port = try_int(self.scenario_helper.options.get("queues_per_port"), 1)
+
trex_path = self.ssh_helper.join_bin_path("trex", "scripts")
path = get_nsb_option("trex_path", trex_path)
- # cmd = "sudo ./t-rex-64 -i --cfg %s > /dev/null 2>&1" % self.CONF_FILE
- cmd = "./t-rex-64 -i --cfg '{}'".format(self.CONF_FILE)
+ cmd = "./t-rex-64 --no-scapy-server -i -c {} --cfg '{}'".format(threads_per_port,
+ self.CONF_FILE)
- # if there are errors we want to see them
+ if self.scenario_helper.options.get("trex_server_debug"):
+ # if there are errors we want to see them
+ redir = ""
+ else:
+ redir = ">/dev/null"
# we have to sudo cd because the path might be owned by root
- trex_cmd = """sudo bash -c "cd '{}' ; {}" >/dev/null""".format(path, cmd)
+ trex_cmd = """sudo bash -c "cd '{}' ; {}" {}""".format(path, cmd, redir)
+ LOG.debug(trex_cmd)
self.ssh_helper.execute(trex_cmd)
def terminate(self):
def scale(self, flavor=""):
pass
- def listen_traffic(self, traffic_profile):
- pass
-
def terminate(self):
self.resource_helper.terminate()
+
+ def wait_for_instantiate(self):
+ return self._wait_for_process()