Improve IXIA IxNetwork library and traffic profile (2) 21/55321/14
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Tue, 10 Apr 2018 08:15:55 +0000 (09:15 +0100)
committerRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Tue, 12 Jun 2018 07:31:00 +0000 (08:31 +0100)
This patch modifies the way the packet frame and the flow is configured
before the injection.

"IxNextgen.update_frame" modifies the L2 frame according to the
test case and setup the frame rate, frame size, traffic injection
duration and MAC addresses.

JIRA: YARDSTICK-1116

Change-Id: Ife08f15a4eda24d7835c92c4172b450854d112ee
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Signed-off-by: Emma Foley <emma.l.foley@intel.com>
yardstick/common/exceptions.py
yardstick/network_services/libs/ixia_libs/ixnet/__init__.py [moved from yardstick/network_services/libs/ixia_libs/IxNet/__init__.py with 100% similarity]
yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py [moved from yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py with 62% similarity]
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py [deleted file]
yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py [new file with mode: 0644]

index 0b16982..966b15c 100644 (file)
@@ -297,3 +297,15 @@ class ScenarioCreateImageError(YardstickException):
 
 class ScenarioDeleteImageError(YardstickException):
     message = 'Glance Delete Image Scenario failed'
+
+
+class IxNetworkClientNotConnected(YardstickException):
+    message = 'IxNetwork client not connected to a TCL server'
+
+
+class IxNetworkFlowNotPresent(YardstickException):
+    message = 'Flow Group "%(flow_group)s" is not present'
+
+
+class IxNetworkFieldNotPresentInStackItem(YardstickException):
+    message = 'Field "%(field_name)s" not present in stack item %(stack_item)s'
 
 import logging
 
-import re
-from itertools import product
 import IxNetwork
 
+from yardstick.common import exceptions
+
 
 log = logging.getLogger(__name__)
 
@@ -30,57 +30,8 @@ PROTO_TCP = 'tcp'
 PROTO_VLAN = 'vlan'
 
 
-class TrafficStreamHelper(object):
-
-    TEMPLATE = '{0.traffic_item}/{0.stream}:{0.param_id}/{1}'
-
-    def __init__(self, traffic_item, stream, param_id):
-        super(TrafficStreamHelper, self).__init__()
-        self.traffic_item = traffic_item
-        self.stream = stream
-        self.param_id = param_id
-
-    def __getattr__(self, item):
-        return self.TEMPLATE.format(self, item)
-
-
-class FramesizeHelper(object):
-
-    def __init__(self):
-        super(FramesizeHelper, self).__init__()
-        self.weighted_pairs = []
-        self.weighted_range_pairs = []
-
-    @property
-    def weighted_pairs_arg(self):
-        return '-weightedPairs', self.weighted_pairs
-
-    @property
-    def weighted_range_pairs_arg(self):
-        return '-weightedRangePairs', self.weighted_range_pairs
-
-    def make_args(self, *args):
-        return self.weighted_pairs_arg + self.weighted_range_pairs_arg + args
-
-    def populate_data(self, framesize_data):
-        for key, value in framesize_data.items():
-            if value == '0':
-                continue
-
-            replaced = re.sub('[Bb]', '', key)
-            self.weighted_pairs.extend([
-                replaced,
-                value,
-            ])
-            pairs = [
-                replaced,
-                replaced,
-                value,
-            ]
-            self.weighted_range_pairs.append(pairs)
-
-
-class IxNextgen(object):
+# NOTE(ralonsoh): this pragma will be removed in the last patch of this series
+class IxNextgen(object):  # pragma: no cover
 
     PORT_STATS_NAME_MAP = {
         "stat_name": 'Stat Name',
@@ -135,59 +86,61 @@ class IxNextgen(object):
 
         return cfg
 
-    def __init__(self, ixnet=None):
-        self.ixnet = ixnet
-        self._objRefs = dict()
+    def __init__(self):  # pragma: no cover
+        self._ixnet = None
         self._cfg = None
         self._params = None
         self._bidir = None
 
+    @property
+    def ixnet(self):  # pragma: no cover
+        if self._ixnet:
+            return self._ixnet
+        raise exceptions.IxNetworkClientNotConnected()
+
+    def _get_config_element_by_flow_group_name(self, flow_group_name):
+        """Get a config element using the flow group name
+
+        Each named flow group contains one config element (by configuration).
+        According to the documentation, "configElements" is a list and "each
+        item in this list is aligned to the sequential order of your endpoint
+        list".
+
+        :param flow_group_name: (str) flow group name; this parameter is
+                                always a number (converted to string) starting
+                                from "1".
+        :return: (str) config element reference ID or None.
+        """
+        traffic_item = self.ixnet.getList(self.ixnet.getRoot() + '/traffic',
+                                          'trafficItem')[0]
+        flow_groups = self.ixnet.getList(traffic_item, 'endpointSet')
+        for flow_group in flow_groups:
+            if (str(self.ixnet.getAttribute(flow_group, '-name')) ==
+                    flow_group_name):
+                return traffic_item + '/configElement:' + flow_group_name
+
+    @staticmethod
+    def _parse_framesize(framesize):
+        """Parse "framesize" config param. to return a list of weighted pairs
+
+        :param framesize: dictionary of frame sizes and weights
+        :return: list of paired frame sizes and weights
+        """
+        weighted_range_pairs = []
+        for size, weight in framesize.items():
+            weighted_range_pairs.append(int(size.upper().replace('B', '')))
+            weighted_range_pairs.append(int(weight))
+        return weighted_range_pairs
+
     def iter_over_get_lists(self, x1, x2, y2, offset=0):
         for x in self.ixnet.getList(x1, x2):
             y_list = self.ixnet.getList(x, y2)
             for i, y in enumerate(y_list, offset):
                 yield x, y, i
 
-    def set_random_ip_multi_attribute(self, ipv4, seed, fixed_bits, random_mask, l3_count):
-        self.ixnet.setMultiAttribute(
-            ipv4,
-            '-seed', str(seed),
-            '-fixedBits', str(fixed_bits),
-            '-randomMask', str(random_mask),
-            '-valueType', 'random',
-            '-countValue', str(l3_count))
-
-    def set_random_ip_multi_attributes(self, ip, version, seeds, l3):
-        try:
-            random_mask = self.RANDOM_MASK_MAP[version]
-        except KeyError:
-            raise ValueError('Unknown version %s' % version)
-
-        l3_count = l3['count']
-        if "srcIp" in ip:
-            fixed_bits = l3['srcip4']
-            self.set_random_ip_multi_attribute(ip, seeds[0], fixed_bits, random_mask, l3_count)
-        if "dstIp" in ip:
-            fixed_bits = l3['dstip4']
-            self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count)
-
-    def add_ip_header(self, params, version):
-        for _, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement", 1):
-            iter1 = (v['outer_l3'] for v in params.values() if str(v['id']) == str(i))
-            try:
-                l3 = next(iter1, {})
-                seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)[1]
-            except (KeyError, IndexError):
-                continue
-
-            for _, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
-                self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3)
-
-        self.ixnet.commit()
-
     def connect(self, tg_cfg):
         self._cfg = self.get_config(tg_cfg)
