Merge "Add OvS 2.8.1 support into SA context"
authorAbhijit Sinha <abhijit.sinha@intel.com>
Fri, 12 Oct 2018 15:39:21 +0000 (15:39 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Fri, 12 Oct 2018 15:39:21 +0000 (15:39 +0000)
28 files changed:
ansible/roles/download_samplevnfs/defaults/main.yml
samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg
samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg
samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml [new file with mode: 0644]
yardstick/benchmark/contexts/standalone/model.py
yardstick/benchmark/contexts/standalone/ovs_dpdk.py
yardstick/benchmark/runners/duration.py
yardstick/benchmark/runners/proxduration.py
yardstick/benchmark/scenarios/base.py
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
yardstick/network_services/traffic_profile/base.py
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/traffic_profile/prox_binsearch.py
yardstick/network_services/traffic_profile/prox_profile.py
yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py [new file with mode: 0644]
yardstick/network_services/vnf_generic/vnf/prox_helpers.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/tests/unit/benchmark/runner/test_duration.py
yardstick/tests/unit/benchmark/runner/test_proxduration.py
yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py [new file with mode: 0644]
yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py

index c5e880e..104f594 100644 (file)
@@ -1,4 +1,16 @@
 ---
+# samplevnf_version must be a valid version accepted by "git checkout"
+# It can be either:
+# - a branch name: fetch branch latest commits, as of installation time
+# - a tag name: frozen and reproducible, from stable branches, or
+# - a commit id: frozen and reproducible, from any branch
+# Some examples:
+# - branch name: "master", "stable/gambia", "stable/fraser"
+# - tag name: "opnfv-6.2.0"
+# - commit id: "3afd384b7e68a3cd29f4d2cdf39785f8441d0b6f"
+# Please refer to https://git.opnfv.org/samplevnf for possible values
+# beyond the one specified below
+
 samplevnf_url: "https://git.opnfv.org/samplevnf"
 samplevnf_dest: "{{ clone_dest }}/samplevnf"
-samplevnf_version: "stable/fraser"
+samplevnf_version: "3afd384b7e68a3cd29f4d2cdf39785f8441d0b6f"
diff --git a/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml
new file mode 100644 (file)
index 0000000..007d16f
--- /dev/null
@@ -0,0 +1,49 @@
+# 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.
+nsd:nsd-catalog:
+    nsd:
+    -   id: agnostic-topology
+        name: agnostic-topology
+        short-name: agnostic-topology
+        description: agnostic-topology
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: tg__0
+            VNF model: ../../vnf_descriptors/ixia_rfc2544_tpl.yaml      #TG type
+        -   member-vnf-index: '2'
+            vnfd-id-ref: vnf__0
+            VNF model: ../../vnf_descriptors/agnostic_vnf.yaml      #VNF type
+
+        vld:
+        -   id: uplink_0
+            name: tg__0 to vnf__0 link 1
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: tg__0
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: vnf__0
+
+        -   id: downlink_0
+            name: vnf__0 to tg__0 link 2
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: vnf__0
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml
new file mode 100644 (file)
index 0000000..173880f
--- /dev/null
@@ -0,0 +1,49 @@
+# 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.
+nsd:nsd-catalog:
+    nsd:
+    -   id: agnostic-topology
+        name: agnostic-topology
+        short-name: agnostic-topology
+        description: agnostic-topology
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: tg__0
+            VNF model: ../../vnf_descriptors/tg_rfc2544_tpl.yaml      #TG type
+        -   member-vnf-index: '2'
+            vnfd-id-ref: vnf__0
+            VNF model: ../../vnf_descriptors/agnostic_vnf.yaml      #VNF type
+
+        vld:
+        -   id: uplink_0
+            name: tg__0 to vnf__0 link 1
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: tg__0
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: vnf__0
+
+        -   id: downlink_0
+            name: vnf__0 to tg__0 link 2
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: vnf__0
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__0
\ No newline at end of file
diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml
new file mode 100644 (file)
index 0000000..53935de
--- /dev/null
@@ -0,0 +1,45 @@
+# 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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+  traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+  topology: agnostic_vnf_topology_trex_2ports.yaml
+  nodes:
+    tg__0: tg_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+      uplink: {64B: 100}
+      downlink: {64B: 100}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+        []
+  runner:
+    type: Iteration
+    iterations: 10
+    interval: 35
+context:
+  type: Node
+  name: yardstick
+  nfvi_type: baremetal
+  file: /etc/yardstick/nodes/pod.yaml
diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml
new file mode 100644 (file)
index 0000000..c054a98
--- /dev/null
@@ -0,0 +1,45 @@
+# 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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+  traffic_profile: ../../traffic_profiles/ixia_ipv4_latency.yaml
+  topology: agnostic_vnf_topology_ixia_2ports.yaml
+  nodes:
+    tg__0: tg_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+      uplink: {64B: 100}
+      downlink: {64B: 100}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+        []
+  runner:
+    type: Iteration
+    iterations: 10
+    interval: 35
+context:
+  type: Node
+  name: yardstick
+  nfvi_type: baremetal
+  file: /etc/yardstick/nodes/pod_ixia.yaml
index 80b29f3..35f3646 100644 (file)
@@ -22,12 +22,16 @@ no-output=no ; disable DPDK debug output
 [port 0]
 name=if0
 mac=hardware
+rx desc=2048
+tx desc=2048
 [port 1]
 name=if1
 mac=hardware
+rx desc=2048
+tx desc=2048
 
 [defaults]
-mempool size=4K
+mempool size=8K
 
 [lua]
 lpm4 = dofile("ipv4-2port.lua")
index 09adbbe..bd696c4 100644 (file)
@@ -22,18 +22,26 @@ no-output=no ; disable DPDK debug output
 [port 0]
 name=if0
 mac=hardware
+rx desc=2048
+tx desc=2048
 [port 1]
 name=if1
 mac=hardware
+rx desc=2048
+tx desc=2048
 [port 2]
 name=if2
 mac=hardware
+rx desc=2048
+tx desc=2048
 [port 3]
 name=if3
 mac=hardware
+rx desc=2048
+tx desc=2048
 
 [defaults]
-mempool size=4K
+mempool size=8K
 
 [lua]
 lpm4 = dofile("ipv4.lua")
diff --git a/samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml b/samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml
new file mode 100644 (file)
index 0000000..14a3910
--- /dev/null
@@ -0,0 +1,44 @@
+# 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.
+
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: AgnosticVnf
+        name: AgnosticVnf
+        short-name: AgnosticVnf
+        description: 'VNFD for AgnosticVNF which wraps around any unsupported VNF
+                      and allows for blackbox testing of the VNF.'
+        mgmt-interface:
+            vdu-id: AgnosticVnf-baremetal
+            {% if user is defined %}
+            user: '{{user}}'  # Value filled by vnfdgen
+            {% endif %}
+            {% if password is defined %}
+            password: '{{password}}'  # Value filled by vnfdgen
+            {% endif %}
+            {% if ip is defined %}
+            ip: '{{ip}}'  # Value filled by vnfdgen
+            {% endif %}
+            {% if key_filename is defined %}
+            key_filename: '{{key_filename}}'  # Value filled by vnfdgen
+            {% endif %}
+        vdu:
+        -   id: AgnosticVnf-baremetal
+            name: AgnosticVnf-baremetal
+            description: Agnostic vnf
+            routing_table: {{ routing_table }}
+            nd_route_tbl: {{ nd_route_tbl }}
+        benchmark:
+            kpi:
+                []
\ No newline at end of file
index fa78fc1..1004c62 100644 (file)
@@ -564,7 +564,7 @@ class StandaloneContextHelper(object):
             key_filename = ''.join(
                 [constants.YARDSTICK_ROOT_PATH,
                  'yardstick/resources/files/yardstick_key-',
-                 id_name])
+                 id_name, '-', vm_name])
             ssh.SSH.gen_keys(key_filename)
             node['key_filename'] = key_filename
         # Update image with public key
