1 # Copyright (c) 2016-2017 Intel Corporation
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
22 from tests.unit import STL_MOCKS
25 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
28 STLClient = mock.MagicMock()
29 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
33 from yardstick.network_services.vnf_generic.vnf.tg_trex import \
34 TrexTrafficGen, TrexResourceHelper
35 from yardstick.network_services.traffic_profile.base import TrafficProfile
38 class TestTrexTrafficGen(unittest.TestCase):
39 VNFD = {'vnfd:vnfd-catalog':
41 [{'short-name': 'VpeVnf',
44 [{'network': '152.16.100.20',
45 'netmask': '255.255.255.0',
46 'gateway': '152.16.100.20',
48 {'network': '152.16.40.20',
49 'netmask': '255.255.255.0',
50 'gateway': '152.16.40.20',
52 'description': 'VPE approximation using DPDK',
53 'name': 'vpevnf-baremetal',
55 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
57 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
59 {'network': '0064:ff9b:0:0:0:0:9810:2814',
61 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
63 'id': 'vpevnf-baremetal',
65 [{'virtual-interface':
66 {'dst_mac': '00:00:00:00:00:04',
67 'vpci': '0000:05:00.0',
68 'local_ip': '152.16.100.19',
69 'type': 'PCI-PASSTHROUGH',
70 'netmask': '255.255.255.0',
72 'bandwidth': '10 Gbps',
74 'dst_ip': '152.16.100.20',
75 'local_iface_name': 'xe0',
76 'vld_id': 'downlink_0',
78 'local_mac': '00:00:00:00:00:02'},
79 'vnfd-connection-point-ref': 'xe0',
82 {'dst_mac': '00:00:00:00:00:03',
83 'vpci': '0000:05:00.1',
84 'local_ip': '152.16.40.19',
85 'type': 'PCI-PASSTHROUGH',
87 'netmask': '255.255.255.0',
89 'bandwidth': '10 Gbps',
90 'dst_ip': '152.16.40.20',
91 'local_iface_name': 'xe1',
94 'local_mac': '00:00:00:00:00:01'},
95 'vnfd-connection-point-ref': 'xe1',
97 'description': 'Vpe approximation using DPDK',
99 {'vdu-id': 'vpevnf-baremetal',
105 {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
106 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
107 {'type': 'VPORT', 'name': 'xe1'}],
108 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
111 "schema": "isb:traffic_profile:0.1",
113 "description": "Fixed traffic profile to run UDP traffic",
115 "traffic_type": "FixedTraffic",
116 "frame_rate": 100, # pps
127 "allowed_drop_rate": "0.8 - 1",
130 "rules": "acl_1rule.yaml",
134 "worker_config": "1C/1T",
139 "task_id": "a70bdf4a-8e67-47a3-9dc1-273c14506eb7",
140 "tc": "tc_ipv4_1Mflow_64B_packetsize",
142 "object": "NetworkServiceTestCase",
144 "output_filename": "/tmp/yardstick.out",
145 "runner_id": 74476, "duration": 400,
148 "traffic_profile": "ipv4_throughput_acl.yaml",
150 "flow": "ipv4_Packets_acl.yaml",
151 "imix": "imix_voice.yaml"
155 "tg__2": "trafficgen_2.yardstick",
156 "tg__1": "trafficgen_1.yardstick",
157 "vnf__1": "vnf.yardstick"
159 "topology": "udpreplay-tg-topology-baremetal.yaml"
165 "vnfd-id-ref": "vnf__1",
169 "local_iface_name": "ens786f0",
170 "vld_id": TrafficProfile.UPLINK,
171 "netmask": "255.255.255.0",
172 "vpci": "0000:05:00.0",
173 "local_ip": "152.16.100.19",
175 "dst_ip": "152.16.100.20",
176 "local_mac": "00:00:00:00:00:02",
177 "dst_mac": "00:00:00:00:00:04",
181 "local_iface_name": "ens786f1",
182 "vld_id": TrafficProfile.DOWNLINK,
183 "netmask": "255.255.255.0",
184 "vpci": "0000:05:00.1",
185 "local_ip": "152.16.40.19",
187 "dst_ip": "152.16.40.20",
188 "local_mac": "00:00:00:00:00:01",
189 "dst_mac": "00:00:00:00:00:03",
199 "gateway": "0064:ff9b:0:0:0:0:9810:6414",
200 "network": "0064:ff9b:0:0:0:0:9810:6414"
205 "gateway": "0064:ff9b:0:0:0:0:9810:2814",
206 "network": "0064:ff9b:0:0:0:0:9810:2814"
210 "VNF model": "udp_replay.yaml",
211 "name": "vnf.yardstick",
212 "member-vnf-index": "2",
215 "netmask": "255.255.255.0",
217 "gateway": "152.16.100.20",
218 "network": "152.16.100.20"
221 "netmask": "255.255.255.0",
223 "gateway": "152.16.40.20",
224 "network": "152.16.40.20"
229 "trafficgen_2.yardstick": {
230 "member-vnf-index": "3",
231 "role": "TrafficGen",
232 "name": "trafficgen_2.yardstick",
233 "vnfd-id-ref": "tg__2",
237 "local_iface_name": "ens513f0",
238 "vld_id": TrafficProfile.DOWNLINK,
239 "netmask": "255.255.255.0",
240 "vpci": "0000:02:00.0",
241 "local_ip": "152.16.40.20",
243 "dst_ip": "152.16.40.19",
244 "local_mac": "00:00:00:00:00:03",
245 "dst_mac": "00:00:00:00:00:01",
249 "local_iface_name": "ens513f1",
250 "netmask": "255.255.255.0",
251 "network": "202.16.100.0",
252 "local_ip": "202.16.100.20",
254 "local_mac": "00:1e:67:d0:60:5d",
255 "vpci": "0000:02:00.1",
260 "VNF model": "l3fwd_vnf.yaml",
263 "trafficgen_1.yardstick": {
264 "member-vnf-index": "1",
265 "role": "TrafficGen",
266 "name": "trafficgen_1.yardstick",
267 "vnfd-id-ref": "tg__1",
271 "local_iface_name": "ens785f0",
272 "vld_id": TrafficProfile.UPLINK,
273 "netmask": "255.255.255.0",
274 "vpci": "0000:05:00.0",
275 "local_ip": "152.16.100.20",
277 "dst_ip": "152.16.100.19",
278 "local_mac": "00:00:00:00:00:04",
279 "dst_mac": "00:00:00:00:00:02",
283 "local_ip": "152.16.100.21",
285 "vpci": "0000:05:00.1",
287 "local_iface_name": "ens785f1",
288 "netmask": "255.255.255.0",
289 "local_mac": "00:00:00:00:00:01"
293 "VNF model": "tg_rfc2544_tpl.yaml",
299 @mock.patch(SSH_HELPER)
300 def test___init__(self, ssh):
302 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
303 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
304 self.assertIsInstance(trex_traffic_gen.resource_helper, TrexResourceHelper)
306 @mock.patch(SSH_HELPER)
307 def test_collect_kpi(self, ssh):
309 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
310 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
311 trex_traffic_gen.resource_helper._queue.put({})
312 result = trex_traffic_gen.collect_kpi()
313 self.assertEqual({}, result)
315 @mock.patch(SSH_HELPER)
316 def test_listen_traffic(self, ssh):
318 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
319 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
320 self.assertIsNone(trex_traffic_gen.listen_traffic({}))
322 @mock.patch(SSH_HELPER)
323 def test_instantiate(self, ssh):
326 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
327 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
328 trex_traffic_gen._start_server = mock.Mock(return_value=0)
329 trex_traffic_gen._tg_process = mock.MagicMock()
330 trex_traffic_gen._tg_process.start = mock.Mock()
331 trex_traffic_gen._tg_process.exitcode = 0
332 trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=1)
333 trex_traffic_gen.ssh_helper = mock.MagicMock()
334 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
335 trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
337 self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
339 @mock.patch(SSH_HELPER)
340 def test_instantiate_error(self, ssh):
341 mock_ssh(ssh, exec_result=(1, "", ""))
343 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
344 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
345 trex_traffic_gen._start_server = mock.Mock(return_value=0)
346 trex_traffic_gen._tg_process = mock.MagicMock()
347 trex_traffic_gen._tg_process.start = mock.Mock()
348 trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=0)
349 trex_traffic_gen.ssh_helper = mock.MagicMock()
350 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
351 trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
352 self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
354 @mock.patch(SSH_HELPER)
355 def test__start_server(self, ssh):
357 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
358 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
359 trex_traffic_gen.ssh_helper = mock.MagicMock()
360 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
361 trex_traffic_gen.scenario_helper.scenario_cfg = {}
362 self.assertIsNone(trex_traffic_gen._start_server())
364 @mock.patch(SSH_HELPER)
365 def test__start_server_multiple_queues(self, ssh):
367 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
368 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
369 trex_traffic_gen.ssh_helper = mock.MagicMock()
370 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
371 trex_traffic_gen.scenario_helper.scenario_cfg = {"options": {NAME: {"queues_per_port": 2}}}
372 self.assertIsNone(trex_traffic_gen._start_server())
374 @mock.patch(SSH_HELPER)
375 def test__traffic_runner(self, ssh):
378 mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
379 mock_traffic_profile.get_traffic_definition.return_value = "64"
380 mock_traffic_profile.execute_traffic.return_value = "64"
381 mock_traffic_profile.params = self.TRAFFIC_PROFILE
383 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
384 self.sut = TrexTrafficGen(NAME, vnfd)
385 self.sut.ssh_helper = mock.Mock()
386 self.sut.ssh_helper.run = mock.Mock()
387 self.sut._connect_client = mock.Mock(autospec=STLClient)
388 self.sut._connect_client.get_stats = mock.Mock(return_value="0")
389 self.sut.resource_helper.RUN_DURATION = 0
390 self.sut.resource_helper.QUEUE_WAIT_TIME = 0
391 # must generate cfg before we can run traffic so Trex port mapping is created
392 self.sut.resource_helper.generate_cfg()
393 self.sut._traffic_runner(mock_traffic_profile)
395 @mock.patch(SSH_HELPER)
396 def test__generate_trex_cfg(self, ssh):
398 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
399 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
400 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
401 self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
403 @mock.patch(SSH_HELPER)
404 def test_build_ports_reversed_pci_ordering(self, ssh):
406 vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
407 vnfd['vdu'][0]['external-interface'] = [
408 {'virtual-interface':
409 {'dst_mac': '00:00:00:00:00:04',
410 'vpci': '0000:05:00.0',
411 'local_ip': '152.16.100.19',
412 'type': 'PCI-PASSTHROUGH',
413 'netmask': '255.255.255.0',
415 'bandwidth': '10 Gbps',
417 'dst_ip': '152.16.100.20',
418 'local_iface_name': 'xe0',
419 'vld_id': 'downlink_0',
421 'local_mac': '00:00:00:00:00:02'},
422 'vnfd-connection-point-ref': 'xe0',
424 {'virtual-interface':
425 {'dst_mac': '00:00:00:00:00:03',
426 'vpci': '0000:04:00.0',
427 'local_ip': '152.16.40.19',
428 'type': 'PCI-PASSTHROUGH',
430 'netmask': '255.255.255.0',
432 'bandwidth': '10 Gbps',
433 'dst_ip': '152.16.40.20',
434 'local_iface_name': 'xe1',
435 'vld_id': 'uplink_0',
437 'local_mac': '00:00:00:00:00:01'},
438 'vnfd-connection-point-ref': 'xe1',
440 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
441 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
442 trex_traffic_gen.resource_helper.generate_cfg()
443 trex_traffic_gen.resource_helper._build_ports()
444 self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
445 # there is a gap in ordering
446 self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
449 @mock.patch(SSH_HELPER)
450 def test_run_traffic(self, ssh):
453 mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
454 mock_traffic_profile.get_traffic_definition.return_value = "64"
455 mock_traffic_profile.params = self.TRAFFIC_PROFILE
457 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
458 self.sut = TrexTrafficGen(NAME, vnfd)
459 self.sut.ssh_helper = mock.Mock()
460 self.sut.ssh_helper.run = mock.Mock()
461 self.sut._traffic_runner = mock.Mock(return_value=0)
462 self.sut.resource_helper.client_started.value = 1
463 result = self.sut.run_traffic(mock_traffic_profile)
464 self.sut._traffic_process.terminate()
465 self.assertIsNotNone(result)
467 @mock.patch(SSH_HELPER)
468 def test_terminate(self, ssh):
470 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
471 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
472 trex_traffic_gen.ssh_helper = mock.MagicMock()
473 trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
474 self.assertIsNone(trex_traffic_gen.terminate())
476 @mock.patch(SSH_HELPER)
477 def test__connect_client(self, ssh):
479 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
480 trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
481 client = mock.Mock(autospec=STLClient)
482 client.connect = mock.Mock(return_value=0)
483 self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))