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):
58 vports = self.client.get_vports()
59 self._uplink_vports = vports[::2]
60 self._downlink_vports = vports[1::2]
61 self.client.create_traffic_model(self._uplink_vports,
62 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 'RxThroughputBps': float(stats['Bytes_Rx'][port_num]) / duration,
84 'TxThroughputBps': float(stats['Bytes_Tx'][port_num]) / duration,
85 'InPackets': int(stats['Valid_Frames_Rx'][port_num]),
86 'OutPackets': int(stats['Frames_Tx'][port_num]),
87 'InBytes': int(stats['Bytes_Rx'][port_num]),
88 'OutBytes': int(stats['Bytes_Tx'][port_num]),
89 'RxThroughput': float(stats['Valid_Frames_Rx'][port_num]) / duration,
90 'TxThroughput': float(stats['Frames_Tx'][port_num]) / duration,
91 'LatencyAvg': utils.safe_cast(avg_latency, int, 0),
92 'LatencyMin': utils.safe_cast(min_latency, int, 0),
93 'LatencyMax': 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):
169 vports = self.client.get_vports()
170 self._uplink_vports = vports[::2]
171 self._downlink_vports = vports[1::2]
173 uplink_endpoints = [port + '/protocols/static'
174 for port in self._uplink_vports]
175 downlink_endpoints = [port + '/protocols/static'
176 for port in self._downlink_vports]
178 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,
222 def run_protocols(self):
223 LOG.info('PPPoE Scenario - Start Protocols')
224 self.client.start_protocols()
225 utils.wait_until_true(
226 lambda: self.client.is_protocols_running(self.protocols),
227 timeout=WAIT_PROTOCOLS_STARTED, sleep=2)
229 def stop_protocols(self):
230 LOG.info('PPPoE Scenario - Stop Protocols')
231 self.client.stop_protocols()
233 def _get_intf_addr(self, intf):
234 """Retrieve interface IP address and mask
236 :param intf: could be the string which represents IP address
237 with mask (e.g 192.168.10.2/24) or a dictionary with the host
238 name and the port (e.g. {'tg__0': 'xe1'})
239 :return: (tuple) pair of ip address and mask
241 if isinstance(intf, six.string_types):
242 ip, mask = tuple(intf.split('/'))
245 node_name, intf_name = next(iter(intf.items()))
246 node = self._context_cfg["nodes"].get(node_name, {})
247 interface = node.get("interfaces", {})[intf_name]
248 ip = interface["local_ip"]
249 mask = interface["netmask"]
250 ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)),
252 return ip, ipaddr.prefixlen
255 def _get_endpoints_src_dst_id_pairs(flows_params):
256 """Get list of flows src/dst port pairs
258 Create list of flows src/dst port pairs based on traffic profile
259 flows data. Each uplink/downlink pair in traffic profile represents
260 specific flows between the pair of ports.
262 Example ('port' key represents port on which flow will be created):
282 Result list: ['xe0', 'xe1', 'xe2', 'xe3']
284 Result list means that the following flows pairs will be created:
285 - uplink 0: port xe0 <-> port xe1
286 - downlink 0: port xe1 <-> port xe0
287 - uplink 1: port xe2 <-> port xe3
288 - downlink 1: port xe3 <-> port xe2
290 :param flows_params: ordered dict of traffic profile flows params
291 :return: (list) list of flows src/dst ports
293 if len(flows_params) % 2:
294 raise RuntimeError('Number of uplink/downlink pairs'
295 ' in traffic profile is not equal')
297 for flow in flows_params:
298 port = flows_params[flow]['ipv4'].get('port')
301 endpoint_pairs.append(port)
302 return endpoint_pairs
304 def _get_endpoints_src_dst_obj_pairs(self, endpoints_id_pairs):
305 """Create list of uplink/downlink device groups pairs
307 Based on traffic profile options, create list of uplink/downlink
308 device groups pairs between which flow groups will be created:
310 1. In case uplink/downlink flows in traffic profile doesn't have
311 specified 'port' key, flows will be created between topologies
312 on corresponding access and core port.
314 Access topology on xe0: topology1
315 Core topology on xe1: topology2
316 Flows will be created between:
317 topology1 -> topology2
318 topology2 -> topology1
320 2. In case uplink/downlink flows in traffic profile have specified
321 'port' key, flows will be created between device groups on this
323 E.g., for the following traffic profile
332 Flows will be created between:
333 Port xe0 (dg1) -> Port xe1 (dg1)
334 Port xe1 (dg1) -> Port xe0 (dg1)
335 Port xe0 (dg2) -> Port xe3 (dg1)
336 Port xe3 (dg3) -> Port xe0 (dg1)
338 :param endpoints_id_pairs: (list) List of uplink/downlink flows ports
340 :return: (list) list of uplink/downlink device groups descriptors pairs
342 pppoe = self._ixia_cfg['pppoe_client']
343 sessions_per_port = pppoe['sessions_per_port']
344 sessions_per_svlan = pppoe['sessions_per_svlan']
345 svlan_count = int(sessions_per_port / sessions_per_svlan)
347 uplink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['src_ip']]
348 downlink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['dst_ip']]
349 uplink_port_topology_map = zip(uplink_ports, self._access_topologies)
350 downlink_port_topology_map = zip(downlink_ports, self._core_topologies)
352 port_to_dev_group_mapping = {}
353 for port, topology in uplink_port_topology_map:
354 topology_dgs = self.client.get_topology_device_groups(topology)
355 port_to_dev_group_mapping[port] = topology_dgs
356 for port, topology in downlink_port_topology_map:
357 topology_dgs = self.client.get_topology_device_groups(topology)
358 port_to_dev_group_mapping[port] = topology_dgs
360 uplink_endpoints = endpoints_id_pairs[::2]
361 downlink_endpoints = endpoints_id_pairs[1::2]
363 uplink_dev_groups = []
364 group_up = [uplink_endpoints[i:i + svlan_count]
365 for i in range(0, len(uplink_endpoints), svlan_count)]
367 for group in group_up:
368 for i, port in enumerate(group):
369 uplink_dev_groups.append(port_to_dev_group_mapping[port][i])
371 downlink_dev_groups = []
372 for port in downlink_endpoints:
373 downlink_dev_groups.append(port_to_dev_group_mapping[port][0])
375 endpoint_obj_pairs = []
376 [endpoint_obj_pairs.extend([up, down])
377 for up, down in zip(uplink_dev_groups, downlink_dev_groups)]
379 return endpoint_obj_pairs
381 def _fill_ixia_config(self):
382 pppoe = self._ixia_cfg["pppoe_client"]
383 ipv4 = self._ixia_cfg["ipv4_client"]
385 _ip = [self._get_intf_addr(intf)[0] for intf in pppoe["ip"]]
386 self._ixia_cfg["pppoe_client"]["ip"] = _ip
388 _ip = [self._get_intf_addr(intf)[0] for intf in ipv4["gateway_ip"]]
389 self._ixia_cfg["ipv4_client"]["gateway_ip"] = _ip
391 addrs = [self._get_intf_addr(intf) for intf in ipv4["ip"]]
392 _ip = [addr[0] for addr in addrs]
393 _prefix = [addr[1] for addr in addrs]
395 self._ixia_cfg["ipv4_client"]["ip"] = _ip
396 self._ixia_cfg["ipv4_client"]["prefix"] = _prefix
398 def _apply_access_network_config(self):
399 pppoe = self._ixia_cfg["pppoe_client"]
400 sessions_per_port = pppoe['sessions_per_port']
401 sessions_per_svlan = pppoe['sessions_per_svlan']
402 svlan_count = int(sessions_per_port / sessions_per_svlan)
404 # add topology per uplink port (access network)
405 for access_tp_id, vport in enumerate(self._uplink_vports):
406 name = 'Topology access {}'.format(access_tp_id)
407 tp = self.client.add_topology(name, vport)
408 self._access_topologies.append(tp)
409 # add device group per svlan
410 for dg_id in range(svlan_count):
411 s_vlan_id = int(pppoe['s_vlan']) + dg_id + access_tp_id * svlan_count
412 s_vlan = ixnet_api.Vlan(vlan_id=s_vlan_id)
413 c_vlan = ixnet_api.Vlan(vlan_id=pppoe['c_vlan'], vlan_id_step=1)
414 name = 'SVLAN {}'.format(s_vlan_id)
415 dg = self.client.add_device_group(tp, name, sessions_per_svlan)
416 self.device_groups.append(dg)
417 # add ethernet layer to device group
418 ethernet = self.client.add_ethernet(dg, 'Ethernet')
419 self.protocols.append(ethernet)
420 self.client.add_vlans(ethernet, [s_vlan, c_vlan])
421 # add ppp over ethernet
422 if 'pap_user' in pppoe:
423 ppp = self.client.add_pppox_client(ethernet, 'pap',
425 pppoe['pap_password'])
427 ppp = self.client.add_pppox_client(ethernet, 'chap',
429 pppoe['chap_password'])
430 self.protocols.append(ppp)
432 def _apply_core_network_config(self):
433 ipv4 = self._ixia_cfg["ipv4_client"]
434 sessions_per_port = ipv4['sessions_per_port']
435 sessions_per_vlan = ipv4['sessions_per_vlan']
436 vlan_count = int(sessions_per_port / sessions_per_vlan)
438 # add topology per downlink port (core network)
439 for core_tp_id, vport in enumerate(self._downlink_vports):
440 name = 'Topology core {}'.format(core_tp_id)
441 tp = self.client.add_topology(name, vport)
442 self._core_topologies.append(tp)
443 # add device group per vlan
444 for dg_id in range(vlan_count):
445 name = 'Core port {}'.format(core_tp_id)
446 dg = self.client.add_device_group(tp, name, sessions_per_vlan)
447 self.device_groups.append(dg)
448 # add ethernet layer to device group
449 ethernet = self.client.add_ethernet(dg, 'Ethernet')
450 self.protocols.append(ethernet)
452 vlan_id = int(ipv4['vlan']) + dg_id + core_tp_id * vlan_count
453 vlan = ixnet_api.Vlan(vlan_id=vlan_id)
454 self.client.add_vlans(ethernet, [vlan])
456 gw_ip = ipv4['gateway_ip'][core_tp_id]
457 # use gw addr to generate ip addr from the same network
458 ip_addr = ipaddress.IPv4Address(gw_ip) + 1
459 ipv4_obj = self.client.add_ipv4(ethernet, name='ipv4',
462 prefix=ipv4['prefix'][core_tp_id],
464 self.protocols.append(ipv4_obj)
466 bgp_peer_obj = self.client.add_bgp(ipv4_obj,
467 dut_ip=ipv4["bgp"]["dut_ip"],
468 local_as=ipv4["bgp"]["as_number"],
469 bgp_type=ipv4["bgp"].get("bgp_type"))
470 self.protocols.append(bgp_peer_obj)
472 def update_tracking_options(self):
475 'tos': {'precedence': 'ipv4Precedence0'},
476 'dscp': {'defaultPHB': 'ipv4DefaultPhb0',
477 'selectorPHB': 'ipv4ClassSelectorPhb0',
478 'assuredPHB': 'ipv4AssuredForwardingPhb0',
479 'expeditedPHB': 'ipv4ExpeditedForwardingPhb0'}
482 prio_trackby_key = 'ipv4Precedence0'
485 priority = list(self._ixia_cfg['priority'])[0]
486 if priority == 'raw':
487 prio_trackby_key = priority_map[priority]
488 elif priority in ['tos', 'dscp']:
489 priority_type = list(self._ixia_cfg['priority'][priority])[0]
490 prio_trackby_key = priority_map[priority][priority_type]
494 tracking_options = ['flowGroup0', 'vlanVlanId0', prio_trackby_key]
495 self.client.set_flow_tracking(tracking_options)
497 def get_tc_rfc2544_options(self):
498 return self._ixia_cfg.get('rfc2544')
500 def _get_stats(self):
501 return self.client.get_pppoe_scenario_statistics()
504 def get_flow_id_data(stats, flow_id, key):
505 result = [float(flow.get(key)) for flow in stats if flow['id'] == flow_id]
506 return sum(result) / len(result)
508 def get_priority_flows_stats(self, samples, duration):
510 priorities = set([flow['IP_Priority'] for flow in samples])
511 for priority in priorities:
513 [int(flow['Tx_Frames']) for flow in samples
514 if flow['IP_Priority'] == priority])
516 [int(flow['Rx_Frames']) for flow in samples
517 if flow['IP_Priority'] == priority])
518 prio_flows_num = len([flow for flow in samples
519 if flow['IP_Priority'] == priority])
520 avg_latency_ns = sum(
521 [int(flow['Store-Forward_Avg_latency_ns']) for flow in samples
522 if flow['IP_Priority'] == priority]) / prio_flows_num
523 min_latency_ns = min(
524 [int(flow['Store-Forward_Min_latency_ns']) for flow in samples
525 if flow['IP_Priority'] == priority])
526 max_latency_ns = max(
527 [int(flow['Store-Forward_Max_latency_ns']) for flow in samples
528 if flow['IP_Priority'] == priority])
529 tx_throughput = float(tx_frames) / duration
530 rx_throughput = float(rx_frames) / duration
531 results[priority] = {
532 'InPackets': rx_frames,
533 'OutPackets': tx_frames,
534 'RxThroughput': round(rx_throughput, 3),
535 'TxThroughput': round(tx_throughput, 3),
536 'LatencyAvg': utils.safe_cast(avg_latency_ns, int, 0),
537 'LatencyMin': utils.safe_cast(min_latency_ns, int, 0),
538 'LatencyMax': utils.safe_cast(max_latency_ns, int, 0)
542 def generate_samples(self, resource_helper, ports, duration):
544 stats = self._get_stats()
546 ports_stats = stats['port_statistics']
547 flows_stats = stats['flow_statistic']
548 pppoe_subs_per_port = stats['pppox_client_per_port']
550 # Get sorted list of ixia ports names
551 ixia_port_names = sorted([data['port_name'] for data in ports_stats])
553 # Set 'port_id' key for ports stats items
554 for item in ports_stats:
555 port_id = item.pop('port_name').split('-')[-1].strip()
556 item['port_id'] = int(port_id)
558 # Set 'id' key for flows stats items
559 for item in flows_stats:
560 flow_id = item.pop('Flow_Group').split('-')[1].strip()
561 item['id'] = int(flow_id)
563 # Set 'port_id' key for pppoe subs per port stats
564 for item in pppoe_subs_per_port:
565 port_id = item.pop('subs_port').split('-')[-1].strip()
566 item['port_id'] = int(port_id)
568 # Map traffic flows to ports
569 port_flow_map = collections.defaultdict(set)
570 for item in flows_stats:
571 tx_port = item.pop('Tx_Port')
572 tx_port_index = ixia_port_names.index(tx_port)
573 port_flow_map[tx_port_index].update([item['id']])
576 ports_stats = sorted(ports_stats, key=lambda k: k['port_id'])
578 # Get priority flows stats
579 prio_flows_stats = self.get_priority_flows_stats(flows_stats, duration)
580 samples['priority_stats'] = prio_flows_stats
582 # this is not DPDK port num, but this is whatever number we gave
583 # when we selected ports and programmed the profile
584 for port_num in ports:
586 # reverse lookup port name from port_num so the stats dict is descriptive
587 intf = resource_helper.vnfd_helper.find_interface_by_port(port_num)
588 port_name = intf['name']
589 port_id = ports_stats[port_num]['port_id']
591 [port_data for port_data in pppoe_subs_per_port
592 if port_data.get('port_id') == port_id]
595 sum([float(self.get_flow_id_data(
596 flows_stats, flow, 'Store-Forward_Avg_latency_ns'))
597 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
599 min([float(self.get_flow_id_data(
600 flows_stats, flow, 'Store-Forward_Min_latency_ns'))
601 for flow in port_flow_map[port_num]])
603 max([float(self.get_flow_id_data(
604 flows_stats, flow, 'Store-Forward_Max_latency_ns'))
605 for flow in port_flow_map[port_num]])
607 samples[port_name] = {
608 'RxThroughputBps': float(ports_stats[port_num]['Bytes_Rx']) / duration,
609 'TxThroughputBps': float(ports_stats[port_num]['Bytes_Tx']) / duration,
610 'InPackets': int(ports_stats[port_num]['Valid_Frames_Rx']),
611 'OutPackets': int(ports_stats[port_num]['Frames_Tx']),
612 'InBytes': int(ports_stats[port_num]['Bytes_Rx']),
613 'OutBytes': int(ports_stats[port_num]['Bytes_Tx']),
614 'RxThroughput': float(ports_stats[port_num]['Valid_Frames_Rx']) / duration,
615 'TxThroughput': float(ports_stats[port_num]['Frames_Tx']) / duration,
616 'LatencyAvg': utils.safe_cast(avg_latency, int, 0),
617 'LatencyMin': utils.safe_cast(min_latency, int, 0),
618 'LatencyMax': utils.safe_cast(max_latency, int, 0)
622 samples[port_name].update(
623 {'SessionsUp': int(port_subs_stats[0]['Sessions_Up']),
624 'SessionsDown': int(port_subs_stats[0]['Sessions_Down']),
625 'SessionsNotStarted': int(port_subs_stats[0]['Sessions_Not_Started']),
626 'SessionsTotal': int(port_subs_stats[0]['Sessions_Total'])}
635 class IxiaRfc2544Helper(Rfc2544ResourceHelper):
638 return self.latency and self.iteration.value > 10
641 class IxiaResourceHelper(ClientResourceHelper):
643 LATENCY_TIME_SLEEP = 120
645 def __init__(self, setup_helper, rfc_helper_type=None):
646 super(IxiaResourceHelper, self).__init__(setup_helper)
647 self.scenario_helper = setup_helper.scenario_helper
649 self._ixia_scenarios = {
650 "IxiaBasic": IxiaBasicScenario,
651 "IxiaL3": IxiaL3Scenario,
652 "IxiaPppoeClient": IxiaPppoeClientScenario,
655 self.client = ixnet_api.IxNextgen()
657 if rfc_helper_type is None:
658 rfc_helper_type = IxiaRfc2544Helper
660 self.rfc_helper = rfc_helper_type(self.scenario_helper)
661 self.uplink_ports = None
662 self.downlink_ports = None
663 self.context_cfg = None
664 self._ix_scenario = None
667 def _connect(self, client=None):
668 self.client.connect(self.vnfd_helper)
671 super(IxiaResourceHelper, self).setup()
672 self._init_ix_scenario()
674 def stop_collect(self):
675 self._ix_scenario.stop_protocols()
676 self._terminated.value = 1
678 def generate_samples(self, ports, duration):
679 return self._ix_scenario.generate_samples(self, ports, duration)
681 def _init_ix_scenario(self):
682 ixia_config = self.scenario_helper.scenario_cfg.get('ixia_config', 'IxiaBasic')
684 if ixia_config in self._ixia_scenarios:
685 scenario_type = self._ixia_scenarios[ixia_config]
687 self._ix_scenario = scenario_type(self.client, self.context_cfg,
688 self.scenario_helper.scenario_cfg['options'])
691 "IXIA config type '{}' not supported".format(ixia_config))
693 def _initialize_client(self, traffic_profile):
694 """Initialize the IXIA IxNetwork client and configure the server"""
695 self.client.clear_config()
696 self.client.assign_ports()
697 self._ix_scenario.apply_config()
698 self._ix_scenario.create_traffic_model(traffic_profile)
700 def update_tracking_options(self):
701 self._ix_scenario.update_tracking_options()
703 def run_traffic(self, traffic_profile):
704 if self._terminated.value:
707 min_tol = self.rfc_helper.tolerance_low
708 max_tol = self.rfc_helper.tolerance_high
709 precision = self.rfc_helper.tolerance_precision
710 resolution = self.rfc_helper.resolution
711 default = "00:00:00:00:00:00"
714 traffic_profile.update_traffic_profile(self)
715 self._initialize_client(traffic_profile)
718 for port_name in self.vnfd_helper.port_pairs.all_ports:
719 intf = self.vnfd_helper.find_interface(name=port_name)
720 virt_intf = intf["virtual-interface"]
721 # we only know static traffic id by reading the json
722 # this is used by _get_ixia_trafficrofile
723 port_num = self.vnfd_helper.port_num(intf)
724 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
725 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
727 self._ix_scenario.run_protocols()
730 while not self._terminated.value:
731 first_run = traffic_profile.execute_traffic(self, self.client,
733 self.client_started.value = 1
734 # pylint: disable=unnecessary-lambda
735 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
736 timeout=traffic_profile.config.duration * 2)
737 rfc2544_opts = self._ix_scenario.get_tc_rfc2544_options()
738 samples = self.generate_samples(traffic_profile.ports,
739 traffic_profile.config.duration)
741 completed, samples = traffic_profile.get_drop_percentage(
742 samples, min_tol, max_tol, precision, resolution,
743 first_run=first_run, tc_rfc2544_opts=rfc2544_opts)
744 self._queue.put(samples)
747 self._terminated.value = 1
749 except Exception: # pylint: disable=broad-except
750 LOG.exception('Run Traffic terminated')
752 self._ix_scenario.stop_protocols()
753 self.client_started.value = 0
754 self._terminated.value = 1
756 def run_test(self, traffic_profile, tasks_queue, results_queue, *args): # pragma: no cover
757 LOG.info("Ixia resource_helper run_test")
758 if self._terminated.value:
761 min_tol = self.rfc_helper.tolerance_low
762 max_tol = self.rfc_helper.tolerance_high
763 precision = self.rfc_helper.tolerance_precision
764 resolution = self.rfc_helper.resolution
765 default = "00:00:00:00:00:00"
768 traffic_profile.update_traffic_profile(self)
769 self._initialize_client(traffic_profile)
772 for port_name in self.vnfd_helper.port_pairs.all_ports:
773 intf = self.vnfd_helper.find_interface(name=port_name)
774 virt_intf = intf["virtual-interface"]
775 # we only know static traffic id by reading the json
776 # this is used by _get_ixia_trafficrofile
777 port_num = self.vnfd_helper.port_num(intf)
778 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
779 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
781 self._ix_scenario.run_protocols()
785 self.rfc_helper.iteration.value = 0
786 self.client_started.value = 1
787 while completed is False and not self._terminated.value:
788 LOG.info("Wait for task ...")
791 task = tasks_queue.get(True, 5)
792 except moves.queue.Empty:
795 if task != 'RUN_TRAFFIC':
798 self.rfc_helper.iteration.value += 1
799 LOG.info("Got %s task, start iteration %d", task,
800 self.rfc_helper.iteration.value)
801 first_run = traffic_profile.execute_traffic(self, self.client,
803 # pylint: disable=unnecessary-lambda
804 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
805 timeout=traffic_profile.config.duration * 2)
806 samples = self.generate_samples(traffic_profile.ports,
807 traffic_profile.config.duration)
809 completed, samples = traffic_profile.get_drop_percentage(
810 samples, min_tol, max_tol, precision, resolution,
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()