index 5d722e2..3ad1097 100644 (file)
@@ -167,8 +167,7 @@ class OvsDpdkContext(base.Context):
         version = self.ovs_properties.get('version', {})
         ovs_ver = [int(x) for x in version.get('ovs', self.DEFAULT_OVS).split('.')]
         ovs_add_port = ('ovs-vsctl add-port {br} {port} -- '
-                        'set Interface {port} type={type_}{dpdk_args}')
-        ovs_add_queue = 'ovs-vsctl set Interface {port} options:n_rxq={queue}'
+                        'set Interface {port} type={type_}{dpdk_args}{dpdk_rxq}')
         chmod_vpath = 'chmod 0777 {0}/var/run/openvswitch/dpdkvhostuser*'
 
         cmd_list = [
@@ -177,6 +176,8 @@ class OvsDpdkContext(base.Context):
             'ovs-vsctl add-br {0} -- set bridge {0} datapath_type=netdev'.
             format(MAIN_BRIDGE)
         ]
+        dpdk_rxq = " options:n_rxq={queue}".format(
+            queue=self.ovs_properties.get("queues", 1))
 
         ordered_network = collections.OrderedDict(self.networks)
         for index, vnf in enumerate(ordered_network.values()):
@@ -184,10 +185,7 @@ class OvsDpdkContext(base.Context):
                 dpdk_args = " options:dpdk-devargs=%s" % vnf.get("phy_port")
             dpdk_list.append(ovs_add_port.format(
                 br=MAIN_BRIDGE, port='dpdk%s' % vnf.get("port_num", 0),
-                type_='dpdk', dpdk_args=dpdk_args))
-            dpdk_list.append(ovs_add_queue.format(
-                port='dpdk%s' % vnf.get("port_num", 0),
-                queue=self.ovs_properties.get("queues", 1)))
+                type_='dpdk', dpdk_args=dpdk_args, dpdk_rxq=dpdk_rxq))
 
         # Sorting the array to make sure we execute dpdk0... in the order
         list.sort(dpdk_list)
@@ -197,7 +195,7 @@ class OvsDpdkContext(base.Context):
         for index, _ in enumerate(ordered_network):
             cmd_list.append(ovs_add_port.format(
                 br=MAIN_BRIDGE, port='dpdkvhostuser%s' % index,
-                type_='dpdkvhostuser', dpdk_args=""))
+                type_='dpdkvhostuser', dpdk_args="", dpdk_rxq=""))
 
         ovs_flow = ("ovs-ofctl add-flow {0} in_port=%s,action=output:%s".
                     format(MAIN_BRIDGE))
index 14fd8bb..55c3690 100644 (file)
@@ -106,7 +106,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         sequence += 1
 
-        if (errors and sla_action is None) or time.time() > timeout or aborted.is_set():
+        if ((errors and sla_action is None) or time.time() > timeout
+                or aborted.is_set() or benchmark.is_ended()):
             LOG.info("Worker END")
             break
 
index 61a468f..e217904 100644 (file)
@@ -112,7 +112,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         sequence += 1
 
-        if (errors and sla_action is None) or time.time() > timeout or aborted.is_set():
+        if ((errors and sla_action is None) or time.time() > timeout
+                or aborted.is_set() or benchmark.is_ended()):
             LOG.info("Worker END")
             break
 
