aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/network_services')
-rw-r--r--yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py103
-rw-r--r--yardstick/network_services/traffic_profile/__init__.py1
-rw-r--r--yardstick/network_services/traffic_profile/base.py4
-rw-r--r--yardstick/network_services/traffic_profile/http_ixload.py8
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py40
-rw-r--r--yardstick/network_services/traffic_profile/prox_irq.py48
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_helpers.py84
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_irq.py200
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py6
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py447
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vpe_vnf.py16
11 files changed, 918 insertions, 39 deletions
diff --git a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
index 1f465bde5..cc627ef78 100644
--- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
+++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
@@ -49,6 +49,19 @@ PROTOCOL_STATUS_DOWN = ['down', 'notStarted']
SUPPORTED_PROTO = [PROTO_UDP]
+SUPPORTED_DSCP_CLASSES = [
+ 'defaultPHB',
+ 'classSelectorPHB',
+ 'assuredForwardingPHB',
+ 'expeditedForwardingPHB']
+
+SUPPORTED_TOS_FIELDS = [
+ 'precedence',
+ 'delay',
+ 'throughput',
+ 'reliability'
+]
+
class Vlan(object):
def __init__(self,
@@ -139,6 +152,9 @@ class IxNextgen(object): # pragma: no cover
vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
return vports
+ def get_static_interface(self, vport):
+ return self.ixnet.getList(vport, 'interface')
+
def _get_config_element_by_flow_group_name(self, flow_group_name):
"""Get a config element using the flow group name
@@ -198,9 +214,18 @@ class IxNextgen(object): # pragma: no cover
:param proto: IxNet protocol str representation, e.g.:
'::ixNet::OBJ-/topology:2/deviceGroup:1/ethernet:1/ipv4:L14'
- :return: (str) protocol status: 'up', 'down' or 'notStarted'
+ :return: (list) protocol status: list of sessions protocol
+ statuses which include states 'up', 'down' and 'notStarted'
+ """
+ return self.ixnet.getAttribute(proto, '-sessionStatus')
+
+ def get_topology_device_groups(self, topology):
+ """Get list of device groups in topology
+
+ :param topology: (str) topology descriptor
+ :return: (list) list of device groups descriptors
"""
- return self.ixnet.getAttribute(proto, '-sessionStatus')[0]
+ return self.ixnet.getList(topology, 'deviceGroup')
def is_traffic_running(self):
"""Returns true if traffic state == TRAFFIC_STATUS_STARTED"""
@@ -218,8 +243,8 @@ class IxNextgen(object): # pragma: no cover
:return: (bool) True if all protocols status is 'up', False if any
protocol status is 'down' or 'notStarted'
"""
- return all(self._get_protocol_status(proto) == PROTOCOL_STATUS_UP
- for proto in protocols)
+ return all(session_status is PROTOCOL_STATUS_UP for proto in protocols
+ for session_status in self._get_protocol_status(proto))
def is_protocols_stopped(self, protocols):
"""Returns true if all protocols statuses are in PROTOCOL_STATUS_DOWN
@@ -229,8 +254,8 @@ class IxNextgen(object): # pragma: no cover
:return: (bool) True if all protocols status is 'down' or 'notStarted',
False if any protocol status is 'up'
"""
- return all(self._get_protocol_status(proto) in PROTOCOL_STATUS_DOWN
- for proto in protocols)
+ return all(session_status in PROTOCOL_STATUS_DOWN for proto in protocols
+ for session_status in self._get_protocol_status(proto))
@staticmethod
def _parse_framesize(framesize):
@@ -392,7 +417,7 @@ class IxNextgen(object): # pragma: no cover
self._create_flow_groups(uplink_endpoints, downlink_endpoints)
self._setup_config_elements()
- def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies):
+ def create_ipv4_traffic_model(self, uplink_endpoints, downlink_endpoints):
"""Create a traffic item and the needed flow groups
Each flow group inside the traffic item (only one is present)
@@ -404,7 +429,7 @@ class IxNextgen(object): # pragma: no cover
FlowGroup4: uplink2 <- downlink2
"""
self._create_traffic_item('ipv4')
- self._create_flow_groups(uplink_topologies, downlink_topologies)
+ self._create_flow_groups(uplink_endpoints, downlink_endpoints)
self._setup_config_elements(False)
def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
@@ -597,23 +622,25 @@ class IxNextgen(object): # pragma: no cover
'precedence': [1, 4, 7]
}
"""
- if 'raw' in priority:
+ if priority.get('raw'):
priority_field = self._get_field_in_stack_item(ip_descriptor,
'priority.raw')
self._set_priority_field(priority_field, priority['raw'])
- elif 'dscp' in priority:
+ elif priority.get('dscp'):
for field, value in priority['dscp'].items():
- priority_field = self._get_field_in_stack_item(
- ip_descriptor,
- 'priority.ds.phb.{field}.{field}'.format(field=field))
- self._set_priority_field(priority_field, value)
+ if field in SUPPORTED_DSCP_CLASSES:
+ priority_field = self._get_field_in_stack_item(
+ ip_descriptor,
+ 'priority.ds.phb.{field}.{field}'.format(field=field))
+ self._set_priority_field(priority_field, value)
- elif 'tos' in priority:
+ elif priority.get('tos'):
for field, value in priority['tos'].items():
- priority_field = self._get_field_in_stack_item(
- ip_descriptor, 'priority.tos.' + field)
- self._set_priority_field(priority_field, value)
+ if field in SUPPORTED_TOS_FIELDS:
+ priority_field = self._get_field_in_stack_item(
+ ip_descriptor, 'priority.tos.' + field)
+ self._set_priority_field(priority_field, value)
def _set_priority_field(self, field_descriptor, value):
"""Set the priority field described by field_descriptor
@@ -938,7 +965,7 @@ class IxNextgen(object): # pragma: no cover
self.ixnet.commit()
return obj
- def add_pppox_client(self, xproto, auth, user, pwd):
+ def add_pppox_client(self, xproto, auth, user, pwd, enable_redial=True):
log.debug(
"add_pppox_client: xproto='%s', auth='%s', user='%s', pwd='%s'",
xproto, auth, user, pwd)
@@ -958,6 +985,10 @@ class IxNextgen(object): # pragma: no cover
else:
raise NotImplementedError()
+ if enable_redial:
+ redial = self.ixnet.getAttribute(obj, '-enableRedial')
+ self.ixnet.setAttribute(redial + '/singleValue', '-value', 'true')
+
self.ixnet.commit()
return obj
@@ -986,3 +1017,37 @@ class IxNextgen(object): # pragma: no cover
'-value', bgp_type)
self.ixnet.commit()
return obj
+
+ def add_interface(self, vport, ip, mac=None, gateway=None):
+ """Add protocol interface to the vport"""
+ log.debug("add_interface: mac='%s', ip='%s', gateway='%s'", mac, ip,
+ gateway)
+ obj = self.ixnet.add(vport, 'interface')
+ self.ixnet.commit()
+
+ if mac is not None:
+ self.ixnet.setMultiAttribute(obj + '/ethernet', '-macAddress', mac)
+
+ ipv4 = self.ixnet.add(obj, 'ipv4')
+ self.ixnet.setMultiAttribute(ipv4, '-ip', ip)
+
+ if gateway is not None:
+ self.ixnet.setMultiAttribute(ipv4, '-gateway', gateway)
+
+ self.ixnet.commit()
+
+ self.ixnet.setMultiAttribute(obj, '-enabled', 'true')
+ self.ixnet.commit()
+
+ return obj
+
+ def add_static_ipv4(self, iface, vport, start_ip, count, mask='24'):
+ """Add static IP range to the interface"""
+ log.debug("add_static_ipv4: start_ip:'%s', count:'%s'",
+ start_ip, count)
+ obj = self.ixnet.add(vport + '/protocols/static', 'ip')
+
+ self.ixnet.setMultiAttribute(obj, '-protocolInterface', iface,
+ '-ipStart', start_ip, '-count', count,
+ '-mask', mask, '-enabled', 'true')
+ self.ixnet.commit()
diff --git a/yardstick/network_services/traffic_profile/__init__.py b/yardstick/network_services/traffic_profile/__init__.py
index 91d8a665f..72a61b6b4 100644
--- a/yardstick/network_services/traffic_profile/__init__.py
+++ b/yardstick/network_services/traffic_profile/__init__.py
@@ -23,6 +23,7 @@ def register_modules():
'yardstick.network_services.traffic_profile.http_ixload',
'yardstick.network_services.traffic_profile.ixia_rfc2544',
'yardstick.network_services.traffic_profile.prox_ACL',
+ 'yardstick.network_services.traffic_profile.prox_irq',
'yardstick.network_services.traffic_profile.prox_binsearch',
'yardstick.network_services.traffic_profile.prox_profile',
'yardstick.network_services.traffic_profile.prox_ramp',
diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py
index ea3f17874..2fdf6ce4a 100644
--- a/yardstick/network_services/traffic_profile/base.py
+++ b/yardstick/network_services/traffic_profile/base.py
@@ -36,7 +36,7 @@ class TrafficProfileConfig(object):
self.description = tp_config.get('description')
tprofile = tp_config['traffic_profile']
self.traffic_type = tprofile.get('traffic_type')
- self.frame_rate, self.rate_unit = self._parse_rate(
+ self.frame_rate, self.rate_unit = self.parse_rate(
tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE))
self.test_precision = tprofile.get('test_precision')
self.packet_sizes = tprofile.get('packet_sizes')
@@ -46,7 +46,7 @@ class TrafficProfileConfig(object):
self.step_interval = tprofile.get('step_interval')
self.enable_latency = tprofile.get('enable_latency', False)
- def _parse_rate(self, rate):
+ def parse_rate(self, rate):
"""Parse traffic profile rate
The line rate can be defined in fps or percentage over the maximum line
diff --git a/yardstick/network_services/traffic_profile/http_ixload.py b/yardstick/network_services/traffic_profile/http_ixload.py
index c64e7511f..b88aadff7 100644
--- a/yardstick/network_services/traffic_profile/http_ixload.py
+++ b/yardstick/network_services/traffic_profile/http_ixload.py
@@ -278,8 +278,12 @@ class IXLOADHttpTest(object):
:param param: (dict) http_client section from traffic profile
:return:
"""
- self.update_page_size(net_traffic, param["page_object"])
- self.update_user_count(net_traffic, param["simulated_users"])
+ page = param.get("page_object")
+ if page:
+ self.update_page_size(net_traffic, page)
+ users = param.get("simulated_users")
+ if users:
+ self.update_user_count(net_traffic, users)
def update_page_size(self, net_traffic, page_object):
"""Update page_object field in http client object in net_traffic
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index 83d24a412..35038891b 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -13,6 +13,7 @@
# limitations under the License.
import logging
+import collections
from yardstick.common import utils
from yardstick.network_services.traffic_profile import base as tp_base
@@ -35,6 +36,7 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
super(IXIARFC2544Profile, self).__init__(yaml_data)
self.rate = self.config.frame_rate
self.rate_unit = self.config.rate_unit
+ self.full_profile = {}
def _get_ip_and_mask(self, ip_range):
_ip_range = ip_range.split('-')
@@ -78,6 +80,12 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
'outer_l4': {},
}
+ frame_rate = value.get('frame_rate')
+ if frame_rate:
+ flow_rate, flow_rate_unit = self.config.parse_rate(frame_rate)
+ result[traffickey]['rate'] = flow_rate
+ result[traffickey]['rate_unit'] = flow_rate_unit
+
outer_l2 = value.get('outer_l2')
if outer_l2:
result[traffickey]['outer_l2'].update({
@@ -164,9 +172,7 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
first_run = self.first_run
if self.first_run:
self.first_run = False
- self.full_profile = {}
self.pg_id = 0
- self.update_traffic_profile(traffic_generator)
self.max_rate = self.rate
self.min_rate = 0.0
else:
@@ -237,3 +243,33 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
samples['latency_ns_max'] = latency_ns_max
return completed, samples
+
+
+class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
+ """Class handles BNG PPPoE scenario tests traffic profile"""
+
+ def __init__(self, yaml_data):
+ super(IXIARFC2544PppoeScenarioProfile, self).__init__(yaml_data)
+ self.full_profile = collections.OrderedDict()
+
+ def _get_flow_groups_params(self):
+ flows_data = [key for key in self.params.keys()
+ if key.split('_')[0] in [self.UPLINK, self.DOWNLINK]]
+ for i in range(len(flows_data)):
+ uplink = '_'.join([self.UPLINK, str(i)])
+ downlink = '_'.join([self.DOWNLINK, str(i)])
+ if uplink in flows_data:
+ self.full_profile.update({uplink: self.params[uplink]})
+ if downlink in flows_data:
+ self.full_profile.update({downlink: self.params[downlink]})
+
+ def update_traffic_profile(self, traffic_generator):
+ def port_generator():
+ for vld_id, intfs in sorted(traffic_generator.networks.items()):
+ if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
+ continue
+ for intf in intfs:
+ yield traffic_generator.vnfd_helper.port_num(intf)
+
+ self._get_flow_groups_params()
+ self.ports = [port for port in port_generator()]
diff --git a/yardstick/network_services/traffic_profile/prox_irq.py b/yardstick/network_services/traffic_profile/prox_irq.py
new file mode 100644
index 000000000..0ea294914
--- /dev/null
+++ b/yardstick/network_services/traffic_profile/prox_irq.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2016-2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+""" Fixed traffic profile definitions """
+
+import logging
+import time
+
+from yardstick.network_services.traffic_profile.prox_profile import ProxProfile
+
+LOG = logging.getLogger(__name__)
+
+
+class ProxIrqProfile(ProxProfile):
+ """
+ This profile adds a single stream at the beginning of the traffic session
+ """
+
+ def __init__(self, tp_config):
+ super(ProxIrqProfile, self).__init__(tp_config)
+
+ def init(self, queue):
+ self.queue = queue
+ self.queue.cancel_join_thread()
+
+ def execute_traffic(self, traffic_generator):
+ LOG.debug("Prox_IRQ Execute Traffic....")
+ time.sleep(5)
+
+ def is_ended(self):
+ return False
+
+ def run_test(self):
+ """Run the test
+ """
+
+ LOG.info("Prox_IRQ ....")
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
index e9d83623b..cd3035ef8 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
@@ -561,6 +561,41 @@ class ProxSocketHelper(object):
tsc = int(ret[3])
return rx, tx, drop, tsc
+ def irq_core_stats(self, cores_tasks):
+ """ get IRQ stats per core"""
+
+ stat = {}
+ core = 0
+ task = 0
+ for core, task in cores_tasks:
+ self.put_command("stats task.core({}).task({}).max_irq,task.core({}).task({}).irq(0),"
+ "task.core({}).task({}).irq(1),task.core({}).task({}).irq(2),"
+ "task.core({}).task({}).irq(3),task.core({}).task({}).irq(4),"
+ "task.core({}).task({}).irq(5),task.core({}).task({}).irq(6),"
+ "task.core({}).task({}).irq(7),task.core({}).task({}).irq(8),"
+ "task.core({}).task({}).irq(9),task.core({}).task({}).irq(10),"
+ "task.core({}).task({}).irq(11),task.core({}).task({}).irq(12)"
+ "\n".format(core, task, core, task, core, task, core, task,
+ core, task, core, task, core, task, core, task,
+ core, task, core, task, core, task, core, task,
+ core, task, core, task))
+ in_data_str = self.get_data().split(",")
+ ret = [try_int(s, 0) for s in in_data_str]
+ key = "core_" + str(core)
+ try:
+ stat[key] = {"cpu": core, "max_irq": ret[0], "bucket_0" : ret[1],
+ "bucket_1" : ret[2], "bucket_2" : ret[3],
+ "bucket_3" : ret[4], "bucket_4" : ret[5],
+ "bucket_5" : ret[6], "bucket_6" : ret[7],
+ "bucket_7" : ret[8], "bucket_8" : ret[9],
+ "bucket_9" : ret[10], "bucket_10" : ret[11],
+ "bucket_11" : ret[12], "bucket_12" : ret[13],
+ "overflow": ret[10] + ret[11] + ret[12] + ret[13]}
+ except (KeyError, IndexError):
+ LOG.error("Corrupted PACKET %s", in_data_str)
+
+ return stat
+
def multi_port_stats(self, ports):
"""get counter values from all ports at once"""
@@ -754,7 +789,6 @@ class ProxSocketHelper(object):
self.put_command("quit_force\n")
time.sleep(3)
-
_LOCAL_OBJECT = object()
@@ -836,6 +870,30 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
file_str[1] = self.additional_files[base_name]
return '"'.join(file_str)
+ def _make_core_list(self, inputStr):
+
+ my_input = inputStr.split("core ", 1)[1]
+ ok_list = set()
+
+ substrs = [x.strip() for x in my_input.split(',')]
+ for i in substrs:
+ try:
+ ok_list.add(int(i))
+
+ except ValueError:
+ try:
+ substr = [int(k.strip()) for k in i.split('-')]
+ if len(substr) > 1:
+ startstr = substr[0]
+ endstr = substr[len(substr) - 1]
+ for z in range(startstr, endstr + 1):
+ ok_list.add(z)
+ except ValueError:
+ LOG.error("Error in cores list ... resuming ")
+ return ok_list
+
+ return ok_list
+
def generate_prox_config_file(self, config_path):
sections = []
prox_config = ConfigParser(config_path, sections)
@@ -855,6 +913,18 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
if section_data[0] == "mac":
section_data[1] = "hardware"
+ # adjust for range of cores
+ new_sections = []
+ for section_name, section in sections:
+ if section_name.startswith('core') and section_name.find('$') == -1:
+ core_list = self._make_core_list(section_name)
+ for core in core_list:
+ new_sections.append(["core " + str(core), section])
+ else:
+ new_sections.append([section_name, section])
+
+ sections = new_sections
+
# search for dst mac
for _, section in sections:
for section_data in section:
@@ -2067,3 +2137,15 @@ class ProxlwAFTRProfileHelper(ProxProfileHelper):
data_helper.latency = self.get_latency()
return data_helper.result_tuple, data_helper.samples
+
+
+class ProxIrqProfileHelper(ProxProfileHelper):
+
+ __prox_profile_type__ = "IRQ Query"
+
+ def __init__(self, resource_helper):
+ super(ProxIrqProfileHelper, self).__init__(resource_helper)
+ self._cores_tuple = None
+ self._ports_tuple = None
+ self.step_delta = 5
+ self.step_time = 0.5
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_irq.py b/yardstick/network_services/vnf_generic/vnf/prox_irq.py
new file mode 100644
index 000000000..dda26b0fe
--- /dev/null
+++ b/yardstick/network_services/vnf_generic/vnf/prox_irq.py
@@ -0,0 +1,200 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import errno
+import logging
+import copy
+import time
+
+from yardstick.common.process import check_if_process_failed
+from yardstick.network_services.utils import get_nsb_option
+from yardstick.network_services.vnf_generic.vnf.prox_vnf import ProxApproxVnf
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
+from yardstick.benchmark.contexts.base import Context
+from yardstick.network_services.vnf_generic.vnf.prox_helpers import CoreSocketTuple
+LOG = logging.getLogger(__name__)
+
+
+class ProxIrq(SampleVNFTrafficGen):
+
+ def __init__(self, name, vnfd, task_id, setup_env_helper_type=None,
+ resource_helper_type=None):
+ vnfd_cpy = copy.deepcopy(vnfd)
+ super(ProxIrq, self).__init__(name, vnfd_cpy, task_id)
+
+ self._vnf_wrapper = ProxApproxVnf(
+ name, vnfd, task_id, setup_env_helper_type, resource_helper_type)
+ self.bin_path = get_nsb_option('bin_path', '')
+ self.name = self._vnf_wrapper.name
+ self.ssh_helper = self._vnf_wrapper.ssh_helper
+ self.setup_helper = self._vnf_wrapper.setup_helper
+ self.resource_helper = self._vnf_wrapper.resource_helper
+ self.scenario_helper = self._vnf_wrapper.scenario_helper
+ self.irq_cores = None
+
+ def terminate(self):
+ self._vnf_wrapper.terminate()
+ super(ProxIrq, self).terminate()
+
+ def instantiate(self, scenario_cfg, context_cfg):
+ self._vnf_wrapper.instantiate(scenario_cfg, context_cfg)
+ self._tg_process = self._vnf_wrapper._vnf_process
+
+ def wait_for_instantiate(self):
+ self._vnf_wrapper.wait_for_instantiate()
+
+ def get_irq_cores(self):
+ cores = []
+ mode = "irq"
+
+ for section_name, section in self.setup_helper.prox_config_data:
+ if not section_name.startswith("core"):
+ continue
+ irq_mode = task_present = False
+ task_present_task = 0
+ for key, value in section:
+ if key == "mode" and value == mode:
+ irq_mode = True
+ if key == "task":
+ task_present = True
+ task_present_task = int(value)
+
+ if irq_mode:
+ if not task_present:
+ task_present_task = 0
+ core_tuple = CoreSocketTuple(section_name)
+ core = core_tuple.core_id
+ cores.append((core, task_present_task))
+
+ return cores
+
+class ProxIrqVNF(ProxIrq, SampleVNFTrafficGen):
+
+ APP_NAME = 'ProxIrqVNF'
+
+ def __init__(self, name, vnfd, task_id, setup_env_helper_type=None,
+ resource_helper_type=None):
+ ProxIrq.__init__(self, name, vnfd, task_id, setup_env_helper_type,
+ resource_helper_type)
+
+ self.start_test_time = None
+ self.end_test_time = None
+
+ def vnf_execute(self, cmd, *args, **kwargs):
+ ignore_errors = kwargs.pop("_ignore_errors", False)
+ try:
+ return self.resource_helper.execute(cmd, *args, **kwargs)
+ except OSError as e:
+ if e.errno in {errno.EPIPE, errno.ESHUTDOWN, errno.ECONNRESET}:
+ if ignore_errors:
+ LOG.debug("ignoring vnf_execute exception %s for command %s", e, cmd)
+ else:
+ raise
+ else:
+ raise
+
+ def collect_kpi(self):
+ # check if the tg processes have exited
+ physical_node = Context.get_physical_node_from_server(
+ self.scenario_helper.nodes[self.name])
+
+ result = {"physical_node": physical_node}
+ for proc in (self._tg_process, self._traffic_process):
+ check_if_process_failed(proc)
+
+ if self.resource_helper is None:
+ return result
+
+ if self.irq_cores is None:
+ self.setup_helper.build_config_file()
+ self.irq_cores = self.get_irq_cores()
+
+ data = self.vnf_execute('irq_core_stats', self.irq_cores)
+ new_data = copy.deepcopy(data)
+
+ self.end_test_time = time.time()
+ self.vnf_execute('reset_stats')
+
+ if self.start_test_time is None:
+ new_data = {}
+ else:
+ test_time = self.end_test_time - self.start_test_time
+ for index, item in data.items():
+ for counter, value in item.items():
+ if counter.startswith("bucket_")or \
+ counter.startswith("overflow"):
+ if value is 0:
+ del new_data[index][counter]
+ else:
+ new_data[index][counter] = float(value) / test_time
+
+ self.start_test_time = time.time()
+
+ result["collect_stats"] = new_data
+ LOG.debug("%s collect KPIs %s", self.APP_NAME, result)
+
+ return result
+
+class ProxIrqGen(ProxIrq, SampleVNFTrafficGen):
+
+ APP_NAME = 'ProxIrqGen'
+
+ def __init__(self, name, vnfd, task_id, setup_env_helper_type=None,
+ resource_helper_type=None):
+ ProxIrq.__init__(self, name, vnfd, task_id, setup_env_helper_type,
+ resource_helper_type)
+ self.start_test_time = None
+ self.end_test_time = None
+
+ def collect_kpi(self):
+ # check if the tg processes have exited
+ physical_node = Context.get_physical_node_from_server(
+ self.scenario_helper.nodes[self.name])
+
+ result = {"physical_node": physical_node}
+ for proc in (self._tg_process, self._traffic_process):
+ check_if_process_failed(proc)
+
+ if self.resource_helper is None:
+ return result
+
+ if self.irq_cores is None:
+ self.setup_helper.build_config_file()
+ self.irq_cores = self.get_irq_cores()
+
+ data = self.resource_helper.sut.irq_core_stats(self.irq_cores)
+ new_data = copy.deepcopy(data)
+
+ self.end_test_time = time.time()
+ self.resource_helper.sut.reset_stats()
+
+ if self.start_test_time is None:
+ new_data = {}
+ else:
+ test_time = self.end_test_time - self.start_test_time
+ for index, item in data.items():
+ for counter, value in item.items():
+ if counter.startswith("bucket_") or \
+ counter.startswith("overflow"):
+ if value is 0:
+ del new_data[index][counter]
+ else:
+ new_data[index][counter] = float(value) / test_time
+
+ self.start_test_time = time.time()
+
+ result["collect_stats"] = new_data
+ LOG.debug("%s collect KPIs %s", self.APP_NAME, result)
+
+ return result
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index 673344f4e..8833b88f2 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -180,7 +180,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
"""No actions/rules (flows) by default"""
return None
- def _build_pipeline_kwargs(self, cfg_file=None):
+ def _build_pipeline_kwargs(self, cfg_file=None, script=None):
tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
# count the number of actual ports in the list of pairs
# remove duplicate ports
@@ -201,7 +201,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
self.pipeline_kwargs = {
'cfg_file': cfg_file if cfg_file else self.CFG_CONFIG,
- 'script': self.CFG_SCRIPT,
+ 'script': script if script else self.CFG_SCRIPT,
'port_mask_hex': ports_mask_hex,
'tool_path': tool_path,
'hwlb': hwlb,
@@ -898,6 +898,8 @@ class SampleVNFTrafficGen(GenericTrafficGen):
self.scenario_helper.nodes[self.name]
)
+ self.resource_helper.context_cfg = context_cfg
+
self.resource_helper.setup()
# must generate_cfg after DPDK bind because we need port number
self.resource_helper.generate_cfg()
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 89f8194c0..4d6bd422d 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2018 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,9 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import ipaddress
import logging
+import six
from yardstick.common import utils
+from yardstick.common import exceptions
from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
@@ -25,6 +28,409 @@ LOG = logging.getLogger(__name__)
WAIT_AFTER_CFG_LOAD = 10
WAIT_FOR_TRAFFIC = 30
+WAIT_PROTOCOLS_STARTED = 360
+
+
+class IxiaBasicScenario(object):
+ """Ixia Basic scenario for flow from port to port"""
+
+ def __init__(self, client, context_cfg, ixia_cfg):
+
+ self.client = client
+ self.context_cfg = context_cfg
+ self.ixia_cfg = ixia_cfg
+
+ self._uplink_vports = None
+ self._downlink_vports = None
+
+ def apply_config(self):
+ pass
+
+ def run_protocols(self):
+ pass
+
+ def stop_protocols(self):
+ pass
+
+ def create_traffic_model(self, traffic_profile=None):
+ # pylint: disable=unused-argument
+ vports = self.client.get_vports()
+ self._uplink_vports = vports[::2]
+ self._downlink_vports = vports[1::2]
+ self.client.create_traffic_model(self._uplink_vports,
+ self._downlink_vports)
+
+
+class IxiaL3Scenario(IxiaBasicScenario):
+ """Ixia scenario for L3 flow between static ip's"""
+
+ def _add_static_ips(self):
+ vports = self.client.get_vports()
+ uplink_intf_vport = [(self.client.get_static_interface(vport), vport)
+ for vport in vports[::2]]
+ downlink_intf_vport = [(self.client.get_static_interface(vport), vport)
+ for vport in vports[1::2]]
+
+ for index in range(len(uplink_intf_vport)):
+ intf, vport = uplink_intf_vport[index]
+ try:
+ iprange = self.ixia_cfg['flow'].get('src_ip')[index]
+ start_ip = utils.get_ip_range_start(iprange)
+ count = utils.get_ip_range_count(iprange)
+ self.client.add_static_ipv4(intf, vport, start_ip, count)
+ except IndexError:
+ raise exceptions.IncorrectFlowOption(
+ option="src_ip", link="uplink_{}".format(index))
+
+ intf, vport = downlink_intf_vport[index]
+ try:
+ iprange = self.ixia_cfg['flow'].get('dst_ip')[index]
+ start_ip = utils.get_ip_range_start(iprange)
+ count = utils.get_ip_range_count(iprange)
+ self.client.add_static_ipv4(intf, vport, start_ip, count)
+ except IndexError:
+ raise exceptions.IncorrectFlowOption(
+ option="dst_ip", link="downlink_{}".format(index))
+
+ def _add_interfaces(self):
+ vports = self.client.get_vports()
+ uplink_vports = (vport for vport in vports[::2])
+ downlink_vports = (vport for vport in vports[1::2])
+
+ ix_node = next(node for _, node in self.context_cfg['nodes'].items()
+ if node['role'] == 'IxNet')
+
+ for intf in ix_node['interfaces'].values():
+ ip = intf.get('local_ip')
+ mac = intf.get('local_mac')
+ gateway = None
+ try:
+ gateway = next(route.get('gateway')
+ for route in ix_node.get('routing_table')
+ if route.get('if') == intf.get('ifname'))
+ except StopIteration:
+ LOG.debug("Gateway not provided")
+
+ if 'uplink' in intf.get('vld_id'):
+ self.client.add_interface(next(uplink_vports),
+ ip, mac, gateway)
+ else:
+ self.client.add_interface(next(downlink_vports),
+ ip, mac, gateway)
+
+ def apply_config(self):
+ self._add_interfaces()
+ self._add_static_ips()
+
+ def create_traffic_model(self, traffic_profile=None):
+ # pylint: disable=unused-argument
+ vports = self.client.get_vports()
+ self._uplink_vports = vports[::2]
+ self._downlink_vports = vports[1::2]
+
+ uplink_endpoints = [port + '/protocols/static'
+ for port in self._uplink_vports]
+ downlink_endpoints = [port + '/protocols/static'
+ for port in self._downlink_vports]
+
+ self.client.create_ipv4_traffic_model(uplink_endpoints,
+ downlink_endpoints)
+
+
+class IxiaPppoeClientScenario(object):
+ def __init__(self, client, context_cfg, ixia_cfg):
+
+ self.client = client
+
+ self._uplink_vports = None
+ self._downlink_vports = None
+
+ self._access_topologies = []
+ self._core_topologies = []
+
+ self._context_cfg = context_cfg
+ self._ixia_cfg = ixia_cfg
+ self.protocols = []
+ self.device_groups = []
+
+ def apply_config(self):
+ vports = self.client.get_vports()
+ self._uplink_vports = vports[::2]
+ self._downlink_vports = vports[1::2]
+ self._fill_ixia_config()
+ self._apply_access_network_config()
+ self._apply_core_network_config()
+
+ def create_traffic_model(self, traffic_profile):
+ endpoints_id_pairs = self._get_endpoints_src_dst_id_pairs(
+ traffic_profile.full_profile)
+ endpoints_obj_pairs = \
+ self._get_endpoints_src_dst_obj_pairs(endpoints_id_pairs)
+ uplink_endpoints = endpoints_obj_pairs[::2]
+ downlink_endpoints = endpoints_obj_pairs[1::2]
+ self.client.create_ipv4_traffic_model(uplink_endpoints,
+ downlink_endpoints)
+
+ def run_protocols(self):
+ LOG.info('PPPoE Scenario - Start Protocols')
+ self.client.start_protocols()
+ utils.wait_until_true(
+ lambda: self.client.is_protocols_running(self.protocols),
+ timeout=WAIT_PROTOCOLS_STARTED, sleep=2)
+
+ def stop_protocols(self):
+ LOG.info('PPPoE Scenario - Stop Protocols')
+ self.client.stop_protocols()
+
+ def _get_intf_addr(self, intf):
+ """Retrieve interface IP address and mask
+
+ :param intf: could be the string which represents IP address
+ with mask (e.g 192.168.10.2/24) or a dictionary with the host
+ name and the port (e.g. {'tg__0': 'xe1'})
+ :return: (tuple) pair of ip address and mask
+ """
+ if isinstance(intf, six.string_types):
+ ip, mask = tuple(intf.split('/'))
+ return ip, int(mask)
+
+ node_name, intf_name = next(iter(intf.items()))
+ node = self._context_cfg["nodes"].get(node_name, {})
+ interface = node.get("interfaces", {})[intf_name]
+ ip = interface["local_ip"]
+ mask = interface["netmask"]
+ ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)),
+ strict=False)
+ return ip, ipaddr.prefixlen
+
+ @staticmethod
+ def _get_endpoints_src_dst_id_pairs(flows_params):
+ """Get list of flows src/dst port pairs
+
+ Create list of flows src/dst port pairs based on traffic profile
+ flows data. Each uplink/downlink pair in traffic profile represents
+ specific flows between the pair of ports.
+
+ Example ('port' key represents port on which flow will be created):
+
+ Input flows data:
+ uplink_0:
+ ipv4:
+ id: 1
+ port: xe0
+ downlink_0:
+ ipv4:
+ id: 2
+ port: xe1
+ uplink_1:
+ ipv4:
+ id: 3
+ port: xe2
+ downlink_1:
+ ipv4:
+ id: 4
+ port: xe3
+
+ Result list: ['xe0', 'xe1', 'xe2', 'xe3']
+
+ Result list means that the following flows pairs will be created:
+ - uplink 0: port xe0 <-> port xe1
+ - downlink 0: port xe1 <-> port xe0
+ - uplink 1: port xe2 <-> port xe3
+ - downlink 1: port xe3 <-> port xe2
+
+ :param flows_params: ordered dict of traffic profile flows params
+ :return: (list) list of flows src/dst ports
+ """
+ if len(flows_params) % 2:
+ raise RuntimeError('Number of uplink/downlink pairs'
+ ' in traffic profile is not equal')
+ endpoint_pairs = []
+ for flow in flows_params:
+ port = flows_params[flow]['ipv4'].get('port')
+ if port is None:
+ continue
+ endpoint_pairs.append(port)
+ return endpoint_pairs
+
+ def _get_endpoints_src_dst_obj_pairs(self, endpoints_id_pairs):
+ """Create list of uplink/downlink device groups pairs
+
+ Based on traffic profile options, create list of uplink/downlink
+ device groups pairs between which flow groups will be created:
+
+ 1. In case uplink/downlink flows in traffic profile doesn't have
+ specified 'port' key, flows will be created between each device
+ group on access port and device group on corresponding core port.
+ E.g.:
+ Device groups created on access port xe0: dg1, dg2, dg3
+ Device groups created on core port xe1: dg4
+ Flows will be created between:
+ dg1 -> dg4
+ dg4 -> dg1
+ dg2 -> dg4
+ dg4 -> dg2
+ dg3 -> dg4
+ dg4 -> dg3
+
+ 2. In case uplink/downlink flows in traffic profile have specified
+ 'port' key, flows will be created between device groups on this
+ port.
+ E.g., for the following traffic profile
+ uplink_0:
+ port: xe0
+ downlink_0:
+ port: xe1
+ uplink_1:
+ port: xe0
+ downlink_0:
+ port: xe3
+ Flows will be created between:
+ Port xe0 (dg1) -> Port xe1 (dg1)
+ Port xe1 (dg1) -> Port xe0 (dg1)
+ Port xe0 (dg2) -> Port xe3 (dg1)
+ Port xe3 (dg3) -> Port xe0 (dg1)
+
+ :param endpoints_id_pairs: (list) List of uplink/downlink flows ports
+ pairs
+ :return: (list) list of uplink/downlink device groups descriptors pairs
+ """
+ pppoe = self._ixia_cfg['pppoe_client']
+ sessions_per_port = pppoe['sessions_per_port']
+ sessions_per_svlan = pppoe['sessions_per_svlan']
+ svlan_count = int(sessions_per_port / sessions_per_svlan)
+
+ uplink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['src_ip']]
+ downlink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['dst_ip']]
+ uplink_port_topology_map = zip(uplink_ports, self._access_topologies)
+ downlink_port_topology_map = zip(downlink_ports, self._core_topologies)
+
+ port_to_dev_group_mapping = {}
+ for port, topology in uplink_port_topology_map:
+ topology_dgs = self.client.get_topology_device_groups(topology)
+ port_to_dev_group_mapping[port] = topology_dgs
+ for port, topology in downlink_port_topology_map:
+ topology_dgs = self.client.get_topology_device_groups(topology)
+ port_to_dev_group_mapping[port] = topology_dgs
+
+ uplink_endpoints = endpoints_id_pairs[::2]
+ downlink_endpoints = endpoints_id_pairs[1::2]
+
+ uplink_dev_groups = []
+ group_up = [uplink_endpoints[i:i + svlan_count]
+ for i in range(0, len(uplink_endpoints), svlan_count)]
+
+ for group in group_up:
+ for i, port in enumerate(group):
+ uplink_dev_groups.append(port_to_dev_group_mapping[port][i])
+
+ downlink_dev_groups = []
+ for port in downlink_endpoints:
+ downlink_dev_groups.append(port_to_dev_group_mapping[port][0])
+
+ endpoint_obj_pairs = []
+ [endpoint_obj_pairs.extend([up, down])
+ for up, down in zip(uplink_dev_groups, downlink_dev_groups)]
+
+ if not endpoint_obj_pairs:
+ for up, down in zip(uplink_ports, downlink_ports):
+ uplink_dev_groups = port_to_dev_group_mapping[up]
+ downlink_dev_groups = \
+ port_to_dev_group_mapping[down] * len(uplink_dev_groups)
+ [endpoint_obj_pairs.extend(list(i))
+ for i in zip(uplink_dev_groups, downlink_dev_groups)]
+ return endpoint_obj_pairs
+
+ def _fill_ixia_config(self):
+ pppoe = self._ixia_cfg["pppoe_client"]
+ ipv4 = self._ixia_cfg["ipv4_client"]
+
+ _ip = [self._get_intf_addr(intf)[0] for intf in pppoe["ip"]]
+ self._ixia_cfg["pppoe_client"]["ip"] = _ip
+
+ _ip = [self._get_intf_addr(intf)[0] for intf in ipv4["gateway_ip"]]
+ self._ixia_cfg["ipv4_client"]["gateway_ip"] = _ip
+
+ addrs = [self._get_intf_addr(intf) for intf in ipv4["ip"]]
+ _ip = [addr[0] for addr in addrs]
+ _prefix = [addr[1] for addr in addrs]
+
+ self._ixia_cfg["ipv4_client"]["ip"] = _ip
+ self._ixia_cfg["ipv4_client"]["prefix"] = _prefix
+
+ def _apply_access_network_config(self):
+ pppoe = self._ixia_cfg["pppoe_client"]
+ sessions_per_port = pppoe['sessions_per_port']
+ sessions_per_svlan = pppoe['sessions_per_svlan']
+ svlan_count = int(sessions_per_port / sessions_per_svlan)
+
+ # add topology per uplink port (access network)
+ for access_tp_id, vport in enumerate(self._uplink_vports):
+ name = 'Topology access {}'.format(access_tp_id)
+ tp = self.client.add_topology(name, vport)
+ self._access_topologies.append(tp)
+ # add device group per svlan
+ for dg_id in range(svlan_count):
+ s_vlan_id = int(pppoe['s_vlan']) + dg_id + access_tp_id * svlan_count
+ s_vlan = ixnet_api.Vlan(vlan_id=s_vlan_id)
+ c_vlan = ixnet_api.Vlan(vlan_id=pppoe['c_vlan'], vlan_id_step=1)
+ name = 'SVLAN {}'.format(s_vlan_id)
+ dg = self.client.add_device_group(tp, name, sessions_per_svlan)
+ self.device_groups.append(dg)
+ # add ethernet layer to device group
+ ethernet = self.client.add_ethernet(dg, 'Ethernet')
+ self.protocols.append(ethernet)
+ self.client.add_vlans(ethernet, [s_vlan, c_vlan])
+ # add ppp over ethernet
+ if 'pap_user' in pppoe:
+ ppp = self.client.add_pppox_client(ethernet, 'pap',
+ pppoe['pap_user'],
+ pppoe['pap_password'])
+ else:
+ ppp = self.client.add_pppox_client(ethernet, 'chap',
+ pppoe['chap_user'],
+ pppoe['chap_password'])
+ self.protocols.append(ppp)
+
+ def _apply_core_network_config(self):
+ ipv4 = self._ixia_cfg["ipv4_client"]
+ sessions_per_port = ipv4['sessions_per_port']
+ sessions_per_vlan = ipv4['sessions_per_vlan']
+ vlan_count = int(sessions_per_port / sessions_per_vlan)
+
+ # add topology per downlink port (core network)
+ for core_tp_id, vport in enumerate(self._downlink_vports):
+ name = 'Topology core {}'.format(core_tp_id)
+ tp = self.client.add_topology(name, vport)
+ self._core_topologies.append(tp)
+ # add device group per vlan
+ for dg_id in range(vlan_count):
+ name = 'Core port {}'.format(core_tp_id)
+ dg = self.client.add_device_group(tp, name, sessions_per_vlan)
+ self.device_groups.append(dg)
+ # add ethernet layer to device group
+ ethernet = self.client.add_ethernet(dg, 'Ethernet')
+ self.protocols.append(ethernet)
+ if 'vlan' in ipv4:
+ vlan_id = int(ipv4['vlan']) + dg_id + core_tp_id * vlan_count
+ vlan = ixnet_api.Vlan(vlan_id=vlan_id)
+ self.client.add_vlans(ethernet, [vlan])
+ # add ipv4 layer
+ gw_ip = ipv4['gateway_ip'][core_tp_id]
+ # use gw addr to generate ip addr from the same network
+ ip_addr = ipaddress.IPv4Address(gw_ip) + 1
+ ipv4_obj = self.client.add_ipv4(ethernet, name='ipv4',
+ addr=ip_addr,
+ addr_step='0.0.0.1',
+ prefix=ipv4['prefix'][core_tp_id],
+ gateway=gw_ip)
+ self.protocols.append(ipv4_obj)
+ if ipv4.get("bgp"):
+ bgp_peer_obj = self.client.add_bgp(ipv4_obj,
+ dut_ip=ipv4["bgp"]["dut_ip"],
+ local_as=ipv4["bgp"]["as_number"],
+ bgp_type=ipv4["bgp"].get("bgp_type"))
+ self.protocols.append(bgp_peer_obj)
class IxiaRfc2544Helper(Rfc2544ResourceHelper):
@@ -41,6 +447,12 @@ class IxiaResourceHelper(ClientResourceHelper):
super(IxiaResourceHelper, self).__init__(setup_helper)
self.scenario_helper = setup_helper.scenario_helper
+ self._ixia_scenarios = {
+ "IxiaBasic": IxiaBasicScenario,
+ "IxiaL3": IxiaL3Scenario,
+ "IxiaPppoeClient": IxiaPppoeClientScenario,
+ }
+
self.client = ixnet_api.IxNextgen()
if rfc_helper_type is None:
@@ -49,6 +461,8 @@ class IxiaResourceHelper(ClientResourceHelper):
self.rfc_helper = rfc_helper_type(self.scenario_helper)
self.uplink_ports = None
self.downlink_ports = None
+ self.context_cfg = None
+ self._ix_scenario = None
self._connect()
def _connect(self, client=None):
@@ -57,7 +471,12 @@ class IxiaResourceHelper(ClientResourceHelper):
def get_stats(self, *args, **kwargs):
return self.client.get_statistics()
+ def setup(self):
+ super(IxiaResourceHelper, self).setup()
+ self._init_ix_scenario()
+
def stop_collect(self):
+ self._ix_scenario.stop_protocols()
self._terminated.value = 1
def generate_samples(self, ports, duration):
@@ -92,14 +511,24 @@ class IxiaResourceHelper(ClientResourceHelper):
return samples
- def _initialize_client(self):
+ def _init_ix_scenario(self):
+ ixia_config = self.scenario_helper.scenario_cfg.get('ixia_config', 'IxiaBasic')
+
+ if ixia_config in self._ixia_scenarios:
+ scenario_type = self._ixia_scenarios[ixia_config]
+
+ self._ix_scenario = scenario_type(self.client, self.context_cfg,
+ self.scenario_helper.scenario_cfg['options'])
+ else:
+ raise RuntimeError(
+ "IXIA config type '{}' not supported".format(ixia_config))
+
+ def _initialize_client(self, traffic_profile):
"""Initialize the IXIA IxNetwork client and configure the server"""
self.client.clear_config()
self.client.assign_ports()
- vports = self.client.get_vports()
- uplink_vports = vports[::2]
- downlink_vports = vports[1::2]
- self.client.create_traffic_model(uplink_vports, downlink_vports)
+ self._ix_scenario.apply_config()
+ self._ix_scenario.create_traffic_model(traffic_profile)
def run_traffic(self, traffic_profile, *args):
if self._terminated.value:
@@ -111,7 +540,8 @@ class IxiaResourceHelper(ClientResourceHelper):
default = "00:00:00:00:00:00"
self._build_ports()
- self._initialize_client()
+ traffic_profile.update_traffic_profile(self)
+ self._initialize_client(traffic_profile)
mac = {}
for port_name in self.vnfd_helper.port_pairs.all_ports:
@@ -123,6 +553,8 @@ class IxiaResourceHelper(ClientResourceHelper):
mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
+ self._ix_scenario.run_protocols()
+
try:
while not self._terminated.value:
first_run = traffic_profile.execute_traffic(
@@ -144,6 +576,7 @@ class IxiaResourceHelper(ClientResourceHelper):
except Exception: # pylint: disable=broad-except
LOG.exception('Run Traffic terminated')
+ self._ix_scenario.stop_protocols()
self._terminated.value = 1
def collect_kpi(self):
diff --git a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
index 349ef7888..dd3221386 100644
--- a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
@@ -106,6 +106,7 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
action_bulk_file = vnf_cfg.get('action_bulk_file', '/tmp/action_bulk_512.txt')
full_tm_profile_file = vnf_cfg.get('full_tm_profile_file', '/tmp/full_tm_profile_10G.cfg')
config_file = vnf_cfg.get('file', '/tmp/vpe_config')
+ script_file = vnf_cfg.get('script_file', None)
vpe_vars = {
"bin_path": self.ssh_helper.bin_path,
"socket": self.socket,
@@ -113,8 +114,16 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
self._build_vnf_ports()
vpe_conf = ConfigCreate(self.vnfd_helper, self.socket)
+ if script_file is None:
+ # autogenerate vpe_script if not given
+ vpe_script = vpe_conf.generate_vpe_script(self.vnfd_helper.interfaces)
+ script_file = self.CFG_SCRIPT
+ else:
+ with utils.open_relative_file(script_file, task_path) as handle:
+ vpe_script = handle.read()
+
config_basename = posixpath.basename(config_file)
- script_basename = posixpath.basename(self.CFG_SCRIPT)
+ script_basename = posixpath.basename(script_file)
with utils.open_relative_file(action_bulk_file, task_path) as handle:
action_bulk = handle.read()
@@ -125,8 +134,6 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
with utils.open_relative_file(config_file, task_path) as handle:
vpe_config = handle.read()
- # vpe_script needs to be autogenerated
- vpe_script = vpe_conf.generate_vpe_script(self.vnfd_helper.interfaces)
# upload the 4 config files to the target server
self.ssh_helper.upload_config_file(config_basename, vpe_config.format(**vpe_vars))
self.ssh_helper.upload_config_file(script_basename, vpe_script.format(**vpe_vars))
@@ -138,7 +145,8 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
LOG.info("Provision and start the %s", self.APP_NAME)
LOG.info(config_file)
LOG.info(self.CFG_SCRIPT)
- self._build_pipeline_kwargs(cfg_file='/tmp/' + config_basename)
+ self._build_pipeline_kwargs(cfg_file='/tmp/' + config_basename,
+ script='/tmp/' + script_basename)
return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs)