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 '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 'RxThroughputBps': float(stats['Bytes_Rx'][port_num]) / duration,
88 'TxThroughputBps': float(stats['Bytes_Tx'][port_num]) / duration,
89 'in_packets': int(stats['Valid_Frames_Rx'][port_num]),
90 'out_packets': int(stats['Frames_Tx'][port_num]),
91 'in_bytes': int(stats['Bytes_Rx'][port_num]),
92 'out_bytes': int(stats['Bytes_Tx'][port_num]),
93 'RxThroughput': float(stats['Valid_Frames_Rx'][port_num]) / duration,
94 'TxThroughput': float(stats['Frames_Tx'][port_num]) / duration,
95 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
96 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
97 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
104 def update_tracking_options(self):
107 def get_tc_rfc2544_options(self):
111 class IxiaL3Scenario(IxiaBasicScenario):
112 """Ixia scenario for L3 flow between static ip's"""
114 def _add_static_ips(self):
115 vports = self.client.get_vports()
116 uplink_intf_vport = [(self.client.get_static_interface(vport), vport)
117 for vport in vports[::2]]
118 downlink_intf_vport = [(self.client.get_static_interface(vport), vport)
119 for vport in vports[1::2]]
121 for index in range(len(uplink_intf_vport)):
122 intf, vport = uplink_intf_vport[index]
124 iprange = self.ixia_cfg['flow'].get('src_ip')[index]
125 start_ip = utils.get_ip_range_start(iprange)
126 count = utils.get_ip_range_count(iprange)
127 self.client.add_static_ipv4(intf, vport, start_ip, count, '32')
129 raise exceptions.IncorrectFlowOption(
130 option="src_ip", link="uplink_{}".format(index))
132 intf, vport = downlink_intf_vport[index]
134 iprange = self.ixia_cfg['flow'].get('dst_ip')[index]
135 start_ip = utils.get_ip_range_start(iprange)
136 count = utils.get_ip_range_count(iprange)
137 self.client.add_static_ipv4(intf, vport, start_ip, count, '32')
139 raise exceptions.IncorrectFlowOption(
140 option="dst_ip", link="downlink_{}".format(index))
142 def _add_interfaces(self):
143 vports = self.client.get_vports()
144 uplink_vports = (vport for vport in vports[::2])
145 downlink_vports = (vport for vport in vports[1::2])
147 ix_node = next(node for _, node in self.context_cfg['nodes'].items()
148 if node['role'] == 'IxNet')
150 for intf in ix_node['interfaces'].values():
151 ip = intf.get('local_ip')
152 mac = intf.get('local_mac')
155 gateway = next(route.get('gateway')
156 for route in ix_node.get('routing_table')
157 if route.get('if') == intf.get('ifname'))
158 except StopIteration:
159 LOG.debug("Gateway not provided")
161 if 'uplink' in intf.get('vld_id'):
162 self.client.add_interface(next(uplink_vports),
165 self.client.add_interface(next(downlink_vports),
168 def apply_config(self):
169 self._add_interfaces()
170 self._add_static_ips()
172 def create_traffic_model(self, traffic_profile):
173 vports = self.client.get_vports()
174 self._uplink_vports = vports[::2]
175 self._downlink_vports = vports[1::2]
177 uplink_endpoints = [port + '/protocols/static'
178 for port in self._uplink_vports]
179 downlink_endpoints = [port + '/protocols/static'
180 for port in self._downlink_vports]
182 self.client.create_ipv4_traffic_model(uplink_endpoints,
187 class IxiaPppoeClientScenario(object):
188 def __init__(self, client, context_cfg, ixia_cfg):
192 self._uplink_vports = None
193 self._downlink_vports = None
195 self._access_topologies = []
196 self._core_topologies = []
198 self._context_cfg = context_cfg
199 self._ixia_cfg = ixia_cfg
201 self.device_groups = []
203 def apply_config(self):
204 vports = self.client.get_vports()
205 self._uplink_vports = vports[::2]
206 self._downlink_vports = vports[1::2]
207 self._fill_ixia_config()
208 self._apply_access_network_config()
209 self._apply_core_network_config()
211 def create_traffic_model(self, traffic_profile):
212 endpoints_id_pairs = self._get_endpoints_src_dst_id_pairs(
213 traffic_profile.full_profile)
214 endpoints_obj_pairs = \
215 self._get_endpoints_src_dst_obj_pairs(endpoints_id_pairs)
216 if endpoints_obj_pairs:
217 uplink_endpoints = endpoints_obj_pairs[::2]
218 downlink_endpoints = endpoints_obj_pairs[1::2]
220 uplink_endpoints = self._access_topologies
221 downlink_endpoints = self._core_topologies
222 self.client.create_ipv4_traffic_model(uplink_endpoints,
226 def run_protocols(self):
227 LOG.info('PPPoE Scenario - Start Protocols')
228 self.client.start_protocols()
229 utils.wait_until_true(
230 lambda: self.client.is_protocols_running(self.protocols),
231 timeout=WAIT_PROTOCOLS_STARTED, sleep=2)
233 def stop_protocols(self):
234 LOG.info('PPPoE Scenario - Stop Protocols')
235 self.client.stop_protocols()
237 def _get_intf_addr(self, intf):
238 """Retrieve interface IP address and mask
240 :param intf: could be the string which represents IP address
241 with mask (e.g 192.168.10.2/24) or a dictionary with the host
242 name and the port (e.g. {'tg__0': 'xe1'})
243 :return: (tuple) pair of ip address and mask
245 if isinstance(intf, six.string_types):
246 ip, mask = tuple(intf.split('/'))
249 node_name, intf_name = next(iter(intf.items()))
250 node = self._context_cfg["nodes"].get(node_name, {})
251 interface = node.get("interfaces", {})[intf_name]
252 ip = interface["local_ip"]
253 mask = interface["netmask"]
254 ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)),
256 return ip, ipaddr.prefixlen
259 def _get_endpoints_src_dst_id_pairs(flows_params):
260 """Get list of flows src/dst port pairs
262 Create list of flows src/dst port pairs based on traffic profile
263 flows data. Each uplink/downlink pair in traffic profile represents
264 specific flows between the pair of ports.
266 Example ('port' key represents port on which flow will be created):
286 Result list: ['xe0', 'xe1', 'xe2', 'xe3']
288 Result list means that the following flows pairs will be created:
289 - uplink 0: port xe0 <-> port xe1
290 - downlink 0: port xe1 <-> port xe0
291 - uplink 1: port xe2 <-> port xe3
292 - downlink 1: port xe3 <-> port xe2
294 :param flows_params: ordered dict of traffic profile flows params
295 :return: (list) list of flows src/dst ports
297 if len(flows_params) % 2:
298 raise RuntimeError('Number of uplink/downlink pairs'
299 ' in traffic profile is not equal')
301 for flow in flows_params:
302 port = flows_params[flow]['ipv4'].get('port')
305 endpoint_pairs.append(port)
306 return endpoint_pairs
308 def _get_endpoints_src_dst_obj_pairs(self, endpoints_id_pairs):
309 """Create list of uplink/downlink device groups pairs
311 Based on traffic profile options, create list of uplink/downlink
312 device groups pairs between which flow groups will be created:
314 1. In case uplink/downlink flows in traffic profile doesn't have
315 specified 'port' key, flows will be created between topologies
316 on corresponding access and core port.
318 Access topology on xe0: topology1
319 Core topology on xe1: topology2
320 Flows will be created between:
321 topology1 -> topology2
322 topology2 -> topology1
324 2. In case uplink/downlink flows in traffic profile have specified
325 'port' key, flows will be created between device groups on this
327 E.g., for the following traffic profile
336 Flows will be created between:
337 Port xe0 (dg1) -> Port xe1 (dg1)
338 Port xe1 (dg1) -> Port xe0 (dg1)
339 Port xe0 (dg2) -> Port xe3 (dg1)
340 Port xe3 (dg3) -> Port xe0 (dg1)
342 :param endpoints_id_pairs: (list) List of uplink/downlink flows ports
344 :return: (list) list of uplink/downlink device groups descriptors pairs
346 pppoe = self._ixia_cfg['pppoe_client']
347 sessions_per_port = pppoe['sessions_per_port']
348 sessions_per_svlan = pppoe['sessions_per_svlan']
349 svlan_count = int(sessions_per_port / sessions_per_svlan)
351 uplink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['src_ip']]
352 downlink_ports = [p['tg__0'] for p in self._ixia_cfg['flow']['dst_ip']]
353 uplink_port_topology_map = zip(uplink_ports, self._access_topologies)
354 downlink_port_topology_map = zip(downlink_ports, self._core_topologies)
356 port_to_dev_group_mapping = {}
357 for port, topology in uplink_port_topology_map:
358 topology_dgs = self.client.get_topology_device_groups(topology)
359 port_to_dev_group_mapping[port] = topology_dgs
360 for port, topology in downlink_port_topology_map:
361 topology_dgs = self.client.get_topology_device_groups(topology)
362 port_to_dev_group_mapping[port] = topology_dgs
364 uplink_endpoints = endpoints_id_pairs[::2]
365 downlink_endpoints = endpoints_id_pairs[1::2]
367 uplink_dev_groups = []
368 group_up = [uplink_endpoints[i:i + svlan_count]
369 for i in range(0, len(uplink_endpoints), svlan_count)]
371 for group in group_up:
372 for i, port in enumerate(group):
373 uplink_dev_groups.append(port_to_dev_group_mapping[port][i])
375 downlink_dev_groups = []
376 for port in downlink_endpoints:
377 downlink_dev_groups.append(port_to_dev_group_mapping[port][0])
379 endpoint_obj_pairs = []
380 [endpoint_obj_pairs.extend([up, down])
381 for up, down in zip(uplink_dev_groups, downlink_dev_groups)]
383 return endpoint_obj_pairs
385 def _fill_ixia_config(self):
386 pppoe = self._ixia_cfg["pppoe_client"]
387 ipv4 = self._ixia_cfg["ipv4_client"]
389 _ip = [self._get_intf_addr(intf)[0] for intf in pppoe["ip"]]
390 self._ixia_cfg["pppoe_client"]["ip"] = _ip
392 _ip = [self._get_intf_addr(intf)[0] for intf in ipv4["gateway_ip"]]
393 self._ixia_cfg["ipv4_client"]["gateway_ip"] = _ip
395 addrs = [self._get_intf_addr(intf) for intf in ipv4["ip"]]
396 _ip = [addr[0] for addr in addrs]
397 _prefix = [addr[1] for addr in addrs]
399 self._ixia_cfg["ipv4_client"]["ip"] = _ip
400 self._ixia_cfg["ipv4_client"]["prefix"] = _prefix
402 def _apply_access_network_config(self):
403 pppoe = self._ixia_cfg["pppoe_client"]
404 sessions_per_port = pppoe['sessions_per_port']
405 sessions_per_svlan = pppoe['sessions_per_svlan']
406 svlan_count = int(sessions_per_port / sessions_per_svlan)
408 # add topology per uplink port (access network)
409 for access_tp_id, vport in enumerate(self._uplink_vports):
410 name = 'Topology access {}'.format(access_tp_id)
411 tp = self.client.add_topology(name, vport)
412 self._access_topologies.append(tp)
413 # add device group per svlan
414 for dg_id in range(svlan_count):
415 s_vlan_id = int(pppoe['s_vlan']) + dg_id + access_tp_id * svlan_count
416 s_vlan = ixnet_api.Vlan(vlan_id=s_vlan_id)
417 c_vlan = ixnet_api.Vlan(vlan_id=pppoe['c_vlan'], vlan_id_step=1)
418 name = 'SVLAN {}'.format(s_vlan_id)
419 dg = self.client.add_device_group(tp, name, sessions_per_svlan)
420 self.device_groups.append(dg)
421 # add ethernet layer to device group
422 ethernet = self.client.add_ethernet(dg, 'Ethernet')
423 self.protocols.append(ethernet)
424 self.client.add_vlans(ethernet, [s_vlan, c_vlan])
425 # add ppp over ethernet
426 if 'pap_user' in pppoe:
427 ppp = self.client.add_pppox_client(ethernet, 'pap',
429 pppoe['pap_password'])
431 ppp = self.client.add_pppox_client(ethernet, 'chap',
433 pppoe['chap_password'])
434 self.protocols.append(ppp)
436 def _apply_core_network_config(self):
437 ipv4 = self._ixia_cfg["ipv4_client"]
438 sessions_per_port = ipv4['sessions_per_port']
439 sessions_per_vlan = ipv4['sessions_per_vlan']
440 vlan_count = int(sessions_per_port / sessions_per_vlan)
442 # add topology per downlink port (core network)
443 for core_tp_id, vport in enumerate(self._downlink_vports):
444 name = 'Topology core {}'.format(core_tp_id)
445 tp = self.client.add_topology(name, vport)
446 self._core_topologies.append(tp)
447 # add device group per vlan
448 for dg_id in range(vlan_count):
449 name = 'Core port {}'.format(core_tp_id)
450 dg = self.client.add_device_group(tp, name, sessions_per_vlan)
451 self.device_groups.append(dg)
452 # add ethernet layer to device group
453 ethernet = self.client.add_ethernet(dg, 'Ethernet')
454 self.protocols.append(ethernet)
456 vlan_id = int(ipv4['vlan']) + dg_id + core_tp_id * vlan_count
457 vlan = ixnet_api.Vlan(vlan_id=vlan_id)
458 self.client.add_vlans(ethernet, [vlan])
460 gw_ip = ipv4['gateway_ip'][core_tp_id]
461 # use gw addr to generate ip addr from the same network
462 ip_addr = ipaddress.IPv4Address(gw_ip) + 1
463 ipv4_obj = self.client.add_ipv4(ethernet, name='ipv4',
466 prefix=ipv4['prefix'][core_tp_id],
468 self.protocols.append(ipv4_obj)
470 bgp_peer_obj = self.client.add_bgp(ipv4_obj,
471 dut_ip=ipv4["bgp"]["dut_ip"],
472 local_as=ipv4["bgp"]["as_number"],
473 bgp_type=ipv4["bgp"].get("bgp_type"))
474 self.protocols.append(bgp_peer_obj)
476 def update_tracking_options(self):
479 'tos': {'precedence': 'ipv4Precedence0'},
480 'dscp': {'defaultPHB': 'ipv4DefaultPhb0',
481 'selectorPHB': 'ipv4ClassSelectorPhb0',
482 'assuredPHB': 'ipv4AssuredForwardingPhb0',
483 'expeditedPHB': 'ipv4ExpeditedForwardingPhb0'}
486 prio_trackby_key = 'ipv4Precedence0'
489 priority = list(self._ixia_cfg['priority'])[0]
490 if priority == 'raw':
491 prio_trackby_key = priority_map[priority]
492 elif priority in ['tos', 'dscp']:
493 priority_type = list(self._ixia_cfg['priority'][priority])[0]
494 prio_trackby_key = priority_map[priority][priority_type]
498 tracking_options = ['flowGroup0', 'vlanVlanId0', prio_trackby_key]
499 self.client.set_flow_tracking(tracking_options)
501 def get_tc_rfc2544_options(self):
502 return self._ixia_cfg.get('rfc2544')
504 def _get_stats(self):
505 return self.client.get_pppoe_scenario_statistics()
508 def get_flow_id_data(stats, flow_id, key):
509 result = [float(flow.get(key)) for flow in stats if flow['id'] == flow_id]
510 return sum(result) / len(result)
512 def get_priority_flows_stats(self, samples, duration):
514 priorities = set([flow['IP_Priority'] for flow in samples])
515 for priority in priorities:
517 [int(flow['Tx_Frames']) for flow in samples
518 if flow['IP_Priority'] == priority])
520 [int(flow['Rx_Frames']) for flow in samples
521 if flow['IP_Priority'] == priority])
522 prio_flows_num = len([flow for flow in samples
523 if flow['IP_Priority'] == priority])
524 avg_latency_ns = sum(
525 [int(flow['Store-Forward_Avg_latency_ns']) for flow in samples
526 if flow['IP_Priority'] == priority]) / prio_flows_num
527 min_latency_ns = sum(
528 [int(flow['Store-Forward_Min_latency_ns']) for flow in samples
529 if flow['IP_Priority'] == priority]) / prio_flows_num
530 max_latency_ns = sum(
531 [int(flow['Store-Forward_Max_latency_ns']) for flow in samples
532 if flow['IP_Priority'] == priority]) / prio_flows_num
533 tx_throughput = float(tx_frames) / duration
534 rx_throughput = float(rx_frames) / duration
535 results[priority] = {
536 'in_packets': rx_frames,
537 'out_packets': tx_frames,
538 'RxThroughput': round(rx_throughput, 3),
539 'TxThroughput': round(tx_throughput, 3),
540 'avg_latency_ns': utils.safe_cast(avg_latency_ns, int, 0),
541 'min_latency_ns': utils.safe_cast(min_latency_ns, int, 0),
542 'max_latency_ns': utils.safe_cast(max_latency_ns, int, 0)
546 def generate_samples(self, resource_helper, ports, duration):
548 stats = self._get_stats()
550 ports_stats = stats['port_statistics']
551 flows_stats = stats['flow_statistic']
552 pppoe_subs_per_port = stats['pppox_client_per_port']
554 # Get sorted list of ixia ports names
555 ixia_port_names = sorted([data['port_name'] for data in ports_stats])
557 # Set 'port_id' key for ports stats items
558 for item in ports_stats:
559 port_id = item.pop('port_name').split('-')[-1].strip()
560 item['port_id'] = int(port_id)
562 # Set 'id' key for flows stats items
563 for item in flows_stats:
564 flow_id = item.pop('Flow_Group').split('-')[1].strip()
565 item['id'] = int(flow_id)
567 # Set 'port_id' key for pppoe subs per port stats
568 for item in pppoe_subs_per_port:
569 port_id = item.pop('subs_port').split('-')[-1].strip()
570 item['port_id'] = int(port_id)
572 # Map traffic flows to ports
573 port_flow_map = collections.defaultdict(set)
574 for item in flows_stats:
575 tx_port = item.pop('Tx_Port')
576 tx_port_index = ixia_port_names.index(tx_port)
577 port_flow_map[tx_port_index].update([item['id']])
580 ports_stats = sorted(ports_stats, key=lambda k: k['port_id'])
582 # Get priority flows stats
583 prio_flows_stats = self.get_priority_flows_stats(flows_stats, duration)
584 samples['priority_stats'] = prio_flows_stats
586 # this is not DPDK port num, but this is whatever number we gave
587 # when we selected ports and programmed the profile
588 for port_num in ports:
590 # reverse lookup port name from port_num so the stats dict is descriptive
591 intf = resource_helper.vnfd_helper.find_interface_by_port(port_num)
592 port_name = intf['name']
593 port_id = ports_stats[port_num]['port_id']
595 [port_data for port_data in pppoe_subs_per_port
596 if port_data.get('port_id') == port_id]
599 sum([float(self.get_flow_id_data(
600 flows_stats, flow, 'Store-Forward_Avg_latency_ns'))
601 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
603 sum([float(self.get_flow_id_data(
604 flows_stats, flow, 'Store-Forward_Min_latency_ns'))
605 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
607 sum([float(self.get_flow_id_data(
608 flows_stats, flow, 'Store-Forward_Max_latency_ns'))
609 for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
611 samples[port_name] = {
612 'rx_throughput_kps': float(ports_stats[port_num]['Rx_Rate_Kbps']),
613 'tx_throughput_kps': float(ports_stats[port_num]['Tx_Rate_Kbps']),
614 'rx_throughput_mbps': float(ports_stats[port_num]['Rx_Rate_Mbps']),
615 'tx_throughput_mbps': float(ports_stats[port_num]['Tx_Rate_Mbps']),
616 'RxThroughputBps': float(ports_stats[port_num]['Bytes_Rx']) / duration,
617 'TxThroughputBps': float(ports_stats[port_num]['Bytes_Tx']) / duration,
618 'in_packets': int(ports_stats[port_num]['Valid_Frames_Rx']),
619 'out_packets': int(ports_stats[port_num]['Frames_Tx']),
620 'in_bytes': int(ports_stats[port_num]['Bytes_Rx']),
621 'out_bytes': int(ports_stats[port_num]['Bytes_Tx']),
622 'RxThroughput': float(ports_stats[port_num]['Valid_Frames_Rx']) / duration,
623 'TxThroughput': float(ports_stats[port_num]['Frames_Tx']) / duration,
624 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
625 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
626 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
630 samples[port_name].update(
631 {'sessions_up': int(port_subs_stats[0]['Sessions_Up']),
632 'sessions_down': int(port_subs_stats[0]['Sessions_Down']),
633 'sessions_not_started': int(port_subs_stats[0]['Sessions_Not_Started']),
634 'sessions_total': int(port_subs_stats[0]['Sessions_Total'])}
643 class IxiaRfc2544Helper(Rfc2544ResourceHelper):
646 return self.latency and self.iteration.value > 10
649 class IxiaResourceHelper(ClientResourceHelper):
651 LATENCY_TIME_SLEEP = 120
653 def __init__(self, setup_helper, rfc_helper_type=None):
654 super(IxiaResourceHelper, self).__init__(setup_helper)
655 self.scenario_helper = setup_helper.scenario_helper
657 self._ixia_scenarios = {
658 "IxiaBasic": IxiaBasicScenario,
659 "IxiaL3": IxiaL3Scenario,
660 "IxiaPppoeClient": IxiaPppoeClientScenario,
663 self.client = ixnet_api.IxNextgen()
665 if rfc_helper_type is None:
666 rfc_helper_type = IxiaRfc2544Helper
668 self.rfc_helper = rfc_helper_type(self.scenario_helper)
669 self.uplink_ports = None
670 self.downlink_ports = None
671 self.context_cfg = None
672 self._ix_scenario = None
675 def _connect(self, client=None):
676 self.client.connect(self.vnfd_helper)
679 super(IxiaResourceHelper, self).setup()
680 self._init_ix_scenario()
682 def stop_collect(self):
683 self._ix_scenario.stop_protocols()
684 self._terminated.value = 1
686 def generate_samples(self, ports, duration):
687 return self._ix_scenario.generate_samples(self, ports, duration)
689 def _init_ix_scenario(self):
690 ixia_config = self.scenario_helper.scenario_cfg.get('ixia_config', 'IxiaBasic')
692 if ixia_config in self._ixia_scenarios:
693 scenario_type = self._ixia_scenarios[ixia_config]
695 self._ix_scenario = scenario_type(self.client, self.context_cfg,
696 self.scenario_helper.scenario_cfg['options'])
699 "IXIA config type '{}' not supported".format(ixia_config))
701 def _initialize_client(self, traffic_profile):
702 """Initialize the IXIA IxNetwork client and configure the server"""
703 self.client.clear_config()
704 self.client.assign_ports()
705 self._ix_scenario.apply_config()
706 self._ix_scenario.create_traffic_model(traffic_profile)
708 def update_tracking_options(self):
709 self._ix_scenario.update_tracking_options()
711 def run_traffic(self, traffic_profile):
712 if self._terminated.value:
715 min_tol = self.rfc_helper.tolerance_low
716 max_tol = self.rfc_helper.tolerance_high
717 precision = self.rfc_helper.tolerance_precision
718 resolution = self.rfc_helper.resolution
719 default = "00:00:00:00:00:00"
722 traffic_profile.update_traffic_profile(self)
723 self._initialize_client(traffic_profile)
726 for port_name in self.vnfd_helper.port_pairs.all_ports:
727 intf = self.vnfd_helper.find_interface(name=port_name)
728 virt_intf = intf["virtual-interface"]
729 # we only know static traffic id by reading the json
730 # this is used by _get_ixia_trafficrofile
731 port_num = self.vnfd_helper.port_num(intf)
732 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
733 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
735 self._ix_scenario.run_protocols()
738 while not self._terminated.value:
739 first_run = traffic_profile.execute_traffic(self, self.client,
741 self.client_started.value = 1
742 # pylint: disable=unnecessary-lambda
743 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
744 timeout=traffic_profile.config.duration * 2)
745 rfc2544_opts = self._ix_scenario.get_tc_rfc2544_options()
746 samples = self.generate_samples(traffic_profile.ports,
747 traffic_profile.config.duration)
749 completed, samples = traffic_profile.get_drop_percentage(
750 samples, min_tol, max_tol, precision, resolution,
751 first_run=first_run, tc_rfc2544_opts=rfc2544_opts)
752 self._queue.put(samples)
755 self._terminated.value = 1
757 except Exception: # pylint: disable=broad-except
758 LOG.exception('Run Traffic terminated')
760 self._ix_scenario.stop_protocols()
761 self.client_started.value = 0
762 self._terminated.value = 1
764 def run_test(self, traffic_profile, tasks_queue, results_queue, *args): # pragma: no cover
765 LOG.info("Ixia resource_helper run_test")
766 if self._terminated.value:
769 min_tol = self.rfc_helper.tolerance_low
770 max_tol = self.rfc_helper.tolerance_high
771 precision = self.rfc_helper.tolerance_precision
772 resolution = self.rfc_helper.resolution
773 default = "00:00:00:00:00:00"
776 traffic_profile.update_traffic_profile(self)
777 self._initialize_client(traffic_profile)
780 for port_name in self.vnfd_helper.port_pairs.all_ports:
781 intf = self.vnfd_helper.find_interface(name=port_name)
782 virt_intf = intf["virtual-interface"]
783 # we only know static traffic id by reading the json
784 # this is used by _get_ixia_trafficrofile
785 port_num = self.vnfd_helper.port_num(intf)
786 mac["src_mac_{}".format(port_num)] = virt_intf.get("local_mac", default)
787 mac["dst_mac_{}".format(port_num)] = virt_intf.get("dst_mac", default)
789 self._ix_scenario.run_protocols()
793 self.rfc_helper.iteration.value = 0
794 self.client_started.value = 1
795 while completed is False and not self._terminated.value:
796 LOG.info("Wait for task ...")
799 task = tasks_queue.get(True, 5)
800 except moves.queue.Empty:
803 if task != 'RUN_TRAFFIC':
806 self.rfc_helper.iteration.value += 1
807 LOG.info("Got %s task, start iteration %d", task,
808 self.rfc_helper.iteration.value)
809 first_run = traffic_profile.execute_traffic(self, self.client,
811 # pylint: disable=unnecessary-lambda
812 utils.wait_until_true(lambda: self.client.is_traffic_stopped(),
813 timeout=traffic_profile.config.duration * 2)
814 samples = self.generate_samples(traffic_profile.ports,
815 traffic_profile.config.duration)
817 completed, samples = traffic_profile.get_drop_percentage(
818 samples, min_tol, max_tol, precision, resolution,
820 self._queue.put(samples)
823 LOG.debug("IxiaResourceHelper::run_test - test completed")
824 results_queue.put('COMPLETE')
826 results_queue.put('CONTINUE')
827 tasks_queue.task_done()
829 except Exception: # pylint: disable=broad-except
830 LOG.exception('Run Traffic terminated')
832 self._ix_scenario.stop_protocols()
833 self.client_started.value = 0
834 LOG.debug("IxiaResourceHelper::run_test done")
837 class IxiaTrafficGen(SampleVNFTrafficGen):
841 def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
842 if resource_helper_type is None:
843 resource_helper_type = IxiaResourceHelper
845 super(IxiaTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
846 resource_helper_type)
847 self._ixia_traffic_gen = None
848 self.ixia_file_name = ''
849 self.vnf_port_pairs = []
851 def _check_status(self):
855 self.resource_helper.stop_collect()
856 super(IxiaTrafficGen, self).terminate()