index 90a87ac..1737bb9 100644 (file)
@@ -50,6 +50,9 @@ class Scenario(object):
     def run(self, *args):
         """Entry point for scenario classes, called from runner worker"""
 
+    def is_ended(self):
+        return False
+
     def teardown(self):
         """Default teardown implementation for Scenario classes"""
         pass
index 6d68c5e..20fff61 100644 (file)
@@ -63,6 +63,9 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         self.bin_path = get_nsb_option('bin_path', '')
         self._mq_ids = []
 
+    def is_ended(self):
+        return self.traffic_profile is not None and self.traffic_profile.is_ended()
+
     def _get_ip_flow_range(self, ip_start_range):
         """Retrieve a CIDR first and last viable IPs
 
index 12f081d..d4f75ba 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-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.
@@ -121,6 +121,11 @@ class IxNextgen(object):  # pragma: no cover
             return self._ixnet
         raise exceptions.IxNetworkClientNotConnected()
 
+    def get_vports(self):
+        """Return the list of assigned ports (vport objects)"""
+        vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
+        return vports
+
     def _get_config_element_by_flow_group_name(self, flow_group_name):
         """Get a config element using the flow group name
 
@@ -252,7 +257,7 @@ class IxNextgen(object):  # pragma: no cover
             if self.ixnet.getAttribute(vport, '-state') != 'up':
                 log.warning('Port %s is down', vport)
 
-    def _create_traffic_item(self):
+    def _create_traffic_item(self, traffic_type='raw'):
         """Create the traffic item to hold the flow groups
 
         The traffic item tracking by "Traffic Item" is enabled to retrieve the
@@ -262,7 +267,7 @@ class IxNextgen(object):  # pragma: no cover
         traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic',
                                       'trafficItem')
         self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544',
-                                     '-trafficType', 'raw')
+                                     '-trafficType', traffic_type)
         self.ixnet.commit()
 
         traffic_item_id = self.ixnet.remapIds(traffic_item)[0]
@@ -270,27 +275,25 @@ class IxNextgen(object):  # pragma: no cover
                                 '-trackBy', 'trafficGroupId0')
         self.ixnet.commit()
 
-    def _create_flow_groups(self):
-        """Create the flow groups between the assigned ports"""
+    def _create_flow_groups(self, uplink, downlink):
+        """Create the flow groups between the endpoints"""
         traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic',
                                              'trafficItem')[0]
         log.info('Create the flow groups')
-        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):
+        for up, down in zip(uplink, downlink):
             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, '-name', str(index + 1),
-                '-sources', [up + '/protocols'],
-                '-destinations', [down + '/protocols'])
+                '-sources', [up],
+                '-destinations', [down])
             self.ixnet.setMultiAttribute(
                 endpoint_set_2, '-name', str(index + 2),
-                '-sources', [down + '/protocols'],
-                '-destinations', [up + '/protocols'])
+                '-sources', [down],
+                '-destinations', [up])
             self.ixnet.commit()
             index += 2
 
@@ -300,7 +303,7 @@ class IxNextgen(object):  # pragma: no cover
                     '/traffic/protocolTemplate:"{}"'.format(protocol_name))
         self.ixnet.execute('append', previous_element, protocol)
 
-    def _setup_config_elements(self):
+    def _setup_config_elements(self, add_default_proto=True):
         """Setup the config elements
 
         The traffic item is configured to allow individual configurations per
@@ -322,12 +325,13 @@ class IxNextgen(object):  # pragma: no cover
             self.ixnet.setAttribute(config_element + '/frameRateDistribution',
                                     '-streamDistribution', 'splitRateEvenly')
             self.ixnet.commit()
-            self._append_procotol_to_stack(
-                PROTO_UDP, config_element + '/stack:"ethernet-1"')
-            self._append_procotol_to_stack(
-                PROTO_IPV4, config_element + '/stack:"ethernet-1"')
+            if add_default_proto:
+                self._append_procotol_to_stack(
+                    PROTO_UDP, config_element + '/stack:"ethernet-1"')
+                self._append_procotol_to_stack(
+                    PROTO_IPV4, config_element + '/stack:"ethernet-1"')
 
-    def create_traffic_model(self):
+    def create_traffic_model(self, uplink_ports, downlink_ports):
         """Create a traffic item and the needed flow groups
 
         Each flow group inside the traffic item (only one is present)
@@ -338,10 +342,27 @@ class IxNextgen(object):  # pragma: no cover
             FlowGroup3: port3    -> port4
             FlowGroup4: port3    <- port4
         """
-        self._create_traffic_item()
-        self._create_flow_groups()
+        self._create_traffic_item('raw')
+        uplink_endpoints = [port + '/protocols' for port in uplink_ports]
+        downlink_endpoints = [port + '/protocols' for port in downlink_ports]
+        self._create_flow_groups(uplink_endpoints, downlink_endpoints)
         self._setup_config_elements()
 