-        self.ixnet = IxNetwork.IxNet()
+        self._ixnet = IxNetwork.IxNet()
 
         machine = self._cfg['machine']
         port = str(self._cfg['port'])
@@ -255,19 +208,21 @@ class IxNextgen(object):
         vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
         uplink_ports = vports[::2]
         downlink_ports = vports[1::2]
+        index = 0
         for up, down in zip(uplink_ports, downlink_ports):
             log.info('FGs: %s <--> %s', up, down)
             endpoint_set_1 = self.ixnet.add(traffic_item_id, 'endpointSet')
             endpoint_set_2 = self.ixnet.add(traffic_item_id, 'endpointSet')
             self.ixnet.setMultiAttribute(
-                endpoint_set_1,
-                '-sources', [up + ' /protocols'],
+                endpoint_set_1, '-name', str(index + 1),
+                '-sources', [up + '/protocols'],
                 '-destinations', [down + '/protocols'])
             self.ixnet.setMultiAttribute(
-                endpoint_set_2,
-                '-sources', [down + ' /protocols'],
+                endpoint_set_2, '-name', str(index + 2),
+                '-sources', [down + '/protocols'],
                 '-destinations', [up + '/protocols'])
             self.ixnet.commit()
+            index += 2
 
     def _append_procotol_to_stack(self, protocol_name, previous_element):
         """Append a new element in the packet definition stack"""
@@ -317,87 +272,134 @@ class IxNextgen(object):
         self._create_flow_groups()
         self._setup_config_elements()
 
