1 # Copyright (c) 2016-2019 Intel Corporation
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 from yardstick.common import utils
22 from yardstick.common import exceptions
23 from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
24 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
25 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
26 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
29 LOG = logging.getLogger(__name__)
31 WAIT_AFTER_CFG_LOAD = 10
33 WAIT_PROTOCOLS_STARTED = 420
36 class IxiaBasicScenario(object):
37 """Ixia Basic scenario for flow from port to port"""
39 def __init__(self, client, context_cfg, ixia_cfg):
42 self.context_cfg = context_cfg
43 self.ixia_cfg = ixia_cfg
45 self._uplink_vports = None
46 self._downlink_vports = None
48 def apply_config(self):
51 def run_protocols(self):
54 def stop_protocols(self):
57 def create_traffic_model(self, traffic_profile=None):
58 # pylint: disable=unused-argument
59 vports = self.client.get_vports()
60 self._uplink_vports = vports[::2]
61 self._downlink_vports = vports[1::2]
62 self.client.create_traffic_model(self._uplink_vports,
63 self._downlink_vports)
66 return self.client.get_statistics()
68 def generate_samples(self, resource_helper, ports, duration):
69 stats = self._get_stats()
72 # this is not DPDK port num, but this is whatever number we gave
73 # when we selected ports and programmed the profile
74 for port_num in ports:
76 # reverse lookup port name from port_num so the stats dict is descriptive
77 intf = resource_helper.vnfd_helper.find_interface_by_port(port_num)
78 port_name = intf['name']
79 avg_latency = stats['Store-Forward_Avg_latency_ns'][port_num]
80 min_latency = stats['Store-Forward_Min_latency_ns'][port_num]
81 max_latency = stats['Store-Forward_Max_latency_ns'][port_num]
82 samples[port_name] = {
83 'rx_throughput_kps': float(stats['Rx_Rate_Kbps'][port_num]),
84 'tx_throughput_kps': float(stats['Tx_Rate_Kbps'][port_num]),
85 'rx_throughput_mbps': float(stats['Rx_Rate_Mbps'][port_num]),
86 'tx_throughput_mbps': float(stats['Tx_Rate_Mbps'][port_num]),
87 'in_packets': int(stats['Valid_Frames_Rx'][port_num]),
88 'out_packets': int(stats['Frames_Tx'][port_num]),
89 'RxThroughput': float(stats['Valid_Frames_Rx'][port_num]) / duration,
90 'TxThroughput': float(stats['Frames_Tx'][port_num]) / duration,
91 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
92 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
93 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
100 def update_tracking_options(self):
103 def get_tc_rfc2544_options(self):
107 class IxiaL3Scenario(IxiaBasicScenario):
108 """Ixia scenario for L3 flow between static ip's"""
110 def _add_static_ips(self):
111 vports = self.client.get_vports()
112 uplink_intf_vport = [(self.client.get_static_interface(vport), vport)
113 for vport in vports[::2]]
114 downlink_intf_vport = [(self.client.get_static_interface(vport), vport)
115 for vport in vports[1::2]]
117 for index in range(len(uplink_intf_vport)):
118 intf, vport = uplink_intf_vport[index]
120 iprange = self.ixia_cfg['flow'].get('src_ip')[index]
121 start_ip = utils.get_ip_range_start(iprange)
122 count = utils.get_ip_range_count(iprange)
123 self.client.add_static_ipv4(intf, vport, start_ip, count, '32')
125 raise exceptions.IncorrectFlowOption(
126 option="src_ip", link="uplink_{}".format(index))
128 intf, vport = downlink_intf_vport[index]
130 iprange = self.ixia_cfg['flow'].get('dst_ip')[index]
131 start_ip = utils.get_ip_range_start(iprange)
132 count = utils.get_ip_range_count(iprange)
133 self.client.add_static_ipv4(intf, vport, start_ip, count, '32')
135 raise exceptions.IncorrectFlowOption(
136 option="dst_ip", link="downlink_{}".format(index))
138 def _add_interfaces(self):
139 vports = self.client.get_vports()
140 uplink_vports = (vport for vport in vports[::2])
141 downlink_vports = (vport for vport in vports[1::2])
143 ix_node = next(node for _, node in self.context_cfg['nodes'].items()
144 if node['role'] == 'IxNet')
146 for intf in ix_node['interfaces'].values():
147 ip = intf.get('local_ip')
148 mac = intf.get('local_mac')
151 gateway = next(route.get('gateway')
152 for route in ix_node.get('routing_table')
153 if route.get('if') == intf.get('ifname'))
154 except StopIteration:
155 LOG.debug("Gateway not provided")
157 if 'uplink' in intf.get('vld_id'):
158 self.client.add_interface(next(uplink_vports),
161 self.client.add_interface(next(downlink_vports),
164 def apply_config(self):
165 self._add_interfaces()
166 self._add_static_ips()
168 def create_traffic_model(self, traffic_profile=None):
169 # pylint: disable=unused-argument
170 vports = self.client.get_vports()
171 self._uplink_vports = vports[::2]
172 self._downlink_vports = vports[1::2]
174 uplink_endpoints = [port + '/protocols/static'
175 for port in self._uplink_vports]
176 downlink_endpoints = [port + '/protocols/static'
177 for port in self._downlink_vports]
179 self.client.create_ipv4_traffic_model(uplink_endpoints,
183 class IxiaPppoeClientScenario(object):
184 def __init__(self, client, context_cfg, ixia_cfg):
188 self._uplink_vports = None
189 self._downlink_vports = None
191 self._access_topologies = []
192 self._core_topologies = []
194 self._context_cfg = context_cfg
195 self._ixia_cfg = ixia_cfg
197 self.device_groups = []
199 def apply_config(self):
200 vports = self.client.get_vports()
201 self._uplink_vports = vports[::2]
202 self._downlink_vports = vports[1::2]
203 self._fill_ixia_config()
204 self._apply_access_network_config()
205 self._apply_core_network_config()
207 def create_traffic_model(self, traffic_profile):
208 endpoints_id_pairs = self._get_endpoints_src_dst_id_pairs(
209 traffic_profile.full_profile)
210 endpoints_obj_pairs = \
211 self._get_endpoints_src_dst_obj_pairs(endpoints_id_pairs)
212 if endpoints_obj_pairs:
213 uplink_endpoints = endpoints_obj_pairs[::2]
214 downlink_endpoints = endpoints_obj_pairs[1::2]
216 uplink_endpoints = self._access_topologies
217 downlink_endpoints = self._core_topologies
218 self.client.create_ipv4_traffic_model(uplink_endpoints,
221 def run_protocols(self):
222 LOG.info('PPPoE Scenario - Start Protocols')
223 self.client.start_protocols()
224 utils.wait_until_true(
225 lambda: self.client.is_protocols_running(self.protocols),
226 timeout=WAIT_PROTOCOLS_STARTED, sleep=2)
228 def stop_protocols(self):
229 LOG.info('PPPoE Scenario - Stop Protocols')
230 self.client.stop_protocols()
232 def _get_intf_addr(self, intf):
233 """Retrieve interface IP address and mask
235 :param intf: could be the string which represents IP address
236 with mask (e.g 192.168.10.2/24) or a dictionary with the host
237 name and the port (e.g. {'tg__0': 'xe1'})
238 :return: (tuple) pair of ip address and mask
240 if isinstance(intf, six.string_types):
241 ip, mask = tuple(intf.split('/'))
244 node_name, intf_name = next(iter(intf.items()))
245 node = self._context_cfg["nodes"].get(node_name, {})
246 interface = node.get("interfaces", {})[intf_name]
247 ip = interface["local_ip"]
248 mask = interface["netmask"]
249 ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)),
251 return ip, ipaddr.prefixlen
254 def _get_endpoints_src_dst_id_pairs(flows_params):
255 """Get list of flows src/dst port pairs
257 Create list of flows src/dst port pairs based on traffic profile
258 flows data. Each uplink/downlink pair in traffic profile represents
259 specific flows between the pair of ports.
261 Example ('port' key represents port on which flow will be created):
281 Result list: ['xe0', 'xe1', 'xe2', 'xe3']
283 Result list means that the following flows pairs will be created:
284 - uplink 0: port xe0 <-> port xe1
285 - downlink 0: port xe1 <-> port xe0
286 - uplink 1: port xe2 <-> port xe3
287 - downlink 1: port xe3 <-> port xe2
289 :param flows_params: ordered dict of traffic profile flows params
290 :return: (list) list of flows src/dst ports
292 if len(flows_params) % 2:
293 raise RuntimeError('Number of uplink/downlink pairs'
294 ' in traffic profile is not equal')
296 for flow in flows_params:
297 port = flows_params[flow]['ipv4'].get('port')
300 endpoint_pairs.append(port)
301 return endpoint_pairs
303 def _get_endpoints_src_dst_obj_pairs(self, endpoints_id_pairs):
304 """Create list of uplink/downlink device groups pairs
306 Based on traffic profile options, create list of uplink/downlink
307 device groups pairs between which flow groups will be created:
309 1. In case uplink/downlink flows in traffic profile doesn't have
310 specified 'port' key, flows will be created between topologies
311 on corresponding access and core port.
313 Access topology on xe0: topology1
314 Core topology on xe1: topology2
315 Flows will be created between:
316 topology1 -> topology2
317 topology2 -> topology1
319 2. In case uplink/downlink flows in traffic profile have specified
320 'port' key, flows will be created between device groups on this
322 E.g., for the following traffic profile
331 Flows will be created between:
332 Port xe0 (dg1) -> Port xe1 (dg1)
333 Port xe1 (dg1) -> Port xe0 (dg1)
334 Port xe0 (dg2) -> Port xe3 (dg1)
335 Port xe3 (dg3) -> Port xe0 (dg1)
337 :param endpoints_id_pairs: (list) List of uplink/downlink flows ports
339 :return: (list) list of uplink/downlink device groups descriptors pairs
341 pppoe = self._ixia_cfg['pppoe_client']
342 sessions_per_port = pppoe['sessions_per_port']
343 sessions_per_svlan = pppoe['sessions_per_svlan']
344 svlan_count = int(sessions_per_port / sessions_per_svlan)
346 uplink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['src_ip']]
347 downlink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['dst_ip']]
348 uplink_port_topology_map = zip(uplink_ports, self._access_topologies)
349 downlink_port_topology_map = zip(downlink_ports, self._core_topologies)
351 port_to_dev_group_mapping = {}
352 for port, topology in uplink_port_topology_map:
353 topology_dgs = self.client.get_topology_device_groups(topology)
354 port_to_dev_group_mapping[port] = topology_dgs
355 for port, topology in downlink_port_topology_map:
356 topology_dgs = self.client.get_topology_device_groups(topology)
357 port_to_dev_group_mapping[port] = topology_dgs
359 uplink_endpoints = endpoints_id_pairs[::2]
360 downlink_endpoints = endpoints_id_pairs[1::2]
362 uplink_dev_groups = []
363 group_up = [uplink_endpoints[i:i + svlan_count]
364 for i in range(0, len(uplink_endpoints), svlan_count)]
366 for group in group_up:
367 for i, port in enumerate(group):
368 uplink_dev_groups.append(port_to_dev_group_mapping[port][i])
370 downlink_dev_groups = []
371 for port in downlink_endpoints:
372 downlink_dev_groups.append(port_to_dev_group_mapping[port][0])
374 endpoint_obj_pairs = []
375 [endpoint_obj_pairs.extend([up, down])
376 for up, down in zip(uplink_dev_groups, downlink_dev_groups)]
378 return endpoint_obj_pairs
380 def _fill_ixia_config(self):
381 pppoe = self._ixia_cfg["pppoe_client"]
382 ipv4 = self._ixia_cfg["ipv4_client"]
384 _ip = [self._get_intf_addr(intf)[0] for intf in pppoe["ip"]]
385 self._ixia_cfg["pppoe_client"]["ip"] = _ip
387 _ip = [self._get_intf_addr(intf)[0] for intf in ipv4["gateway_ip"]]
388 self._ixia_cfg["ipv4_client"]["gateway_ip"] = _ip
390 addrs = [self._get_intf_addr(intf) for intf in ipv4["ip"]]
391 _ip = [addr[0] for addr in addrs]
392 _prefix = [addr[1] for addr in addrs]
394 self._ixia_cfg["ipv4_client"]["ip"] = _ip
395 self._ixia_cfg["ipv4_client"]["prefix"] = _prefix
397 def _apply_access_network_config(self):
398 pppoe = self._ixia_cfg["pppoe_client"]
399 sessions_per_port = pppoe['sessions_per_port']
400 sessions_per_svlan = pppoe['sessions_per_svlan']
401 svlan_count = int(sessions_per_port / sessions_per_svlan)
403 # add topology per uplink port (access network)
404 for access_tp_id, vport in enumerate(self._uplink_vports):
405 name = 'Topology access {}'.format(access_tp_id)
406 tp = self.client.add_topology(name, vport)
407 self._access_topologies.append(tp)
408 # add device group per svlan
409 for dg_id in range(svlan_count):
410 s_vlan_id = int(pppoe['s_vlan']) + dg_id + access_tp_id * svlan_count
411 s_vlan = ixnet_api.Vlan(vlan_id=s_vlan_id)
412 c_vlan = ixnet_api.Vlan(vlan_id=pppoe['c_vlan'], vlan_id_step=1)
413 name = 'SVLAN {}'.format(s_vlan_id)
414 dg = self.client.add_device_group(tp, name, sessions_per_svlan)
415 self.device_groups.append(dg)
416 # add ethernet layer to device group
417 ethernet = self.client.add_ethernet(dg, 'Ethernet')
418 self.protocols.append(ethernet)
419 self.client.add_vlans(ethernet, [s_vlan, c_vlan])
420 # add ppp over ethernet
421 if 'pap_user' in pppoe:
422 ppp = self.client.add_pppox_client(ethernet, 'pap',
424 pppoe['pap_password'])
426 ppp = self.client.add_pppox_client(ethernet, 'chap',
428 pppoe['chap_password'])
429 self.protocols.append(ppp)
431 def _apply_core_network_config(self):
432 ipv4 = self._ixia_cfg["ipv4_client"]
433 sessions_per_port = ipv4['sessions_per_port']
434 sessions_per_vlan = ipv4['sessions_per_vlan']
435 vlan_count = int(sessions_per_port / sessions_per_vlan)
437 # add topology per downlink port (core network)
438 for core_tp_id, vport in enumerate(self._downlink_vports):
439 name = 'Topology core {}'.format(core_tp_id)
440 tp = self.client.add_topology(name, vport)
441 self._core_topologies.append(tp)
442 # add device group per vlan
443 for dg_id in range(vlan_count):
444 name = 'Core port {}'.format(core_tp_id)
445 dg = self.client.add_device_group(tp, name, sessions_per_vlan)
446 self.device_groups.append(dg)
447 # add ethernet layer to device group
448 ethernet = self.client.add_ethernet(dg, 'Ethernet')
449 self.protocols.append(ethernet)
451 vlan_id = int(ipv4['vlan']) + dg_id + core_tp_id * vlan_count
452 vlan = ixnet_api.Vlan(vlan_id=vlan_id)
453 self.client.add_vlans(ethernet, [vlan])
455 gw_ip = ipv4['gateway_ip'][core_tp_id]
456 # use gw addr to generate ip addr from the same network
457 ip_addr = ipaddress.IPv4Address(gw_ip) + 1
458 ipv4_obj = self.client.add_ipv4(ethernet, name='ipv4',
461 prefix=ipv4['prefix'][core_tp_id],
463 self.protocols.append(ipv4_obj)
465 bgp_peer_obj = self.client.add_bgp(ipv4_obj,
466 dut_ip=ipv4["bgp"]["dut_ip"],
467 local_as=ipv4["bgp"]["as_number"],
468 bgp_type=ipv4["bgp"].get("bgp_type"))
469 self.protocols.append(bgp_peer_obj)
471 def update_tracking_options(self):
474 'tos': {'precedence': 'ipv4Precedence0'},
475 'dscp': {'defaultPHB': 'ipv4DefaultPhb0',
476 'selectorPHB': 'ipv4ClassSelectorPhb0',
477 'assuredPHB': 'ipv4AssuredForwardingPhb0',
478 'expeditedPHB': 'ipv4ExpeditedForwardingPhb0'}
481 prio_trackby_key = 'ipv4Precedence0'
484 priority = list(self._ixia_cfg['priority'])[0]
485 if priority == 'raw':
486 prio_trackby_key = priority_map[priority]
487 elif priority in ['tos', 'dscp']:
488 priority_type = list(self._ixia_cfg['priority'][priority])[0]
489 prio_trackby_key = priority_map[priority][priority_type]
493 tracking_options = ['flowGroup0', 'vlanVlanId0', prio_trackby_key]
494 self.client.set_flow_tracking(tracking_options)
496 def get_tc_rfc2544_options(self):
497 return self._ixia_cfg.get('rfc2544')
499 def _get_stats(self):
500 return self.client.get_pppoe_scenario_statistics()
503 def get_flow_id_data(stats, flow_id, key):
504 result = [float(flow.get(key)) for flow in stats if flow['id'] == flow_id]
505 return sum(result) / len(result)
507 def get_priority_flows_stats(self, samples, duration):
509 priorities = set([flow['IP_Priority'] for flow in samples])
510 for priority in priorities:
512 [int(flow['Tx_Frames']) for flow in samples
513 if flow['IP_Priority'] == priority])
515 [int(flow['Rx_Frames']) for flow in samples
516 if flow['IP_Priority'] == priority])
517 prio_flows_num = len([flow for flow in samples
518 if flow['IP_Priority'] == priority])
519 avg_latency_ns = sum(
520 [int(flow['Store-Forward_Avg_latency_ns']) for flow in samples
521 if flow['IP_Priority'] == priority]) / prio_flows_num
522 min_latency_ns = sum(
523 [int(flow['Store-Forward_Min_latency_ns']) for flow in samples
524 if flow['IP_Priority'] == priority]) / prio_flows_num
525 max_latency_ns = sum(
526 [int(flow['Store-Forward_Max_latency_ns']) for flow in samples
527 if flow['IP_Priority'] == priority]) / prio_flows_num
528 tx_throughput = float(tx_frames) / duration
529 rx_throughput = float(rx_frames) / duration
530 results[priority] = {
531 'in_packets': rx_frames,
532 'out_packets': tx_frames,
533 'RxThroughput': round(rx_throughput, 3),
534 'TxThroughput': round(tx_throughput, 3),
535 'avg_latency_ns': utils.safe_cast(avg_latency_ns, int, 0),
536 'min_latency_ns': utils.safe_cast(min_latency_ns, int, 0),
537 'max_latency_ns': utils.safe_cast(max_latency_ns, int, 0)
541 def generate_samples(self, resource_helper, ports, duration):
543 stats = self._get_stats()
545 ports_stats = stats['port_statistics']
546 flows_stats = stats['flow_statistic']
547 pppoe_subs_per_port = stats['pppox_client_per_port']
549 # Get sorted list of ixia ports names
550 ixia_port_names = sorted([data['port_name'] for data in ports_stats])
552 # Set 'port_id' key for ports stats items
553 for item in ports_stats:
554 port_id = item.pop('port_name').split('-')[-1].strip()
555 item['port_id'] = int(port_id)
557 # Set 'id' key for flows stats items
558 for item in flows_stats:
559 flow_id = item.pop('Flow_Group').split('-')[1].strip()
560 item['id'] = int(flow_id)
562 # Set 'port_id' key for pppoe subs per port stats
563 for item in pppoe_subs_per_port:
564 port_id = item.pop('subs_port').split('-')[-1].strip()
565 item['port_id'] = int(port_id)
567 # Map traffic flows to ports
568 port_flow_map = collections.defaultdict(set)
569 for item in flows_stats:
570 tx_port = item.pop('Tx_Port')
571 tx_port_index = ixia_port_names.index(tx_port)
572 port_flow_map[tx_port_index].update([item['id']])
575 ports_stats = sorted(ports_stats, key=lambda k: k['port_id'])
577 # Get priority flows stats
578 prio_flows_stats = self.get_priority_flows_stats(flows_stats, duration)
579 samples['priority_stats'] = prio_flows_stats
581 # this is not DPDK port num, but this is whatever number we gave
582 # when we selected ports and programmed the profile
583 for port_num in ports:
585 # reverse lookup port name from port_num so the stats dict is descriptive
586 intf = resource_helper.vnfd_helper.find_interface_by_port(port_num)
587 port_name = intf['name']
588 port_id = ports_stats[port_num]['port_id']
590 [port_data for port_data in pppoe_subs_per_port
591 if port_data.get('port_id') == port_id]
594 sum([float(self.get_flow_id_data(
595 flows_stats, flow, 'Store-Forward_Avg_latency_ns'))
596 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
598 sum([float(self.get_flow_id_data(
599 flows_stats, flow, 'Store-Forward_Min_latency_ns'))
600 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
602 sum([float(self.get_flow_id_data(
603 flows_stats, flow, 'Store-Forward_Max_latency_ns'))
604 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
606 samples[port_name] = {
607 'rx_throughput_kps': float(ports_stats[port_num]['Rx_Rate_Kbps']),
608 'tx_throughput_kps': float(ports_stats[port_num]['Tx_Rate_Kbps']),
609 'rx_throughput_mbps': float(ports_stats[port_num]['Rx_Rate_Mbps']),
610 'tx_throughput_mbps': float(ports_stats[port_num]['Tx_Rate_Mbps']),
611 'in_packets': int(ports_stats[port_num]['Valid_Frames_Rx']),
612 'out_packets': int(ports_stats[port_num]['Frames_Tx']),
613 'RxThroughput': float(ports_stats[port_num]['Valid_Frames_Rx']) / duration,
614 'TxThroughput': float(ports_stats[port_num]['Frames_Tx']) / duration,
615 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
616 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
617 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
621 samples[port_name].update(
622 {'sessions_up': int(port_subs_stats[0]['Sessions_Up']),
623 'sessions_down': int(port_subs_stats[0]['Sessions_Down']),
624 'sessions_not_started': int(port_subs_stats[0]['Sessions_Not_Started']),
625 'sessions_total': int(port_subs_stats[0]['Sessions_Total'])}
634 class IxiaRfc2544Helper(Rfc2544ResourceHelper):
637 return self.latency and self.iteration.value > 10
640 class IxiaResourceHelper(ClientResourceHelper):
642 LATENCY_TIME_SLEEP = 120
644 def __init__(self, setup_helper, rfc_helper_type=None):
645 super(IxiaResourceHelper, self).__init__(setup_helper)
646 self.scenario_helper = setup_helper.scenario_helper
648 self._ixia_scenarios = {
649 "IxiaBasic": IxiaBasicScenario,
650 "IxiaL3": IxiaL3Scenario,
651 "IxiaPppoeClient": IxiaPppoeClientScenario,
654 self.client = ixnet_api.IxNextgen()
656 if rfc_helper_type is None:
657 rfc_helper_type = IxiaRfc2544Helper
659 self.rfc_helper = rfc_helper_type(self.scenario_helper)
660 self.uplink_ports = None
661 self.downlink_ports = None
662 self.context_cfg = None
663 self._ix_scenario = None
666 def _connect(self, client=None):
667 self.client.connect(self.vnfd_helper)
670 super(IxiaResourceHelper, self).setup()
671 self._init_ix_scenario()
673 def stop_collect(self):
674 self._ix_scenario.stop_protocols()
675 self._terminated.value = 1
677 def generate_samples(self, ports, duration):
678 return self._ix_scenario.generate_samples(self, ports, duration)
680 def _init_ix_scenario(self):
681 ixia_config = self.scenario_helper.scenario_cfg.get('ixia_config', 'IxiaBasic')
683 if ixia_config in self._ixia_scenarios:
684 scenario_type = self._ixia_scenarios[ixia_config]
686 self._ix_scenario = scenario_type(self.client, self.context_cfg,
687 self.scenario_helper.scenario_cfg['options'])
690 "IXIA config type '{}' not supported".format(ixia_config))
692 def _initialize_client(self, traffic_profile):
693 """Initialize the IXIA IxNetwork client and configure the server"""
694 self.client.clear_config()
695 self.client.assign_ports()
696 self._ix_scenario.apply_config()
697 self._ix_scenario.create_traffic_model(traffic_profile)
699 def update_tracking_options(self):
700 self._ix_scenario.update_tracking_options()
702 def run_traffic(self, traffic_profile):
703 if self._terminated.value:
706 min_tol = self.rfc_helper.tolerance_low
707 max_tol = self.rfc_helper.tolerance_high
708 precision = self.rfc_helper.tolerance_precision
709 resolution = self.rfc_helper.resolution
710 default = "00:00:00:00:00:00"
713 traffic_profile.update_traffic_profile(self)
714 self._initialize_client(traffic_profile)
717 for port_name in self.vnfd_helper.port_pairs.all_ports:
718 intf = self.vnfd_helper.find_interface(name=port_name)
719 virt_intf = intf["virtual-interface"]
720 # we only know static traffic id by reading the json
721 # this is used by _get_ixia_trafficrofile
722 port_num = self.vnfd_helper.port_num(intf)
723 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
724 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
726 self._ix_scenario.run_protocols()
729 while not self._terminated.value:
730 first_run = traffic_profile.execute_traffic(self, self.client,
732 self.client_started.value = 1
733 # pylint: disable=unnecessary-lambda
734 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
735 timeout=traffic_profile.config.duration * 2)
736 rfc2544_opts = self._ix_scenario.get_tc_rfc2544_options()
737 samples = self.generate_samples(traffic_profile.ports,
738 traffic_profile.config.duration)
740 completed, samples = traffic_profile.get_drop_percentage(
741 samples, min_tol, max_tol, precision, resolution,
742 first_run=first_run, tc_rfc2544_opts=rfc2544_opts)
743 self._queue.put(samples)
746 self._terminated.value = 1
748 except Exception: # pylint: disable=broad-except
749 LOG.exception('Run Traffic terminated')
751 self._ix_scenario.stop_protocols()
752 self.client_started.value = 0
753 self._terminated.value = 1
755 def run_test(self, traffic_profile, tasks_queue, results_queue, *args): # pragma: no cover
756 LOG.info("Ixia resource_helper run_test")
757 if self._terminated.value:
760 min_tol = self.rfc_helper.tolerance_low
761 max_tol = self.rfc_helper.tolerance_high
762 precision = self.rfc_helper.tolerance_precision
763 resolution = self.rfc_helper.resolution
764 default = "00:00:00:00:00:00"
767 traffic_profile.update_traffic_profile(self)
768 self._initialize_client(traffic_profile)
771 for port_name in self.vnfd_helper.port_pairs.all_ports:
772 intf = self.vnfd_helper.find_interface(name=port_name)
773 virt_intf = intf["virtual-interface"]
774 # we only know static traffic id by reading the json
775 # this is used by _get_ixia_trafficrofile
776 port_num = self.vnfd_helper.port_num(intf)
777 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
778 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
780 self._ix_scenario.run_protocols()
784 self.rfc_helper.iteration.value = 0
785 self.client_started.value = 1
786 while completed is False and not self._terminated.value:
787 LOG.info("Wait for task ...")
790 task = tasks_queue.get(True, 5)
791 except moves.queue.Empty:
794 if task != 'RUN_TRAFFIC':
797 self.rfc_helper.iteration.value += 1
798 LOG.info("Got %s task, start iteration %d", task,
799 self.rfc_helper.iteration.value)
800 first_run = traffic_profile.execute_traffic(self, self.client,
802 # pylint: disable=unnecessary-lambda
803 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
804 timeout=traffic_profile.config.duration * 2)
805 samples = self.generate_samples(traffic_profile.ports,
806 traffic_profile.config.duration)
808 completed, samples = traffic_profile.get_drop_percentage(
809 samples, min_tol, max_tol, precision, resolution,
811 samples['Iteration'] = self.rfc_helper.iteration.value
812 self._queue.put(samples)
815 LOG.debug("IxiaResourceHelper::run_test - test completed")
816 results_queue.put('COMPLETE')
818 results_queue.put('CONTINUE')
819 tasks_queue.task_done()
821 except Exception: # pylint: disable=broad-except
822 LOG.exception('Run Traffic terminated')
824 self._ix_scenario.stop_protocols()
825 self.client_started.value = 0
826 LOG.debug("IxiaResourceHelper::run_test done")
829 class IxiaTrafficGen(SampleVNFTrafficGen):
833 def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
834 if resource_helper_type is None:
835 resource_helper_type = IxiaResourceHelper
837 super(IxiaTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
838 resource_helper_type)
839 self._ixia_traffic_gen = None
840 self.ixia_file_name = ''
841 self.vnf_port_pairs = []
843 def _check_status(self):
847 self.resource_helper.stop_collect()
848 super(IxiaTrafficGen, self).terminate()