+    def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies):
+        """Create a traffic item and the needed flow groups
+
+        Each flow group inside the traffic item (only one is present)
+        represents the traffic between two topologies:
+                        (uplink)    (downlink)
+            FlowGroup1: uplink1    -> downlink1
+            FlowGroup2: uplink1    <- downlink1
+            FlowGroup3: uplink2    -> downlink2
+            FlowGroup4: uplink2    <- downlink2
+        """
+        self._create_traffic_item('ipv4')
+        self._create_flow_groups(uplink_topologies, downlink_topologies)
+        self._setup_config_elements(False)
+
     def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
         """Set the MAC address in a config element stack Ethernet field
 
@@ -385,16 +406,15 @@ class IxNextgen(object):  # pragma: no cover
                 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
 
             type = traffic_param.get('traffic_type', 'fixedDuration')
-            rate = traffic_param['rate']
             rate_unit = (
                 'framesPerSecond' if traffic_param['rate_unit'] ==
                 tp_base.TrafficProfileConfig.RATE_FPS else 'percentLineRate')
             weighted_range_pairs = self._parse_framesize(
-                traffic_param['outer_l2']['framesize'])
+                traffic_param['outer_l2'].get('framesize', {}))
             srcmac = str(traffic_param['outer_l2'].get('srcmac', '00:00:00:00:00:01'))
             dstmac = str(traffic_param['outer_l2'].get('dstmac', '00:00:00:00:00:02'))
 
-            if traffic_param['outer_l2']['QinQ']:
+            if traffic_param['outer_l2'].get('QinQ'):
                 s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN']
                 c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN']
 
@@ -419,21 +439,27 @@ class IxNextgen(object):  # pragma: no cover
             self.ixnet.setMultiAttribute(
                 config_element + '/transmissionControl',
                 '-type', type, '-duration', duration)
+
             self.ixnet.setMultiAttribute(
                 config_element + '/frameRate',
-                '-rate', rate, '-type', rate_unit)
-            self.ixnet.setMultiAttribute(
-                config_element + '/frameSize',
-                '-type', 'weightedPairs',
-                '-weightedRangePairs', weighted_range_pairs)
+                '-rate', traffic_param['rate'], '-type', rate_unit)
+
+            if len(weighted_range_pairs):
+                self.ixnet.setMultiAttribute(
+                    config_element + '/frameSize',
+                    '-type', 'weightedPairs',
+                    '-weightedRangePairs', weighted_range_pairs)
+
             self.ixnet.commit()
 
-            self._update_frame_mac(
-                self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
-                'destinationAddress', dstmac)
-            self._update_frame_mac(
-                self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
-                'sourceAddress', srcmac)
+            if dstmac:
+                self._update_frame_mac(
+                    self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
+                    'destinationAddress', dstmac)
+            if srcmac:
+                self._update_frame_mac(
+                    self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
+                    'sourceAddress', srcmac)
 
     def _update_vlan_tag(self, fg_id, params, vlan=0):
         field_to_param_map = {
@@ -493,20 +519,24 @@ class IxNextgen(object):  # pragma: no cover
             if not self._get_config_element_by_flow_group_name(fg_id):
                 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
 
-            count = traffic_param['outer_l3']['count']
-            srcip = str(traffic_param['outer_l3']['srcip'])
-            dstip = str(traffic_param['outer_l3']['dstip'])
-            srcseed = traffic_param['outer_l3']['srcseed']
-            dstseed = traffic_param['outer_l3']['dstseed']
-            srcmask = traffic_param['outer_l3']['srcmask'] or IP_VERSION_4_MASK
-            dstmask = traffic_param['outer_l3']['dstmask'] or IP_VERSION_4_MASK
-
-            self._update_ipv4_address(
-                self._get_stack_item(fg_id, PROTO_IPV4)[0],
-                'srcIp', srcip, srcseed, srcmask, count)
-            self._update_ipv4_address(
-                self._get_stack_item(fg_id, PROTO_IPV4)[0],
-                'dstIp', dstip, dstseed, dstmask, count)
+            if traffic_param['outer_l3']:
+                count = traffic_param['outer_l3']['count']
+                srcip = traffic_param['outer_l3']['srcip']
+                dstip = traffic_param['outer_l3']['dstip']
+                srcseed = traffic_param['outer_l3']['srcseed']
+                dstseed = traffic_param['outer_l3']['dstseed']
+                srcmask = traffic_param['outer_l3']['srcmask'] \
+                          or IP_VERSION_4_MASK
+                dstmask = traffic_param['outer_l3']['dstmask'] \
+                          or IP_VERSION_4_MASK
+                if srcip:
+                    self._update_ipv4_address(
+                        self._get_stack_item(fg_id, PROTO_IPV4)[0],
+                        'srcIp', str(srcip), srcseed, srcmask, count)
+                if dstip:
+                    self._update_ipv4_address(
+                        self._get_stack_item(fg_id, PROTO_IPV4)[0],
+                        'dstIp', str(dstip), dstseed, dstmask, count)
 
     def update_l4(self, traffic):
         """Update the L4 headers
@@ -520,7 +550,10 @@ class IxNextgen(object):  # pragma: no cover
             if not self._get_config_element_by_flow_group_name(fg_id):
                 raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
 
-            proto = traffic_param['outer_l3']['proto']
+            proto = traffic_param['outer_l3'].get('proto')
+            if not (proto and traffic_param['outer_l4']):
+                continue
+
             if proto not in SUPPORTED_PROTO:
                 raise exceptions.IXIAUnsupportedProtocol(protocol=proto)
 
@@ -533,12 +566,15 @@ class IxNextgen(object):  # pragma: no cover
             dstport = traffic_param['outer_l4']['dstport']
             dstmask = traffic_param['outer_l4']['dstportmask']
 
-            if proto in SUPPORTED_PROTO:
-                self._update_udp_port(self._get_stack_item(fg_id, proto)[0],
-                                      'srcPort', srcport, seed, srcmask, count)
-
-                self._update_udp_port(self._get_stack_item(fg_id, proto)[0],
-                                      'dstPort', dstport, seed, dstmask, count)
+            if proto == PROTO_UDP:
+                if srcport:
+                    self._update_udp_port(
+                        self._get_stack_item(fg_id, proto)[0],
+                        'srcPort', srcport, seed, srcmask, count)
+                if dstport:
+                    self._update_udp_port(
+                        self._get_stack_item(fg_id, proto)[0],
+                        'dstPort', dstport, seed, dstmask, count)
 
     def _update_udp_port(self, descriptor, field, value,
                          seed=1, mask=0, count=1):
