aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services/vnf_generic
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/network_services/vnf_generic')
-rw-r--r--yardstick/network_services/vnf_generic/vnf/acl_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/base.py28
-rw-r--r--yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py53
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_helpers.py49
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_vnf.py11
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py182
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_ping.py74
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_prox.py1
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py63
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py38
-rw-r--r--yardstick/network_services/vnf_generic/vnf/udp_replay.py49
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vfw_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vpe_vnf.py73
13 files changed, 320 insertions, 305 deletions
diff --git a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
index 5f3c8a0cd..3ba38dec2 100644
--- a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
@@ -24,7 +24,7 @@ LOG = logging.getLogger(__name__)
# ACL should work the same on all systems, we can provide the binary
ACL_PIPELINE_COMMAND = \
- 'sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+ 'sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
ACL_COLLECT_KPI = r"""\
ACL TOTAL:[^p]+pkts_processed"?:\s(\d+),[^p]+pkts_drop"?:\s(\d+),[^p]+pkts_received"?:\s(\d+),"""
diff --git a/yardstick/network_services/vnf_generic/vnf/base.py b/yardstick/network_services/vnf_generic/vnf/base.py
index 955f9f03d..e32e5fb50 100644
--- a/yardstick/network_services/vnf_generic/vnf/base.py
+++ b/yardstick/network_services/vnf_generic/vnf/base.py
@@ -16,6 +16,8 @@
from __future__ import absolute_import
import logging
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
+
LOG = logging.getLogger(__name__)
@@ -59,6 +61,10 @@ class QueueFileWrapper(object):
class VnfdHelper(dict):
+ def __init__(self, *args, **kwargs):
+ super(VnfdHelper, self).__init__(*args, **kwargs)
+ self.port_pairs = PortPairs(self['vdu'][0]['external-interface'])
+
@property
def mgmt_interface(self):
return self["mgmt-interface"]
@@ -92,6 +98,28 @@ class VnfdHelper(dict):
if interface[key] == value:
return interface
+ # hide dpdk_port_num key so we can abstract
+ def find_interface_by_port(self, port):
+ for interface in self.interfaces:
+ virtual_intf = interface["virtual-interface"]
+ # we have to convert to int to compare
+ if int(virtual_intf['dpdk_port_num']) == port:
+ return interface
+
+ def port_num(self, name):
+ # we need interface name -> DPDK port num (PMD ID) -> LINK ID
+ # LINK ID -> PMD ID is governed by the port mask
+ """
+
+ :rtype: int
+ :type name: str
+ """
+ intf = self.find_interface(name=name)
+ return int(intf["virtual-interface"]["dpdk_port_num"])
+
+ def port_nums(self, intfs):
+ return [self.port_num(i) for i in intfs]
+
class VNFObject(object):
diff --git a/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py b/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
index f9980b165..45ef757b3 100644
--- a/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
@@ -13,16 +13,14 @@
# limitations under the License.
from __future__ import absolute_import
-import time
import logging
-from six.moves import zip
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
LOG = logging.getLogger(__name__)
# CGNAPT should work the same on all systems, we can provide the binary
-CGNAPT_PIPELINE_COMMAND = 'sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+CGNAPT_PIPELINE_COMMAND = 'sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
WAIT_FOR_STATIC_NAPT = 4
CGNAPT_COLLECT_KPI = """\
@@ -55,7 +53,7 @@ class CgnaptApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
yield '.'.join(ip_parts)
@staticmethod
- def _update_cgnat_script_file(ip_pipeline_cfg, mcpi, vnf_str):
+ def _update_cgnat_script_file(ip_pipeline_cfg, mcpi):
pipeline_config_str = str(ip_pipeline_cfg)
input_cmds = '\n'.join(mcpi)
icmp_flag = 'link 0 down' in input_cmds
@@ -67,16 +65,13 @@ class CgnaptApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
raise NotImplementedError
def _get_cgnapt_config(self, interfaces=None):
+ # TODO: static CGNAPT is broken, don't use it
if interfaces is None:
interfaces = self.vnfd_helper.interfaces
- gateway_ips = []
-
# fixme: Get private port and gateway from port list
- priv_ports = interfaces[::2]
- for interface in priv_ports:
- gateway_ips.append(self._get_ports_gateway(interface["name"]))
- return gateway_ips
+ priv_ports = self.vnfd_helper.port_pairs.priv_ports
+ return [self._get_ports_gateway(intf["name"]) for intf in priv_ports]
class CgnaptApproxVnf(SampleVNF):
@@ -103,21 +98,23 @@ class CgnaptApproxVnf(SampleVNF):
if self.scenario_helper.options.get('napt', 'static') != 'static':
return
- ip_iter = self.setup_helper._generate_ip_from_pool("152.16.40.10")
- gw_ips = self.setup_helper._get_cgnapt_config()
- if self.scenario_helper.vnf_cfg.get("lb_config", "SW") == 'HW':
- pipeline = self.setup_helper.HW_DEFAULT_CORE
- offset = 3
- else:
- pipeline = self.setup_helper.SW_DEFAULT_CORE - 1
- offset = 0
-
- worker_threads = int(self.scenario_helper.vnf_cfg["worker_threads"])
- cmd_template = "p {0} entry addm {1} 1 {2} 1 0 32 65535 65535 65535"
- for gw, ip in zip(gw_ips, ip_iter):
- cmd = cmd_template.format(pipeline, gw, ip)
- pipeline += worker_threads
- pipeline += offset
- self.vnf_execute(cmd)
-
- time.sleep(WAIT_FOR_STATIC_NAPT)
+ # ip_iter = self.setup_helper._generate_ip_from_pool("152.16.40.10")
+ # gw_ips = self.setup_helper._get_cgnapt_config()
+ # if self.scenario_helper.vnf_cfg.get("lb_config", "SW") == 'HW':
+ # pipeline = self.setup_helper.HW_DEFAULT_CORE
+ # offset = 3
+ # else:
+ # pipeline = self.setup_helper.SW_DEFAULT_CORE - 1
+ # offset = 0
+ #
+ # worker_threads = int(self.scenario_helper.vnf_cfg["worker_threads"])
+ # # p <pipeline id> entry addm <prv_ipv4/6> prvport> <pub_ip> <pub_port> <phy_port> <ttl>
+ # # <no_of_entries> <end_prv_port> <end_pub_port>
+ # cmd_template = "p {0} entry addm {1} 1 {2} 1 0 32 65535 65535 65535"
+ # for gw, ip in zip(gw_ips, ip_iter):
+ # cmd = cmd_template.format(pipeline, gw, ip)
+ # pipeline += worker_threads
+ # pipeline += offset
+ # self.vnf_execute(cmd)
+ #
+ # time.sleep(WAIT_FOR_STATIC_NAPT)
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
index d6ec271c9..00ab6c24c 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
@@ -639,9 +639,10 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
prox_config.parse()
# Ensure MAC is set "hardware"
- ext_intf = self.vnfd_helper.interfaces
- # we are using enumeration to map logical port numbers to interfaces
- for port_num, intf in enumerate(ext_intf):
+ all_ports = self.vnfd_helper.port_pairs.all_ports
+ # use dpdk port number
+ for port_name in all_ports:
+ port_num = self.vnfd_helper.port_num(port_name)
port_section_name = "port {}".format(port_num)
for section_name, section in sections:
if port_section_name != section_name:
@@ -659,13 +660,15 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
if item_val.startswith("@@dst_mac"):
tx_port_iter = re.finditer(r'\d+', item_val)
tx_port_no = int(next(tx_port_iter).group(0))
- mac = ext_intf[tx_port_no]["virtual-interface"]["dst_mac"]
+ intf = self.vnfd_helper.find_interface_by_port(tx_port_no)
+ mac = intf["virtual-interface"]["dst_mac"]
section_data[1] = mac.replace(":", " ", 6)
if item_key == "dst mac" and item_val.startswith("@@"):
tx_port_iter = re.finditer(r'\d+', item_val)
tx_port_no = int(next(tx_port_iter).group(0))
- mac = ext_intf[tx_port_no]["virtual-interface"]["dst_mac"]
+ intf = self.vnfd_helper.find_interface_by_port(tx_port_no)
+ mac = intf["virtual-interface"]["dst_mac"]
section_data[1] = mac
# if addition file specified in prox config
@@ -714,13 +717,15 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
def generate_prox_lua_file(self):
p = OrderedDict()
- ext_intf = self.vnfd_helper.interfaces
+ all_ports = self.vnfd_helper.port_pairs.all_ports
lua_param = self.LUA_PARAMETER_NAME
- for intf in ext_intf:
+ for port_name in all_ports:
peer = self.LUA_PARAMETER_PEER[lua_param]
- port_num = intf["virtual-interface"]["dpdk_port_num"]
- local_ip = intf["local_ip"]
- dst_ip = intf["dst_ip"]
+ port_num = self.vnfd_helper.port_num(port_name)
+ intf = self.vnfd_helper.find_interface(name=port_name)
+ vintf = intf['virtual-interface']
+ local_ip = vintf["local_ip"]
+ dst_ip = vintf["dst_ip"]
local_ip_hex = ip_to_hex(local_ip, separator=' ')
dst_ip_hex = ip_to_hex(dst_ip, separator=' ')
p.update([
@@ -880,7 +885,7 @@ class ProxResourceHelper(ClientResourceHelper):
self._run_traffic_once(traffic_profile)
def _run_traffic_once(self, traffic_profile):
- traffic_profile.execute(self)
+ traffic_profile.execute_traffic(self)
if traffic_profile.done:
self._queue.put({'done': True})
LOG.debug("tg_prox done")
@@ -922,12 +927,11 @@ class ProxResourceHelper(ClientResourceHelper):
self.sut.stop_all()
def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
- # type: (object, object, object, object) -> object
# do this assert in init? unless we expect interface count to
# change from one run to another run...
- interfaces = self.vnfd_helper.interfaces
- interface_count = len(interfaces)
- assert interface_count in {1, 2, 4}, \
+ ports = self.vnfd_helper.port_pairs.all_ports
+ port_count = len(ports)
+ assert port_count in {1, 2, 4}, \
"Invalid number of ports: 1, 2 or 4 ports only supported at this time"
with self.traffic_context(pkt_size, value):
@@ -942,15 +946,18 @@ class ProxResourceHelper(ClientResourceHelper):
latency = self.get_latency()
deltas = data['delta']
- rx_total, tx_total = self.sut.port_stats(range(interface_count))[6:8]
- pps = value / 100.0 * self.line_rate_to_pps(pkt_size, interface_count)
+ rx_total, tx_total = self.sut.port_stats(range(port_count))[6:8]
+ pps = value / 100.0 * self.line_rate_to_pps(pkt_size, port_count)
samples = {}
# we are currently using enumeration to map logical port num to interface
- for index, iface in enumerate(interfaces):
- port_rx_total, port_tx_total = self.sut.port_stats([index])[6:8]
- samples[iface["name"]] = {"in_packets": port_rx_total,
- "out_packets": port_tx_total}
+ for port_name in ports:
+ port = self.vnfd_helper.port_num(port_name)
+ port_rx_total, port_tx_total = self.sut.port_stats([port])[6:8]
+ samples[port_name] = {
+ "in_packets": port_rx_total,
+ "out_packets": port_tx_total,
+ }
result = ProxTestDataTuple(tolerated_loss, tsc_hz, deltas.rx, deltas.tx,
deltas.tsc, latency, rx_total, tx_total, pps)
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
index cb09b43f6..bef7c5a33 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
@@ -51,9 +51,7 @@ class ProxApproxVnf(SampleVNF):
try:
return self.resource_helper.execute(cmd, *args, **kwargs)
except OSError as e:
- if ignore_errors and e.errno in {errno.EPIPE, errno.ESHUTDOWN}:
- pass
- else:
+ if not ignore_errors or e.errno not in {errno.EPIPE, errno.ESHUTDOWN}:
raise
def collect_kpi(self):
@@ -66,11 +64,12 @@ class ProxApproxVnf(SampleVNF):
}
return result
- if len(self.vnfd_helper.interfaces) not in {1, 2, 4}:
+ intf_count = len(self.vnfd_helper.interfaces)
+ if intf_count not in {1, 2, 4}:
raise RuntimeError("Failed ..Invalid no of ports .. "
"1, 2 or 4 ports only supported at this time")
- port_stats = self.vnf_execute('port_stats', range(len(self.vnfd_helper.interfaces)))
+ port_stats = self.vnf_execute('port_stats', range(intf_count))
try:
rx_total = port_stats[6]
tx_total = port_stats[7]
@@ -90,7 +89,7 @@ class ProxApproxVnf(SampleVNF):
def _tear_down(self):
# this should be standardized for all VNFs or removed
- self.setup_helper.rebind_drivers()
+ self.setup_helper.tear_down()
def terminate(self):
# try to quit with socket commands
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index 1b2533aad..96e703060 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -30,7 +30,9 @@ from six.moves import cStringIO
from yardstick.benchmark.contexts.base import Context
from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
from yardstick.network_services.helpers.cpu import CpuSysCores
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
+from yardstick.network_services.helpers.dpdknicbind_helper import DpdkBindHelper
from yardstick.network_services.nfvi.resource import ResourceProfile
from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
@@ -126,15 +128,11 @@ class SetupEnvHelper(object):
class DpdkVnfSetupEnvHelper(SetupEnvHelper):
APP_NAME = 'DpdkVnf'
- DPDK_BIND_CMD = "sudo {dpdk_nic_bind} {force} -b {driver} {vpci}"
- DPDK_UNBIND_CMD = "sudo {dpdk_nic_bind} --force -b {driver} {vpci}"
FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'"
HW_DEFAULT_CORE = 3
SW_DEFAULT_CORE = 2
- DPDK_STATUS_DRIVER_RE = re.compile(r"(\d{2}:\d{2}\.\d).*drv=([-\w]+)")
-
@staticmethod
def _update_packet_type(ip_pipeline_cfg, traffic_options):
match_str = 'pkt_type = ipv4'
@@ -165,15 +163,9 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
super(DpdkVnfSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper, scenario_helper)
self.all_ports = None
self.bound_pci = None
- self._dpdk_nic_bind = None
self.socket = None
self.used_drivers = None
-
- @property
- def dpdk_nic_bind(self):
- if self._dpdk_nic_bind is None:
- self._dpdk_nic_bind = self.ssh_helper.provision_tool(tool_file="dpdk-devbind.py")
- return self._dpdk_nic_bind
+ self.dpdk_bind_helper = DpdkBindHelper(ssh_helper)
def _setup_hugepages(self):
cmd = "awk '/Hugepagesize/ { print $2$3 }' < /proc/meminfo"
@@ -190,10 +182,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.ssh_helper.execute("echo %s | sudo tee %s" % (pages, memory_path))
- def _get_dpdk_port_num(self, name):
- interface = self.vnfd_helper.find_interface(name=name)
- return interface['virtual-interface']['dpdk_port_num']
-
def build_config(self):
vnf_cfg = self.scenario_helper.vnf_cfg
task_path = self.scenario_helper.task_path
@@ -216,7 +204,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
multiport = MultiPortConfig(self.scenario_helper.topology,
config_tpl_cfg,
config_basename,
- self.vnfd_helper.interfaces,
+ self.vnfd_helper,
self.VNF_TYPE,
lb_count,
worker_threads,
@@ -234,7 +222,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.ssh_helper.upload_config_file(config_basename, new_config)
self.ssh_helper.upload_config_file(script_basename,
multiport.generate_script(self.vnfd_helper))
- self.all_ports = multiport.port_pair_list
LOG.info("Provision and start the %s", self.APP_NAME)
self._build_pipeline_kwargs()
@@ -242,11 +229,19 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def _build_pipeline_kwargs(self):
tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
- ports_len_hex = hex(2 ** (len(self.all_ports) + 1) - 1)
+ # count the number of actual ports in the list of pairs
+ # remove duplicate ports
+ # this is really a mapping from LINK ID to DPDK PMD ID
+ # e.g. 0x110 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_2
+ # 0x1010 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_3
+ ports = self.vnfd_helper.port_pairs.all_ports
+ port_nums = self.vnfd_helper.port_nums(ports)
+ # create mask from all the dpdk port numbers
+ ports_mask_hex = hex(sum(2 ** num for num in port_nums))
self.pipeline_kwargs = {
'cfg_file': self.CFG_CONFIG,
'script': self.CFG_SCRIPT,
- 'ports_len_hex': ports_len_hex,
+ 'port_mask_hex': ports_mask_hex,
'tool_path': tool_path,
}
@@ -285,17 +280,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def _validate_cpu_cfg(self):
return self._get_cpu_sibling_list()
- def _find_used_drivers(self):
- cmd = "{0} -s".format(self.dpdk_nic_bind)
- rc, dpdk_status, _ = self.ssh_helper.execute(cmd)
-
- self.used_drivers = {
- vpci: (index, driver)
- for index, (vpci, driver)
- in enumerate(self.DPDK_STATUS_DRIVER_RE.findall(dpdk_status))
- if any(b.endswith(vpci) for b in self.bound_pci)
- }
-
def setup_vnf_environment(self):
self._setup_dpdk()
resource = self._setup_resources()
@@ -341,65 +325,31 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
def _detect_and_bind_drivers(self):
interfaces = self.vnfd_helper.interfaces
- self._find_used_drivers()
- for vpci, (index, _) in self.used_drivers.items():
- try:
- intf1 = next(v for v in interfaces if vpci == v['virtual-interface']['vpci'])
- except StopIteration:
- pass
- else:
- intf1['dpdk_port_num'] = index
-
- for vpci in self.bound_pci:
- self._bind_dpdk('igb_uio', vpci)
- time.sleep(2)
-
- # debug dump after binding
- self.ssh_helper.execute("sudo {} -s".format(self.dpdk_nic_bind))
+ self.dpdk_bind_helper.read_status()
+ self.dpdk_bind_helper.save_used_drivers()
- def rebind_drivers(self, force=True):
- if not self.used_drivers:
- self._find_used_drivers()
- for vpci, (_, driver) in self.used_drivers.items():
- self._bind_dpdk(driver, vpci, force)
+ self.dpdk_bind_helper.bind(self.bound_pci, 'igb_uio')
- def _bind_dpdk(self, driver, vpci, force=True):
- if force:
- force = '--force '
- else:
- force = ''
- cmd = self.DPDK_BIND_CMD.format(force=force,
- dpdk_nic_bind=self.dpdk_nic_bind,
- driver=driver,
- vpci=vpci)
- self.ssh_helper.execute(cmd)
+ sorted_dpdk_pci_addresses = sorted(self.dpdk_bind_helper.dpdk_bound_pci_addresses)
+ for dpdk_port_num, vpci in enumerate(sorted_dpdk_pci_addresses):
+ try:
+ intf = next(v for v in interfaces
+ if vpci == v['virtual-interface']['vpci'])
+ # force to int
+ intf['virtual-interface']['dpdk_port_num'] = int(dpdk_port_num)
+ except:
+ pass
+ time.sleep(2)
- def _detect_and_bind_dpdk(self, vpci, driver):
+ def get_local_iface_name_by_vpci(self, vpci):
find_net_cmd = self.FIND_NET_CMD.format(vpci)
- exit_status, _, _ = self.ssh_helper.execute(find_net_cmd)
- if exit_status == 0:
- # already bound
- return None
- self._bind_dpdk(driver, vpci)
exit_status, stdout, _ = self.ssh_helper.execute(find_net_cmd)
- if exit_status != 0:
- # failed to bind
- return None
- return stdout
-
- def _bind_kernel_devices(self):
- # only used by PingSetupEnvHelper?
- for intf in self.vnfd_helper.interfaces:
- vi = intf["virtual-interface"]
- stdout = self._detect_and_bind_dpdk(vi["vpci"], vi["driver"])
- if stdout is not None:
- vi["local_iface_name"] = posixpath.basename(stdout)
+ if exit_status == 0:
+ return stdout
+ return None
def tear_down(self):
- for vpci, (_, driver) in self.used_drivers.items():
- self.ssh_helper.execute(self.DPDK_UNBIND_CMD.format(dpdk_nic_bind=self.dpdk_nic_bind,
- driver=driver,
- vpci=vpci))
+ self.dpdk_bind_helper.rebind_drivers()
class ResourceHelper(object):
@@ -458,14 +408,17 @@ class ClientResourceHelper(ResourceHelper):
self.client = None
self.client_started = Value('i', 0)
- self.my_ports = None
+ self.all_ports = None
self._queue = Queue()
self._result = {}
self._terminated = Value('i', 0)
self._vpci_ascending = None
def _build_ports(self):
- self.my_ports = [0, 1]
+ self.networks = self.vnfd_helper.port_pairs.networks
+ self.priv_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.priv_ports)
+ self.pub_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.pub_ports)
+ self.all_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.all_ports)
def get_stats(self, *args, **kwargs):
try:
@@ -474,8 +427,9 @@ class ClientResourceHelper(ResourceHelper):
LOG.exception("TRex client not connected")
return {}
- def generate_samples(self, key=None, default=None):
- last_result = self.get_stats(self.my_ports)
+ def generate_samples(self, ports, key=None, default=None):
+ # needs to be used ports
+ last_result = self.get_stats(ports)
key_value = last_result.get(key, default)
if not isinstance(last_result, Mapping): # added for mock unit test
@@ -483,27 +437,29 @@ class ClientResourceHelper(ResourceHelper):
return {}
samples = {}
- for vpci_idx, vpci in enumerate(self._vpci_ascending):
- name = self.vnfd_helper.find_virtual_interface(vpci=vpci)["name"]
- # fixme: VNFDs KPIs values needs to be mapped to TRex structure
- xe_value = last_result.get(vpci_idx, {})
- samples[name] = {
- "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
- "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
- "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
- "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
- "in_packets": int(xe_value.get("ipackets", 0)),
- "out_packets": int(xe_value.get("opackets", 0)),
- }
- if key:
- samples[name][key] = key_value
+ # recalculate port for interface and see if it matches ports provided
+ for intf in self.vnfd_helper.interfaces:
+ name = intf["name"]
+ port = self.vnfd_helper.port_num(name)
+ if port in ports:
+ xe_value = last_result.get(port, {})
+ samples[name] = {
+ "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
+ "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
+ "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
+ "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
+ "in_packets": int(xe_value.get("ipackets", 0)),
+ "out_packets": int(xe_value.get("opackets", 0)),
+ }
+ if key:
+ samples[name][key] = key_value
return samples
def _run_traffic_once(self, traffic_profile):
- traffic_profile.execute(self)
+ traffic_profile.execute_traffic(self)
self.client_started.value = 1
time.sleep(self.RUN_DURATION)
- samples = self.generate_samples()
+ samples = self.generate_samples(traffic_profile.ports)
time.sleep(self.QUEUE_WAIT_TIME)
self._queue.put(samples)
@@ -513,14 +469,14 @@ class ClientResourceHelper(ResourceHelper):
try:
self._build_ports()
self.client = self._connect()
- self.client.reset(ports=self.my_ports)
- self.client.remove_all_streams(self.my_ports) # remove all streams
+ self.client.reset(ports=self.all_ports)
+ self.client.remove_all_streams(self.all_ports) # remove all streams
traffic_profile.register_generator(self)
while self._terminated.value == 0:
self._run_traffic_once(traffic_profile)
- self.client.stop(self.my_ports)
+ self.client.stop(self.all_ports)
self.client.disconnect()
self._terminated.value = 0
except STLError:
@@ -534,12 +490,12 @@ class ClientResourceHelper(ResourceHelper):
def clear_stats(self, ports=None):
if ports is None:
- ports = self.my_ports
+ ports = self.all_ports
self.client.clear_stats(ports=ports)
def start(self, ports=None, *args, **kwargs):
if ports is None:
- ports = self.my_ports
+ ports = self.all_ports
self.client.start(ports=ports, *args, **kwargs)
def collect_kpi(self):
@@ -730,7 +686,6 @@ class SampleVNF(GenericVNF):
self.resource_helper = resource_helper_type(self.setup_helper)
- self.all_ports = None
self.context_cfg = None
self.nfvi_context = None
self.pipeline_kwargs = {}
@@ -742,11 +697,17 @@ class SampleVNF(GenericVNF):
self.q_out = Queue()
self.queue_wrapper = None
self.run_kwargs = {}
- self.tg_port_pairs = None
self.used_drivers = {}
self.vnf_port_pairs = None
self._vnf_process = None
+ def _build_ports(self):
+ self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+ self.networks = self._port_pairs.networks
+ self.priv_ports = self.vnfd_helper.port_nums(self._port_pairs.priv_ports)
+ self.pub_ports = self.vnfd_helper.port_nums(self._port_pairs.pub_ports)
+ self.my_ports = self.vnfd_helper.port_nums(self._port_pairs.all_ports)
+
def _get_route_data(self, route_index, route_type):
route_iter = iter(self.vnfd_helper.vdu0.get('nd_route_tbl', []))
for _ in range(route_index):
@@ -825,6 +786,8 @@ class SampleVNF(GenericVNF):
LOG.info("Waiting for %s VNF to start.. ", self.APP_NAME)
time.sleep(1)
+ # put newline to force new prompt?
+ self.q_in.put("\r\n")
def _build_run_kwargs(self):
self.run_kwargs = {
@@ -925,7 +888,6 @@ class SampleVNFTrafficGen(GenericTrafficGen):
self.runs_traffic = True
self.traffic_finished = False
- self.tg_port_pairs = None
self._tg_process = None
self._traffic_process = None
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_ping.py b/yardstick/network_services/vnf_generic/vnf/tg_ping.py
index e65296287..9cd9f2574 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_ping.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_ping.py
@@ -23,6 +23,7 @@ from ipaddress import IPv4Interface
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
LOG = logging.getLogger(__name__)
@@ -59,7 +60,38 @@ class PingParser(object):
class PingSetupEnvHelper(DpdkVnfSetupEnvHelper):
def setup_vnf_environment(self):
- self._bind_kernel_devices()
+ for intf in self.vnfd_helper.interfaces:
+ vi = intf['virtual-interface']
+ vi['local_iface_name'] = self.get_local_iface_name_by_vpci(vi['vpci'])
+
+
+class PingResourceHelper(ClientResourceHelper):
+
+ def __init__(self, setup_helper):
+ super(PingResourceHelper, self).__init__(setup_helper)
+ self._queue = Queue()
+ self._parser = PingParser(self._queue)
+
+ def run_traffic(self, traffic_profile):
+ # drop the connection in order to force a new one
+ self.ssh_helper.drop_connection()
+
+ self.client_started.value = 1
+ cmd_list = [
+ "sudo ip addr flush {local_if_name}",
+ "sudo ip addr add {local_ip}/24 dev {local_if_name}",
+ "sudo ip link set {local_if_name} up",
+ ]
+
+ self.cmd_kwargs['packet_size'] = traffic_profile.params['traffic_profile']['frame_size']
+
+ for cmd in cmd_list:
+ self.ssh_helper.execute(cmd.format(**self.cmd_kwargs))
+
+ ping_cmd = "nohup ping -s {packet_size} {target_ip}&"
+ self.ssh_helper.run(ping_cmd.format(**self.cmd_kwargs),
+ stdout=self._parser,
+ keep_stdin_open=True, pty=True)
class PingTrafficGen(SampleVNFTrafficGen):
@@ -69,16 +101,17 @@ class PingTrafficGen(SampleVNFTrafficGen):
"""
TG_NAME = 'Ping'
+ APP_NAME = 'Ping'
RUN_WAIT = 4
def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
if setup_env_helper_type is None:
setup_env_helper_type = PingSetupEnvHelper
+ if resource_helper_type is None:
+ resource_helper_type = PingResourceHelper
super(PingTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
resource_helper_type)
- self._queue = Queue()
- self._parser = PingParser(self._queue)
self._result = {}
def scale(self, flavor=""):
@@ -89,12 +122,23 @@ class PingTrafficGen(SampleVNFTrafficGen):
return self._tg_process.is_alive()
def instantiate(self, scenario_cfg, context_cfg):
+ self._start_server()
self._result = {
"packets_received": 0,
"rtt": 0,
}
+ intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
+ self.resource_helper.cmd_kwargs = {
+ 'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
+ 'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
+ 'local_if_name': intf["local_iface_name"].split('/')[0],
+ }
+
self.setup_helper.setup_vnf_environment()
+ def wait_for_instantiate(self):
+ pass
+
def listen_traffic(self, traffic_profile):
""" Not needed for ping
@@ -102,27 +146,3 @@ class PingTrafficGen(SampleVNFTrafficGen):
:return:
"""
pass
-
- def _traffic_runner(self, traffic_profile):
- intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
- profile = traffic_profile.params["traffic_profile"]
- cmd_kwargs = {
- 'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
- 'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
- 'local_if_name': intf["local_iface_name"].split('/')[0],
- 'packet_size': profile["frame_size"],
- }
-
- cmd_list = [
- "sudo ip addr flush {local_if_name}",
- "sudo ip addr add {local_ip}/24 dev {local_if_name}",
- "sudo ip link set {local_if_name} up",
- ]
-
- for cmd in cmd_list:
- self.ssh_helper.execute(cmd.format(**cmd_kwargs))
-
- ping_cmd = "ping -s {packet_size} {target_ip}"
- self.ssh_helper.run(ping_cmd.format(**cmd_kwargs),
- stdout=self._parser,
- keep_stdin_open=True, pty=True)
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_prox.py b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
index c266f2c0f..40eda753f 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_prox.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
@@ -56,7 +56,6 @@ class ProxTrafficGen(SampleVNFTrafficGen):
self.runs_traffic = True
self.traffic_finished = False
- self.tg_port_pairs = None
self._tg_process = None
self._traffic_process = None
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
index a52416dd9..93e496969 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -58,19 +58,12 @@ class IxiaResourceHelper(ClientResourceHelper):
rfc_helper_type = IxiaRfc2544Helper
self.rfc_helper = rfc_helper_type(self.scenario_helper)
- self.tg_port_pairs = []
self.priv_ports = None
self.pub_ports = None
def _connect(self, client=None):
self.client._connect(self.vnfd_helper)
- def _build_ports(self):
- # self.generate_port_pairs(self.topology)
- self.priv_ports = [int(x[0][2:]) for x in self.tg_port_pairs]
- self.pub_ports = [int(x[1][2:]) for x in self.tg_port_pairs]
- self.my_ports = list(set(self.priv_ports).union(set(self.pub_ports)))
-
def get_stats(self, *args, **kwargs):
return self.client.ix_get_statistics()
@@ -79,33 +72,37 @@ class IxiaResourceHelper(ClientResourceHelper):
if self.client and self.client.ixnet:
self.client.ix_stop_traffic()
- def generate_samples(self, key=None, default=None):
+ def generate_samples(self, ports, key=None, default=None):
stats = self.get_stats()
last_result = stats[1]
latency = stats[0]
samples = {}
- for vpci_idx, interface in enumerate(self.vnfd_helper.interfaces):
+ for interface in self.vnfd_helper.interfaces:
try:
- name = "xe{0}".format(vpci_idx)
- samples[name] = {
- "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][vpci_idx]),
- "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][vpci_idx]),
- "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][vpci_idx]),
- "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][vpci_idx]),
- "in_packets": int(last_result["Valid_Frames_Rx"][vpci_idx]),
- "out_packets": int(last_result["Frames_Tx"][vpci_idx]),
- "RxThroughput": int(last_result["Valid_Frames_Rx"][vpci_idx]) / 30,
- "TxThroughput": int(last_result["Frames_Tx"][vpci_idx]) / 30,
- }
- if key:
- avg_latency = latency["Store-Forward_Avg_latency_ns"][vpci_idx]
- min_latency = latency["Store-Forward_Min_latency_ns"][vpci_idx]
- max_latency = latency["Store-Forward_Max_latency_ns"][vpci_idx]
- samples[name][key] = \
- {"Store-Forward_Avg_latency_ns": avg_latency,
- "Store-Forward_Min_latency_ns": min_latency,
- "Store-Forward_Max_latency_ns": max_latency}
+ name = interface["name"]
+ # this is not DPDK port num, but this is whatever number we gave
+ # when we selected ports and programmed the profile
+ port = self.vnfd_helper.port_num(name)
+ if port in ports:
+ samples[name] = {
+ "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][port]),
+ "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][port]),
+ "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][port]),
+ "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][port]),
+ "in_packets": int(last_result["Valid_Frames_Rx"][port]),
+ "out_packets": int(last_result["Frames_Tx"][port]),
+ "RxThroughput": int(last_result["Valid_Frames_Rx"][port]) / 30,
+ "TxThroughput": int(last_result["Frames_Tx"][port]) / 30,
+ }
+ if key:
+ avg_latency = latency["Store-Forward_Avg_latency_ns"][port]
+ min_latency = latency["Store-Forward_Min_latency_ns"][port]
+ max_latency = latency["Store-Forward_Max_latency_ns"][port]
+ samples[name][key] = \
+ {"Store-Forward_Avg_latency_ns": avg_latency,
+ "Store-Forward_Min_latency_ns": min_latency,
+ "Store-Forward_Max_latency_ns": max_latency}
except IndexError:
pass
@@ -132,6 +129,7 @@ class IxiaResourceHelper(ClientResourceHelper):
self.client.ix_assign_ports()
mac = {}
+ # TODO: shouldn't this index map to port number we used to generate the profile
for index, interface in enumerate(self.vnfd_helper.interfaces, 1):
virt_intf = interface["virtual-interface"]
mac.update({
@@ -145,11 +143,11 @@ class IxiaResourceHelper(ClientResourceHelper):
self.scenario_helper.scenario_cfg["task_path"])
# Generate ixia traffic config...
while not self._terminated.value:
- traffic_profile.execute(self, self.client, mac, ixia_file)
+ traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
self.client_started.value = 1
time.sleep(WAIT_FOR_TRAFFIC)
self.client.ix_stop_traffic()
- samples = self.generate_samples()
+ samples = self.generate_samples(traffic_profile.ports)
self._queue.put(samples)
status, samples = traffic_profile.get_drop_percentage(self, samples, min_tol,
max_tol, self.client, mac,
@@ -167,11 +165,11 @@ class IxiaResourceHelper(ClientResourceHelper):
self._terminated.value = 1
return
- traffic_profile.execute(self, self.client, mac, ixia_file)
+ traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
for _ in range(5):
time.sleep(self.LATENCY_TIME_SLEEP)
self.client.ix_stop_traffic()
- samples = self.generate_samples('latency', {})
+ samples = self.generate_samples(traffic_profile.ports, 'latency', {})
self._queue.put(samples)
traffic_profile.start_ixia_latency(self, self.client, mac, ixia_file)
if self._terminated.value:
@@ -197,7 +195,6 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
resource_helper_type)
self._ixia_traffic_gen = None
self.ixia_file_name = ''
- self.tg_port_pairs = []
self.vnf_port_pairs = []
def _check_status(self):
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
index 15c9c0e1d..4e9f4bdc1 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
@@ -18,9 +18,7 @@ from __future__ import print_function
import time
import logging
from collections import Mapping
-from itertools import chain
-from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexResourceHelper
@@ -47,23 +45,15 @@ class TrexRfcResourceHelper(TrexResourceHelper):
rfc_helper_type = TrexRfc2544ResourceHelper
self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
- # self.tg_port_pairs = []
-
- def _build_ports(self):
- self.tg_port_pairs, self.networks = MultiPortConfig.get_port_pairs(
- self.vnfd_helper.interfaces)
- self.priv_ports = [int(x[0][2:]) for x in self.tg_port_pairs]
- self.pub_ports = [int(x[1][2:]) for x in self.tg_port_pairs]
- self.my_ports = list(set(chain(self.priv_ports, self.pub_ports)))
def _run_traffic_once(self, traffic_profile):
if self._terminated.value:
return
- traffic_profile.execute(self)
+ traffic_profile.execute_traffic(self)
self.client_started.value = 1
time.sleep(self.RUN_DURATION)
- self.client.stop(self.my_ports)
+ self.client.stop(traffic_profile.ports)
time.sleep(self.WAIT_TIME)
samples = traffic_profile.get_drop_percentage(self)
self._queue.put(samples)
@@ -71,30 +61,30 @@ class TrexRfcResourceHelper(TrexResourceHelper):
if not self.rfc2544_helper.is_done():
return
- self.client.stop(self.my_ports)
- self.client.reset(ports=self.my_ports)
- self.client.remove_all_streams(self.my_ports)
- traffic_profile.execute_latency(samples=samples)
+ self.client.stop(traffic_profile.ports)
+ self.client.reset(ports=traffic_profile.ports)
+ self.client.remove_all_streams(traffic_profile.ports)
+ traffic_profile.execute_traffic_latency(samples=samples)
multiplier = traffic_profile.calculate_pps(samples)[1]
for _ in range(5):
time.sleep(self.LATENCY_TIME_SLEEP)
- self.client.stop(self.my_ports)
+ self.client.stop(traffic_profile.ports)
time.sleep(self.WAIT_TIME)
- last_res = self.client.get_stats(self.my_ports)
+ last_res = self.client.get_stats(traffic_profile.ports)
if not isinstance(last_res, Mapping):
self._terminated.value = 1
continue
- self.generate_samples('latency', {})
+ self.generate_samples(traffic_profile.ports, 'latency', {})
self._queue.put(samples)
self.client.start(mult=str(multiplier),
- ports=self.my_ports,
+ ports=traffic_profile.ports,
duration=120, force=True)
- def start_client(self, mult, duration, force=True):
- self.client.start(ports=self.my_ports, mult=mult, duration=duration, force=force)
+ def start_client(self, ports, mult=None, duration=None, force=True):
+ self.client.start(ports=ports, mult=mult, duration=duration, force=force)
- def clear_client_stats(self):
- self.client.clear_stats(ports=self.my_ports)
+ def clear_client_stats(self, ports):
+ self.client.clear_stats(ports=ports)
def collect_kpi(self):
self.rfc2544_helper.iteration.value += 1
diff --git a/yardstick/network_services/vnf_generic/vnf/udp_replay.py b/yardstick/network_services/vnf_generic/vnf/udp_replay.py
index a9bc204d5..88773387e 100644
--- a/yardstick/network_services/vnf_generic/vnf/udp_replay.py
+++ b/yardstick/network_services/vnf_generic/vnf/udp_replay.py
@@ -19,14 +19,22 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
+
LOG = logging.getLogger(__name__)
# UDP_Replay should work the same on all systems, we can provide the binary
+
+# we can't match the prompt regexp due to extra noise
+# yardstick.ssh ssh.py:302 DEBUG stdout: UDP_Replay: lcore 0 has nothing to do
+# eplUDP_Replay: -- lcoreid=1 portid=0 rxqueueid=0
+# ay>
+#
+# try decreasing log level to RTE_LOG_NOTICE (5)
REPLAY_PIPELINE_COMMAND = (
- """sudo {tool_path} -c {cpu_mask_hex} -n 4 -w {whitelist} -- """
- """{hw_csum} -p {ports_len_hex} --config='{config}'"""
+ """sudo {tool_path} --log-level=5 -c {cpu_mask_hex} -n 4 -w {whitelist} -- """
+ """{hw_csum} -p {port_mask_hex} --config='{config}'"""
)
-# {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+# {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
class UdpReplaySetupEnvHelper(DpdkVnfSetupEnvHelper):
@@ -42,7 +50,8 @@ class UdpReplayApproxVnf(SampleVNF):
APP_NAME = "UDP_Replay"
APP_WORD = "UDP_Replay"
- VNF_PROMPT = 'Replay>'
+ # buffering issue?
+ VNF_PROMPT = 'eplay>'
VNF_TYPE = 'UdpReplay'
@@ -60,36 +69,30 @@ class UdpReplayApproxVnf(SampleVNF):
super(UdpReplayApproxVnf, self).__init__(name, vnfd, setup_env_helper_type,
resource_helper_type)
- def _start_server(self):
- super(UdpReplayApproxVnf, self)._start_server()
- self.resource_helper.start()
-
- def scale(self, flavor=""):
- """ scale vnfbased on flavor input """
- raise NotImplementedError
-
- def _deploy(self):
- self.generate_port_pairs()
- super(UdpReplayApproxVnf, self)._deploy()
-
def _build_pipeline_kwargs(self):
- all_ports = [i for i, _ in enumerate(self.vnfd_helper.interfaces)]
- number_of_ports = len(all_ports)
+ ports = self.vnfd_helper.port_pairs.all_ports
+ number_of_ports = len(ports)
tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
- ports_mask = 2 ** number_of_ports - 1
- ports_mask_hex = hex(ports_mask)
+ port_nums = self.vnfd_helper.port_nums(ports)
+ ports_mask_hex = hex(sum(2 ** num for num in port_nums))
+ # one core extra for master
cpu_mask_hex = hex(2 ** (number_of_ports + 1) - 1)
hw_csum = ""
if (not self.scenario_helper.options.get('hw_csum', False) or
self.nfvi_context.attrs.get('nfvi_type') not in self.HW_OFFLOADING_NFVI_TYPES):
hw_csum = '--no-hw-csum'
- config_value = "".join(str((port, 0, port + 1)) for port in all_ports)
+ # tuples of (FLD_PORT, FLD_QUEUE, FLD_LCORE)
+ # [--config (port,queue,lcore)[,(port,queue,lcore]]"
+ # start with lcore = 1 since we use lcore=0 for master
+ config_value = ",".join(
+ str((self.vnfd_helper.port_num(port), 0, core)).replace(" ", "") for core, port in
+ enumerate(self.vnfd_helper.port_pairs.all_ports, 1))
whitelist = " -w ".join(self.setup_helper.bound_pci)
self.pipeline_kwargs = {
- 'ports_len_hex': ports_mask_hex,
+ 'port_mask_hex': ports_mask_hex,
'tool_path': tool_path,
'hw_csum': hw_csum,
'whitelist': whitelist,
@@ -105,7 +108,7 @@ class UdpReplayApproxVnf(SampleVNF):
def get_sum(offset):
return sum(int(i) for i in split_stats[offset::5])
- number_of_ports = len(self.vnfd_helper.interfaces)
+ number_of_ports = len(self.vnfd_helper.port_pairs.all_ports)
stats = self.get_stats()
stats_words = stats.split()
diff --git a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
index 32a08c7bd..6c95648ce 100644
--- a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
@@ -22,7 +22,7 @@ from yardstick.network_services.yang_model import YangModel
LOG = logging.getLogger(__name__)
# vFW should work the same on all systems, we can provide the binary
-FW_PIPELINE_COMMAND = """sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}"""
+FW_PIPELINE_COMMAND = """sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}"""
FW_COLLECT_KPI = (r"""VFW TOTAL:[^p]+pkts_received"?:\s(\d+),[^p]+pkts_fw_forwarded"?:\s(\d+),"""
r"""[^p]+pkts_drop_fw"?:\s(\d+),\s""")
diff --git a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
index 310ab67cb..72c1514f1 100644
--- a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
@@ -15,6 +15,8 @@
from __future__ import absolute_import
from __future__ import print_function
+
+
import os
import logging
import re
@@ -22,17 +24,17 @@ import posixpath
from six.moves import configparser, zip
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
from yardstick.network_services.pipeline import PipelineRules
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
LOG = logging.getLogger(__name__)
-VPE_PIPELINE_COMMAND = """sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}"""
+VPE_PIPELINE_COMMAND = """sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}"""
VPE_COLLECT_KPI = """\
Pkts in:\s(\d+)\r\n\
-\tPkts dropped by Pkts in:\s(\d+)\r\n\
-\tPkts dropped by AH:\s(\d+)\r\n\\
+\tPkts dropped by AH:\s(\d+)\r\n\
\tPkts dropped by other:\s(\d+)\
"""
@@ -92,24 +94,23 @@ class ConfigCreate(object):
pktq = "SWQ{0}{1}".format(self.sw_q, sink)
return pktq
- def vpe_upstream(self, vnf_cfg, intf):
+ def vpe_upstream(self, vnf_cfg, index=0):
parser = configparser.ConfigParser()
parser.read(os.path.join(vnf_cfg, 'vpe_upstream'))
+
for pipeline in parser.sections():
for k, v in parser.items(pipeline):
if k == "pktq_in":
- index = intf['index']
if "RXQ" in v:
- value = "RXQ{0}.0".format(index)
+ value = "RXQ{0}.0".format(self.priv_ports[index])
else:
value = self.get_sink_swq(parser, pipeline, k, index)
parser.set(pipeline, k, value)
elif k == "pktq_out":
- index = intf['peer_intf']['index']
if "TXQ" in v:
- value = "TXQ{0}.0".format(index)
+ value = "TXQ{0}.0".format(self.pub_ports[index])
else:
self.sw_q += 1
value = self.get_sink_swq(parser, pipeline, k, index)
@@ -123,21 +124,19 @@ class ConfigCreate(object):
self.n_pipeline += 1
return parser
- def vpe_downstream(self, vnf_cfg, intf):
+ def vpe_downstream(self, vnf_cfg, index):
parser = configparser.ConfigParser()
parser.read(os.path.join(vnf_cfg, 'vpe_downstream'))
for pipeline in parser.sections():
for k, v in parser.items(pipeline):
- index = intf['dpdk_port_num']
- peer_index = intf['peer_intf']['dpdk_port_num']
if k == "pktq_in":
if "RXQ" not in v:
value = self.get_sink_swq(parser, pipeline, k, index)
elif "TM" in v:
- value = "RXQ{0}.0 TM{1}".format(peer_index, index)
+ value = "RXQ{0}.0 TM{1}".format(self.pub_ports[index], index)
else:
- value = "RXQ{0}.0".format(peer_index)
+ value = "RXQ{0}.0".format(self.pub_ports[index])
parser.set(pipeline, k, value)
@@ -146,9 +145,9 @@ class ConfigCreate(object):
self.sw_q += 1
value = self.get_sink_swq(parser, pipeline, k, index)
elif "TM" in v:
- value = "TXQ{0}.0 TM{1}".format(peer_index, index)
+ value = "TXQ{0}.0 TM{1}".format(self.priv_ports[index], index)
else:
- value = "TXQ{0}.0".format(peer_index)
+ value = "TXQ{0}.0".format(self.priv_ports[index])
parser.set(pipeline, k, value)
@@ -166,10 +165,10 @@ class ConfigCreate(object):
config = self.vpe_initialize(config)
config = self.vpe_rxq(config)
config.write(cfg_file)
- for index, priv_port in enumerate(self.priv_ports):
- config = self.vpe_upstream(vnf_cfg, priv_port)
+ for index in range(0, len(self.priv_ports)):
+ config = self.vpe_upstream(vnf_cfg, index)
config.write(cfg_file)
- config = self.vpe_downstream(vnf_cfg, priv_port)
+ config = self.vpe_downstream(vnf_cfg, index)
config = self.vpe_tmq(config, index)
config.write(cfg_file)
@@ -199,36 +198,41 @@ class ConfigCreate(object):
return rules.get_string()
+ def generate_tm_cfg(self, vnf_cfg, index=0):
+ vnf_cfg = os.path.join(vnf_cfg, "full_tm_profile_10G.cfg")
+ if os.path.exists(vnf_cfg):
+ return open(vnf_cfg).read()
+
class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
+ APP_NAME = 'vPE_vnf'
CFG_CONFIG = "/tmp/vpe_config"
CFG_SCRIPT = "/tmp/vpe_script"
+ TM_CONFIG = "/tmp/full_tm_profile_10G.cfg"
CORES = ['0', '1', '2', '3', '4', '5']
PIPELINE_COMMAND = VPE_PIPELINE_COMMAND
+ def _build_vnf_ports(self):
+ self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+ self.priv_ports = self._port_pairs.priv_ports
+ self.pub_ports = self._port_pairs.pub_ports
+ self.all_ports = self._port_pairs.all_ports
+
def build_config(self):
vpe_vars = {
"bin_path": self.ssh_helper.bin_path,
"socket": self.socket,
}
- all_ports = []
- priv_ports = []
- pub_ports = []
- for interface in self.vnfd_helper.interfaces:
- all_ports.append(interface['name'])
- vld_id = interface['virtual-interface']['vld_id']
- if vld_id.startswith('private'):
- priv_ports.append(interface)
- elif vld_id.startswith('public'):
- pub_ports.append(interface)
-
- vpe_conf = ConfigCreate(priv_ports, pub_ports, self.socket)
+ self._build_vnf_ports()
+ vpe_conf = ConfigCreate(self.vnfd_helper.port_pairs.priv_ports,
+ self.vnfd_helper.port_pairs.pub_ports, self.socket)
vpe_conf.create_vpe_config(self.scenario_helper.vnf_cfg)
config_basename = posixpath.basename(self.CFG_CONFIG)
script_basename = posixpath.basename(self.CFG_SCRIPT)
+ tm_basename = posixpath.basename(self.TM_CONFIG)
with open(self.CFG_CONFIG) as handle:
vpe_config = handle.read()
@@ -237,6 +241,15 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
vpe_script = vpe_conf.generate_vpe_script(self.vnfd_helper.interfaces)
self.ssh_helper.upload_config_file(script_basename, vpe_script.format(**vpe_vars))
+ tm_config = vpe_conf.generate_tm_cfg(self.scenario_helper.vnf_cfg)
+ self.ssh_helper.upload_config_file(tm_basename, tm_config)
+
+ LOG.info("Provision and start the %s", self.APP_NAME)
+ LOG.info(self.CFG_CONFIG)
+ LOG.info(self.CFG_SCRIPT)
+ self._build_pipeline_kwargs()
+ return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs)
+
class VpeApproxVnf(SampleVNF):
""" This class handles vPE VNF model-driver definitions """