1 # Copyright (c) 2016-2018 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.
20 from yardstick.common import exceptions
21 from yardstick.common import utils
22 from yardstick.network_services.traffic_profile import base as tp_base
25 log = logging.getLogger(__name__)
30 PROTO_ETHERNET = 'ethernet'
37 SINGLE_VALUE = "singleValue"
42 ETHER_TYPE_802_1ad = '0x88a8'
44 TRAFFIC_STATUS_STARTED = 'started'
45 TRAFFIC_STATUS_STOPPED = 'stopped'
47 PROTOCOL_STATUS_UP = 'up'
48 PROTOCOL_STATUS_DOWN = ['down', 'notStarted']
50 SUPPORTED_PROTO = [PROTO_UDP]
52 SUPPORTED_DSCP_CLASSES = [
55 'assuredForwardingPHB',
56 'expeditedForwardingPHB']
58 SUPPORTED_TOS_FIELDS = [
68 vlan_id, vlan_id_step=None, vlan_id_direction='increment',
69 prio=None, prio_step=None, prio_direction='increment',
71 self.vlan_id = vlan_id
72 self.vlan_id_step = vlan_id_step
73 self.vlan_id_direction = vlan_id_direction
75 self.prio_step = prio_step
76 self.prio_direction = prio_direction
80 # NOTE(ralonsoh): this pragma will be removed in the last patch of this series
81 class IxNextgen(object): # pragma: no cover
83 PORT_STATS_NAME_MAP = {
84 "stat_name": 'Stat Name',
85 "port_name": 'Port Name',
86 "Frames_Tx": 'Frames Tx.',
87 "Valid_Frames_Rx": 'Valid Frames Rx.',
88 "Frames_Tx_Rate": 'Frames Tx. Rate',
89 "Valid_Frames_Rx_Rate": 'Valid Frames Rx. Rate',
90 "Tx_Rate_Kbps": 'Tx. Rate (Kbps)',
91 "Rx_Rate_Kbps": 'Rx. Rate (Kbps)',
92 "Tx_Rate_Mbps": 'Tx. Rate (Mbps)',
93 "Rx_Rate_Mbps": 'Rx. Rate (Mbps)',
97 "Store-Forward_Avg_latency_ns": 'Store-Forward Avg Latency (ns)',
98 "Store-Forward_Min_latency_ns": 'Store-Forward Min Latency (ns)',
99 "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)',
102 PPPOX_CLIENT_PER_PORT_NAME_MAP = {
104 'Sessions_Up': 'Sessions Up',
105 'Sessions_Down': 'Sessions Down',
106 'Sessions_Not_Started': 'Sessions Not Started',
107 'Sessions_Total': 'Sessions Total'
110 PORT_STATISTICS = '::ixNet::OBJ-/statistics/view:"Port Statistics"'
111 FLOW_STATISTICS = '::ixNet::OBJ-/statistics/view:"Flow Statistics"'
112 PPPOX_CLIENT_PER_PORT = '::ixNet::OBJ-/statistics/view:"PPPoX Client Per Port"'
115 def get_config(tg_cfg):
118 external_interface = tg_cfg["vdu"][0]["external-interface"]
119 for intf in external_interface:
120 card_port0 = intf["virtual-interface"]["vpci"]
121 card0, port0 = card_port0.split(':')[:2]
126 'machine': tg_cfg["mgmt-interface"]["ip"],
127 'port': tg_cfg["mgmt-interface"]["tg-config"]["tcl_port"],
128 'chassis': tg_cfg["mgmt-interface"]["tg-config"]["ixchassis"],
131 'output_dir': tg_cfg["mgmt-interface"]["tg-config"]["dut_result_dir"],
132 'version': tg_cfg["mgmt-interface"]["tg-config"]["version"],
138 def __init__(self): # pragma: no cover
145 def ixnet(self): # pragma: no cover
148 raise exceptions.IxNetworkClientNotConnected()
150 def get_vports(self):
151 """Return the list of assigned ports (vport objects)"""
152 vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
155 def _get_config_element_by_flow_group_name(self, flow_group_name):
156 """Get a config element using the flow group name
158 Each named flow group contains one config element (by configuration).
159 According to the documentation, "configElements" is a list and "each
160 item in this list is aligned to the sequential order of your endpoint
163 :param flow_group_name: (str) flow group name; this parameter is
164 always a number (converted to string) starting
166 :return: (str) config element reference ID or None.
168 traffic_item = self.ixnet.getList(self.ixnet.getRoot() + '/traffic',
170 flow_groups = self.ixnet.getList(traffic_item, 'endpointSet')
171 for flow_group in flow_groups:
172 if (str(self.ixnet.getAttribute(flow_group, '-name')) ==
174 return traffic_item + '/configElement:' + flow_group_name
176 def _get_stack_item(self, flow_group_name, protocol_name):
177 """Return the stack item given the flow group name and the proto name
179 :param flow_group_name: (str) flow group name
180 :param protocol_name: (str) protocol name, referred to PROTO_*
182 :return: list of stack item descriptors
184 celement = self._get_config_element_by_flow_group_name(flow_group_name)
186 raise exceptions.IxNetworkFlowNotPresent(
187 flow_group=flow_group_name)
188 stack_items = self.ixnet.getList(celement, 'stack')
189 return [s_i for s_i in stack_items if protocol_name in s_i]
191 def _get_field_in_stack_item(self, stack_item, field_name):
192 """Return the field in a stack item given the name
194 :param stack_item: (str) stack item descriptor
195 :param field_name: (str) field name
196 :return: (str) field descriptor
198 fields = self.ixnet.getList(stack_item, 'field')
199 for field in (field for field in fields if field_name in field):
201 raise exceptions.IxNetworkFieldNotPresentInStackItem(
202 field_name=field_name, stack_item=stack_item)
204 def _get_traffic_state(self):
205 """Get traffic state"""
206 return self.ixnet.getAttribute(self.ixnet.getRoot() + 'traffic',
209 def _get_protocol_status(self, proto):
210 """Get protocol status
212 :param proto: IxNet protocol str representation, e.g.:
213 '::ixNet::OBJ-/topology:2/deviceGroup:1/ethernet:1/ipv4:L14'
214 :return: (list) protocol status: list of sessions protocol
215 statuses which include states 'up', 'down' and 'notStarted'
217 return self.ixnet.getAttribute(proto, '-sessionStatus')
219 def is_traffic_running(self):
220 """Returns true if traffic state == TRAFFIC_STATUS_STARTED"""
221 return self._get_traffic_state() == TRAFFIC_STATUS_STARTED
223 def is_traffic_stopped(self):
224 """Returns true if traffic state == TRAFFIC_STATUS_STOPPED"""
225 return self._get_traffic_state() == TRAFFIC_STATUS_STOPPED
227 def is_protocols_running(self, protocols):
228 """Returns true if all protocols statuses are PROTOCOL_STATUS_UP
230 :param protocols: list of protocols str representations, e.g.:
231 ['::ixNet::OBJ-/topology:2/deviceGroup:1/ethernet:1/ipv4:L14', ...]
232 :return: (bool) True if all protocols status is 'up', False if any
233 protocol status is 'down' or 'notStarted'
235 return all(session_status is PROTOCOL_STATUS_UP for proto in protocols
236 for session_status in self._get_protocol_status(proto))
238 def is_protocols_stopped(self, protocols):
239 """Returns true if all protocols statuses are in PROTOCOL_STATUS_DOWN
241 :param protocols: list of protocols str representations, e.g.:
242 ['::ixNet::OBJ-/topology:2/deviceGroup:1/ethernet:1/ipv4:L14', ...]
243 :return: (bool) True if all protocols status is 'down' or 'notStarted',
244 False if any protocol status is 'up'
246 return all(session_status in PROTOCOL_STATUS_DOWN for proto in protocols
247 for session_status in self._get_protocol_status(proto))
250 def _parse_framesize(framesize):
251 """Parse "framesize" config param. to return a list of weighted pairs
253 :param framesize: dictionary of frame sizes and weights
254 :return: list of paired frame sizes and weights
256 weighted_range_pairs = []
257 for size, weight in ((s, w) for (s, w) in framesize.items()
259 size = int(size.upper().replace('B', ''))
260 weighted_range_pairs.append([size, size, int(weight)])
261 return weighted_range_pairs
263 def iter_over_get_lists(self, x1, x2, y2, offset=0):
264 for x in self.ixnet.getList(x1, x2):
265 y_list = self.ixnet.getList(x, y2)
266 for i, y in enumerate(y_list, offset):
269 def connect(self, tg_cfg):
270 self._cfg = self.get_config(tg_cfg)
271 self._ixnet = IxNetwork.IxNet()
273 machine = self._cfg['machine']
274 port = str(self._cfg['port'])
275 version = str(self._cfg['version'])
276 return self.ixnet.connect(machine, '-port', port,
279 def clear_config(self):
280 """Wipe out any possible configuration present in the client"""
281 self.ixnet.execute('newConfig')
283 def assign_ports(self):
284 """Create and assign vports for each physical port defined in config
286 This configuration is present in the IXIA profile file. E.g.:
291 vpci: "2:15" # Card:port
294 local_ip: "152.16.100.20"
295 netmask: "255.255.0.0"
296 local_mac: "00:98:10:64:14:00"
300 chassis_ip = self._cfg['chassis']
301 ports = [(chassis_ip, card, port) for card, port in
302 zip(self._cfg['cards'], self._cfg['ports'])]
304 log.info('Create and assign vports: %s', ports)
308 vports.append(self.ixnet.add(self.ixnet.getRoot(), 'vport'))
311 self.ixnet.execute('assignPorts', ports, [], vports, True)
315 if self.ixnet.getAttribute(vport, '-state') != 'up':
316 log.warning('Port %s is down', vport)
318 def _create_traffic_item(self, traffic_type='raw'):
319 """Create the traffic item to hold the flow groups
321 The traffic item tracking by "Traffic Item" is enabled to retrieve the
324 log.info('Create the traffic item "RFC2544"')
325 traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic',
327 self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544',
328 '-trafficType', traffic_type)
331 traffic_item_id = self.ixnet.remapIds(traffic_item)[0]
332 self.ixnet.setAttribute(traffic_item_id + '/tracking',
333 '-trackBy', 'trafficGroupId0')
336 def _create_flow_groups(self, uplink, downlink):
337 """Create the flow groups between the endpoints"""
338 traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic',
340 log.info('Create the flow groups')
343 for up, down in zip(uplink, downlink):
344 log.info('FGs: %s <--> %s', up, down)
345 endpoint_set_1 = self.ixnet.add(traffic_item_id, 'endpointSet')
346 endpoint_set_2 = self.ixnet.add(traffic_item_id, 'endpointSet')
347 self.ixnet.setMultiAttribute(
348 endpoint_set_1, '-name', str(index + 1),
350 '-destinations', [down])
351 self.ixnet.setMultiAttribute(
352 endpoint_set_2, '-name', str(index + 2),
354 '-destinations', [up])
358 def _append_procotol_to_stack(self, protocol_name, previous_element):
359 """Append a new element in the packet definition stack"""
360 protocol = (self.ixnet.getRoot() +
361 '/traffic/protocolTemplate:"{}"'.format(protocol_name))
362 self.ixnet.execute('append', previous_element, protocol)
364 def _setup_config_elements(self, add_default_proto=True):
365 """Setup the config elements
367 The traffic item is configured to allow individual configurations per
368 config element. The default frame configuration is applied:
369 Ethernet II: added by default
372 Payload: added by default
373 Ethernet II (Trailer): added by default
376 traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic',
378 log.info('Split the frame rate distribution per config element')
379 config_elements = self.ixnet.getList(traffic_item_id, 'configElement')
380 for config_element in config_elements:
381 self.ixnet.setAttribute(config_element + '/frameRateDistribution',
382 '-portDistribution', 'splitRateEvenly')
383 self.ixnet.setAttribute(config_element + '/frameRateDistribution',
384 '-streamDistribution', 'splitRateEvenly')
386 if add_default_proto:
387 self._append_procotol_to_stack(
388 PROTO_UDP, config_element + '/stack:"ethernet-1"')
389 self._append_procotol_to_stack(
390 PROTO_IPV4, config_element + '/stack:"ethernet-1"')
392 def create_traffic_model(self, uplink_ports, downlink_ports):
393 """Create a traffic item and the needed flow groups
395 Each flow group inside the traffic item (only one is present)
396 represents the traffic between two ports:
398 FlowGroup1: port1 -> port2
399 FlowGroup2: port1 <- port2
400 FlowGroup3: port3 -> port4
401 FlowGroup4: port3 <- port4
403 self._create_traffic_item('raw')
404 uplink_endpoints = [port + '/protocols' for port in uplink_ports]
405 downlink_endpoints = [port + '/protocols' for port in downlink_ports]
406 self._create_flow_groups(uplink_endpoints, downlink_endpoints)
407 self._setup_config_elements()
409 def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies):
410 """Create a traffic item and the needed flow groups
412 Each flow group inside the traffic item (only one is present)
413 represents the traffic between two topologies:
415 FlowGroup1: uplink1 -> downlink1
416 FlowGroup2: uplink1 <- downlink1
417 FlowGroup3: uplink2 -> downlink2
418 FlowGroup4: uplink2 <- downlink2
420 self._create_traffic_item('ipv4')
421 self._create_flow_groups(uplink_topologies, downlink_topologies)
422 self._setup_config_elements(False)
424 def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
425 """Set the MAC address in a config element stack Ethernet field
427 :param ethernet_descriptor: (str) ethernet descriptor, e.g.:
428 /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"
429 :param field: (str) field name, e.g.: destinationAddress
430 :param mac_address: (str) MAC address
432 field_descriptor = self._get_field_in_stack_item(ethernet_descriptor,
434 self.ixnet.setMultiAttribute(field_descriptor,
435 '-singleValue', mac_address,
436 '-fieldValue', mac_address,
437 '-valueType', 'singleValue')
440 def update_frame(self, traffic, duration):
441 """Update the L2 frame
443 This function updates the L2 frame options:
444 - Traffic type: "continuous", "fixedDuration".
445 - Duration: in case of traffic_type="fixedDuration", amount of seconds
447 - Rate: in frames per seconds or percentage.
448 - Type of rate: "framesPerSecond" or "percentLineRate" ("bitsPerSecond"
450 - Frame size: custom IMIX [1] definition; a list of packet size in
451 bytes and the weight. E.g.:
452 [[64, 64, 10], [128, 128, 15], [512, 512, 5]]
454 [1] https://en.wikipedia.org/wiki/Internet_Mix
456 :param traffic: list of traffic elements; each traffic element contains
457 the injection parameter for each flow group.
458 :param duration: (int) injection time in seconds.
460 for traffic_param in traffic.values():
461 fg_id = str(traffic_param['id'])
462 config_element = self._get_config_element_by_flow_group_name(fg_id)
463 if not config_element:
464 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
466 type = traffic_param.get('traffic_type', 'fixedDuration')
468 'framesPerSecond' if traffic_param['rate_unit'] ==
469 tp_base.TrafficProfileConfig.RATE_FPS else 'percentLineRate')
470 weighted_range_pairs = self._parse_framesize(
471 traffic_param['outer_l2'].get('framesize', {}))
472 srcmac = str(traffic_param['outer_l2'].get('srcmac', '00:00:00:00:00:01'))
473 dstmac = str(traffic_param['outer_l2'].get('dstmac', '00:00:00:00:00:02'))
475 if traffic_param['outer_l2'].get('QinQ'):
476 s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN']
477 c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN']
479 field_descriptor = self._get_field_in_stack_item(
480 self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
483 self.ixnet.setMultiAttribute(field_descriptor,
485 '-singleValue', ETHER_TYPE_802_1ad,
486 '-fieldValue', ETHER_TYPE_802_1ad,
487 '-valueType', SINGLE_VALUE)
489 self._append_procotol_to_stack(
490 PROTO_VLAN, config_element + '/stack:"ethernet-1"')
491 self._append_procotol_to_stack(
492 PROTO_VLAN, config_element + '/stack:"ethernet-1"')
494 self._update_vlan_tag(fg_id, s_vlan, S_VLAN)
495 self._update_vlan_tag(fg_id, c_vlan, C_VLAN)
497 self.ixnet.setMultiAttribute(
498 config_element + '/transmissionControl',
499 '-type', type, '-duration', duration)
501 self.ixnet.setMultiAttribute(
502 config_element + '/frameRate',
503 '-rate', traffic_param['rate'], '-type', rate_unit)
505 if len(weighted_range_pairs):
506 self.ixnet.setMultiAttribute(
507 config_element + '/frameSize',
508 '-type', 'weightedPairs',
509 '-weightedRangePairs', weighted_range_pairs)
514 self._update_frame_mac(
515 self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
516 'destinationAddress', dstmac)
518 self._update_frame_mac(
519 self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
520 'sourceAddress', srcmac)
522 def _update_vlan_tag(self, fg_id, params, vlan=0):
523 field_to_param_map = {
524 'vlanUserPriority': 'priority',
528 for field, param in field_to_param_map.items():
529 value = params.get(param)
531 field_descriptor = self._get_field_in_stack_item(
532 self._get_stack_item(fg_id, PROTO_VLAN)[vlan],
535 self.ixnet.setMultiAttribute(field_descriptor,
537 '-singleValue', value,
538 '-fieldValue', value,
539 '-valueType', SINGLE_VALUE)
543 def _update_ipv4_address(self, ip_descriptor, field, ip_address, seed,
545 """Set the IPv4 address in a config element stack IP field
547 :param ip_descriptor: (str) IP descriptor, e.g.:
548 /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"
549 :param field: (str) field name, e.g.: scrIp, dstIp
550 :param ip_address: (str) IP address
551 :param seed: (int) seed length
552 :param mask: (int) IP address mask length
553 :param count: (int) number of random IPs to generate
555 field_descriptor = self._get_field_in_stack_item(ip_descriptor,
557 random_mask = str(ipaddress.IPv4Address(
558 2**(ipaddress.IPV4LENGTH - mask) - 1).compressed)
559 self.ixnet.setMultiAttribute(field_descriptor,
561 '-fixedBits', ip_address,
562 '-randomMask', random_mask,
563 '-valueType', 'random',
564 '-countValue', count)
567 def update_ip_packet(self, traffic):
568 """Update the IP packet
570 NOTE: Only IPv4 is currently supported.
571 :param traffic: list of traffic elements; each traffic element contains
572 the injection parameter for each flow group.
574 # NOTE(ralonsoh): L4 configuration is not set.
575 for traffic_param in traffic.values():
576 fg_id = str(traffic_param['id'])
577 if not self._get_config_element_by_flow_group_name(fg_id):
578 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
580 if traffic_param['outer_l3']:
581 count = traffic_param['outer_l3']['count']
582 srcip = traffic_param['outer_l3']['srcip']
583 dstip = traffic_param['outer_l3']['dstip']
584 srcseed = traffic_param['outer_l3']['srcseed']
585 dstseed = traffic_param['outer_l3']['dstseed']
586 srcmask = traffic_param['outer_l3']['srcmask'] \
587 or ipaddress.IPV4LENGTH
588 dstmask = traffic_param['outer_l3']['dstmask'] \
589 or ipaddress.IPV4LENGTH
590 priority = traffic_param['outer_l3']['priority']
593 self._update_ipv4_address(
594 self._get_stack_item(fg_id, PROTO_IPV4)[0],
595 'srcIp', str(srcip), srcseed, srcmask, count)
597 self._update_ipv4_address(
598 self._get_stack_item(fg_id, PROTO_IPV4)[0],
599 'dstIp', str(dstip), dstseed, dstmask, count)
601 self._update_ipv4_priority(
602 self._get_stack_item(fg_id, PROTO_IPV4)[0], priority)
604 def _update_ipv4_priority(self, ip_descriptor, priority):
605 """Set the IPv4 priority in a config element stack IP field
607 :param ip_descriptor: (str) IP descriptor, e.g.:
608 /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"
609 :param priority: (dict) priority configuration from traffic profile, e.g.:
611 'precedence': [1, 4, 7]
614 if priority.get('raw'):
615 priority_field = self._get_field_in_stack_item(ip_descriptor,
617 self._set_priority_field(priority_field, priority['raw'])
619 elif priority.get('dscp'):
620 for field, value in priority['dscp'].items():
621 if field in SUPPORTED_DSCP_CLASSES:
622 priority_field = self._get_field_in_stack_item(
624 'priority.ds.phb.{field}.{field}'.format(field=field))
625 self._set_priority_field(priority_field, value)
627 elif priority.get('tos'):
628 for field, value in priority['tos'].items():
629 if field in SUPPORTED_TOS_FIELDS:
630 priority_field = self._get_field_in_stack_item(
631 ip_descriptor, 'priority.tos.' + field)
632 self._set_priority_field(priority_field, value)
634 def _set_priority_field(self, field_descriptor, value):
635 """Set the priority field described by field_descriptor
637 :param field_descriptor: (str) field descriptor, e.g.:
638 /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/ \
639 field:"ipv4.header.priority.raw-3
640 :param value: (list, int) list of integers or single integer value
642 if isinstance(value, list):
643 self.ixnet.setMultiAttribute(field_descriptor,
645 '-activeFieldChoice', 'true',
646 '-valueType', 'valueList')
648 self.ixnet.setMultiAttribute(field_descriptor,
649 '-activeFieldChoice', 'true',
650 '-singleValue', str(value))
653 def update_l4(self, traffic):
654 """Update the L4 headers
656 NOTE: Only UDP is currently supported
657 :param traffic: list of traffic elements; each traffic element contains
658 the injection parameter for each flow group
660 for traffic_param in traffic.values():
661 fg_id = str(traffic_param['id'])
662 if not self._get_config_element_by_flow_group_name(fg_id):
663 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
665 proto = traffic_param['outer_l3'].get('proto')
666 if not (proto and traffic_param['outer_l4']):
669 if proto not in SUPPORTED_PROTO:
670 raise exceptions.IXIAUnsupportedProtocol(protocol=proto)
672 count = traffic_param['outer_l4']['count']
673 seed = traffic_param['outer_l4']['seed']
675 srcport = traffic_param['outer_l4']['srcport']
676 srcmask = traffic_param['outer_l4']['srcportmask']
678 dstport = traffic_param['outer_l4']['dstport']
679 dstmask = traffic_param['outer_l4']['dstportmask']
681 if proto == PROTO_UDP:
683 self._update_udp_port(
684 self._get_stack_item(fg_id, proto)[0],
685 'srcPort', srcport, seed, srcmask, count)
687 self._update_udp_port(
688 self._get_stack_item(fg_id, proto)[0],
689 'dstPort', dstport, seed, dstmask, count)
691 def _update_udp_port(self, descriptor, field, value,
692 seed=1, mask=0, count=1):
693 """Set the UDP port in a config element stack UDP field
695 :param udp_descriptor: (str) UDP descriptor, e.g.:
696 /traffic/trafficItem:1/configElement:1/stack:"udp-3"
697 :param field: (str) field name, e.g.: scrPort, dstPort
698 :param value: (int) UDP port fixed bits
699 :param seed: (int) seed length
700 :param mask: (int) UDP port mask
701 :param count: (int) number of random ports to generate
703 field_descriptor = self._get_field_in_stack_item(descriptor, field)
708 self.ixnet.setMultiAttribute(field_descriptor,
713 '-valueType', 'random',
714 '-countValue', count)
718 def _build_stats_map(self, view_obj, name_map):
719 return {data_yardstick: self.ixnet.execute(
720 'getColumnValues', view_obj, data_ixia)
721 for data_yardstick, data_ixia in name_map.items()}
723 def _set_egress_flow_tracking(self, encapsulation, offset):
724 """Set egress flow tracking options
726 :param encapsulation: encapsulation type
727 :type encapsulation: str, e.g. 'Ethernet'
728 :param offset: offset type
729 :type offset: str, e.g. 'IPv4 TOS Precedence (3 bits)'
731 traffic_item = self.ixnet.getList(self.ixnet.getRoot() + '/traffic',
733 # Enable Egress Tracking
734 self.ixnet.setAttribute(traffic_item, '-egressEnabled', True)
737 # Set encapsulation type
738 enc_obj = self.ixnet.getList(traffic_item, 'egressTracking')[0]
739 self.ixnet.setAttribute(enc_obj, '-encapsulation', encapsulation)
742 self.ixnet.setAttribute(enc_obj, '-offset', offset)
745 def _set_flow_tracking(self, track_by):
746 """Set flow tracking options
748 :param track_by: list of tracking fields
749 :type track_by: list, e.g. ['vlanVlanId0','ipv4Precedence0']
751 traffic_item = self.ixnet.getList(self.ixnet.getRoot() + '/traffic',
753 self.ixnet.setAttribute(traffic_item + '/tracking', '-trackBy', track_by)
756 def get_statistics(self):
757 """Retrieve port and flow statistics
759 "Port Statistics" parameters are stored in self.PORT_STATS_NAME_MAP.
760 "Flow Statistics" parameters are stored in self.LATENCY_NAME_MAP.
762 :return: dictionary with the statistics; the keys of this dictionary
763 are PORT_STATS_NAME_MAP and LATENCY_NAME_MAP keys.
765 stats = self._build_stats_map(self.PORT_STATISTICS,
766 self.PORT_STATS_NAME_MAP)
767 stats.update(self._build_stats_map(self.FLOW_STATISTICS,
768 self.LATENCY_NAME_MAP))
771 def get_pppoe_scenario_statistics(self):
772 """Retrieve port, flow and PPPoE subscribers statistics
774 "Port Statistics" parameters are stored in self.PORT_STATS_NAME_MAP.
775 "Flow Statistics" parameters are stored in self.LATENCY_NAME_MAP.
776 "PPPoX Client Per Port" parameters are stored in
777 self.PPPOE_CLIENT_PER_PORT_NAME_MAP
779 :return: dictionary with the statistics; the keys of this dictionary
780 are PORT_STATS_NAME_MAP, LATENCY_NAME_MAP and
781 PPPOE_CLIENT_PER_PORT_NAME_MAP keys.
783 stats = self._build_stats_map(self.PORT_STATISTICS,
784 self.PORT_STATS_NAME_MAP)
785 stats.update(self._build_stats_map(self.FLOW_STATISTICS,
786 self.LATENCY_NAME_MAP))
787 stats.update(self._build_stats_map(self.PPPOX_CLIENT_PER_PORT,
788 self.PPPOX_CLIENT_PER_PORT_NAME_MAP))
791 def start_protocols(self):
792 self.ixnet.execute('startAllProtocols')
794 def stop_protocols(self):
795 self.ixnet.execute('stopAllProtocols')
797 def start_traffic(self):
798 """Start the traffic injection in the traffic item
800 By configuration, there is only one traffic item. This function returns
801 when the traffic state is TRAFFIC_STATUS_STARTED.
803 traffic_items = self.ixnet.getList('/traffic', 'trafficItem')
804 if self.is_traffic_running():
805 self.ixnet.execute('stop', '/traffic')
806 # pylint: disable=unnecessary-lambda
807 utils.wait_until_true(lambda: self.is_traffic_stopped())
809 self.ixnet.execute('generate', traffic_items)
810 self.ixnet.execute('apply', '/traffic')
811 self.ixnet.execute('start', '/traffic')
812 # pylint: disable=unnecessary-lambda
813 utils.wait_until_true(lambda: self.is_traffic_running())
815 def add_topology(self, name, vports):
816 log.debug("add_topology: name='%s' ports='%s'", name, vports)
817 obj = self.ixnet.add(self.ixnet.getRoot(), 'topology')
818 self.ixnet.setMultiAttribute(obj, '-name', name, '-vports', vports)
822 def add_device_group(self, topology, name, multiplier):
823 log.debug("add_device_group: tpl='%s', name='%s', multiplier='%s'",
824 topology, name, multiplier)
826 obj = self.ixnet.add(topology, 'deviceGroup')
827 self.ixnet.setMultiAttribute(obj, '-name', name, '-multiplier',
832 def add_ethernet(self, dev_group, name):
834 "add_ethernet: device_group='%s' name='%s'", dev_group, name)
835 obj = self.ixnet.add(dev_group, 'ethernet')
836 self.ixnet.setMultiAttribute(obj, '-name', name)
840 def _create_vlans(self, ethernet, count):
841 self.ixnet.setMultiAttribute(ethernet, '-useVlans', 'true')
842 self.ixnet.setMultiAttribute(ethernet, '-vlanCount', count)
845 def _configure_vlans(self, ethernet, vlans):
846 vlans_obj = self.ixnet.getList(ethernet, 'vlan')
847 for i, vlan_obj in enumerate(vlans_obj):
848 if vlans[i].vlan_id_step is not None:
849 vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId')
850 self.ixnet.setMultiAttribute(vlan_id_obj, '-clearOverlays',
851 'true', '-pattern', 'counter')
852 vlan_id_counter = self.ixnet.add(vlan_id_obj, 'counter')
853 self.ixnet.setMultiAttribute(vlan_id_counter, '-start',
854 vlans[i].vlan_id, '-step',
855 vlans[i].vlan_id_step,
857 vlans[i].vlan_id_direction)
859 vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId')
860 self.ixnet.setMultiAttribute(vlan_id_obj + '/singleValue',
861 '-value', vlans[i].vlan_id)
863 if vlans[i].prio_step is not None:
864 prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority')
865 self.ixnet.setMultiAttribute(prio_obj, '-clearOverlays', 'true',
866 '-pattern', 'counter')
867 prio_counter = self.ixnet.add(prio_obj, 'counter')
868 self.ixnet.setMultiAttribute(prio_counter,
869 '-start', vlans[i].prio,
870 '-step', vlans[i].prio_step,
871 '-direction', vlans[i].prio_direction)
872 elif vlans[i].prio is not None:
873 prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority')
874 self.ixnet.setMultiAttribute(prio_obj + '/singleValue',
875 '-value', vlans[i].prio)
877 if vlans[i].tp_id is not None:
878 tp_id_obj = self.ixnet.getAttribute(vlan_obj, '-tpid')
879 self.ixnet.setMultiAttribute(tp_id_obj + '/singleValue',
880 '-value', vlans[i].tp_id)
884 def add_vlans(self, ethernet, vlans):
885 log.debug("add_vlans: ethernet='%s'", ethernet)
887 if vlans is None or len(vlans) == 0:
889 "Invalid 'vlans' argument. Expected list of Vlan instances.")
891 self._create_vlans(ethernet, len(vlans))
892 self._configure_vlans(ethernet, vlans)
894 def add_ipv4(self, ethernet, name='',
895 addr=None, addr_step=None, addr_direction='increment',
896 prefix=None, prefix_step=None, prefix_direction='increment',
897 gateway=None, gw_step=None, gw_direction='increment'):
898 log.debug("add_ipv4: ethernet='%s' name='%s'", ethernet, name)
899 obj = self.ixnet.add(ethernet, 'ipv4')
901 self.ixnet.setAttribute(obj, '-name', name)
904 if addr_step is not None:
905 # handle counter pattern
906 _address = self.ixnet.getAttribute(obj, '-address')
907 self.ixnet.setMultiAttribute(_address, '-clearOverlays', 'true',
908 '-pattern', 'counter')
910 address_counter = self.ixnet.add(_address, 'counter')
911 self.ixnet.setMultiAttribute(address_counter,
914 '-direction', addr_direction)
915 elif addr is not None:
916 # handle single value
917 _address = self.ixnet.getAttribute(obj, '-address')
918 self.ixnet.setMultiAttribute(_address + '/singleValue', '-value',
921 if prefix_step is not None:
922 # handle counter pattern
923 _prefix = self.ixnet.getAttribute(obj, '-prefix')
924 self.ixnet.setMultiAttribute(_prefix, '-clearOverlays', 'true',
925 '-pattern', 'counter')
926 prefix_counter = self.ixnet.add(_prefix, 'counter')
927 self.ixnet.setMultiAttribute(prefix_counter,
929 '-step', prefix_step,
930 '-direction', prefix_direction)
931 elif prefix is not None:
932 # handle single value
933 _prefix = self.ixnet.getAttribute(obj, '-prefix')
934 self.ixnet.setMultiAttribute(_prefix + '/singleValue', '-value',
937 if gw_step is not None:
938 # handle counter pattern
939 _gateway = self.ixnet.getAttribute(obj, '-gatewayIp')
940 self.ixnet.setMultiAttribute(_gateway, '-clearOverlays', 'true',
941 '-pattern', 'counter')
943 gateway_counter = self.ixnet.add(_gateway, 'counter')
944 self.ixnet.setMultiAttribute(gateway_counter,
947 '-direction', gw_direction)
948 elif gateway is not None:
949 # handle single value
950 _gateway = self.ixnet.getAttribute(obj, '-gatewayIp')
951 self.ixnet.setMultiAttribute(_gateway + '/singleValue', '-value',
957 def add_pppox_client(self, xproto, auth, user, pwd, enable_redial=True):
959 "add_pppox_client: xproto='%s', auth='%s', user='%s', pwd='%s'",
960 xproto, auth, user, pwd)
961 obj = self.ixnet.add(xproto, 'pppoxclient')
965 auth_type = self.ixnet.getAttribute(obj, '-authType')
966 self.ixnet.setMultiAttribute(auth_type + '/singleValue', '-value',
968 pap_user = self.ixnet.getAttribute(obj, '-papUser')
969 self.ixnet.setMultiAttribute(pap_user + '/singleValue', '-value',
971 pap_pwd = self.ixnet.getAttribute(obj, '-papPassword')
972 self.ixnet.setMultiAttribute(pap_pwd + '/singleValue', '-value',
975 raise NotImplementedError()
978 redial = self.ixnet.getAttribute(obj, '-enableRedial')
979 self.ixnet.setAttribute(redial + '/singleValue', '-value', 'true')
984 def add_bgp(self, ipv4, dut_ip, local_as, bgp_type=None):
985 """Add BGP protocol"""
986 log.debug("add_bgp: ipv4='%s', dut_ip='%s', local_as='%s'", ipv4,
988 obj = self.ixnet.add(ipv4, 'bgpIpv4Peer')
992 dut_ip_addr = self.ixnet.getAttribute(obj, '-dutIp')
993 self.ixnet.setAttribute(dut_ip_addr + '/singleValue',
996 # Set local AS number
997 local_as_number = self.ixnet.getAttribute(obj, '-localAs2Bytes')
998 self.ixnet.setAttribute(local_as_number + '/singleValue',
1002 # Set BGP type. If not specified, default value is using.
1003 # Default type is "internal"
1004 bgp_type_field = self.ixnet.getAttribute(obj, '-type')
1005 self.ixnet.setAttribute(bgp_type_field + '/singleValue',
1010 def add_interface(self, vport, ip, mac=None, gateway=None):
1011 """Add protocol interface to the vport"""
1012 log.debug("add_interface: mac='%s', ip='%s', gateway='%s'", mac, ip,
1014 obj = self.ixnet.add(vport, 'interface')
1018 self.ixnet.setMultiAttribute(obj + '/ethernet', '-macAddress', mac)
1020 ipv4 = self.ixnet.add(obj, 'ipv4')
1021 self.ixnet.setMultiAttribute(ipv4, '-ip', ip)
1023 if gateway is not None:
1024 self.ixnet.setMultiAttribute(ipv4, '-gateway', gateway)
1028 self.ixnet.setMultiAttribute(obj, '-enabled', 'true')
1033 def add_static_ipv4(self, iface, vport, start_ip, count):
1034 """Add static IP range to the interface"""
1035 log.debug("add_static_ipv4: start_ip:'%s', count:'%s'",
1037 obj = self.ixnet.add(vport + '/protocols/static', 'ip')
1039 self.ixnet.setMultiAttribute(obj, '-protocolInterface', iface,
1040 '-ipStart', start_ip, '-count', count,