@@ -589,6 +625,12 @@ class IxNextgen(object):  # pragma: no cover
                                           self.LATENCY_NAME_MAP))
         return stats
 
+    def start_protocols(self):
+        self.ixnet.execute('startAllProtocols')
+
+    def stop_protocols(self):
+        self.ixnet.execute('stopAllProtocols')
+
     def start_traffic(self):
         """Start the traffic injection in the traffic item
 
@@ -771,3 +813,29 @@ class IxNextgen(object):  # pragma: no cover
 
         self.ixnet.commit()
         return obj
+
+    def add_bgp(self, ipv4, dut_ip, local_as, bgp_type=None):
+        """Add BGP protocol"""
+        log.debug("add_bgp: ipv4='%s', dut_ip='%s', local_as='%s'", ipv4,
+                  dut_ip, local_as)
+        obj = self.ixnet.add(ipv4, 'bgpIpv4Peer')
+        self.ixnet.commit()
+
+        # Set DUT IP address
+        dut_ip_addr = self.ixnet.getAttribute(obj, '-dutIp')
+        self.ixnet.setAttribute(dut_ip_addr + '/singleValue',
+                                '-value', dut_ip)
+
+        # Set local AS number
+        local_as_number = self.ixnet.getAttribute(obj, '-localAs2Bytes')
+        self.ixnet.setAttribute(local_as_number + '/singleValue',
+                                '-value', local_as)
+
+        if bgp_type:
+            # Set BGP type. If not specified, default value is using.
+            # Default type is "internal"
+            bgp_type_field = self.ixnet.getAttribute(obj, '-type')
+            self.ixnet.setAttribute(bgp_type_field + '/singleValue',
+                                    '-value', bgp_type)
+        self.ixnet.commit()
+        return obj
index 4fbceea..ea3f178 100644 (file)
@@ -97,6 +97,9 @@ class TrafficProfile(object):
         self.params = tp_config
         self.config = TrafficProfileConfig(tp_config)
 
+    def is_ended(self):
+        return False
+
     def execute_traffic(self, traffic_generator, **kawrgs):
         """ This methods defines the behavior of the traffic generator.
         It will be called in a loop until the traffic generator exits.
index 44bf2ea..b8aa78d 100644 (file)
@@ -56,68 +56,83 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
             if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
                 continue
 
+            # values should be single-item dict, so just grab the first item
             try:
-                # values should be single-item dict, so just grab the first item
-                try:
-                    key, value = next(iter(values.items()))
-                except StopIteration:
-                    result[traffickey] = {}
-                    continue
-
-                port_id = value.get('id', 1)
-                port_index = port_id - 1
-
-                if value.get('outer_l3v4'):
-                    ip = value['outer_l3v4']
-                    src_key, dst_key = 'srcip4', 'dstip4'
-                else:
-                    ip = value['outer_l3v6']
-                    src_key, dst_key = 'srcip6', 'dstip6'
-
-                srcip, srcmask = self._get_ip_and_mask(ip[src_key])
-                dstip, dstmask = self._get_ip_and_mask(ip[dst_key])
-
-                outer_l4 = value.get('outer_l4')
-                src_port, src_port_mask = self._get_fixed_and_mask(outer_l4['srcport'])
-                dst_port, dst_port_mask = self._get_fixed_and_mask(outer_l4['dstport'])
-                result[traffickey] = {
-                    'bidir': False,
-                    'id': port_id,
-                    'rate': self.rate,
-                    'rate_unit': self.rate_unit,
-                    'outer_l2': {
-                        'framesize': value['outer_l2']['framesize'],
-                        'framesPerSecond': True,
-                        'QinQ': value['outer_l2'].get('QinQ'),
-                        'srcmac': mac['src_mac_{}'.format(port_index)],
-                        'dstmac': mac['dst_mac_{}'.format(port_index)],
-                    },
-                    'outer_l3': {
-                        'count': ip['count'],
-                        'dscp': ip['dscp'],
-                        'ttl': ip['ttl'],
-                        'srcseed': ip.get('srcseed', 1),
-                        'dstseed': ip.get('dstseed', 1),
-                        'srcip': srcip,
-                        'dstip': dstip,
-                        'srcmask': srcmask,
-                        'dstmask': dstmask,
-                        'type': key,
-                        'proto': ip['proto'],
-                    },
-                    'outer_l4': {
-                        'srcport': src_port,
-                        'dstport': dst_port,
-                        'srcportmask': src_port_mask,
-                        'dstportmask': dst_port_mask,
-                        'count': outer_l4['count'],
-                        'seed': outer_l4.get('seed', 1)
-                    }
-
-                }
-            except KeyError:
+                key, value = next(iter(values.items()))
+            except StopIteration:
+                result[traffickey] = {}
                 continue
 