-    def ix_update_frame(self, params):
-        streams = ["configElement"]
-
-        for param in params.values():
-            framesize_data = FramesizeHelper()
-            traffic_items = self.ixnet.getList('/traffic', 'trafficItem')
-            param_id = param['id']
-            for traffic_item, stream in product(traffic_items, streams):
-                helper = TrafficStreamHelper(traffic_item, stream, param_id)
-
-                self.ixnet.setMultiAttribute(helper.transmissionControl,
-                                             '-type', '{0}'.format(param.get('traffic_type',
-                                                                             'fixedDuration')),
-                                             '-duration', '{0}'.format(param.get('duration',
-                                                                                 "30")))
-
-                stream_frame_rate_path = helper.frameRate
-                self.ixnet.setMultiAttribute(stream_frame_rate_path, '-rate', param['iload'])
-                if param['outer_l2']['framesPerSecond']:
-                    self.ixnet.setMultiAttribute(stream_frame_rate_path,
-                                                 '-type', 'framesPerSecond')
-
-                framesize_data.populate_data(param['outer_l2']['framesize'])
-
-                make_attr_args = framesize_data.make_args('-incrementFrom', '66',
-                                                          '-randomMin', '66',
-                                                          '-quadGaussian', [],
-                                                          '-type', 'weightedPairs',
-                                                          '-presetDistribution', 'cisco',
-                                                          '-incrementTo', '1518')
-
-                self.ixnet.setMultiAttribute(helper.frameSize, *make_attr_args)
-
-                self.ixnet.commit()
-
-    def update_ether_multi_attribute(self, ether, mac_addr):
-        self.ixnet.setMultiAttribute(ether,
-                                     '-singleValue', mac_addr,
-                                     '-fieldValue', mac_addr,
+    def _get_field_in_stack_item(self, stack_item, field_name):
+        """List all fields in a stack item an return t
+
+        :param stack_item: (str) stack item descriptor
+        :param field_name: (str) field name
+        :return: (str) field descriptor
+        """
+        fields = self.ixnet.getList(stack_item, 'field')
+        for field in (field for field in fields if field_name in field):
+            return field
+        raise exceptions.IxNetworkFieldNotPresentInStackItem(
+            field_name=field_name, stack_item=stack_item)
+
+    def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
+        """Set the MAC address in a config element stack Ethernet field
+
+        :param ethernet_descriptor: (str) ethernet descriptor, e.g.:
+            /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"
+        :param field: (str) field name, e.g.: destinationAddress
+        :param mac_address: (str) MAC address
+        """
+        field_descriptor = self._get_field_in_stack_item(ethernet_descriptor,
+                                                         field)
+        self.ixnet.setMultiAttribute(field_descriptor,
+                                     '-singleValue', mac_address,
+                                     '-fieldValue', mac_address,
                                      '-valueType', 'singleValue')
+        self.ixnet.commit()
 
-    def update_ether_multi_attributes(self, ether, l2):
-        if "ethernet.header.destinationAddress" in ether:
-            self.update_ether_multi_attribute(ether, str(l2.get('dstmac', "00:00:00:00:00:02")))
+    def update_frame(self, traffic):
+        """Update the L2 frame
 
-        if "ethernet.header.sourceAddress" in ether:
-            self.update_ether_multi_attribute(ether, str(l2.get('srcmac', "00:00:00:00:00:01")))
+        This function updates the L2 frame options:
+        - Traffic type: "continuous", "fixedDuration".
+        - Duration: in case of traffic_type="fixedDuration", amount of seconds
+                    to inject traffic.
+        - Rate: in frames per seconds or percentage.
+        - Type of rate: "framesPerSecond" ("bitsPerSecond" and
+                        "percentLineRate" no used)
+        - Frame size: custom IMIX [1] definition; a list of packet size in
+                      bytes and the weight. E.g.:
+                      [64, 10, 128, 15, 512, 5]
 
-    def ix_update_ether(self, params):
-        for _, ep, index in self.iter_over_get_lists('/traffic', 'trafficItem',
-                                                      "configElement", 1):
-            iter1 = (v['outer_l2'] for v in params.values() if str(v['id']) == str(index))
-            try:
-                l2 = next(iter1, {})
-            except KeyError:
-                continue
+        [1] https://en.wikipedia.org/wiki/Internet_Mix
 
-            for _, ether, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
-                self.update_ether_multi_attributes(ether, l2)
+        :param traffic: list of traffic elements; each traffic element contains
+                        the injection parameter for each flow group.
+        """
+        for traffic_param in traffic.values():
+            config_element = self._get_config_element_by_flow_group_name(
+                str(traffic_param['id']))
+            if not config_element:
+                raise exceptions.IxNetworkFlowNotPresent(
+                    flow_group=traffic_param['id'])
+
+            type = traffic_param.get('traffic_type', 'fixedDuration')
+            duration = traffic_param.get('duration', 30)
+            rate = traffic_param['iload']
+            weighted_range_pairs = self._parse_framesize(
+                traffic_param['outer_l2']['framesize'])
+            srcmac = str(traffic_param.get('srcmac', '00:00:00:00:00:01'))
+            dstmac = str(traffic_param.get('dstmac', '00:00:00:00:00:02'))
+            # NOTE(ralonsoh): add QinQ tagging when
+            # traffic_param['outer_l2']['QinQ'] exists.
+            # s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN']
+            # c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN']
 
-        self.ixnet.commit()
+            self.ixnet.setMultiAttribute(
+                config_element + '/transmissionControl',
+                '-type', type, '-duration', duration)
+            self.ixnet.setMultiAttribute(
+                config_element + '/frameRate',
+                '-rate', rate, '-type', 'framesPerSecond')
+            self.ixnet.setMultiAttribute(
+                config_element + '/frameSize',
+                '-type', 'weightedPairs',
+                '-weightedRangePairs', weighted_range_pairs)
+            self.ixnet.commit()
 
-    def ix_update_udp(self, params):
-        pass
+            self._update_frame_mac(
+                config_element + '/stack:"ethernet-1"',
+                'destinationAddress', dstmac)
+            self._update_frame_mac(
+                config_element + '/stack:"ethernet-1"',
+                'sourceAddress', srcmac)
 
-    def ix_update_tcp(self, params):
-        pass
+    def set_random_ip_multi_attribute(self, ipv4, seed, fixed_bits, random_mask, l3_count):
+        self.ixnet.setMultiAttribute(
+            ipv4,
+            '-seed', str(seed),
+            '-fixedBits', str(fixed_bits),
+            '-randomMask', str(random_mask),
+            '-valueType', 'random',
+            '-countValue', str(l3_count))
 
-    def ix_start_traffic(self):
-        tis = self.ixnet.getList('/traffic', 'trafficItem')
-        for ti in tis:
-            self.ixnet.execute('generate', [ti])
-            self.ixnet.execute('apply', '/traffic')
-            self.ixnet.execute('start', '/traffic')
+    # NOTE(ralonsoh): to be updated in next patchset
+    # pragma: no cover
+    def set_random_ip_multi_attributes(self, ip, version, seeds, l3):
+        try:
+            random_mask = self.RANDOM_MASK_MAP[version]
+        except KeyError:
+            raise ValueError('Unknown version %s' % version)
 
-    def ix_stop_traffic(self):
-        tis = self.ixnet.getList('/traffic', 'trafficItem')
-        for _ in tis:
-            self.ixnet.execute('stop', '/traffic')
+        l3_count = l3['count']
+        if 'srcIp' in ip:
+            fixed_bits = l3['srcip4']
+            self.set_random_ip_multi_attribute(ip, seeds[0], fixed_bits, random_mask, l3_count)
+        if 'dstIp' in ip:
+            fixed_bits = l3['dstip4']
+            self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count)
+
+    # NOTE(ralonsoh): to be updated in next patchset
+    # pragma: no cover
+    def add_ip_header(self, params, version):
+        for _, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement", 1):
+            iter1 = (v['outer_l3'] for v in params.values() if str(v['id']) == str(i))
+            try:
+                l3 = next(iter1, {})
+                seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)[1]
+            except (KeyError, IndexError):
+                continue
 
-    def build_stats_map(self, view_obj, name_map):
+            for _, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'):
+                self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3)
+
+        self.ixnet.commit()
+
+    def _build_stats_map(self, view_obj, name_map):
         return {data_yardstick: self.ixnet.execute(
                 'getColumnValues', view_obj, data_ixia)
             for data_yardstick, data_ixia in name_map.items()}
