aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services/vnf_generic
diff options
context:
space:
mode:
authorMartin Banszel <martinx.banszel@intel.com>2017-07-19 19:35:02 +0000
committerEdward MacGillivray <edward.s.macgillivray@intel.com>2017-09-14 15:46:38 -0700
commitbe6e7ed6f053a4a697af939fa0ddcd5dce54c0c8 (patch)
tree5bc4b5bed762d9d4ddf79369d3e925acf86596e2 /yardstick/network_services/vnf_generic
parentac0c076ffc701333aed7d65112a0f2e15fda825a (diff)
NSB: fix port topology
Add a new PortPair class to resolve the topology into list of public and private ports. Before we were calculating public/private in multiple locations and using different conventions. In addition for all the DPDK test we need to use the DPDK port number and no rely on interface ordering or interface naming conventions. We used to use xe0 -> 0, xe1 -> 1, etc. This is not the DPDK port number. Use the new dpdknicbind_helper class to parse the output of dpdk-devbind.py to find the actual DPDK port number at runtime. We then use this DPDK port number to correctly calculate the port_mask_hex. The port mask maps the DPDK port num (PMD ID) to the LINK ID used in the pipeline config We also need to make sure we only use the interfaces matched to the topology and not use all the interfaces, because in some cases we will have unused interfaces. In particular TRex always requires an even number of interfaces, so for single port TRex tests we have to create the second port and not use it. Thus we had to modify the traffic generator stats code to only dump stats for used ports and no unused ports. Ixia was using interface ordering to map to Ixia ports, instead we use the dpdk_port_num which must be hardcoded for Ixia. Renamed traffic_profile.execute to traffic_profile.execute_traffic so we can trace the code easier. We pass the port used by the traffic profile to generate_samples so we don't get stats for unused ports. Fixed up vPE config creation and bring up issues. Fixed up CGNAPT and UDP_Replay to work correctly. Tested with 4-port scale-out Change-Id: I2e4f328bff2904108081e92a4bf712333fa73869 Signed-off-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Edward MacGillivray <edward.s.macgillivray@intel.com>
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 """