+            port_id = value.get('id', 1)
+            port_index = port_id - 1
+
+            result[traffickey] = {
+                'bidir': False,
+                'id': port_id,
+                'rate': self.rate,
+                'rate_unit': self.rate_unit,
+                'outer_l2': {},
+                'outer_l3': {},
+                'outer_l4': {},
+            }
+
+            outer_l2 = value.get('outer_l2')
+            if outer_l2:
+                result[traffickey]['outer_l2'].update({
+                    'framesize': outer_l2.get('framesize'),
+                    'framesPerSecond': True,
+                    'QinQ': outer_l2.get('QinQ'),
+                    'srcmac': mac.get('src_mac_{}'.format(port_index)),
+                    'dstmac': mac.get('dst_mac_{}'.format(port_index)),
+                })
+
+            if value.get('outer_l3v4'):
+                outer_l3 = value['outer_l3v4']
+                src_key, dst_key = 'srcip4', 'dstip4'
+            else:
+                outer_l3 = value.get('outer_l3v6')
+                src_key, dst_key = 'srcip6', 'dstip6'
+            if outer_l3:
+                srcip = srcmask = dstip = dstmask = None
+                if outer_l3.get(src_key):
+                    srcip, srcmask = self._get_ip_and_mask(outer_l3[src_key])
+                if outer_l3.get(dst_key):
+                    dstip, dstmask = self._get_ip_and_mask(outer_l3[dst_key])
+
+                result[traffickey]['outer_l3'].update({
+                    'count': outer_l3.get('count', 1),
+                    'dscp': outer_l3.get('dscp'),
+                    'ttl': outer_l3.get('ttl'),
+                    'srcseed': outer_l3.get('srcseed', 1),
+                    'dstseed': outer_l3.get('dstseed', 1),
+                    'srcip': srcip,
+                    'dstip': dstip,
+                    'srcmask': srcmask,
+                    'dstmask': dstmask,
+                    'type': key,
+                    'proto': outer_l3.get('proto'),
+                })
+
+            outer_l4 = value.get('outer_l4')
+            if outer_l4:
+                src_port = src_port_mask = dst_port = dst_port_mask = None
+                if outer_l4.get('srcport'):
+                    src_port, src_port_mask = (
+                        self._get_fixed_and_mask(outer_l4['srcport']))
+
+                if outer_l4.get('dstport'):
+                    dst_port, dst_port_mask = (
+                        self._get_fixed_and_mask(outer_l4['dstport']))
+
+                result[traffickey]['outer_l4'].update({
+                    'srcport': src_port,
+                    'dstport': dst_port,
+                    'srcportmask': src_port_mask,
+                    'dstportmask': dst_port_mask,
+                    'count': outer_l4.get('count', 1),
+                    'seed': outer_l4.get('seed', 1),
+                })
+
         return result
 
     def _ixia_traffic_generate(self, traffic, ixia_obj):
index 16a0411..f924cf4 100644 (file)
@@ -66,6 +66,9 @@ class ProxBinSearchProfile(ProxProfile):
             yield test_value
             test_value = self.mid_point
 