@@ -413,7 +415,24 @@ class IxNextgen(object):
         """
         port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"'
         flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"'
-        stats = self.build_stats_map(port_statistics, self.PORT_STATS_NAME_MAP)
-        stats.update(self.build_stats_map(flow_statistics,
+        stats = self._build_stats_map(port_statistics,
+                                      self.PORT_STATS_NAME_MAP)
+        stats.update(self._build_stats_map(flow_statistics,
                                           self.LATENCY_NAME_MAP))
         return stats
+
+    # NOTE(ralonsoh): to be updated in next patchset
+    # pragma: no cover
+    def ix_start_traffic(self):
+        tis = self.ixnet.getList('/traffic', 'trafficItem')
+        for ti in tis:
+            self.ixnet.execute('generate', [ti])
+            self.ixnet.execute('apply', '/traffic')
+            self.ixnet.execute('start', '/traffic')
+
+    # NOTE(ralonsoh): to be updated in next patchset
+    # pragma: no cover
+    def ix_stop_traffic(self):
+        tis = self.ixnet.getList('/traffic', 'trafficItem')
+        for _ in tis:
+            self.ixnet.execute('stop', '/traffic')
index 7f04722..ec354c8 100644 (file)
@@ -83,8 +83,7 @@ class IXIARFC2544Profile(TrexProfile):
         for key, value in traffic.items():
             if key.startswith((self.UPLINK, self.DOWNLINK)):
                 value["iload"] = str(self.rate)
-        ixia_obj.ix_update_frame(traffic)
-        ixia_obj.ix_update_ether(traffic)
+        ixia_obj.update_frame(traffic)
         ixia_obj.add_ip_header(traffic, 4)
         ixia_obj.ix_start_traffic()
         self.tmp_drop = 0
index f8799c8..deb0a80 100644 (file)
@@ -74,8 +74,6 @@ class IxiaResourceHelper(ClientResourceHelper):
 
     def generate_samples(self, ports, key=None, default=None):
         stats = self.get_stats()
-        last_result = stats[1]
-        latency = stats[0]
 
         samples = {}
         # this is not DPDK port num, but this is whatever number we gave
@@ -86,19 +84,21 @@ class IxiaResourceHelper(ClientResourceHelper):
                 intf = self.vnfd_helper.find_interface_by_port(port_num)
                 port_name = intf["name"]
                 samples[port_name] = {
-                    "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][port_num]),
-                    "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][port_num]),
-                    "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][port_num]),
-                    "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][port_num]),
-                    "in_packets": int(last_result["Valid_Frames_Rx"][port_num]),
-                    "out_packets": int(last_result["Frames_Tx"][port_num]),
-                    "RxThroughput": int(last_result["Valid_Frames_Rx"][port_num]) / 30,
-                    "TxThroughput": int(last_result["Frames_Tx"][port_num]) / 30,
+                    "rx_throughput_kps": float(stats["Rx_Rate_Kbps"][port_num]),
+                    "tx_throughput_kps": float(stats["Tx_Rate_Kbps"][port_num]),
+                    "rx_throughput_mbps": float(stats["Rx_Rate_Mbps"][port_num]),
+                    "tx_throughput_mbps": float(stats["Tx_Rate_Mbps"][port_num]),
+                    "in_packets": int(stats["Valid_Frames_Rx"][port_num]),
+                    "out_packets": int(stats["Frames_Tx"][port_num]),
+                    # NOTE(ralonsoh): we need to make the traffic injection
+                    # time variable.
+                    "RxThroughput": int(stats["Valid_Frames_Rx"][port_num]) / 30,
+                    "TxThroughput": int(stats["Frames_Tx"][port_num]) / 30,
                 }
                 if key:
-                    avg_latency = latency["Store-Forward_Avg_latency_ns"][port_num]
-                    min_latency = latency["Store-Forward_Min_latency_ns"][port_num]
-                    max_latency = latency["Store-Forward_Max_latency_ns"][port_num]
+                    avg_latency = stats["Store-Forward_Avg_latency_ns"][port_num]
+                    min_latency = stats["Store-Forward_Min_latency_ns"][port_num]
+                    max_latency = stats["Store-Forward_Max_latency_ns"][port_num]
                     samples[port_name][key] = \
                         {"Store-Forward_Avg_latency_ns": avg_latency,
                          "Store-Forward_Min_latency_ns": min_latency,
diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py
deleted file mode 100644 (file)
index deae693..0000000
+++ /dev/null
@@ -1,973 +0,0 @@
-# Copyright (c) 2016-2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import mock
-import IxNetwork
-import unittest
-
-from yardstick.network_services.libs.ixia_libs.IxNet import IxNet
-
-
-UPLINK = 'uplink'
-DOWNLINK = 'downlink'
-
-
-class TestIxNextgen(unittest.TestCase):
-
-    def setUp(self):
-        self.ixnet = mock.Mock()
-        self.ixnet.execute = mock.Mock()
-
-    def test___init__(self):
-        ixnet_gen = IxNet.IxNextgen()
-        self.assertIsNone(ixnet_gen.ixnet)
-        self.assertTrue(isinstance(ixnet_gen._objRefs, dict))
-        self.assertIsNone(ixnet_gen._cfg)
-        self.assertIsNone(ixnet_gen._params)
-        self.assertIsNone(ixnet_gen._bidir)
-
-    def test___init__ixnet(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        self.assertIsNotNone(ixnet_gen.ixnet)
-
-    @mock.patch.object(IxNetwork, 'IxNet')
-    def test_connect(self, mock_ixnet):
-        mock_ixnet.return_value = self.ixnet
-        ixnet_gen = IxNet.IxNextgen()
-        with mock.patch.object(ixnet_gen, 'get_config') as mock_config:
-            mock_config.return_value = {'machine': 'machine_fake',
-                                        'port': 'port_fake',
-                                        'version': 12345}
-            ixnet_gen.connect(mock.ANY)
-
-        self.ixnet.connect.assert_called_once_with(
-            'machine_fake', '-port', 'port_fake', '-version', '12345')
-        mock_config.assert_called_once()
-
-    def test_connect_invalid_config_no_machine(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.get_config = mock.Mock(return_value={
-            'port': 'port_fake',
-            'version': '12345'})
-        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
-        self.ixnet.connect.assert_not_called()
-
-    def test_connect_invalid_config_no_port(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.get_config = mock.Mock(return_value={
-            'machine': 'machine_fake',
-            'version': '12345'})
-        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
-        self.ixnet.connect.assert_not_called()
-
-    def test_connect_invalid_config_no_version(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.get_config = mock.Mock(return_value={
-            'machine': 'machine_fake',
-            'port': 'port_fake'})
-        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
-        self.ixnet.connect.assert_not_called()
-
-    def test_connect_no_config(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.get_config = mock.Mock(return_value={})
-        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
-        self.ixnet.connect.assert_not_called()
-
-    def test_clear_config(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.clear_config()
-        self.ixnet.execute.assert_called_once_with('newConfig')
-
-    def test_assign_ports_2_ports(self):
-        self.ixnet.getAttribute.side_effect = ['up', 'down']
-
-        config = {
-            'chassis': '1.1.1.1',
-            'cards': ['1', '2'],
-            'ports': ['2', '2'],
-        }
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen._cfg = config
-
-        self.assertIsNone(ixnet_gen.assign_ports())
-
-        self.assertEqual(self.ixnet.execute.call_count, 2)
-        self.assertEqual(self.ixnet.commit.call_count, 4)
-        self.assertEqual(self.ixnet.getAttribute.call_count, 2)
-
-    @mock.patch.object(IxNet, 'log')
-    def test_assign_ports_port_down(self, mock_log):
-        self.ixnet.getAttribute.return_value = 'down'
-
-        config = {
-            'chassis': '1.1.1.1',
-            'cards': ['1', '2'],
-            'ports': ['3', '4'],
-        }
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen._cfg = config
-        ixnet_gen.assign_ports()
-        mock_log.warning.assert_called()
-
-    def test_assign_ports_no_config(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen._cfg = {}
-
-        self.assertRaises(KeyError, ixnet_gen.assign_ports)
-
-    def test__create_traffic_item(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        self.ixnet.getRoot.return_value = 'rootyrootroot'
-        self.ixnet.add.return_value = 'my_new_traffic_item'
-        self.ixnet.remapIds.return_value = ['my_traffic_item_id']
-
-        ixnet_gen._create_traffic_item()
-
-        self.ixnet.add.assert_called_once_with(
-            'rootyrootroot/traffic', 'trafficItem')
-        self.ixnet.setMultiAttribute.assert_called_once_with(
-            'my_new_traffic_item', '-name', 'RFC2544', '-trafficType', 'raw')
-        self.assertEqual(2, self.ixnet.commit.call_count)
-        self.ixnet.remapIds.assert_called_once_with('my_new_traffic_item')
-        self.ixnet.setAttribute('my_traffic_item_id/tracking',
-                                '-trackBy', 'trafficGroupId0')
-
-    def test__create_flow_groups(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        self.ixnet.getRoot.return_value = 'rootyrootroot'
-        ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
-        ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
-        ixnet_gen._create_flow_groups()
-        ixnet_gen.ixnet.add.assert_has_calls([
-            mock.call('traffic_item', 'endpointSet'),
-            mock.call('traffic_item', 'endpointSet')])
-        ixnet_gen.ixnet.setMultiAttribute.asser_has_calls([
-            mock.call('endp1', '-sources', ['1/protocols'], '-destinations',
-                      ['2/protocols']),
-            mock.call('endp2', '-sources', ['2/protocols'], '-destinations',
-                      ['1/protocols'])])
-
-    def test__append_protocol_to_stack(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        self.ixnet.getRoot.return_value = 'my_root'
-
-        ixnet_gen._append_procotol_to_stack('my_protocol', 'prev_element')
-        self.ixnet.execute.assert_called_with(
-            'append', 'prev_element',
-            'my_root/traffic/protocolTemplate:"my_protocol"')
-
-    def test__setup_config_elements(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-        ixnet_gen.ixnet.getRoot.return_value = 'root_element'
-        ixnet_gen.ixnet.getList.side_effect = [['traffic_item'],
-                                               ['cfg_element']]
-        with mock.patch.object(ixnet_gen, '_append_procotol_to_stack') as \
-                mock_append_proto:
-            ixnet_gen._setup_config_elements()
-        mock_append_proto.assert_has_calls([
-            mock.call(IxNet.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'),
-            mock.call(IxNet.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')])
-        ixnet_gen.ixnet.setAttribute.assert_has_calls([
-            mock.call('cfg_element/frameRateDistribution', '-portDistribution',
-                      'splitRateEvenly'),
-            mock.call('cfg_element/frameRateDistribution',
-                      '-streamDistribution', 'splitRateEvenly')])
-
-    @mock.patch.object(IxNet.IxNextgen, '_create_traffic_item')
-    @mock.patch.object(IxNet.IxNextgen, '_create_flow_groups')
-    @mock.patch.object(IxNet.IxNextgen, '_setup_config_elements')
-    def test_create_traffic_model(self, mock__setup_config_elements,
-                                  mock__create_flow_groups,
-                                  mock__create_traffic_item):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        ixnet_gen.create_traffic_model()
-        mock__create_traffic_item.assert_called_once()
-        mock__create_flow_groups.assert_called_once()
-        mock__setup_config_elements.assert_called_once()
-
-    def test_ix_update_frame(self):
-        static_traffic_params = {
-            UPLINK: {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": {
-                        "64B": "100",
-                        "1KB": "0",
-                    },
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            DOWNLINK: {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": False,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.remapIds.return_value = ["0"]
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-        self.ixnet.getList.side_effect = [
-            [1],
-            [1],
-            [1],
-            [
-                "ethernet.header.destinationAddress",
-                "ethernet.header.sourceAddress",
-            ],
-        ]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_update_frame(static_traffic_params)
-        self.assertIsNone(result)
-        self.assertEqual(self.ixnet.setMultiAttribute.call_count, 7)
-        self.assertEqual(self.ixnet.commit.call_count, 2)
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_update_ether_multi_attribute(self):
-        pass
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_update_ether_multi_attributes(self):
-        pass
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_update_ether(self):
-        pass
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_ix_update_udp(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_update_udp({})
-        self.assertIsNone(result)
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_ix_update_tcp(self):
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_update_tcp({})
-        self.assertIsNone(result)
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_ix_start_traffic(self):
-        self.ixnet.getList.return_value = [0]
-        self.ixnet.getAttribute.return_value = 'down'
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_start_traffic()
-        self.assertIsNone(result)
-        self.ixnet.getList.assert_called_once()
-        self.assertEqual(self.ixnet.execute.call_count, 3)
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_ix_stop_traffic(self):
-        self.ixnet.getList.return_value = [0]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_stop_traffic()
-        self.assertIsNone(result)
-        self.ixnet.getList.assert_called_once()
-        self.ixnet.execute.assert_called_once()
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_build_stats_map(self):
-        pass
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_get_statistics(self):
-        self.ixnet.execute.return_value = ""
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.get_statistics()
-        self.assertIsNotNone(result)
-        self.assertEqual(self.ixnet.execute.call_count, 12)
-
-    # NOTE(ralonsoh): to be updated in next patchset
-    def test_add_ip_header_v4(self):
-        static_traffic_params = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "count": 1024,
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.remapIds.return_value = ["0"]
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-        self.ixnet.getList.side_effect = [[1], [0], [0], ["srcIp", "dstIp"]]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.add_ip_header(static_traffic_params,
-                                         IxNet.IP_VERSION_4)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_called()
-        self.ixnet.commit.assert_called_once()
-
-    def test_add_ip_header_v4_nothing_to_do(self):
-        static_traffic_params = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "count": 1024,
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.remapIds.return_value = ["0"]
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-        self.ixnet.getList.side_effect = [[1], [0, 1], [0], ["srcIp", "dstIp"]]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.add_ip_header(static_traffic_params,
-                                         IxNet.IP_VERSION_4)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_called()
-        self.ixnet.commit.assert_called_once()
-
-    def test_add_ip_header_v6(self):
-        static_traffic_profile = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.getList.side_effect = [[1], [1], [1], ["srcIp", "dstIp"]]
-        self.ixnet.remapIds.return_value = ["0"]
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.add_ip_header(static_traffic_profile,
-                                         IxNet.IP_VERSION_6)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_called()
-        self.ixnet.commit.assert_called_once()
-
-    def test_add_ip_header_v6_nothing_to_do(self):
-        static_traffic_params = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "count": 1024,
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": True,
-                    "framesize": {"64B": "100"},
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.getList.side_effect = [[1], [0, 1], [1], ["srcIP", "dstIP"]]
-        self.ixnet.remapIds.return_value = ["0"]
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.add_ip_header(static_traffic_params,
-                                         IxNet.IP_VERSION_6)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_not_called()
-
-    def test_set_random_ip_multi_attributes_bad_ip_version(self):
-        bad_ip_version = object()
-        ixnet_gen = IxNet.IxNextgen(mock.Mock())
-        with self.assertRaises(ValueError):
-            ixnet_gen.set_random_ip_multi_attributes(
-                mock.Mock(), bad_ip_version, mock.Mock(), mock.Mock())
-
-    def test_get_config(self):
-        tg_cfg = {
-            "vdu": [
-                {
-                    "external-interface": [
-                        {
-                            "virtual-interface": {
-                                "vpci": "0000:07:00.1",
-                            },
-                        },
-                        {
-                            "virtual-interface": {
-                                "vpci": "0001:08:01.2",
-                            },
-                        },
-                    ],
-                },
-            ],
-            "mgmt-interface": {
-                "ip": "test1",
-                "tg-config": {
-                    "dut_result_dir": "test2",
-                    "version": "test3",
-                    "ixchassis": "test4",
-                    "tcl_port": "test5",
-                },
-            }
-        }
-
-        expected = {
-            'machine': 'test1',
-            'port': 'test5',
-            'chassis': 'test4',
-            'cards': ['0000', '0001'],
-            'ports': ['07', '08'],
-            'output_dir': 'test2',
-            'version': 'test3',
-            'bidir': True,
-        }
-
-        result = IxNet.IxNextgen.get_config(tg_cfg)
-        self.assertEqual(result, expected)
-
-    def test_ix_update_ether(self):
-        static_traffic_params = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:03",
-                    "framesPerSecond": True,
-                    "framesize": 64,
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l2": {
-                    "dstmac": "00:00:00:00:00:04",
-                    "framesPerSecond": True,
-                    "framesize": 64,
-                    "srcmac": "00:00:00:00:00:01"
-                },
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-        self.ixnet.getList.side_effect = [
-            [1],
-            [1],
-            [1],
-            [
-                "ethernet.header.destinationAddress",
-                "ethernet.header.sourceAddress",
-            ],
-        ]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_update_ether(static_traffic_params)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_called()
-
-    def test_ix_update_ether_nothing_to_do(self):
-        static_traffic_params = {
-            "uplink_0": {
-                "id": 1,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l3": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "dscp": 0,
-                    "dstip4": "152.16.40.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.100.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "2001",
-                    "srcport": "1234"
-                },
-                "traffic_type": "continuous"
-            },
-            "downlink_0": {
-                "id": 2,
-                "bidir": "False",
-                "duration": 60,
-                "iload": "100",
-                "outer_l3": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v4": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l3v6": {
-                    "count": 1024,
-                    "dscp": 0,
-                    "dstip4": "152.16.100.20",
-                    "proto": "udp",
-                    "srcip4": "152.16.40.20",
-                    "ttl": 32
-                },
-                "outer_l4": {
-                    "dstport": "1234",
-                    "srcport": "2001"
-                },
-                "traffic_type": "continuous"
-            }
-        }
-
-        self.ixnet.setMultiAttribute.return_value = [1]
-        self.ixnet.commit.return_value = [1]
-        self.ixnet.getList.side_effect = [
-            [1],
-            [1],
-            [1],
-            [
-                "ethernet.header.destinationAddress",
-                "ethernet.header.sourceAddress",
-            ],
-        ]
-
-        ixnet_gen = IxNet.IxNextgen(self.ixnet)
-
-        result = ixnet_gen.ix_update_ether(static_traffic_params)
-        self.assertIsNone(result)
-        self.ixnet.setMultiAttribute.assert_not_called()
diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
new file mode 100644 (file)
index 0000000..5bc2d8b
--- /dev/null
@@ -0,0 +1,406 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+import IxNetwork
+import unittest
+
+from yardstick.common import exceptions
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
+
+
+UPLINK = 'uplink'
+DOWNLINK = 'downlink'
+
+TRAFFIC_PARAMETERS = {
+    UPLINK: {
+        'id': 1,
+        'bidir': 'False',
+        'duration': 60,
+        'iload': '100',
+        'outer_l2': {
+            'framesize': {'64B': '25', '256B': '75'}
+        },
+        'outer_l3': {
+            'dscp': 0,
+            'dstip4': '152.16.40.20',
+            'proto': 'udp',
+            'srcip4': '152.16.100.20',
+            'ttl': 32
+        },
+        'outer_l3v4': {
+            'dscp': 0,
+            'dstip4': '152.16.40.20',
+            'proto': 'udp',
+            'srcip4': '152.16.100.20',
+            'ttl': 32
+        },
+        'outer_l3v6': {
+            'count': 1024,
+            'dscp': 0,
+            'dstip4': '152.16.100.20',
+            'proto': 'udp',
+            'srcip4': '152.16.40.20',
+            'ttl': 32
+        },
+        'outer_l4': {
+            'dstport': '2001',
+            'srcport': '1234'
+        },
+        'traffic_type': 'continuous'
+    },
+    DOWNLINK: {
+        'id': 2,
+        'bidir': 'False',
+        'duration': 60,
+        'iload': '100',
+        'outer_l2': {
+            'framesize': {'128B': '35', '1024B': '65'}
+        },
+        'outer_l3': {
+            'count': 1024,
+            'dscp': 0,
+            'dstip4': '152.16.100.20',
+            'proto': 'udp',
+            'srcip4': '152.16.40.20',
+            'ttl': 32
+        },
+        'outer_l3v4': {
+            'count': 1024,
+            'dscp': 0,
+            'dstip4': '152.16.100.20',
+            'proto': 'udp',
+            'srcip4': '152.16.40.20',
+            'ttl': 32
+        },
+        'outer_l3v6': {
+            'count': 1024,
+            'dscp': 0,
+            'dstip4': '152.16.100.20',
+            'proto': 'udp',
+            'srcip4': '152.16.40.20',
+            'ttl': 32
+        },
+        'outer_l4': {
+            'dstport': '1234',
+            'srcport': '2001'
+        },
+        'traffic_type': 'continuous'
+    }
+}
+
+
+class TestIxNextgen(unittest.TestCase):
+
+    def setUp(self):
+        self.ixnet = mock.Mock()
+        self.ixnet.execute = mock.Mock()
+        self.ixnet.getRoot.return_value = 'my_root'
+
+    def test_get_config(self):
+        tg_cfg = {
+            'vdu': [
+                {
+                    'external-interface': [
+                        {'virtual-interface': {'vpci': '0000:07:00.1'}},
+                        {'virtual-interface': {'vpci': '0001:08:01.2'}}
+                    ]
+                },
+            ],
+            'mgmt-interface': {
+                'ip': 'test1',
+                'tg-config': {
+                    'dut_result_dir': 'test2',
+                    'version': 'test3',
+                    'ixchassis': 'test4',
+                    'tcl_port': 'test5',
+                },
+            }
+        }
+
+        expected = {
+            'machine': 'test1',
+            'port': 'test5',
+            'chassis': 'test4',
+            'cards': ['0000', '0001'],
+            'ports': ['07', '08'],
+            'output_dir': 'test2',
+            'version': 'test3',
+            'bidir': True,
+        }
+
+        result = ixnet_api.IxNextgen.get_config(tg_cfg)
+        self.assertEqual(result, expected)
+
+    def test__get_config_element_by_flow_group_name(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
+                                                ['fg_01']]
+        ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_01'
+        output = ixnet_gen._get_config_element_by_flow_group_name(
+            'flow_group_01')
+        self.assertEqual('traffic_item/configElement:flow_group_01', output)
+
+    def test__get_config_element_by_flow_group_name_no_match(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
+                                                ['fg_01']]
+        ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_02'
+        output = ixnet_gen._get_config_element_by_flow_group_name(
+            'flow_group_01')
+        self.assertIsNone(output)
+
+    def test__parse_framesize(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        framesize = {'64B': '75', '512b': '25'}
+        output = ixnet_gen._parse_framesize(framesize)
+        for idx in range(len(framesize)):
+            if output[idx * 2] == 64:
+                self.assertEqual(75, output[idx * 2 + 1])
+            elif output[idx * 2] == 512:
+                self.assertEqual(25, output[idx * 2 + 1])
+            else:
+                raise self.failureException('Framesize (64, 512) not present')
+
+    @mock.patch.object(IxNetwork, 'IxNet')
+    def test_connect(self, mock_ixnet):
+        mock_ixnet.return_value = self.ixnet
+        ixnet_gen = ixnet_api.IxNextgen()
+        with mock.patch.object(ixnet_gen, 'get_config') as mock_config:
+            mock_config.return_value = {'machine': 'machine_fake',
+                                        'port': 'port_fake',
+                                        'version': 12345}
+            ixnet_gen.connect(mock.ANY)
+
+        self.ixnet.connect.assert_called_once_with(
+            'machine_fake', '-port', 'port_fake', '-version', '12345')
+        mock_config.assert_called_once()
+
+    def test_connect_invalid_config_no_machine(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.get_config = mock.Mock(return_value={
+            'port': 'port_fake',
+            'version': '12345'})
+        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
+        self.ixnet.connect.assert_not_called()
+
+    def test_connect_invalid_config_no_port(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.get_config = mock.Mock(return_value={
+            'machine': 'machine_fake',
+            'version': '12345'})
+        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
+        self.ixnet.connect.assert_not_called()
+
+    def test_connect_invalid_config_no_version(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.get_config = mock.Mock(return_value={
+            'machine': 'machine_fake',
+            'port': 'port_fake'})
+        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
+        self.ixnet.connect.assert_not_called()
+
+    def test_connect_no_config(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.get_config = mock.Mock(return_value={})
+        self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
+        self.ixnet.connect.assert_not_called()
+
+    def test_clear_config(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.clear_config()
+        self.ixnet.execute.assert_called_once_with('newConfig')
+
+    @mock.patch.object(ixnet_api, 'log')
+    def test_assign_ports_2_ports(self, *args):
+        self.ixnet.getAttribute.side_effect = ['up', 'down']
+        config = {
+            'chassis': '1.1.1.1',
+            'cards': ['1', '2'],
+            'ports': ['2', '2']}
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._cfg = config
+
+        self.assertIsNone(ixnet_gen.assign_ports())
+        self.assertEqual(self.ixnet.execute.call_count, 2)
+        self.assertEqual(self.ixnet.commit.call_count, 4)
+        self.assertEqual(self.ixnet.getAttribute.call_count, 2)
+
+    @mock.patch.object(ixnet_api, 'log')
+    def test_assign_ports_port_down(self, mock_log):
+        self.ixnet.getAttribute.return_value = 'down'
+        config = {
+            'chassis': '1.1.1.1',
+            'cards': ['1', '2'],
+            'ports': ['3', '4']}
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._cfg = config
+        ixnet_gen.assign_ports()
+        mock_log.warning.assert_called()
+
+    def test_assign_ports_no_config(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._cfg = {}
+        self.assertRaises(KeyError, ixnet_gen.assign_ports)
+
+    def test__create_traffic_item(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        self.ixnet.add.return_value = 'my_new_traffic_item'
+        self.ixnet.remapIds.return_value = ['my_traffic_item_id']
+
+        ixnet_gen._create_traffic_item()
+        self.ixnet.add.assert_called_once_with(
+            'my_root/traffic', 'trafficItem')
+        self.ixnet.setMultiAttribute.assert_called_once_with(
+            'my_new_traffic_item', '-name', 'RFC2544', '-trafficType', 'raw')
+        self.assertEqual(2, self.ixnet.commit.call_count)
+        self.ixnet.remapIds.assert_called_once_with('my_new_traffic_item')
+        self.ixnet.setAttribute('my_traffic_item_id/tracking',
+                                '-trackBy', 'trafficGroupId0')
+
+    def test__create_flow_groups(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
+        ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
+        ixnet_gen._create_flow_groups()
+        ixnet_gen.ixnet.add.assert_has_calls([
+            mock.call('traffic_item', 'endpointSet'),
+            mock.call('traffic_item', 'endpointSet')])
+        ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
+            mock.call('endp1', '-name', '1', '-sources', ['1/protocols'],
+                      '-destinations', ['2/protocols']),
+            mock.call('endp2', '-name', '2', '-sources', ['2/protocols'],
+                      '-destinations', ['1/protocols'])])
+
+    def test__append_protocol_to_stack(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+
+        ixnet_gen._append_procotol_to_stack('my_protocol', 'prev_element')
+        self.ixnet.execute.assert_called_with(
+            'append', 'prev_element',
+            'my_root/traffic/protocolTemplate:"my_protocol"')
+
+    def test__setup_config_elements(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.ixnet.getList.side_effect = [['traffic_item'],
+                                               ['cfg_element']]
+        with mock.patch.object(ixnet_gen, '_append_procotol_to_stack') as \
+                mock_append_proto:
+            ixnet_gen._setup_config_elements()
+        mock_append_proto.assert_has_calls([
+            mock.call(ixnet_api.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'),
+            mock.call(ixnet_api.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')])
+        ixnet_gen.ixnet.setAttribute.assert_has_calls([
+            mock.call('cfg_element/frameRateDistribution', '-portDistribution',
+                      'splitRateEvenly'),
+            mock.call('cfg_element/frameRateDistribution',
+                      '-streamDistribution', 'splitRateEvenly')])
+
+    @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
+    @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
+    @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
+    def test_create_traffic_model(self, mock__setup_config_elements,
+                                  mock__create_flow_groups,
+                                  mock__create_traffic_item):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+
+        ixnet_gen.create_traffic_model()
+        mock__create_traffic_item.assert_called_once()
+        mock__create_flow_groups.assert_called_once()
+        mock__setup_config_elements.assert_called_once()
+
+    def test__get_field_in_stack_item(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
+        output = ixnet_gen._get_field_in_stack_item(mock.ANY, 'field2')
+        self.assertEqual('field2', output)
+
+    def test__get_field_in_stack_item_field_not_present(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
+        with self.assertRaises(exceptions.IxNetworkFieldNotPresentInStackItem):
+            ixnet_gen._get_field_in_stack_item(mock.ANY, 'field3')
+
+    def test__update_frame_mac(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        with mock.patch.object(ixnet_gen, '_get_field_in_stack_item') as \
+                mock_get_field:
+            mock_get_field.return_value = 'field_descriptor'
+            ixnet_gen._update_frame_mac('ethernet_descriptor', 'field', 'mac')
+        mock_get_field.assert_called_once_with('ethernet_descriptor', 'field')
+        ixnet_gen.ixnet.setMultiAttribute(
+            'field_descriptor', '-singleValue', 'mac', '-fieldValue', 'mac',
+            '-valueType', 'singleValue')
+        ixnet_gen.ixnet.commit.assert_called_once()
+
+    def test_update_frame(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        with mock.patch.object(
+                ixnet_gen, '_get_config_element_by_flow_group_name',
+                return_value='cfg_element'), \
+                mock.patch.object(ixnet_gen, '_update_frame_mac') as \
+                mock_update_frame:
+            ixnet_gen.update_frame(TRAFFIC_PARAMETERS)
+
+        self.assertEqual(6, len(ixnet_gen.ixnet.setMultiAttribute.mock_calls))
+        self.assertEqual(4, len(mock_update_frame.mock_calls))
+
+    def test_update_frame_flow_not_present(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        with mock.patch.object(
+                ixnet_gen, '_get_config_element_by_flow_group_name',
+                return_value=None):
+            with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
+                ixnet_gen.update_frame(TRAFFIC_PARAMETERS)
+
+    def test_set_random_ip_multi_attribute(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        ixnet_gen._ixnet = self.ixnet
+        ixnet_gen.set_random_ip_multi_attribute('ipv4', 20, 30, 40, 100)
+        ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+            'ipv4', '-seed', '20', '-fixedBits', '30', '-randomMask', '40',
+            '-valueType', 'random', '-countValue', '100')
+
+    def test_get_statistics(self):
+        ixnet_gen = ixnet_api.IxNextgen()
+        port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"'
+        flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"'
+        with mock.patch.object(ixnet_gen, '_build_stats_map') as \
+                mock_build_stats:
+            ixnet_gen.get_statistics()
+
+        mock_build_stats.assert_has_calls([
+            mock.call(port_statistics, ixnet_gen.PORT_STATS_NAME_MAP),
+            mock.call(flow_statistics, ixnet_gen.LATENCY_NAME_MAP)])