Merge "Add "host_name_separator" variable to Context class"
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_tg_trex.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
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
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14 #
15
16 import copy
17
18 import mock
19 import unittest
20
21 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
22 from yardstick.tests import STL_MOCKS
23
24
25 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
26 NAME = 'vnf_1'
27
28 STLClient = mock.MagicMock()
29 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
30 stl_patch.start()
31
32 if stl_patch:
33     from yardstick.network_services.vnf_generic.vnf.tg_trex import \
34         TrexTrafficGen, TrexResourceHelper
35     from yardstick.network_services.traffic_profile.base import TrafficProfile
36
37
38 class TestTrexTrafficGen(unittest.TestCase):
39     VNFD = {'vnfd:vnfd-catalog':
40             {'vnfd':
41              [{'short-name': 'VpeVnf',
42                'vdu':
43                [{'routing_table':
44                              [{'network': '152.16.100.20',
45                                'netmask': '255.255.255.0',
46                                'gateway': '152.16.100.20',
47                                'if': 'xe0'},
48                               {'network': '152.16.40.20',
49                                'netmask': '255.255.255.0',
50                                'gateway': '152.16.40.20',
51                                'if': 'xe1'}],
52                              'description': 'VPE approximation using DPDK',
53                              'name': 'vpevnf-baremetal',
54                              'nd_route_tbl':
55                                  [{'network': '0064:ff9b:0:0:0:0:9810:6414',
56                                    'netmask': '112',
57                                    'gateway': '0064:ff9b:0:0:0:0:9810:6414',
58                                    'if': 'xe0'},
59                                   {'network': '0064:ff9b:0:0:0:0:9810:2814',
60                                    'netmask': '112',
61                                    'gateway': '0064:ff9b:0:0:0:0:9810:2814',
62                                    'if': 'xe1'}],
63                              'id': 'vpevnf-baremetal',
64                              'external-interface':
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',
71                                     'dpdk_port_num': 0,
72                                     'bandwidth': '10 Gbps',
73                                     'driver': "i40e",
74                                     'dst_ip': '152.16.100.20',
75                                     'local_iface_name': 'xe0',
76                                     'vld_id': 'downlink_0',
77                                     'ifname': 'xe0',
78                                     'local_mac': '00:00:00:00:00:02'},
79                                    'vnfd-connection-point-ref': 'xe0',
80                                    'name': 'xe0'},
81                                   {'virtual-interface':
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',
86                                     'driver': "i40e",
87                                     'netmask': '255.255.255.0',
88                                     'dpdk_port_num': 1,
89                                     'bandwidth': '10 Gbps',
90                                     'dst_ip': '152.16.40.20',
91                                     'local_iface_name': 'xe1',
92                                     'vld_id': 'uplink_0',
93                                     'ifname': 'xe1',
94                                     'local_mac': '00:00:00:00:00:01'},
95                                    'vnfd-connection-point-ref': 'xe1',
96                                    'name': 'xe1'}]}],
97                'description': 'Vpe approximation using DPDK',
98                'mgmt-interface':
99                {'vdu-id': 'vpevnf-baremetal',
100                 'host': '1.1.1.1',
101                 'password': 'r00t',
102                             'user': 'root',
103                             'ip': '1.1.1.1'},
104                'benchmark':
105                {'kpi': ['packets_in', 'packets_fwd',
106                         'packets_dropped']},
107                'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
108                                     {'type': 'VPORT', 'name': 'xe1'}],
109                'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
110
111     TRAFFIC_PROFILE = {
112         "schema": "isb:traffic_profile:0.1",
113         "name": "fixed",
114         "description": "Fixed traffic profile to run UDP traffic",
115         "traffic_profile": {
116             "traffic_type": "FixedTraffic",
117             "frame_rate": 100,  # pps
118             "flow_number": 10,
119             "frame_size": 64
120         },
121     }
122
123     SCENARIO_CFG = {
124         "options": {
125             "packetsize": 64,
126             "traffic_type": 4,
127             "rfc2544": {
128                 "allowed_drop_rate": "0.8 - 1",
129             },
130             "vnf__1": {
131                 "rules": "acl_1rule.yaml",
132                 "vnf_config": {
133                     "lb_config": "SW",
134                     "lb_count": 1,
135                     "worker_config": "1C/1T",
136                     "worker_threads": 1,
137                 }
138             }
139         },
140         "task_id": "a70bdf4a-8e67-47a3-9dc1-273c14506eb7",
141         "tc": "tc_ipv4_1Mflow_64B_packetsize",
142         "runner": {
143             "object": "NetworkServiceTestCase",
144             "interval": 35,
145             "output_filename": "/tmp/yardstick.out",
146             "runner_id": 74476, "duration": 400,
147             "type": "Duration"
148         },
149         "traffic_profile": "ipv4_throughput_acl.yaml",
150         "traffic_options": {
151             "flow": "ipv4_Packets_acl.yaml",
152             "imix": "imix_voice.yaml"
153         },
154         "type": "ISB",
155         "nodes": {
156             "tg__2": "trafficgen_2.yardstick",
157             "tg__1": "trafficgen_1.yardstick",
158             "vnf__1": "vnf.yardstick"
159         },
160         "topology": "udpreplay-tg-topology-baremetal.yaml"
161     }
162
163     CONTEXT_CFG = {
164         "nodes": {
165             "vnf__1": {
166                 "vnfd-id-ref": "vnf__1",
167                 "ip": "1.2.1.1",
168                 "interfaces": {
169                     "xe0": {
170                         "local_iface_name": "ens786f0",
171                         "vld_id": TrafficProfile.UPLINK,
172                         "netmask": "255.255.255.0",
173                         "vpci": "0000:05:00.0",
174                         "local_ip": "152.16.100.19",
175                         "driver": "i40e",
176                         "dst_ip": "152.16.100.20",
177                         "local_mac": "00:00:00:00:00:02",
178                         "dst_mac": "00:00:00:00:00:04",
179                         "dpdk_port_num": 0
180                     },
181                     "xe1": {
182                         "local_iface_name": "ens786f1",
183                         "vld_id": TrafficProfile.DOWNLINK,
184                         "netmask": "255.255.255.0",
185                         "vpci": "0000:05:00.1",
186                         "local_ip": "152.16.40.19",
187                         "driver": "i40e",
188                         "dst_ip": "152.16.40.20",
189                         "local_mac": "00:00:00:00:00:01",
190                         "dst_mac": "00:00:00:00:00:03",
191                         "dpdk_port_num": 1
192                     }
193                 },
194                 "host": "1.2.1.1",
195                 "user": "root",
196                 "nd_route_tbl": [
197                     {
198                         "netmask": "112",
199                         "if": "xe0",
200                         "gateway": "0064:ff9b:0:0:0:0:9810:6414",
201                         "network": "0064:ff9b:0:0:0:0:9810:6414"
202                     },
203                     {
204                         "netmask": "112",
205                         "if": "xe1",
206                         "gateway": "0064:ff9b:0:0:0:0:9810:2814",
207                         "network": "0064:ff9b:0:0:0:0:9810:2814"
208                     }
209                 ],
210                 "password": "r00t",
211                 "VNF model": "udp_replay.yaml",
212                 "name": "vnf.yardstick",
213                 "member-vnf-index": "2",
214                 "routing_table": [
215                     {
216                         "netmask": "255.255.255.0",
217                         "if": "xe0",
218                         "gateway": "152.16.100.20",
219                         "network": "152.16.100.20"
220                     },
221                     {
222                         "netmask": "255.255.255.0",
223                         "if": "xe1",
224                         "gateway": "152.16.40.20",
225                         "network": "152.16.40.20"
226                     }
227                 ],
228                 "role": "vnf"
229             },
230             "trafficgen_2.yardstick": {
231                 "member-vnf-index": "3",
232                 "role": "TrafficGen",
233                 "name": "trafficgen_2.yardstick",
234                 "vnfd-id-ref": "tg__2",
235                 "ip": "1.2.1.1",
236                 "interfaces": {
237                     "xe0": {
238                         "local_iface_name": "ens513f0",
239                         "vld_id": TrafficProfile.DOWNLINK,
240                         "netmask": "255.255.255.0",
241                         "vpci": "0000:02:00.0",
242                         "local_ip": "152.16.40.20",
243                         "driver": "ixgbe",
244                         "dst_ip": "152.16.40.19",
245                         "local_mac": "00:00:00:00:00:03",
246                         "dst_mac": "00:00:00:00:00:01",
247                         "dpdk_port_num": 0
248                     },
249                     "xe1": {
250                         "local_iface_name": "ens513f1",
251                         "netmask": "255.255.255.0",
252                         "network": "202.16.100.0",
253                         "local_ip": "202.16.100.20",
254                         "driver": "ixgbe",
255                         "local_mac": "00:1e:67:d0:60:5d",
256                         "vpci": "0000:02:00.1",
257                         "dpdk_port_num": 1
258                     }
259                 },
260                 "password": "r00t",
261                 "VNF model": "l3fwd_vnf.yaml",
262                 "user": "root"
263             },
264             "trafficgen_1.yardstick": {
265                 "member-vnf-index": "1",
266                 "role": "TrafficGen",
267                 "name": "trafficgen_1.yardstick",
268                 "vnfd-id-ref": "tg__1",
269                 "ip": "1.2.1.1",
270                 "interfaces": {
271                     "xe0": {
272                         "local_iface_name": "ens785f0",
273                         "vld_id": TrafficProfile.UPLINK,
274                         "netmask": "255.255.255.0",
275                         "vpci": "0000:05:00.0",
276                         "local_ip": "152.16.100.20",
277                         "driver": "i40e",
278                         "dst_ip": "152.16.100.19",
279                         "local_mac": "00:00:00:00:00:04",
280                         "dst_mac": "00:00:00:00:00:02",
281                         "dpdk_port_num": 0
282                     },
283                     "xe1": {
284                         "local_ip": "152.16.100.21",
285                         "driver": "i40e",
286                         "vpci": "0000:05:00.1",
287                         "dpdk_port_num": 1,
288                         "local_iface_name": "ens785f1",
289                         "netmask": "255.255.255.0",
290                         "local_mac": "00:00:00:00:00:01"
291                     }
292                 },
293                 "password": "r00t",
294                 "VNF model": "tg_rfc2544_tpl.yaml",
295                 "user": "root"
296             }
297         }
298     }
299
300     @mock.patch(SSH_HELPER)
301     def test___init__(self, ssh):
302         mock_ssh(ssh)
303         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
304         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
305         self.assertIsInstance(
306             trex_traffic_gen.resource_helper, TrexResourceHelper)
307
308     @mock.patch(SSH_HELPER)
309     def test_collect_kpi(self, ssh):
310         mock_ssh(ssh)
311         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
312         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
313         trex_traffic_gen.resource_helper._queue.put({})
314         result = trex_traffic_gen.collect_kpi()
315         self.assertEqual({}, result)
316
317     @mock.patch(SSH_HELPER)
318     def test_listen_traffic(self, ssh):
319         mock_ssh(ssh)
320         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
321         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
322         self.assertIsNone(trex_traffic_gen.listen_traffic({}))
323
324     @mock.patch(SSH_HELPER)
325     def test_instantiate(self, ssh):
326         mock_ssh(ssh)
327
328         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
329         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
330         trex_traffic_gen._start_server = mock.Mock(return_value=0)
331         trex_traffic_gen._tg_process = mock.MagicMock()
332         trex_traffic_gen._tg_process.start = mock.Mock()
333         trex_traffic_gen._tg_process.exitcode = 0
334         trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=1)
335         trex_traffic_gen.ssh_helper = mock.MagicMock()
336         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
337         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
338
339         self.assertIsNone(trex_traffic_gen.instantiate(
340             self.SCENARIO_CFG, self.CONTEXT_CFG))
341
342     @mock.patch(SSH_HELPER)
343     def test_instantiate_error(self, ssh):
344         mock_ssh(ssh, exec_result=(1, "", ""))
345
346         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
347         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
348         trex_traffic_gen._start_server = mock.Mock(return_value=0)
349         trex_traffic_gen._tg_process = mock.MagicMock()
350         trex_traffic_gen._tg_process.start = mock.Mock()
351         trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=0)
352         trex_traffic_gen.ssh_helper = mock.MagicMock()
353         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
354         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
355         self.assertIsNone(trex_traffic_gen.instantiate(
356             self.SCENARIO_CFG, self.CONTEXT_CFG))
357
358     @mock.patch(SSH_HELPER)
359     def test__start_server(self, ssh):
360         mock_ssh(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())
367
368     @mock.patch(SSH_HELPER)
369     def test__start_server_multiple_queues(self, ssh):
370         mock_ssh(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 = {
376             "options": {NAME: {"queues_per_port": 2}}}
377         self.assertIsNone(trex_traffic_gen._start_server())
378
379     @mock.patch(SSH_HELPER)
380     def test__traffic_runner(self, ssh):
381         mock_ssh(ssh)
382
383         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
384         mock_traffic_profile.get_traffic_definition.return_value = "64"
385         mock_traffic_profile.execute_traffic.return_value = "64"
386         mock_traffic_profile.params = self.TRAFFIC_PROFILE
387
388         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
389         self.sut = TrexTrafficGen(NAME, vnfd)
390         self.sut.ssh_helper = mock.Mock()
391         self.sut.ssh_helper.run = mock.Mock()
392         self.sut._connect_client = mock.Mock(autospec=STLClient)
393         self.sut._connect_client.get_stats = mock.Mock(return_value="0")
394         self.sut.resource_helper.RUN_DURATION = 0
395         self.sut.resource_helper.QUEUE_WAIT_TIME = 0
396         # must generate cfg before we can run traffic so Trex port mapping is created
397         self.sut.resource_helper.generate_cfg()
398         self.sut._traffic_runner(mock_traffic_profile)
399
400     @mock.patch(SSH_HELPER)
401     def test__generate_trex_cfg(self, ssh):
402         mock_ssh(ssh)
403         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
404         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
405         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
406         self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
407
408     @mock.patch(SSH_HELPER)
409     def test_build_ports_reversed_pci_ordering(self, ssh):
410         mock_ssh(ssh)
411         vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
412         vnfd['vdu'][0]['external-interface'] = [
413             {'virtual-interface':
414              {'dst_mac': '00:00:00:00:00:04',
415               'vpci': '0000:05:00.0',
416               'local_ip': '152.16.100.19',
417               'type': 'PCI-PASSTHROUGH',
418               'netmask': '255.255.255.0',
419               'dpdk_port_num': 2,
420               'bandwidth': '10 Gbps',
421               'driver': "i40e",
422               'dst_ip': '152.16.100.20',
423               'local_iface_name': 'xe0',
424               'vld_id': 'downlink_0',
425               'ifname': 'xe0',
426               'local_mac': '00:00:00:00:00:02'},
427              'vnfd-connection-point-ref': 'xe0',
428              'name': 'xe0'},
429             {'virtual-interface':
430              {'dst_mac': '00:00:00:00:00:03',
431               'vpci': '0000:04:00.0',
432               'local_ip': '152.16.40.19',
433               'type': 'PCI-PASSTHROUGH',
434               'driver': "i40e",
435               'netmask': '255.255.255.0',
436               'dpdk_port_num': 0,
437               'bandwidth': '10 Gbps',
438               'dst_ip': '152.16.40.20',
439               'local_iface_name': 'xe1',
440               'vld_id': 'uplink_0',
441               'ifname': 'xe1',
442               'local_mac': '00:00:00:00:00:01'},
443              'vnfd-connection-point-ref': 'xe1',
444              'name': 'xe1'}]
445         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
446         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
447         trex_traffic_gen.resource_helper.generate_cfg()
448         trex_traffic_gen.resource_helper._build_ports()
449         self.assertEqual(
450             sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
451         # there is a gap in ordering
452         self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
453                          {0: 0, 2: 1})
454
455     @mock.patch(SSH_HELPER)
456     def test_run_traffic(self, ssh):
457         mock_ssh(ssh)
458
459         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
460         mock_traffic_profile.get_traffic_definition.return_value = "64"
461         mock_traffic_profile.params = self.TRAFFIC_PROFILE
462
463         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
464         self.sut = TrexTrafficGen(NAME, vnfd)
465         self.sut.ssh_helper = mock.Mock()
466         self.sut.ssh_helper.run = mock.Mock()
467         self.sut._traffic_runner = mock.Mock(return_value=0)
468         self.sut.resource_helper.client_started.value = 1
469         result = self.sut.run_traffic(mock_traffic_profile)
470         self.sut._traffic_process.terminate()
471         self.assertIsNotNone(result)
472
473     @mock.patch(SSH_HELPER)
474     def test_terminate(self, ssh):
475         mock_ssh(ssh)
476         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
477         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
478         trex_traffic_gen.ssh_helper = mock.MagicMock()
479         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
480         self.assertIsNone(trex_traffic_gen.terminate())
481
482     @mock.patch(SSH_HELPER)
483     def test__connect_client(self, ssh):
484         mock_ssh(ssh)
485         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
486         trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
487         client = mock.Mock(autospec=STLClient)
488         client.connect = mock.Mock(return_value=0)
489         self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))