diff options
Diffstat (limited to 'yardstick/tests/unit/network_services/vnf_generic')
4 files changed, 1561 insertions, 53 deletions
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py index 6d1d8c6a1..9a30fb9e9 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py @@ -590,6 +590,27 @@ class TestProxSocketHelper(unittest.TestCase): self.assertEqual(result, expected) @mock.patch.object(prox_helpers.LOG, 'error') + def test_irq_core_stats(self, *args): + mock_socket = mock.MagicMock() + prox = prox_helpers.ProxSocketHelper(mock_socket) + prox.get_data = mock.MagicMock(return_value=('0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3')) + + data_0 = {"cpu": 0, 'bucket_0': 1, 'bucket_1': 2, 'bucket_2': 3, 'bucket_3': 4, + 'bucket_4': 5, 'bucket_5': 0, 'bucket_6': 1, 'bucket_7': 2, 'bucket_8': 3, + 'bucket_9': 4, 'bucket_10': 5, 'bucket_11': 0, 'bucket_12': 1, + "max_irq": 0, "overflow": 10} + + data_1 = {"cpu": 1, 'bucket_0': 1, 'bucket_1': 2, 'bucket_2': 3, 'bucket_3': 4, + 'bucket_4': 5, 'bucket_5': 0, 'bucket_6': 1, 'bucket_7': 2, 'bucket_8': 3, + 'bucket_9': 4, 'bucket_10': 5, 'bucket_11': 0, 'bucket_12': 1, + "max_irq": 0, "overflow": 10} + + expected = {"core_0": data_0, "core_1": data_1} + + result = prox.irq_core_stats([[0, 1], [1, 0]]) + self.assertDictEqual(result, expected) + + @mock.patch.object(prox_helpers.LOG, 'error') def test_multi_port_stats(self, *args): mock_socket = mock.MagicMock() prox = prox_helpers.ProxSocketHelper(mock_socket) @@ -1353,6 +1374,36 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase): ['missing_addtional_file', 'dofile("nosuch")'], ], ], + [ + 'core 0', + [ + ['name', 'p0'] + ] + ], + [ + 'core 1-4', + [ + ['name', 'p1'] + ] + ], + [ + 'core 5,6', + [ + ['name', 'p2'] + ] + ], + [ + 'core xx', + [ + ['name', 'p3'] + ] + ], + [ + 'core $x', + [ + ['name', 'p4'] + ] + ] ] expected = [ @@ -1382,6 +1433,54 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase): ['missing_addtional_file', 'dofile("nosuch")'], ], ], + [ + 'core 0', + [ + ['name', 'p0'] + ] + ], + [ + 'core 1', + [ + ['name', 'p1'] + ] + ], + [ + 'core 2', + [ + ['name', 'p1'] + ] + ], + [ + 'core 3', + [ + ['name', 'p1'] + ] + ], + [ + 'core 4', + [ + ['name', 'p1'] + ] + ], + [ + 'core 5', + [ + ['name', 'p2'] + ] + ], + [ + 'core 6', + [ + ['name', 'p2'] + ] + ], + [ + 'core $x', + [ + ['name', 'p4'] + ] + ] ] result = helper.generate_prox_config_file('/c/d/e') self.assertEqual(result, expected, str(result)) @@ -2708,3 +2807,15 @@ class TestProxlwAFTRProfileHelper(unittest.TestCase): # negative pkt_size is the only way to make ratio > 1 helper.run_test(pkt_size=-1000, duration=5, value=6.5, tolerated_loss=0.0, line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS) + + +class TestProxIrqProfileHelper(unittest.TestCase): + + def test_run_test(self, *args): + resource_helper = mock.MagicMock() + helper = prox_helpers.ProxIrqProfileHelper(resource_helper) + self.assertIsNone(helper._cores_tuple) + self.assertIsNone(helper._ports_tuple) + self.assertIsNone(helper._latency_cores) + self.assertIsNone(helper._test_cores) + self.assertIsNone(helper._cpu_topology) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py new file mode 100644 index 000000000..4eaa38c27 --- /dev/null +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py @@ -0,0 +1,828 @@ +# Copyright (c) 2017-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 mock +import errno + +from yardstick.tests import STL_MOCKS +from yardstick.common import exceptions as y_exceptions +from yardstick.network_services.vnf_generic.vnf.prox_irq import ProxIrqGen +from yardstick.network_services.vnf_generic.vnf.prox_irq import ProxIrqVNF +from yardstick.benchmark.contexts import base as ctx_base + +SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper' + +STLClient = mock.MagicMock() +stl_patch = mock.patch.dict("sys.modules", STL_MOCKS) +stl_patch.start() + +if stl_patch: + from yardstick.network_services.vnf_generic.vnf import prox_vnf + from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh + +VNF_NAME = "vnf__1" + +class TestProxIrqVNF(unittest.TestCase): + + SCENARIO_CFG = { + 'task_path': "", + 'nodes': { + 'tg__1': 'trafficgen_1.yardstick', + 'vnf__1': 'vnf.yardstick'}, + 'runner': { + 'duration': 600, 'type': 'Duration'}, + 'topology': 'prox-tg-topology-2.yaml', + 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml', + 'type': 'NSPerf', + 'options': { + 'tg__1': {'prox_args': {'-e': '', + '-t': ''}, + 'prox_config': 'configs/l3-gen-2.cfg', + 'prox_path': + '/root/dppd-PROX-v035/build/prox'}, + 'vnf__1': { + 'prox_args': {'-t': ''}, + 'prox_config': 'configs/l3-swap-2.cfg', + 'prox_path': '/root/dppd-PROX-v035/build/prox'}}} + + VNFD_0 = { + 'short-name': 'VpeVnf', + 'vdu': [ + { + 'routing_table': [ + { + 'network': '152.16.100.20', + 'netmask': '255.255.255.0', + 'gateway': '152.16.100.20', + 'if': 'xe0' + }, + { + 'network': '152.16.40.20', + 'netmask': '255.255.255.0', + 'gateway': '152.16.40.20', + 'if': 'xe1' + }, + ], + 'description': 'VPE approximation using DPDK', + 'name': 'vpevnf-baremetal', + 'nd_route_tbl': [ + { + 'network': '0064:ff9b:0:0:0:0:9810:6414', + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:6414', + 'if': 'xe0' + }, + { + 'network': '0064:ff9b:0:0:0:0:9810:2814', + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:2814', + 'if': 'xe1' + }, + ], + 'id': 'vpevnf-baremetal', + 'external-interface': [ + { + 'virtual-interface': { + 'dst_mac': '00:00:00:00:00:03', + 'vpci': '0000:05:00.0', + 'local_ip': '152.16.100.19', + 'type': 'PCI-PASSTHROUGH', + 'netmask': '255.255.255.0', + 'dpdk_port_num': 0, + 'bandwidth': '10 Gbps', + 'dst_ip': '152.16.100.20', + 'local_mac': '00:00:00:00:00:01' + }, + 'vnfd-connection-point-ref': 'xe0', + 'name': 'xe0' + }, + { + 'virtual-interface': { + 'dst_mac': '00:00:00:00:00:04', + 'vpci': '0000:05:00.1', + 'local_ip': '152.16.40.19', + 'type': 'PCI-PASSTHROUGH', + 'netmask': '255.255.255.0', + 'dpdk_port_num': 1, + 'bandwidth': '10 Gbps', + 'dst_ip': '152.16.40.20', + 'local_mac': '00:00:00:00:00:02' + }, + 'vnfd-connection-point-ref': 'xe1', + 'name': 'xe1' + }, + ], + }, + ], + 'description': 'Vpe approximation using DPDK', + 'mgmt-interface': { + 'vdu-id': 'vpevnf-baremetal', + 'host': '1.1.1.1', + 'password': 'r00t', + 'user': 'root', + 'ip': '1.1.1.1' + }, + 'benchmark': { + 'kpi': [ + 'packets_in', + 'packets_fwd', + 'packets_dropped', + ], + }, + 'connection-point': [ + { + 'type': 'VPORT', + 'name': 'xe0', + }, + { + 'type': 'VPORT', + 'name': 'xe1', + }, + ], + 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh' + } + + VNFD = { + 'vnfd:vnfd-catalog': { + 'vnfd': [ + VNFD_0, + ] + } + } + + TRAFFIC_PROFILE = { + "schema": "isb:traffic_profile:0.1", + "name": "fixed", + "description": "Fixed traffic profile to run UDP traffic", + "traffic_profile": { + "traffic_type": "FixedTraffic", + "frame_rate": 100, # pps + "flow_number": 10, + "frame_size": 64, + }, + } + + CONTEXT_CFG = { + 'nodes': { + 'tg__2': { + 'member-vnf-index': '3', + 'role': 'TrafficGen', + 'name': 'trafficgen_2.yardstick', + 'vnfd-id-ref': 'tg__2', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens513f0', + 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.40.20', + 'dst_mac': '00:00:00:00:00:01', + 'local_mac': '00:00:00:00:00:03', + 'dst_ip': '152.16.40.19', + 'driver': 'ixgbe', + 'vpci': '0000:02:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens513f1', + 'netmask': '255.255.255.0', + 'network': '202.16.100.0', + 'local_ip': '202.16.100.20', + 'local_mac': '00:1e:67:d0:60:5d', + 'driver': 'ixgbe', + 'vpci': '0000:02:00.1', + 'dpdk_port_num': 1, + }, + }, + 'password': 'r00t', + 'VNF model': 'l3fwd_vnf.yaml', + 'user': 'root', + }, + 'tg__1': { + 'member-vnf-index': '1', + 'role': 'TrafficGen', + 'name': 'trafficgen_1.yardstick', + 'vnfd-id-ref': 'tg__1', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens785f0', + 'vld_id': prox_vnf.ProxApproxVnf.UPLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.20', + 'dst_mac': '00:00:00:00:00:02', + 'local_mac': '00:00:00:00:00:04', + 'dst_ip': '152.16.100.19', + 'driver': 'i40e', + 'vpci': '0000:05:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens785f1', + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.21', + 'local_mac': '00:00:00:00:00:01', + 'driver': 'i40e', + 'vpci': '0000:05:00.1', + 'dpdk_port_num': 1, + }, + }, + 'password': 'r00t', + 'VNF model': 'tg_rfc2544_tpl.yaml', + 'user': 'root', + }, + 'vnf__1': { + 'name': 'vnf.yardstick', + 'vnfd-id-ref': 'vnf__1', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens786f0', + 'vld_id': prox_vnf.ProxApproxVnf.UPLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.19', + 'dst_mac': '00:00:00:00:00:04', + 'local_mac': '00:00:00:00:00:02', + 'dst_ip': '152.16.100.20', + 'driver': 'i40e', + 'vpci': '0000:05:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens786f1', + 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.40.19', + 'dst_mac': '00:00:00:00:00:03', + 'local_mac': '00:00:00:00:00:01', + 'dst_ip': '152.16.40.20', + 'driver': 'i40e', + 'vpci': '0000:05:00.1', + 'dpdk_port_num': 1, + }, + }, + 'routing_table': [ + { + 'netmask': '255.255.255.0', + 'gateway': '152.16.100.20', + 'network': '152.16.100.20', + 'if': 'xe0', + }, + { + 'netmask': '255.255.255.0', + 'gateway': '152.16.40.20', + 'network': '152.16.40.20', + 'if': 'xe1', + }, + ], + 'member-vnf-index': '2', + 'host': '1.2.1.1', + 'role': 'vnf', + 'user': 'root', + 'nd_route_tbl': [ + { + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:6414', + 'network': '0064:ff9b:0:0:0:0:9810:6414', + 'if': 'xe0', + }, + { + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:2814', + 'network': '0064:ff9b:0:0:0:0:9810:2814', + 'if': 'xe1', + }, + ], + 'password': 'r00t', + 'VNF model': 'prox_vnf.yaml', + }, + }, + } + + def test___init__(self): + prox_irq_vnf = ProxIrqVNF('vnf1', self.VNFD_0, 'task_id') + + self.assertEqual(prox_irq_vnf.name, 'vnf1') + self.assertDictEqual(prox_irq_vnf.vnfd_helper, self.VNFD_0) + + @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node') + @mock.patch(SSH_HELPER) + def test_collect_kpi(self, ssh, *args): + mock_ssh(ssh) + + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + resource_helper = mock.MagicMock() + + resource_helper = mock.MagicMock() + + core_1 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5, + 'bucket_6': 6, 'bucket_7': 7, 'bucket_8': 8, 'bucket_9': 9, 'bucket_10': 10, + 'bucket_11': 11, 'bucket_12': 12, 'bucket_0': 100, 'cpu': 1, 'max_irq': 12, + 'overflow': 10} + core_2 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5, + 'bucket_6': 0, 'bucket_7': 0, 'bucket_8': 0, 'bucket_9': 0, 'bucket_10': 0, + 'bucket_11': 0, 'bucket_12': 0, 'bucket_0': 100, 'cpu': 2, 'max_irq': 12, + 'overflow': 10} + + irq_data = {'core_1': core_1, 'core_2': core_2} + resource_helper.execute.return_value = (irq_data) + + build_config_file = mock.MagicMock() + build_config_file.return_value = None + + prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd, 'task_id') + + startup = ["global", [["eal", "-4"]]] + master_0 = ["core 0", [["mode", "master"]]] + core_1 = ["core 1", [["mode", "irq"]]] + core_2 = ["core 2", [["mode", "irq"], ["task", "2"]]] + + prox_irq_vnf.setup_helper._prox_config_data = \ + [startup, master_0, core_1, core_2] + + prox_irq_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG + prox_irq_vnf.resource_helper = resource_helper + prox_irq_vnf.setup_helper.build_config_file = build_config_file + + result = prox_irq_vnf.collect_kpi() + self.assertDictEqual(result["collect_stats"], {}) + + result = prox_irq_vnf.collect_kpi() + self.assertFalse('bucket_10' in result["collect_stats"]['core_2']) + self.assertFalse('bucket_11' in result["collect_stats"]['core_2']) + self.assertFalse('bucket_12' in result["collect_stats"]['core_2']) + self.assertEqual(result["collect_stats"]['core_2']['max_irq'], 12) + + + @mock.patch(SSH_HELPER) + def test_vnf_execute_oserror(self, ssh, *args): + mock_ssh(ssh) + + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd, 'task_id') + prox_irq_vnf.resource_helper = resource_helper = mock.Mock() + + resource_helper.execute.side_effect = OSError(errno.EPIPE, "") + prox_irq_vnf.vnf_execute("", _ignore_errors=True) + + resource_helper.execute.side_effect = OSError(errno.ESHUTDOWN, "") + prox_irq_vnf.vnf_execute("", _ignore_errors=True) + + resource_helper.execute.side_effect = OSError(errno.EADDRINUSE, "") + with self.assertRaises(OSError): + prox_irq_vnf.vnf_execute("", _ignore_errors=True) + + @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket') + @mock.patch(SSH_HELPER) + def test_terminate(self, ssh, *args): + mock_ssh(ssh) + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + + mock_ssh(ssh, exec_result=(1, "", "")) + prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd, 'task_id') + + prox_irq_vnf._terminated = mock.MagicMock() + prox_irq_vnf._traffic_process = mock.MagicMock() + prox_irq_vnf._traffic_process.terminate = mock.Mock() + prox_irq_vnf.ssh_helper = mock.MagicMock() + prox_irq_vnf.setup_helper = mock.MagicMock() + prox_irq_vnf.resource_helper = mock.MagicMock() + prox_irq_vnf._vnf_wrapper.setup_helper = mock.MagicMock() + prox_irq_vnf._vnf_wrapper._vnf_process = mock.MagicMock(**{"is_alive.return_value": False}) + prox_irq_vnf._vnf_wrapper.resource_helper = mock.MagicMock() + + prox_irq_vnf._run_prox = mock.Mock(return_value=0) + prox_irq_vnf.q_in = mock.Mock() + prox_irq_vnf.q_out = mock.Mock() + + self.assertIsNone(prox_irq_vnf.terminate()) + + @mock.patch(SSH_HELPER) + def test_wait_for_instantiate_panic(self, ssh, *args): + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + + mock_ssh(ssh, exec_result=(1, "", "")) + prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd, 'task_id') + + prox_irq_vnf._terminated = mock.MagicMock() + prox_irq_vnf._traffic_process = mock.MagicMock() + prox_irq_vnf._traffic_process.terminate = mock.Mock() + prox_irq_vnf.ssh_helper = mock.MagicMock() + prox_irq_vnf.setup_helper = mock.MagicMock() + prox_irq_vnf.resource_helper = mock.MagicMock() + prox_irq_vnf._vnf_wrapper.setup_helper = mock.MagicMock() + prox_irq_vnf._vnf_wrapper._vnf_process = mock.MagicMock(**{"is_alive.return_value": False}) + prox_irq_vnf._vnf_wrapper.resource_helper = mock.MagicMock() + + prox_irq_vnf._run_prox = mock.Mock(return_value=0) + prox_irq_vnf.q_in = mock.Mock() + prox_irq_vnf.q_out = mock.Mock() + prox_irq_vnf.WAIT_TIME = 0 + with self.assertRaises(RuntimeError): + prox_irq_vnf.wait_for_instantiate() + +class TestProxIrqGen(unittest.TestCase): + + SCENARIO_CFG = { + 'task_path': "", + 'nodes': { + 'tg__1': 'trafficgen_1.yardstick', + 'vnf__1': 'vnf.yardstick'}, + 'runner': { + 'duration': 600, 'type': 'Duration'}, + 'topology': 'prox-tg-topology-2.yaml', + 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml', + 'type': 'NSPerf', + 'options': { + 'tg__1': {'prox_args': {'-e': '', + '-t': ''}, + 'prox_config': 'configs/l3-gen-2.cfg', + 'prox_path': + '/root/dppd-PROX-v035/build/prox'}, + 'vnf__1': { + 'prox_args': {'-t': ''}, + 'prox_config': 'configs/l3-swap-2.cfg', + 'prox_path': '/root/dppd-PROX-v035/build/prox'}}} + + VNFD_0 = { + 'short-name': 'VpeVnf', + 'vdu': [ + { + 'routing_table': [ + { + 'network': '152.16.100.20', + 'netmask': '255.255.255.0', + 'gateway': '152.16.100.20', + 'if': 'xe0' + }, + { + 'network': '152.16.40.20', + 'netmask': '255.255.255.0', + 'gateway': '152.16.40.20', + 'if': 'xe1' + }, + ], + 'description': 'VPE approximation using DPDK', + 'name': 'vpevnf-baremetal', + 'nd_route_tbl': [ + { + 'network': '0064:ff9b:0:0:0:0:9810:6414', + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:6414', + 'if': 'xe0' + }, + { + 'network': '0064:ff9b:0:0:0:0:9810:2814', + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:2814', + 'if': 'xe1' + }, + ], + 'id': 'vpevnf-baremetal', + 'external-interface': [ + { + 'virtual-interface': { + 'dst_mac': '00:00:00:00:00:03', + 'vpci': '0000:05:00.0', + 'driver': 'i40e', + 'local_ip': '152.16.100.19', + 'type': 'PCI-PASSTHROUGH', + 'netmask': '255.255.255.0', + 'dpdk_port_num': 0, + 'bandwidth': '10 Gbps', + 'dst_ip': '152.16.100.20', + 'local_mac': '00:00:00:00:00:01' + }, + 'vnfd-connection-point-ref': 'xe0', + 'name': 'xe0' + }, + { + 'virtual-interface': { + 'dst_mac': '00:00:00:00:00:04', + 'vpci': '0000:05:00.1', + 'driver': 'ixgbe', + 'local_ip': '152.16.40.19', + 'type': 'PCI-PASSTHROUGH', + 'netmask': '255.255.255.0', + 'dpdk_port_num': 1, + 'bandwidth': '10 Gbps', + 'dst_ip': '152.16.40.20', + 'local_mac': '00:00:00:00:00:02' + }, + 'vnfd-connection-point-ref': 'xe1', + 'name': 'xe1' + }, + ], + }, + ], + 'description': 'Vpe approximation using DPDK', + 'mgmt-interface': { + 'vdu-id': 'vpevnf-baremetal', + 'host': '1.1.1.1', + 'password': 'r00t', + 'user': 'root', + 'ip': '1.1.1.1' + }, + 'benchmark': { + 'kpi': [ + 'packets_in', + 'packets_fwd', + 'packets_dropped', + ], + }, + 'connection-point': [ + { + 'type': 'VPORT', + 'name': 'xe0', + }, + { + 'type': 'VPORT', + 'name': 'xe1', + }, + ], + 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh' + } + + VNFD = { + 'vnfd:vnfd-catalog': { + 'vnfd': [ + VNFD_0, + ], + }, + } + + TRAFFIC_PROFILE = { + "schema": "isb:traffic_profile:0.1", + "name": "fixed", + "description": "Fixed traffic profile to run UDP traffic", + "traffic_profile": { + "traffic_type": "FixedTraffic", + "frame_rate": 100, # pps + "flow_number": 10, + "frame_size": 64, + }, + } + + CONTEXT_CFG = { + 'nodes': { + 'tg__2': { + 'member-vnf-index': '3', + 'role': 'TrafficGen', + 'name': 'trafficgen_2.yardstick', + 'vnfd-id-ref': 'tg__2', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens513f0', + 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.40.20', + 'dst_mac': '00:00:00:00:00:01', + 'local_mac': '00:00:00:00:00:03', + 'dst_ip': '152.16.40.19', + 'driver': 'ixgbe', + 'vpci': '0000:02:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens513f1', + 'netmask': '255.255.255.0', + 'network': '202.16.100.0', + 'local_ip': '202.16.100.20', + 'local_mac': '00:1e:67:d0:60:5d', + 'driver': 'ixgbe', + 'vpci': '0000:02:00.1', + 'dpdk_port_num': 1, + }, + }, + 'password': 'r00t', + 'VNF model': 'l3fwd_vnf.yaml', + 'user': 'root', + }, + 'tg__1': { + 'member-vnf-index': '1', + 'role': 'TrafficGen', + 'name': 'trafficgen_1.yardstick', + 'vnfd-id-ref': 'tg__1', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens785f0', + 'vld_id': prox_vnf.ProxApproxVnf.UPLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.20', + 'dst_mac': '00:00:00:00:00:02', + 'local_mac': '00:00:00:00:00:04', + 'dst_ip': '152.16.100.19', + 'driver': 'i40e', + 'vpci': '0000:05:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens785f1', + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.21', + 'local_mac': '00:00:00:00:00:01', + 'driver': 'i40e', + 'vpci': '0000:05:00.1', + 'dpdk_port_num': 1, + }, + }, + 'password': 'r00t', + 'VNF model': 'tg_rfc2544_tpl.yaml', + 'user': 'root', + }, + 'vnf__1': { + 'name': 'vnf.yardstick', + 'vnfd-id-ref': 'vnf__1', + 'ip': '1.2.1.1', + 'interfaces': { + 'xe0': { + 'local_iface_name': 'ens786f0', + 'vld_id': prox_vnf.ProxApproxVnf.UPLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.100.19', + 'dst_mac': '00:00:00:00:00:04', + 'local_mac': '00:00:00:00:00:02', + 'dst_ip': '152.16.100.20', + 'driver': 'i40e', + 'vpci': '0000:05:00.0', + 'dpdk_port_num': 0, + }, + 'xe1': { + 'local_iface_name': 'ens786f1', + 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK, + 'netmask': '255.255.255.0', + 'local_ip': '152.16.40.19', + 'dst_mac': '00:00:00:00:00:03', + 'local_mac': '00:00:00:00:00:01', + 'dst_ip': '152.16.40.20', + 'driver': 'i40e', + 'vpci': '0000:05:00.1', + 'dpdk_port_num': 1, + }, + }, + 'routing_table': [ + { + 'netmask': '255.255.255.0', + 'gateway': '152.16.100.20', + 'network': '152.16.100.20', + 'if': 'xe0', + }, + { + 'netmask': '255.255.255.0', + 'gateway': '152.16.40.20', + 'network': '152.16.40.20', + 'if': 'xe1', + }, + ], + 'member-vnf-index': '2', + 'host': '1.2.1.1', + 'role': 'vnf', + 'user': 'root', + 'nd_route_tbl': [ + { + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:6414', + 'network': '0064:ff9b:0:0:0:0:9810:6414', + 'if': 'xe0', + }, + { + 'netmask': '112', + 'gateway': '0064:ff9b:0:0:0:0:9810:2814', + 'network': '0064:ff9b:0:0:0:0:9810:2814', + 'if': 'xe1', + }, + ], + 'password': 'r00t', + 'VNF model': 'prox_vnf.yaml', + }, + }, + } + + + def test__check_status(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + + with self.assertRaises(NotImplementedError): + prox_irq_gen._check_status() + + def test_listen_traffic(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + + prox_irq_gen.listen_traffic(mock.Mock()) + + def test_verify_traffic(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + + prox_irq_gen.verify_traffic(mock.Mock()) + + mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket') + @mock.patch(SSH_HELPER) + def test_terminate(self, ssh, *args): + mock_ssh(ssh) + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + prox_traffic_gen = ProxIrqGen(VNF_NAME, vnfd, 'task_id') + prox_traffic_gen._terminated = mock.MagicMock() + prox_traffic_gen._traffic_process = mock.MagicMock() + prox_traffic_gen._traffic_process.terminate = mock.Mock() + prox_traffic_gen.ssh_helper = mock.MagicMock() + prox_traffic_gen.setup_helper = mock.MagicMock() + prox_traffic_gen.resource_helper = mock.MagicMock() + prox_traffic_gen._vnf_wrapper.setup_helper = mock.MagicMock() + prox_traffic_gen._vnf_wrapper._vnf_process = mock.MagicMock() + prox_traffic_gen._vnf_wrapper.resource_helper = mock.MagicMock() + self.assertIsNone(prox_traffic_gen.terminate()) + + def test__wait_for_process(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + with mock.patch.object(prox_irq_gen, '_check_status', + return_value=0) as mock_status, \ + mock.patch.object(prox_irq_gen, '_tg_process') as mock_proc: + mock_proc.is_alive.return_value = True + mock_proc.exitcode = 234 + self.assertEqual(prox_irq_gen._wait_for_process(), 234) + mock_proc.is_alive.assert_called_once() + mock_status.assert_called_once() + + def test__wait_for_process_not_alive(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + with mock.patch.object(prox_irq_gen, '_tg_process') as mock_proc: + mock_proc.is_alive.return_value = False + self.assertRaises(RuntimeError, prox_irq_gen._wait_for_process) + mock_proc.is_alive.assert_called_once() + + def test__wait_for_process_delayed(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + with mock.patch.object(prox_irq_gen, '_check_status', + side_effect=[1, 0]) as mock_status, \ + mock.patch.object(prox_irq_gen, + '_tg_process') as mock_proc: + mock_proc.is_alive.return_value = True + mock_proc.exitcode = 234 + self.assertEqual(prox_irq_gen._wait_for_process(), 234) + mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()]) + mock_status.assert_has_calls([mock.call(), mock.call()]) + + def test_scale(self): + prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0, 'task_id') + self.assertRaises(y_exceptions.FunctionNotImplemented, + prox_irq_gen.scale) + + @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node') + @mock.patch(SSH_HELPER) + def test_collect_kpi(self, ssh, *args): + mock_ssh(ssh) + + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + resource_helper = mock.MagicMock() + + core_1 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5, + 'bucket_6': 6, 'bucket_7': 7, 'bucket_8': 8, 'bucket_9': 9, 'bucket_10': 10, + 'bucket_11': 11, 'bucket_12': 12, 'bucket_0': 100, 'cpu': 1, 'max_irq': 12, + 'overflow': 10} + core_2 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5, + 'bucket_6': 0, 'bucket_7': 0, 'bucket_8': 0, 'bucket_9': 0, 'bucket_10': 0, + 'bucket_11': 0, 'bucket_12': 0, 'bucket_0': 100, 'cpu': 2, 'max_irq': 12, + 'overflow': 10} + + irq_data = {'core_1': core_1, 'core_2': core_2} + resource_helper.sut.irq_core_stats.return_value = (irq_data) + + build_config_file = mock.MagicMock() + build_config_file.return_value = None + + prox_irq_gen = ProxIrqGen(VNF_NAME, vnfd, 'task_id') + + startup = ["global", [["eal", "-4"]]] + master_0 = ["core 0", [["mode", "master"]]] + core_1 = ["core 1", [["mode", "irq"]]] + core_2 = ["core 2", [["mode", "irq"], ["task", "2"]]] + + prox_irq_gen.setup_helper._prox_config_data = \ + [startup, master_0, core_1, core_2] + + prox_irq_gen.scenario_helper.scenario_cfg = self.SCENARIO_CFG + prox_irq_gen.resource_helper = resource_helper + prox_irq_gen.setup_helper.build_config_file = build_config_file + + result = prox_irq_gen.collect_kpi() + self.assertDictEqual(result["collect_stats"], {}) + + result = prox_irq_gen.collect_kpi() + self.assertFalse('bucket_10' in result["collect_stats"]['core_2']) + self.assertFalse('bucket_11' in result["collect_stats"]['core_2']) + self.assertFalse('bucket_12' in result["collect_stats"]['core_2']) + self.assertEqual(result["collect_stats"]['core_2']['max_irq'], 12) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py index 43682dd07..a1802aa55 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py @@ -17,12 +17,14 @@ from copy import deepcopy import unittest import mock +import paramiko + from yardstick.common import exceptions as y_exceptions from yardstick.common import utils from yardstick.network_services.nfvi.resource import ResourceProfile from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper from yardstick.network_services.vnf_generic.vnf import sample_vnf -from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper +from yardstick.network_services.vnf_generic.vnf import vnf_ssh_helper from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper @@ -34,6 +36,7 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTraff from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base from yardstick.benchmark.contexts import base as ctx_base +from yardstick import ssh class MockError(Exception): @@ -82,10 +85,11 @@ class TestVnfSshHelper(unittest.TestCase): 'virtual-interface': { 'dst_mac': '00:00:00:00:00:03', 'vpci': '0000:05:00.0', + 'dpdk_port_num': 0, + 'driver': 'i40e', 'local_ip': '152.16.100.19', 'type': 'PCI-PASSTHROUGH', 'netmask': '255.255.255.0', - 'dpdk_port_num': 0, 'bandwidth': '10 Gbps', 'dst_ip': '152.16.100.20', 'local_mac': '00:00:00:00:00:01', @@ -99,10 +103,11 @@ class TestVnfSshHelper(unittest.TestCase): 'virtual-interface': { 'dst_mac': '00:00:00:00:00:04', 'vpci': '0000:05:00.1', + 'dpdk_port_num': 1, + 'driver': 'ixgbe', 'local_ip': '152.16.40.19', 'type': 'PCI-PASSTHROUGH', 'netmask': '255.255.255.0', - 'dpdk_port_num': 1, 'bandwidth': '10 Gbps', 'dst_ip': '152.16.40.20', 'local_mac': '00:00:00:00:00:02', @@ -151,90 +156,88 @@ class TestVnfSshHelper(unittest.TestCase): } } + def setUp(self): + self.ssh_helper = vnf_ssh_helper.VnfSshHelper( + self.VNFD_0['mgmt-interface'], 'my/bin/path') + self.ssh_helper._run = mock.Mock() + def assertAll(self, iterable, message=None): self.assertTrue(all(iterable), message) def test_get_class(self): - self.assertIs(VnfSshHelper.get_class(), VnfSshHelper) + self.assertIs(vnf_ssh_helper.VnfSshHelper.get_class(), + vnf_ssh_helper.VnfSshHelper) - @mock.patch('yardstick.ssh.paramiko') + @mock.patch.object(ssh, 'paramiko') def test_copy(self, _): - ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path') - ssh_helper._run = mock.Mock() - - ssh_helper.execute('ls') - self.assertTrue(ssh_helper.is_connected) - result = ssh_helper.copy() - self.assertIsInstance(result, VnfSshHelper) + self.ssh_helper.execute('ls') + self.assertTrue(self.ssh_helper.is_connected) + result = self.ssh_helper.copy() + self.assertIsInstance(result, vnf_ssh_helper.VnfSshHelper) self.assertFalse(result.is_connected) - self.assertEqual(result.bin_path, ssh_helper.bin_path) - self.assertEqual(result.host, ssh_helper.host) - self.assertEqual(result.port, ssh_helper.port) - self.assertEqual(result.user, ssh_helper.user) - self.assertEqual(result.password, ssh_helper.password) - self.assertEqual(result.key_filename, ssh_helper.key_filename) - - @mock.patch('yardstick.ssh.paramiko') + self.assertEqual(result.bin_path, self.ssh_helper.bin_path) + self.assertEqual(result.host, self.ssh_helper.host) + self.assertEqual(result.port, self.ssh_helper.port) + self.assertEqual(result.user, self.ssh_helper.user) + self.assertEqual(result.password, self.ssh_helper.password) + self.assertEqual(result.key_filename, self.ssh_helper.key_filename) + + @mock.patch.object(paramiko, 'SSHClient') def test_upload_config_file(self, mock_paramiko): - ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path') - ssh_helper._run = mock.MagicMock() + self.assertFalse(self.ssh_helper.is_connected) + cfg_file = self.ssh_helper.upload_config_file('/my/prefix', 'my content') + self.assertTrue(self.ssh_helper.is_connected) + mock_paramiko.assert_called_once() + self.assertEqual(cfg_file, '/my/prefix') - self.assertFalse(ssh_helper.is_connected) - cfg_file = ssh_helper.upload_config_file('my/prefix', 'my content') - self.assertTrue(ssh_helper.is_connected) - mock_paramiko.SSHClient.assert_called_once() + @mock.patch.object(paramiko, 'SSHClient') + def test_upload_config_file_path_does_not_exist(self, mock_paramiko): + self.assertFalse(self.ssh_helper.is_connected) + cfg_file = self.ssh_helper.upload_config_file('my/prefix', 'my content') + self.assertTrue(self.ssh_helper.is_connected) + mock_paramiko.assert_called_once() self.assertTrue(cfg_file.startswith('/tmp')) - cfg_file = ssh_helper.upload_config_file('/my/prefix', 'my content') - self.assertTrue(ssh_helper.is_connected) - mock_paramiko.SSHClient.assert_called_once() - self.assertEqual(cfg_file, '/my/prefix') - def test_join_bin_path(self): - ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path') - expected_start = 'my' expected_middle_list = ['bin'] expected_end = 'path' - result = ssh_helper.join_bin_path() + result = self.ssh_helper.join_bin_path() self.assertTrue(result.startswith(expected_start)) self.assertAll(middle in result for middle in expected_middle_list) self.assertTrue(result.endswith(expected_end)) expected_middle_list.append(expected_end) expected_end = 'some_file.sh' - result = ssh_helper.join_bin_path('some_file.sh') + result = self.ssh_helper.join_bin_path('some_file.sh') self.assertTrue(result.startswith(expected_start)) self.assertAll(middle in result for middle in expected_middle_list) self.assertTrue(result.endswith(expected_end)) expected_middle_list.append('some_dir') expected_end = 'some_file.sh' - result = ssh_helper.join_bin_path('some_dir', 'some_file.sh') + result = self.ssh_helper.join_bin_path('some_dir', 'some_file.sh') self.assertTrue(result.startswith(expected_start)) self.assertAll(middle in result for middle in expected_middle_list) self.assertTrue(result.endswith(expected_end)) - @mock.patch('yardstick.ssh.paramiko') - @mock.patch('yardstick.ssh.provision_tool') + @mock.patch.object(paramiko, 'SSHClient') + @mock.patch.object(ssh, 'provision_tool') def test_provision_tool(self, mock_provision_tool, mock_paramiko): - ssh_helper = VnfSshHelper(self.VNFD_0['mgmt-interface'], 'my/bin/path') - ssh_helper._run = mock.MagicMock() - - self.assertFalse(ssh_helper.is_connected) - ssh_helper.provision_tool() - self.assertTrue(ssh_helper.is_connected) - mock_paramiko.SSHClient.assert_called_once() + self.assertFalse(self.ssh_helper.is_connected) + self.ssh_helper.provision_tool() + self.assertTrue(self.ssh_helper.is_connected) + mock_paramiko.assert_called_once() mock_provision_tool.assert_called_once() - ssh_helper.provision_tool(tool_file='my_tool.sh') - self.assertTrue(ssh_helper.is_connected) - mock_paramiko.SSHClient.assert_called_once() + self.ssh_helper.provision_tool(tool_file='my_tool.sh') + self.assertTrue(self.ssh_helper.is_connected) + mock_paramiko.assert_called_once() self.assertEqual(mock_provision_tool.call_count, 2) - ssh_helper.provision_tool('tool_path', 'my_tool.sh') - self.assertTrue(ssh_helper.is_connected) - mock_paramiko.SSHClient.assert_called_once() + self.ssh_helper.provision_tool('tool_path', 'my_tool.sh') + self.assertTrue(self.ssh_helper.is_connected) + mock_paramiko.assert_called_once() self.assertEqual(mock_provision_tool.call_count, 3) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py index 741201fdb..ab7a6a88e 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py @@ -17,8 +17,11 @@ import os import mock import six import unittest +import ipaddress +from collections import OrderedDict from yardstick.common import utils +from yardstick.common import exceptions from yardstick.benchmark import contexts from yardstick.benchmark.contexts import base as ctx_base from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api @@ -49,12 +52,43 @@ class TestIxiaResourceHelper(unittest.TestCase): mock.Mock(), MyRfcHelper) self.assertIsInstance(ixia_resource_helper.rfc_helper, MyRfcHelper) + def test__init_ix_scenario(self): + mock_scenario = mock.Mock() + mock_scenario_helper = mock.Mock() + mock_scenario_helper.scenario_cfg = {'ixia_config': 'TestScenario', + 'options': 'scenario_options'} + mock_setup_helper = mock.Mock(scenario_helper=mock_scenario_helper) + ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock_setup_helper) + ixia_resource_helper._ixia_scenarios = {'TestScenario': mock_scenario} + ixia_resource_helper.client = 'client' + ixia_resource_helper.context_cfg = 'context' + ixia_resource_helper._init_ix_scenario() + mock_scenario.assert_called_once_with('client', 'context', 'scenario_options') + + def test__init_ix_scenario_not_supported_cfg_type(self): + mock_scenario_helper = mock.Mock() + mock_scenario_helper.scenario_cfg = {'ixia_config': 'FakeScenario', + 'options': 'scenario_options'} + mock_setup_helper = mock.Mock(scenario_helper=mock_scenario_helper) + ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock_setup_helper) + ixia_resource_helper._ixia_scenarios = {'TestScenario': mock.Mock()} + with self.assertRaises(RuntimeError): + ixia_resource_helper._init_ix_scenario() + + @mock.patch.object(tg_rfc2544_ixia.IxiaResourceHelper, '_init_ix_scenario') + def test_setup(self, mock__init_ix_scenario): + ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock()) + ixia_resource_helper.setup() + mock__init_ix_scenario.assert_called_once() + def test_stop_collect_with_client(self): mock_client = mock.Mock() ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock()) ixia_resource_helper.client = mock_client + ixia_resource_helper._ix_scenario = mock.Mock() ixia_resource_helper.stop_collect() self.assertEqual(1, ixia_resource_helper._terminated.value) + ixia_resource_helper._ix_scenario.stop_protocols.assert_called_once() def test_run_traffic(self): mock_tprofile = mock.Mock() @@ -63,6 +97,7 @@ class TestIxiaResourceHelper(unittest.TestCase): ixia_rhelper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock()) ixia_rhelper.rfc_helper = mock.Mock() ixia_rhelper.vnfd_helper = mock.Mock() + ixia_rhelper._ix_scenario = mock.Mock() ixia_rhelper.vnfd_helper.port_pairs.all_ports = [] with mock.patch.object(ixia_rhelper, 'generate_samples'), \ mock.patch.object(ixia_rhelper, '_build_ports'), \ @@ -71,6 +106,7 @@ class TestIxiaResourceHelper(unittest.TestCase): ixia_rhelper.run_traffic(mock_tprofile) self.assertEqual('fake_samples', ixia_rhelper._queue.get()) + mock_tprofile.update_traffic_profile.assert_called_once() @mock.patch.object(tg_rfc2544_ixia, 'ixnet_api') @@ -261,8 +297,8 @@ class TestIXIATrafficGen(unittest.TestCase): ssh_mock.execute = \ mock.Mock(return_value=(0, "", "")) ssh.from_node.return_value = ssh_mock - ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd, - 'task_id') + ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen( + NAME, vnfd, 'task_id', resource_helper_type=mock.Mock()) ixnet_traffic_gen._terminated = mock.MagicMock() ixnet_traffic_gen._terminated.value = 0 ixnet_traffic_gen._ixia_traffic_gen = mock.MagicMock() @@ -360,6 +396,7 @@ class TestIXIATrafficGen(unittest.TestCase): sut.resource_helper.client_started = mock.MagicMock() sut.resource_helper.client_started.value = 1 sut.resource_helper.rfc_helper.iteration.value = 11 + sut.resource_helper._ix_scenario = mock.Mock() sut.scenario_helper.scenario_cfg = { 'options': { @@ -392,3 +429,532 @@ class TestIXIATrafficGen(unittest.TestCase): self.assertIsNone(result) _traffic_runner() + + +class TestIxiaBasicScenario(unittest.TestCase): + def setUp(self): + self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen') + self.mock_IxNextgen = self._mock_IxNextgen.start() + self.context_cfg = mock.Mock() + self.ixia_cfg = mock.Mock() + self.scenario = tg_rfc2544_ixia.IxiaBasicScenario(self.mock_IxNextgen, + self.context_cfg, + self.ixia_cfg) + self.addCleanup(self._stop_mocks) + + def _stop_mocks(self): + self._mock_IxNextgen.stop() + + def test___init___(self): + self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaBasicScenario) + self.assertEqual(self.scenario.client, self.mock_IxNextgen) + + def test_create_traffic_model(self): + self.mock_IxNextgen.get_vports.return_value = [1, 2, 3, 4] + self.scenario.create_traffic_model() + self.scenario.client.get_vports.assert_called_once() + self.scenario.client.create_traffic_model.assert_called_once_with([1, 3], [2, 4]) + + def test_apply_config(self): + self.assertIsNone(self.scenario.apply_config()) + + def test_run_protocols(self): + self.assertIsNone(self.scenario.run_protocols()) + + def test_stop_protocols(self): + self.assertIsNone(self.scenario.stop_protocols()) + + +class TestIxiaL3Scenario(TestIxiaBasicScenario): + IXIA_CFG = { + 'flow': { + 'src_ip': ['192.168.0.1-192.168.0.50'], + 'dst_ip': ['192.168.1.1-192.168.1.150'] + } + } + + CONTEXT_CFG = { + 'nodes': { + 'tg__0': { + 'role': 'IxNet', + 'interfaces': { + 'xe0': { + 'vld_id': 'uplink_0', + 'local_ip': '10.1.1.1', + 'local_mac': 'aa:bb:cc:dd:ee:ff', + 'ifname': 'xe0' + }, + 'xe1': { + 'vld_id': 'downlink_0', + 'local_ip': '20.2.2.2', + 'local_mac': 'bb:bb:cc:dd:ee:ee', + 'ifname': 'xe1' + } + }, + 'routing_table': [{ + 'network': "152.16.100.20", + 'netmask': '255.255.0.0', + 'gateway': '152.16.100.21', + 'if': 'xe0' + }] + } + } + } + + def setUp(self): + super(TestIxiaL3Scenario, self).setUp() + self.ixia_cfg = self.IXIA_CFG + self.context_cfg = self.CONTEXT_CFG + self.scenario = tg_rfc2544_ixia.IxiaL3Scenario(self.mock_IxNextgen, + self.context_cfg, + self.ixia_cfg) + + def test___init___(self): + self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaL3Scenario) + self.assertEqual(self.scenario.client, self.mock_IxNextgen) + + def test_create_traffic_model(self): + self.mock_IxNextgen.get_vports.return_value = ['1', '2'] + self.scenario.create_traffic_model() + self.scenario.client.get_vports.assert_called_once() + self.scenario.client.create_ipv4_traffic_model.\ + assert_called_once_with(['1/protocols/static'], + ['2/protocols/static']) + + def test_apply_config(self): + self.scenario._add_interfaces = mock.Mock() + self.scenario._add_static_ips = mock.Mock() + self.assertIsNone(self.scenario.apply_config()) + + def test__add_static(self): + self.mock_IxNextgen.get_vports.return_value = ['1', '2'] + self.mock_IxNextgen.get_static_interface.side_effect = ['intf1', + 'intf2'] + + self.scenario._add_static_ips() + + self.mock_IxNextgen.get_static_interface.assert_any_call('1') + self.mock_IxNextgen.get_static_interface.assert_any_call('2') + + self.scenario.client.add_static_ipv4.assert_any_call( + 'intf1', '1', '192.168.0.1', 49, '32') + self.scenario.client.add_static_ipv4.assert_any_call( + 'intf2', '2', '192.168.1.1', 149, '32') + + def test__add_interfaces(self): + self.mock_IxNextgen.get_vports.return_value = ['1', '2'] + + self.scenario._add_interfaces() + + self.mock_IxNextgen.add_interface.assert_any_call('1', + '10.1.1.1', + 'aa:bb:cc:dd:ee:ff', + '152.16.100.21') + self.mock_IxNextgen.add_interface.assert_any_call('2', + '20.2.2.2', + 'bb:bb:cc:dd:ee:ee', + None) + + +class TestIxiaPppoeClientScenario(unittest.TestCase): + + IXIA_CFG = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1, + 's_vlan': 10, + 'c_vlan': 20, + 'ip': ['10.3.3.1', '10.4.4.1'] + }, + 'ipv4_client': { + 'sessions_per_port': 1, + 'sessions_per_vlan': 1, + 'vlan': 101, + 'gateway_ip': ['10.1.1.1', '10.2.2.1'], + 'ip': ['10.1.1.1', '10.2.2.1'], + 'prefix': ['24', '24'] + } + } + + CONTEXT_CFG = { + 'nodes': {'tg__0': { + 'interfaces': {'xe0': { + 'local_ip': '10.1.1.1', + 'netmask': '255.255.255.0' + }}}}} + + def setUp(self): + self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen') + self.mock_IxNextgen = self._mock_IxNextgen.start() + self.scenario = tg_rfc2544_ixia.IxiaPppoeClientScenario( + self.mock_IxNextgen, self.CONTEXT_CFG, self.IXIA_CFG) + tg_rfc2544_ixia.WAIT_PROTOCOLS_STARTED = 2 + self.addCleanup(self._stop_mocks) + + def _stop_mocks(self): + self._mock_IxNextgen.stop() + + def test___init___(self): + self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaPppoeClientScenario) + self.assertEqual(self.scenario.client, self.mock_IxNextgen) + + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_fill_ixia_config') + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_apply_access_network_config') + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_apply_core_network_config') + def test_apply_config(self, mock_apply_core_net_cfg, + mock_apply_access_net_cfg, + mock_fill_ixia_config): + self.mock_IxNextgen.get_vports.return_value = [1, 2, 3, 4] + self.scenario.apply_config() + self.scenario.client.get_vports.assert_called_once() + self.assertEqual(self.scenario._uplink_vports, [1, 3]) + self.assertEqual(self.scenario._downlink_vports, [2, 4]) + mock_fill_ixia_config.assert_called_once() + mock_apply_core_net_cfg.assert_called_once() + mock_apply_access_net_cfg.assert_called_once() + + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_get_endpoints_src_dst_id_pairs') + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_get_endpoints_src_dst_obj_pairs') + def test_create_traffic_model(self, mock_obj_pairs, mock_id_pairs): + uplink_endpoints = ['group1', 'group2'] + downlink_endpoints = ['group3', 'group3'] + mock_id_pairs.return_value = ['xe0', 'xe1', 'xe0', 'xe1'] + mock_obj_pairs.return_value = ['group1', 'group3', 'group2', 'group3'] + mock_tp = mock.Mock() + mock_tp.full_profile = {'uplink_0': 'data', + 'downlink_0': 'data', + 'uplink_1': 'data', + 'downlink_1': 'data' + } + self.scenario.create_traffic_model(mock_tp) + mock_id_pairs.assert_called_once_with(mock_tp.full_profile) + mock_obj_pairs.assert_called_once_with(['xe0', 'xe1', 'xe0', 'xe1']) + self.scenario.client.create_ipv4_traffic_model.assert_called_once_with( + uplink_endpoints, downlink_endpoints) + + def test__get_endpoints_src_dst_id_pairs(self): + full_tp = OrderedDict([ + ('uplink_0', {'ipv4': {'port': 'xe0'}}), + ('downlink_0', {'ipv4': {'port': 'xe1'}}), + ('uplink_1', {'ipv4': {'port': 'xe0'}}), + ('downlink_1', {'ipv4': {'port': 'xe3'}})]) + endpoints_src_dst_pairs = ['xe0', 'xe1', 'xe0', 'xe3'] + res = self.scenario._get_endpoints_src_dst_id_pairs(full_tp) + self.assertEqual(res, endpoints_src_dst_pairs) + + def test__get_endpoints_src_dst_id_pairs_wrong_flows_number(self): + full_tp = OrderedDict([ + ('uplink_0', {'ipv4': {'port': 'xe0'}}), + ('downlink_0', {'ipv4': {'port': 'xe1'}}), + ('uplink_1', {'ipv4': {'port': 'xe0'}})]) + with self.assertRaises(RuntimeError): + self.scenario._get_endpoints_src_dst_id_pairs(full_tp) + + def test__get_endpoints_src_dst_id_pairs_no_port_key(self): + full_tp = OrderedDict([ + ('uplink_0', {'ipv4': {'id': 1}}), + ('downlink_0', {'ipv4': {'id': 2}})]) + self.assertEqual( + self.scenario._get_endpoints_src_dst_id_pairs(full_tp), []) + + def test__get_endpoints_src_dst_obj_pairs_tp_with_port_key(self): + endpoints_id_pairs = ['xe0', 'xe1', + 'xe0', 'xe1', + 'xe0', 'xe3', + 'xe0', 'xe3'] + ixia_cfg = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1 + }, + 'flow': { + 'src_ip': [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}], + 'dst_ip': [{'tg__0': 'xe1'}, {'tg__0': 'xe3'}] + } + } + + expected_result = ['tp1_dg1', 'tp3_dg1', 'tp1_dg2', 'tp3_dg1', + 'tp1_dg3', 'tp4_dg1', 'tp1_dg4', 'tp4_dg1'] + + self.scenario._ixia_cfg = ixia_cfg + self.scenario._access_topologies = ['topology1', 'topology2'] + self.scenario._core_topologies = ['topology3', 'topology4'] + self.mock_IxNextgen.get_topology_device_groups.side_effect = \ + [['tp1_dg1', 'tp1_dg2', 'tp1_dg3', 'tp1_dg4'], + ['tp2_dg1', 'tp2_dg2', 'tp2_dg3', 'tp2_dg4'], + ['tp3_dg1'], + ['tp4_dg1']] + res = self.scenario._get_endpoints_src_dst_obj_pairs( + endpoints_id_pairs) + self.assertEqual(res, expected_result) + + def test__get_endpoints_src_dst_obj_pairs_default_flows_mapping(self): + endpoints_id_pairs = [] + ixia_cfg = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1 + }, + 'flow': { + 'src_ip': [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}], + 'dst_ip': [{'tg__0': 'xe1'}, {'tg__0': 'xe3'}] + } + } + + expected_result = ['tp1_dg1', 'tp3_dg1', 'tp1_dg2', 'tp3_dg1', + 'tp1_dg3', 'tp3_dg1', 'tp1_dg4', 'tp3_dg1', + 'tp2_dg1', 'tp4_dg1', 'tp2_dg2', 'tp4_dg1', + 'tp2_dg3', 'tp4_dg1', 'tp2_dg4', 'tp4_dg1'] + + self.scenario._ixia_cfg = ixia_cfg + self.scenario._access_topologies = ['topology1', 'topology2'] + self.scenario._core_topologies = ['topology3', 'topology4'] + self.mock_IxNextgen.get_topology_device_groups.side_effect = \ + [['tp1_dg1', 'tp1_dg2', 'tp1_dg3', 'tp1_dg4'], + ['tp2_dg1', 'tp2_dg2', 'tp2_dg3', 'tp2_dg4'], + ['tp3_dg1'], + ['tp4_dg1']] + res = self.scenario._get_endpoints_src_dst_obj_pairs( + endpoints_id_pairs) + self.assertEqual(res, expected_result) + + def test_run_protocols(self): + self.scenario.client.is_protocols_running.return_value = True + self.scenario.run_protocols() + self.scenario.client.start_protocols.assert_called_once() + + def test_run_protocols_timeout_exception(self): + self.scenario.client.is_protocols_running.return_value = False + with self.assertRaises(exceptions.WaitTimeout): + self.scenario.run_protocols() + self.scenario.client.start_protocols.assert_called_once() + + def test_stop_protocols(self): + self.scenario.stop_protocols() + self.scenario.client.stop_protocols.assert_called_once() + + def test__get_intf_addr_str_type_input(self): + intf = '192.168.10.2/24' + ip, mask = self.scenario._get_intf_addr(intf) + self.assertEqual(ip, '192.168.10.2') + self.assertEqual(mask, 24) + + def test__get_intf_addr_dict_type_input(self): + intf = {'tg__0': 'xe0'} + ip, mask = self.scenario._get_intf_addr(intf) + self.assertEqual(ip, '10.1.1.1') + self.assertEqual(mask, 24) + + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, '_get_intf_addr') + def test__fill_ixia_config(self, mock_get_intf_addr): + + ixia_cfg = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1, + 's_vlan': 10, + 'c_vlan': 20, + 'ip': ['10.3.3.1/24', '10.4.4.1/24'] + }, + 'ipv4_client': { + 'sessions_per_port': 1, + 'sessions_per_vlan': 1, + 'vlan': 101, + 'gateway_ip': ['10.1.1.1/24', '10.2.2.1/24'], + 'ip': ['10.1.1.1/24', '10.2.2.1/24'] + } + } + + mock_get_intf_addr.side_effect = [ + ('10.3.3.1', '24'), + ('10.4.4.1', '24'), + ('10.1.1.1', '24'), + ('10.2.2.1', '24'), + ('10.1.1.1', '24'), + ('10.2.2.1', '24') + ] + self.scenario._ixia_cfg = ixia_cfg + self.scenario._fill_ixia_config() + self.assertEqual(mock_get_intf_addr.call_count, 6) + self.assertEqual(self.scenario._ixia_cfg['pppoe_client']['ip'], + ['10.3.3.1', '10.4.4.1']) + self.assertEqual(self.scenario._ixia_cfg['ipv4_client']['ip'], + ['10.1.1.1', '10.2.2.1']) + self.assertEqual(self.scenario._ixia_cfg['ipv4_client']['prefix'], + ['24', '24']) + + @mock.patch('yardstick.network_services.libs.ixia_libs.ixnet.ixnet_api.Vlan') + def test__apply_access_network_config_pap_auth(self, mock_vlan): + _ixia_cfg = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1, + 's_vlan': 10, + 'c_vlan': 20, + 'pap_user': 'test_pap', + 'pap_password': 'pap' + }} + pap_user = _ixia_cfg['pppoe_client']['pap_user'] + pap_passwd = _ixia_cfg['pppoe_client']['pap_password'] + self.scenario._ixia_cfg = _ixia_cfg + self.scenario._uplink_vports = [0, 2] + self.scenario.client.add_topology.side_effect = ['Topology 1', 'Topology 2'] + self.scenario.client.add_device_group.side_effect = ['Dg1', 'Dg2', 'Dg3', + 'Dg4', 'Dg5', 'Dg6', + 'Dg7', 'Dg8'] + self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2', 'Eth3', + 'Eth4', 'Eth5', 'Eth6', + 'Eth7', 'Eth8'] + self.scenario._apply_access_network_config() + self.assertEqual(self.scenario.client.add_topology.call_count, 2) + self.assertEqual(self.scenario.client.add_device_group.call_count, 8) + self.assertEqual(self.scenario.client.add_ethernet.call_count, 8) + self.assertEqual(mock_vlan.call_count, 16) + self.assertEqual(self.scenario.client.add_vlans.call_count, 8) + self.assertEqual(self.scenario.client.add_pppox_client.call_count, 8) + self.scenario.client.add_topology.assert_has_calls([ + mock.call('Topology access 0', 0), + mock.call('Topology access 1', 2) + ]) + self.scenario.client.add_device_group.assert_has_calls([ + mock.call('Topology 1', 'SVLAN 10', 1), + mock.call('Topology 1', 'SVLAN 11', 1), + mock.call('Topology 1', 'SVLAN 12', 1), + mock.call('Topology 1', 'SVLAN 13', 1), + mock.call('Topology 2', 'SVLAN 14', 1), + mock.call('Topology 2', 'SVLAN 15', 1), + mock.call('Topology 2', 'SVLAN 16', 1), + mock.call('Topology 2', 'SVLAN 17', 1) + ]) + self.scenario.client.add_ethernet.assert_has_calls([ + mock.call('Dg1', 'Ethernet'), + mock.call('Dg2', 'Ethernet'), + mock.call('Dg3', 'Ethernet'), + mock.call('Dg4', 'Ethernet'), + mock.call('Dg5', 'Ethernet'), + mock.call('Dg6', 'Ethernet'), + mock.call('Dg7', 'Ethernet'), + mock.call('Dg8', 'Ethernet') + ]) + mock_vlan.assert_has_calls([ + mock.call(vlan_id=10), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=11), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=12), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=13), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=14), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=15), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=16), + mock.call(vlan_id=20, vlan_id_step=1), + mock.call(vlan_id=17), + mock.call(vlan_id=20, vlan_id_step=1) + ]) + self.scenario.client.add_pppox_client.assert_has_calls([ + mock.call('Eth1', 'pap', pap_user, pap_passwd), + mock.call('Eth2', 'pap', pap_user, pap_passwd), + mock.call('Eth3', 'pap', pap_user, pap_passwd), + mock.call('Eth4', 'pap', pap_user, pap_passwd), + mock.call('Eth5', 'pap', pap_user, pap_passwd), + mock.call('Eth6', 'pap', pap_user, pap_passwd), + mock.call('Eth7', 'pap', pap_user, pap_passwd), + mock.call('Eth8', 'pap', pap_user, pap_passwd) + ]) + + def test__apply_access_network_config_chap_auth(self): + _ixia_cfg = { + 'pppoe_client': { + 'sessions_per_port': 4, + 'sessions_per_svlan': 1, + 's_vlan': 10, + 'c_vlan': 20, + 'chap_user': 'test_chap', + 'chap_password': 'chap' + }} + chap_user = _ixia_cfg['pppoe_client']['chap_user'] + chap_passwd = _ixia_cfg['pppoe_client']['chap_password'] + self.scenario._ixia_cfg = _ixia_cfg + self.scenario._uplink_vports = [0, 2] + self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2', 'Eth3', + 'Eth4', 'Eth5', 'Eth6', + 'Eth7', 'Eth8'] + self.scenario._apply_access_network_config() + self.assertEqual(self.scenario.client.add_pppox_client.call_count, 8) + self.scenario.client.add_pppox_client.assert_has_calls([ + mock.call('Eth1', 'chap', chap_user, chap_passwd), + mock.call('Eth2', 'chap', chap_user, chap_passwd), + mock.call('Eth3', 'chap', chap_user, chap_passwd), + mock.call('Eth4', 'chap', chap_user, chap_passwd), + mock.call('Eth5', 'chap', chap_user, chap_passwd), + mock.call('Eth6', 'chap', chap_user, chap_passwd), + mock.call('Eth7', 'chap', chap_user, chap_passwd), + mock.call('Eth8', 'chap', chap_user, chap_passwd) + ]) + + @mock.patch('yardstick.network_services.libs.ixia_libs.ixnet.ixnet_api.Vlan') + def test__apply_core_network_config_no_bgp_proto(self, mock_vlan): + self.scenario._downlink_vports = [1, 3] + self.scenario.client.add_topology.side_effect = ['Topology 1', 'Topology 2'] + self.scenario.client.add_device_group.side_effect = ['Dg1', 'Dg2'] + self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2'] + self.scenario._apply_core_network_config() + self.assertEqual(self.scenario.client.add_topology.call_count, 2) + self.assertEqual(self.scenario.client.add_device_group.call_count, 2) + self.assertEqual(self.scenario.client.add_ethernet.call_count, 2) + self.assertEqual(mock_vlan.call_count, 2) + self.assertEqual(self.scenario.client.add_vlans.call_count, 2) + self.assertEqual(self.scenario.client.add_ipv4.call_count, 2) + self.scenario.client.add_topology.assert_has_calls([ + mock.call('Topology core 0', 1), + mock.call('Topology core 1', 3) + ]) + self.scenario.client.add_device_group.assert_has_calls([ + mock.call('Topology 1', 'Core port 0', 1), + mock.call('Topology 2', 'Core port 1', 1) + ]) + self.scenario.client.add_ethernet.assert_has_calls([ + mock.call('Dg1', 'Ethernet'), + mock.call('Dg2', 'Ethernet') + ]) + mock_vlan.assert_has_calls([ + mock.call(vlan_id=101), + mock.call(vlan_id=102) + ]) + self.scenario.client.add_ipv4.assert_has_calls([ + mock.call('Eth1', name='ipv4', addr=ipaddress.IPv4Address('10.1.1.2'), + addr_step='0.0.0.1', prefix='24', gateway='10.1.1.1'), + mock.call('Eth2', name='ipv4', addr=ipaddress.IPv4Address('10.2.2.2'), + addr_step='0.0.0.1', prefix='24', gateway='10.2.2.1') + ]) + self.scenario.client.add_bgp.assert_not_called() + + def test__apply_core_network_config_with_bgp_proto(self): + bgp_params = { + 'bgp': { + 'bgp_type': 'external', + 'dut_ip': '10.0.0.1', + 'as_number': 65000 + } + } + self.scenario._ixia_cfg['ipv4_client'].update(bgp_params) + self.scenario._downlink_vports = [1, 3] + self.scenario.client.add_ipv4.side_effect = ['ipv4_1', 'ipv4_2'] + self.scenario._apply_core_network_config() + self.assertEqual(self.scenario.client.add_bgp.call_count, 2) + self.scenario.client.add_bgp.assert_has_calls([ + mock.call('ipv4_1', dut_ip=bgp_params["bgp"]["dut_ip"], + local_as=bgp_params["bgp"]["as_number"], + bgp_type=bgp_params["bgp"]["bgp_type"]), + mock.call('ipv4_2', dut_ip=bgp_params["bgp"]["dut_ip"], + local_as=bgp_params["bgp"]["as_number"], + bgp_type=bgp_params["bgp"]["bgp_type"]) + ]) |