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.py54
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py212
3 files changed, 247 insertions, 21 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..b5e4172a9 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,
@@ -198,9 +211,10 @@ 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')[0]
+ return self.ixnet.getAttribute(proto, '-sessionStatus')
def is_traffic_running(self):
"""Returns true if traffic state == TRAFFIC_STATUS_STARTED"""
@@ -218,8 +232,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 +243,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):
@@ -597,23 +611,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 +954,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 +974,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
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index 673344f4e..ebe3ff774 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -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..4c13112be 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -12,7 +12,9 @@
# 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.network_services.libs.ixia_libs.ixnet import ixnet_api
@@ -25,6 +27,183 @@ LOG = logging.getLogger(__name__)
WAIT_AFTER_CFG_LOAD = 10
WAIT_FOR_TRAFFIC = 30
+WAIT_PROTOCOLS_STARTED = 360
+
+
+class IxiaBasicScenario(object):
+ 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 create_traffic_model(self):
+ 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)
+
+ def run_protocols(self):
+ pass
+
+ def stop_protocols(self):
+ pass
+
+
+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 = []
+
+ 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):
+ self.client.create_ipv4_traffic_model(self._access_topologies,
+ self._core_topologies)
+
+ 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
+
+ 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)
+ # 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)
+ # 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 +220,11 @@ class IxiaResourceHelper(ClientResourceHelper):
super(IxiaResourceHelper, self).__init__(setup_helper)
self.scenario_helper = setup_helper.scenario_helper
+ self._ixia_scenarios = {
+ "IxiaBasic": IxiaBasicScenario,
+ "IxiaPppoeClient": IxiaPppoeClientScenario,
+ }
+
self.client = ixnet_api.IxNextgen()
if rfc_helper_type is None:
@@ -49,6 +233,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 +243,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 +283,24 @@ class IxiaResourceHelper(ClientResourceHelper):
return samples
+ 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):
"""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()
def run_traffic(self, traffic_profile, *args):
if self._terminated.value:
@@ -123,6 +324,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 +347,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):