3 # Copyright (c) 2016-2017 Intel Corporation
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 from __future__ import absolute_import
25 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
27 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
28 from tests.unit import STL_MOCKS
32 STLClient = mock.MagicMock()
33 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
37 from yardstick.network_services.vnf_generic.vnf.tg_trex import \
38 TrexTrafficGen, TrexResourceHelper
39 from yardstick.network_services.traffic_profile.base import TrafficProfile
42 class TestTrexTrafficGen(unittest.TestCase):
43 VNFD = {'vnfd:vnfd-catalog':
45 [{'short-name': 'VpeVnf',
48 [{'network': '152.16.100.20',
49 'netmask': '255.255.255.0',
50 'gateway': '152.16.100.20',
52 {'network': '152.16.40.20',
53 'netmask': '255.255.255.0',
54 'gateway': '152.16.40.20',
56 'description': 'VPE approximation using DPDK',
57 'name': 'vpevnf-baremetal',
59 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
61 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
63 {'network': '0064:ff9b:0:0:0:0:9810:2814',
65 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
67 'id': 'vpevnf-baremetal',
69 [{'virtual-interface':
70 {'dst_mac': '00:00:00:00:00:04',
71 'vpci': '0000:05:00.0',
72 'local_ip': '152.16.100.19',
73 'type': 'PCI-PASSTHROUGH',
74 'netmask': '255.255.255.0',
76 'bandwidth': '10 Gbps',
78 'dst_ip': '152.16.100.20',
79 'local_iface_name': 'xe0',
80 'vld_id': 'downlink_0',
82 'local_mac': '00:00:00:00:00:02'},
83 'vnfd-connection-point-ref': 'xe0',
86 {'dst_mac': '00:00:00:00:00:03',
87 'vpci': '0000:05:00.1',
88 'local_ip': '152.16.40.19',
89 'type': 'PCI-PASSTHROUGH',
91 'netmask': '255.255.255.0',
93 'bandwidth': '10 Gbps',
94 'dst_ip': '152.16.40.20',
95 'local_iface_name': 'xe1',
98 'local_mac': '00:00:00:00:00:01'},
99 'vnfd-connection-point-ref': 'xe1',
101 'description': 'Vpe approximation using DPDK',
103 {'vdu-id': 'vpevnf-baremetal',
109 {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
110 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
111 {'type': 'VPORT', 'name': 'xe1'}],
112 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
115 "schema": "isb:traffic_profile:0.1",
117 "description": "Fixed traffic profile to run UDP traffic",
119 "traffic_type": "FixedTraffic",
120 "frame_rate": 100, # pps
131 "allowed_drop_rate": "0.8 - 1",
134 "rules": "acl_1rule.yaml",
138 "worker_config": "1C/1T",
143 "task_id": "a70bdf4a-8e67-47a3-9dc1-273c14506eb7",
144 "tc": "tc_ipv4_1Mflow_64B_packetsize",
146 "object": "NetworkServiceTestCase",
148 "output_filename": "/tmp/yardstick.out",
149 "runner_id": 74476, "duration": 400,
152 "traffic_profile": "ipv4_throughput_acl.yaml",
154 "flow": "ipv4_Packets_acl.yaml",
155 "imix": "imix_voice.yaml"
159 "tg__2": "trafficgen_2.yardstick",
160 "tg__1": "trafficgen_1.yardstick",
161 "vnf__1": "vnf.yardstick"
163 "topology": "udpreplay-tg-topology-baremetal.yaml"
169 "vnfd-id-ref": "vnf__1",
173 "local_iface_name": "ens786f0",
174 "vld_id": TrafficProfile.UPLINK,
175 "netmask": "255.255.255.0",
176 "vpci": "0000:05:00.0",
177 "local_ip": "152.16.100.19",
179 "dst_ip": "152.16.100.20",
180 "local_mac": "00:00:00:00:00:02",
181 "dst_mac": "00:00:00:00:00:04",
185 "local_iface_name": "ens786f1",
186 "vld_id": TrafficProfile.DOWNLINK,
187 "netmask": "255.255.255.0",
188 "vpci": "0000:05:00.1",
189 "local_ip": "152.16.40.19",
191 "dst_ip": "152.16.40.20",
192 "local_mac": "00:00:00:00:00:01",
193 "dst_mac": "00:00:00:00:00:03",
203 "gateway": "0064:ff9b:0:0:0:0:9810:6414",
204 "network": "0064:ff9b:0:0:0:0:9810:6414"
209 "gateway": "0064:ff9b:0:0:0:0:9810:2814",
210 "network": "0064:ff9b:0:0:0:0:9810:2814"
214 "VNF model": "udp_replay.yaml",
215 "name": "vnf.yardstick",
216 "member-vnf-index": "2",
219 "netmask": "255.255.255.0",
221 "gateway": "152.16.100.20",
222 "network": "152.16.100.20"
225 "netmask": "255.255.255.0",
227 "gateway": "152.16.40.20",
228 "network": "152.16.40.20"
233 "trafficgen_2.yardstick": {
234 "member-vnf-index": "3",
235 "role": "TrafficGen",
236 "name": "trafficgen_2.yardstick",
237 "vnfd-id-ref": "tg__2",
241 "local_iface_name": "ens513f0",
242 "vld_id": TrafficProfile.DOWNLINK,
243 "netmask": "255.255.255.0",
244 "vpci": "0000:02:00.0",
245 "local_ip": "152.16.40.20",
247 "dst_ip": "152.16.40.19",
248 "local_mac": "00:00:00:00:00:03",
249 "dst_mac": "00:00:00:00:00:01",
253 "local_iface_name": "ens513f1",
254 "netmask": "255.255.255.0",
255 "network": "202.16.100.0",
256 "local_ip": "202.16.100.20",
258 "local_mac": "00:1e:67:d0:60:5d",
259 "vpci": "0000:02:00.1",
264 "VNF model": "l3fwd_vnf.yaml",
267 "trafficgen_1.yardstick": {
268 "member-vnf-index": "1",
269 "role": "TrafficGen",
270 "name": "trafficgen_1.yardstick",
271 "vnfd-id-ref": "tg__1",
275 "local_iface_name": "ens785f0",
276 "vld_id": TrafficProfile.UPLINK,
277 "netmask": "255.255.255.0",
278 "vpci": "0000:05:00.0",
279 "local_ip": "152.16.100.20",
281 "dst_ip": "152.16.100.19",
282 "local_mac": "00:00:00:00:00:04",
283 "dst_mac": "00:00:00:00:00:02",
287 "local_ip": "152.16.100.21",
289 "vpci": "0000:05:00.1",
291 "local_iface_name": "ens785f1",
292 "netmask": "255.255.255.0",
293 "local_mac": "00:00:00:00:00:01"
297 "VNF model": "tg_rfc2544_tpl.yaml",
303 @mock.patch(SSH_HELPER)
304 def test___init__(self, ssh):
306 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
307 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
308 self.assertIsInstance(trex_traffic_gen.resource_helper, TrexResourceHelper)
310 @mock.patch(SSH_HELPER)
311 def test_collect_kpi(self, ssh):
313 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
314 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
315 trex_traffic_gen.resource_helper._queue.put({})
316 result = trex_traffic_gen.collect_kpi()
317 self.assertEqual({}, result)
319 @mock.patch(SSH_HELPER)
320 def test_listen_traffic(self, ssh):
322 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
323 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
324 self.assertIsNone(trex_traffic_gen.listen_traffic({}))
326 @mock.patch(SSH_HELPER)
327 def test_instantiate(self, ssh):
330 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
331 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
332 trex_traffic_gen._start_server = mock.Mock(return_value=0)
333 trex_traffic_gen._tg_process = mock.MagicMock()
334 trex_traffic_gen._tg_process.start = mock.Mock()
335 trex_traffic_gen._tg_process.exitcode = 0
336 trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=1)
337 trex_traffic_gen.ssh_helper = mock.MagicMock()
338 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
339 trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
341 self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
343 @mock.patch(SSH_HELPER)
344 def test_instantiate_error(self, ssh):
345 mock_ssh(ssh, exec_result=(1, "", ""))
347 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
348 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
349 trex_traffic_gen._start_server = mock.Mock(return_value=0)
350 trex_traffic_gen._tg_process = mock.MagicMock()
351 trex_traffic_gen._tg_process.start = mock.Mock()
352 trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=0)
353 trex_traffic_gen.ssh_helper = mock.MagicMock()
354 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
355 trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
356 self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
358 @mock.patch(SSH_HELPER)
359 def test__start_server(self, ssh):
361 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
362 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
363 trex_traffic_gen.ssh_helper = mock.MagicMock()
364 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
365 trex_traffic_gen.scenario_helper.scenario_cfg = {}
366 self.assertIsNone(trex_traffic_gen._start_server())
368 @mock.patch(SSH_HELPER)
369 def test__start_server_multiple_queues(self, ssh):
371 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
372 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
373 trex_traffic_gen.ssh_helper = mock.MagicMock()
374 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
375 trex_traffic_gen.scenario_helper.scenario_cfg = {"options": {NAME: {"queues_per_port": 2}}}
376 self.assertIsNone(trex_traffic_gen._start_server())
378 @mock.patch(SSH_HELPER)
379 def test__traffic_runner(self, ssh):
382 mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
383 mock_traffic_profile.get_traffic_definition.return_value = "64"
384 mock_traffic_profile.execute_traffic.return_value = "64"
385 mock_traffic_profile.params = self.TRAFFIC_PROFILE
387 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
388 self.sut = TrexTrafficGen(NAME, vnfd)
389 self.sut.ssh_helper = mock.Mock()
390 self.sut.ssh_helper.run = mock.Mock()
391 self.sut._connect_client = mock.Mock(autospec=STLClient)
392 self.sut._connect_client.get_stats = mock.Mock(return_value="0")
393 self.sut.resource_helper.RUN_DURATION = 0
394 self.sut.resource_helper.QUEUE_WAIT_TIME = 0
395 # must generate cfg before we can run traffic so Trex port mapping is created
396 self.sut.resource_helper.generate_cfg()
397 self.sut._traffic_runner(mock_traffic_profile)
399 @mock.patch(SSH_HELPER)
400 def test__generate_trex_cfg(self, ssh):
402 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
403 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
404 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
405 self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
407 @mock.patch(SSH_HELPER)
408 def test_build_ports_reversed_pci_ordering(self, ssh):
410 vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
411 vnfd['vdu'][0]['external-interface'] = [
412 {'virtual-interface':
413 {'dst_mac': '00:00:00:00:00:04',
414 'vpci': '0000:05:00.0',
415 'local_ip': '152.16.100.19',
416 'type': 'PCI-PASSTHROUGH',
417 'netmask': '255.255.255.0',
419 'bandwidth': '10 Gbps',
421 'dst_ip': '152.16.100.20',
422 'local_iface_name': 'xe0',
423 'vld_id': 'downlink_0',
425 'local_mac': '00:00:00:00:00:02'},
426 'vnfd-connection-point-ref': 'xe0',
428 {'virtual-interface':
429 {'dst_mac': '00:00:00:00:00:03',
430 'vpci': '0000:04:00.0',
431 'local_ip': '152.16.40.19',
432 'type': 'PCI-PASSTHROUGH',
434 'netmask': '255.255.255.0',
436 'bandwidth': '10 Gbps',
437 'dst_ip': '152.16.40.20',
438 'local_iface_name': 'xe1',
439 'vld_id': 'uplink_0',
441 'local_mac': '00:00:00:00:00:01'},
442 'vnfd-connection-point-ref': 'xe1',
444 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
445 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
446 trex_traffic_gen.resource_helper.generate_cfg()
447 trex_traffic_gen.resource_helper._build_ports()
448 self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
449 # there is a gap in ordering
450 self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
453 @mock.patch(SSH_HELPER)
454 def test_run_traffic(self, ssh):
457 mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
458 mock_traffic_profile.get_traffic_definition.return_value = "64"
459 mock_traffic_profile.params = self.TRAFFIC_PROFILE
461 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
462 self.sut = TrexTrafficGen(NAME, vnfd)
463 self.sut.ssh_helper = mock.Mock()
464 self.sut.ssh_helper.run = mock.Mock()
465 self.sut._traffic_runner = mock.Mock(return_value=0)
466 self.sut.resource_helper.client_started.value = 1
467 result = self.sut.run_traffic(mock_traffic_profile)
468 self.sut._traffic_process.terminate()
469 self.assertIsNotNone(result)
471 @mock.patch(SSH_HELPER)
472 def test_scale(self, ssh):
473 mock_ssh(ssh, exec_result=(1, "", ""))
474 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
475 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
476 trex_traffic_gen.scale('')
478 @mock.patch(SSH_HELPER)
479 def test_terminate(self, ssh):
481 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
482 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
483 trex_traffic_gen.ssh_helper = mock.MagicMock()
484 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
485 self.assertIsNone(trex_traffic_gen.terminate())
487 @mock.patch(SSH_HELPER)
488 def test__connect_client(self, ssh):
490 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
491 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
492 client = mock.Mock(autospec=STLClient)
493 client.connect = mock.Mock(return_value=0)
494 self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
497 if __name__ == '__main__':