+    def is_ended(self):
+        return self.done.is_set()
+
     def run_test_with_pkt_size(self, traffic_gen, pkt_size, duration):
         """Run the test for a single packet size.
 
@@ -93,7 +96,7 @@ class ProxBinSearchProfile(ProxProfile):
         # success, the binary search will complete on an integer multiple
         # of the precision, rather than on a fraction of it.
 
-        theor_max_thruput = 0
+        theor_max_thruput = 0.0
 
         result_samples = {}
 
@@ -195,9 +198,9 @@ class ProxBinSearchProfile(ProxProfile):
 
         LOG.info(
             ">>>##>> Result Reached PktSize %s Theor_Max_Thruput %s Actual_throughput %s",
-            pkt_size, theor_max_thruput, result_samples.get("RxThroughput", 0))
+            pkt_size, theor_max_thruput, result_samples.get("RxThroughput", 0.0))
         result_samples["Status"] = STATUS_RESULT
         result_samples["Next_Step"] = ""
-        result_samples["Actual_throughput"] = result_samples.get("RxThroughput", 0)
+        result_samples["Actual_throughput"] = result_samples.get("RxThroughput", 0.0)
         result_samples["theor_max_throughput"] = theor_max_thruput
         self.queue.put(result_samples)
index 343ef1d..de4b3f9 100644 (file)
@@ -16,6 +16,7 @@
 from __future__ import absolute_import
 
 import logging
+import multiprocessing
 
 from yardstick.network_services.traffic_profile.base import TrafficProfile
 from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxProfileHelper
@@ -56,7 +57,7 @@ class ProxProfile(TrafficProfile):
     def __init__(self, tp_config):
         super(ProxProfile, self).__init__(tp_config)
         self.queue = None
-        self.done = False
+        self.done = multiprocessing.Event()
         self.results = []
 
         # TODO: get init values from tp_config
@@ -116,7 +117,7 @@ class ProxProfile(TrafficProfile):
         try:
             pkt_size = next(self.pkt_size_iterator)
         except StopIteration:
-            self.done = True
+            self.done.set()
             return
 
         # Adjust packet size upwards if it's less than the minimum
diff --git a/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py b/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
new file mode 100644 (file)
index 0000000..115fddc
--- /dev/null
@@ -0,0 +1,46 @@
+# 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 logging
+
+from yardstick.network_services.vnf_generic.vnf import base
+
+LOG = logging.getLogger(__name__)
+
+
+class AgnosticVnf(base.GenericVNF):
+    """ AgnosticVnf implementation. """
+    def __init__(self, name, vnfd, task_id):
+        super(AgnosticVnf, self).__init__(name, vnfd, task_id)
+
+    def instantiate(self, scenario_cfg, context_cfg):
+        pass
+
+    def wait_for_instantiate(self):
+        pass
+
+    def terminate(self):
+        pass
+
+    def scale(self, flavor=""):
+        pass
+
+    def collect_kpi(self):
+        pass
+
+    def start_collect(self):
+        pass
+
+    def stop_collect(self):
+        pass
index 3241719..321c057 100644 (file)
@@ -984,7 +984,7 @@ class ProxResourceHelper(ClientResourceHelper):
 
     def _run_traffic_once(self, traffic_profile):
         traffic_profile.execute_traffic(self)
-        if traffic_profile.done:
+        if traffic_profile.done.is_set():
             self._queue.put({'done': True})
             LOG.debug("tg_prox done")
             self._terminated.value = 1
index 94ab069..558a629 100644 (file)
@@ -96,7 +96,10 @@ class IxiaResourceHelper(ClientResourceHelper):
         """Initialize the IXIA IxNetwork client and configure the server"""
         self.client.clear_config()
         self.client.assign_ports()
-        self.client.create_traffic_model()
+        vports = self.client.get_vports()
+        uplink_vports = vports[::2]
+        downlink_vports = vports[1::2]
+        self.client.create_traffic_model(uplink_vports, downlink_vports)
 
     def run_traffic(self, traffic_profile, *args):
         if self._terminated.value:
index d4801ef..fa47e96 100644 (file)
@@ -97,9 +97,9 @@ class DurationRunnerTest(unittest.TestCase):
                                  multiprocessing.Event(), mock.Mock())
 
         self._assert_defaults__worker_run_setup_and_teardown()
-        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
-        self.assertGreater(self.benchmark.my_method.call_count, 2)
-        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+        self.assertGreater(self.benchmark.my_method.call_count, 0)
+        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
 
     def test__worker_process_called_without_cfg(self):
         scenario_cfg = {'runner': {}}
@@ -140,9 +140,9 @@ class DurationRunnerTest(unittest.TestCase):
         time.sleep(0.1)
 
         self._assert_defaults__worker_run_setup_and_teardown()
-        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
-        self.assertGreater(self.benchmark.my_method.count, 103)
-        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+        self.assertGreater(self.benchmark.my_method.count, 1)
+        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
 
         count = 101
         while not output_queue.empty():
@@ -181,9 +181,9 @@ class DurationRunnerTest(unittest.TestCase):
         time.sleep(0.1)
 
         self._assert_defaults__worker_run_setup_and_teardown()
-        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
-        self.assertGreater(self.benchmark.my_method.count, 103)
-        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+        self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+        self.assertGreater(self.benchmark.my_method.count, 1)
+        self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
 
         count = 0
         while not queue.empty():
index 3299c5b..056195f 100644 (file)
@@ -97,7 +97,7 @@ class ProxDurationRunnerTest(unittest.TestCase):
             {}, multiprocessing.Event(), mock.Mock())
 
         self._assert_defaults__worker_run_setup_and_teardown()
-        self.assertGreater(self.benchmark.my_method.call_count, 2)
+        self.assertGreater(self.benchmark.my_method.call_count, 0)
 
     def test__worker_process_called_without_cfg(self):
         scenario_cfg = {'runner': {}}
index 4e3199a..66fed81 100644 (file)
@@ -334,6 +334,21 @@ class TestIxNextgen(unittest.TestCase):
 
         self.ixnet_gen.ixnet.setMultiAttribute.assert_not_called()
 
+    def test_add_bgp(self):
+        self.ixnet_gen.ixnet.add.return_value = 'obj'
+        self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+        self.ixnet_gen.add_bgp(ipv4='ipv4 1',
+                               dut_ip='10.0.0.1',
+                               local_as=65000,
+                               bgp_type='external')
+        self.ixnet_gen.ixnet.add.assert_called_once_with('ipv4 1', 'bgpIpv4Peer')
+        self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+            'attr/singleValue', '-value', '10.0.0.1')
+        self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+            'attr/singleValue', '-value', 65000)
+        self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+            'attr/singleValue', '-value', 'external')
+
     @mock.patch.object(IxNetwork, 'IxNet')
     def test_connect(self, mock_ixnet):
         mock_ixnet.return_value = self.ixnet
@@ -421,17 +436,24 @@ class TestIxNextgen(unittest.TestCase):
                                 '-trackBy', 'trafficGroupId0')
 
     def test__create_flow_groups(self):
+        uplink_endpoints = ['up_endp1', 'up_endp2']
+        downlink_endpoints = ['down_endp1', 'down_endp2']
         self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
-        self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
-        self.ixnet_gen._create_flow_groups()
+        self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2', 'endp3',
+                                                'endp4']
+        self.ixnet_gen._create_flow_groups(uplink_endpoints, downlink_endpoints)
         self.ixnet_gen.ixnet.add.assert_has_calls([
             mock.call('traffic_item', 'endpointSet'),
             mock.call('traffic_item', 'endpointSet')])
         self.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'])])
+            mock.call('endp1', '-name', '1', '-sources', ['up_endp1'],
+                      '-destinations', ['down_endp1']),
+            mock.call('endp2', '-name', '2', '-sources', ['down_endp1'],
+                      '-destinations', ['up_endp1']),
+            mock.call('endp3', '-name', '3', '-sources', ['up_endp2'],
+                      '-destinations', ['down_endp2']),
+            mock.call('endp4', '-name', '4', '-sources', ['down_endp2'],
+                      '-destinations', ['up_endp2'])])
 
     def test__append_protocol_to_stack(self):
 
@@ -461,12 +483,31 @@ class TestIxNextgen(unittest.TestCase):
     def test_create_traffic_model(self, mock__setup_config_elements,
                                   mock__create_flow_groups,
                                   mock__create_traffic_item):
-
-        self.ixnet_gen.create_traffic_model()
-        mock__create_traffic_item.assert_called_once()
-        mock__create_flow_groups.assert_called_once()
+        uplink_ports = ['port1', 'port3']
+        downlink_ports = ['port2', 'port4']
+        uplink_endpoints = ['port1/protocols', 'port3/protocols']
+        downlink_endpoints = ['port2/protocols', 'port4/protocols']
+        self.ixnet_gen.create_traffic_model(uplink_ports, downlink_ports)
+        mock__create_traffic_item.assert_called_once_with('raw')
+        mock__create_flow_groups.assert_called_once_with(uplink_endpoints,
+                                                         downlink_endpoints)
         mock__setup_config_elements.assert_called_once()
 
+    @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_ipv4_traffic_model(self, mock__setup_config_elements,
+                                       mock__create_flow_groups,
+                                       mock__create_traffic_item):
+        uplink_topologies = ['up1', 'up3']
+        downlink_topologies = ['down2', 'down4']
+        self.ixnet_gen.create_ipv4_traffic_model(uplink_topologies,
+                                                 downlink_topologies)
+        mock__create_traffic_item.assert_called_once_with('ipv4')
+        mock__create_flow_groups.assert_called_once_with(uplink_topologies,
+                                                         downlink_topologies)
+        mock__setup_config_elements.assert_called_once_with(False)
+
     def test__update_frame_mac(self):
         with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item') as \
                 mock_get_field:
@@ -617,6 +658,9 @@ class TestIxNextgen(unittest.TestCase):
                 'outer_l3': {
                     'proto': 'unsupported',
                 },
+                'outer_l4': {
+                    'seed': 1
+                }
             },
         }
         with mock.patch.object(self.ixnet_gen,
@@ -672,3 +716,16 @@ class TestIxNextgen(unittest.TestCase):
         self.assertIsNone(result)
         self.ixnet.getList.assert_called_once()
         self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
+
+    def test_start_protocols(self):
+        self.ixnet_gen.start_protocols()
+        self.ixnet.execute.assert_called_once_with('startAllProtocols')
+
+    def test_stop_protocols(self):
+        self.ixnet_gen.stop_protocols()
+        self.ixnet.execute.assert_called_once_with('stopAllProtocols')
+
+    def test_get_vports(self):
+        self.ixnet_gen._ixnet.getRoot.return_value = 'root'
+        self.ixnet_gen.get_vports()
+        self.ixnet.getList.assert_called_once_with('root', 'vport')
index cf31cc2..11bee03 100644 (file)
@@ -100,13 +100,13 @@ class TestProxProfile(unittest.TestCase):
 
         profile = ProxProfile(tp_config)
 
-        self.assertFalse(profile.done)
+        self.assertFalse(profile.done.is_set())
         for _ in packet_sizes:
             with self.assertRaises(NotImplementedError):
                 profile.execute_traffic(traffic_generator)
 
         self.assertIsNone(profile.execute_traffic(traffic_generator))
-        self.assertTrue(profile.done)
+        self.assertTrue(profile.done.is_set())
 
     def test_bounds_iterator(self):
         tp_config = {
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py
new file mode 100644 (file)
index 0000000..3374cbe
--- /dev/null
@@ -0,0 +1,70 @@
+# 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 unittest
+import uuid
+
+from yardstick.network_services.vnf_generic.vnf import agnostic_vnf
+
+NAME = 'vnf__0'
+
+VNFD = {
+    'vnfd:vnfd-catalog': {
+        'vnfd': [{
+            'id': 'AgnosticVnf',  # NSB python class mapping
+            'name': 'AgnosticVnf',
+            'short-name': 'AgnosticVnf',
+            'description': 'AgnosticVnf',
+            'mgmt-interface': {
+                'vdu-id': 'vepcvnf-baremetal',
+                'user': 'user',
+                'password': 'password',
+                'ip': 'ip'
+            },
+            'vdu': [{
+                'id': 'vepcvnf-baremetal',
+                'name': 'vepc-vnf-baremetal',
+                'description': 'vAgnosticVnf workload',
+                'external-interface': []}],
+            'benchmark': {
+                'kpi': []}}]}}
+
+
+class TestAgnosticVnf(unittest.TestCase):
+
+    def setUp(self):
+        self._id = uuid.uuid1().int
+        self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        self.agnostic_vnf = agnostic_vnf.AgnosticVnf(NAME, self.vnfd, self._id)
+
+    def test_instantiate(self):
+        self.assertIsNone(self.agnostic_vnf.instantiate({}, {}))
+
+    def test_wait_for_instantiate(self):
+        self.assertIsNone(self.agnostic_vnf.wait_for_instantiate())
+
+    def test_terminate(self):
+        self.assertIsNone(self.agnostic_vnf.terminate())
+
+    def test_scale(self):
+        self.assertIsNone(self.agnostic_vnf.scale())
+
+    def test_collect_kpi(self):
+        self.assertIsNone(self.agnostic_vnf.collect_kpi())
+
+    def test_start_collect(self):
+        self.assertIsNone(self.agnostic_vnf.start_collect())
+
+    def test_stop_collect(self):
+        self.assertIsNone(self.agnostic_vnf.stop_collect())
index 3b09564..3d6ebb2 100644 (file)
@@ -1527,14 +1527,16 @@ class TestProxResourceHelper(unittest.TestCase):
     def test_run_traffic(self):
         setup_helper = mock.MagicMock()
         helper = prox_helpers.ProxResourceHelper(setup_helper)
-        traffic_profile = mock.MagicMock(**{"done": True})
+        traffic_profile = mock.MagicMock()
+        traffic_profile.done.is_set.return_value = True
         helper.run_traffic(traffic_profile)
         self.assertEqual(helper._terminated.value, 1)
 
     def test__run_traffic_once(self):
         setup_helper = mock.MagicMock()
         helper = prox_helpers.ProxResourceHelper(setup_helper)
-        traffic_profile = mock.MagicMock(**{"done": True})
+        traffic_profile = mock.MagicMock()
+        traffic_profile.done.is_set.return_value = True
         helper._run_traffic_once(traffic_profile)
         self.assertEqual(helper._terminated.value, 1)