Merge "NSB TREX RFC2544 scenario fails with correlated traffic"
[yardstick.git] / yardstick / tests / unit / network_services / libs / ixia_libs / test_ixnet_api.py
1 # Copyright (c) 2018 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 import mock
16 import IxNetwork
17 import unittest
18
19 from yardstick.common import exceptions
20 from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
21
22
23 UPLINK = 'uplink'
24 DOWNLINK = 'downlink'
25
26 TRAFFIC_PARAMETERS = {
27     UPLINK: {
28         'id': 1,
29         'bidir': 'False',
30         'duration': 60,
31         'rate': 10000.5,
32         'rate_unit': 'fps',
33         'outer_l2': {
34             'framesize': {'64B': '25', '256B': '75'}
35         },
36         'outer_l3': {
37             'count': 512,
38             'dscp': 0,
39             'proto': 'udp',
40             'ttl': 32,
41             'dstip': '152.16.40.20',
42             'srcip': '152.16.100.20',
43             'dstmask': 24,
44             'srcmask': 24
45         },
46         'outer_l4': {
47             'dstport': '2001',
48             'srcport': '1234'
49         },
50         'traffic_type': 'continuous'
51     },
52     DOWNLINK: {
53         'id': 2,
54         'bidir': 'False',
55         'duration': 60,
56         'rate': 75.2,
57         'rate_unit': '%',
58         'outer_l2': {
59             'framesize': {'128B': '35', '1024B': '65'}
60         },
61         'outer_l3': {
62             'count': 1024,
63             'dscp': 0,
64             'proto': 'udp',
65             'ttl': 32,
66             'dstip': '2001::10',
67             'srcip': '2021::10',
68             'dstmask': 64,
69             'srcmask': 64
70         },
71         'outer_l4': {
72             'dstport': '1234',
73             'srcport': '2001'
74         },
75         'traffic_type': 'continuous'
76     }
77 }
78
79
80 class TestIxNextgen(unittest.TestCase):
81
82     def setUp(self):
83         self.ixnet = mock.Mock()
84         self.ixnet.execute = mock.Mock()
85         self.ixnet.getRoot.return_value = 'my_root'
86
87     def test_get_config(self):
88         tg_cfg = {
89             'vdu': [
90                 {
91                     'external-interface': [
92                         {'virtual-interface': {'vpci': '0000:07:00.1'}},
93                         {'virtual-interface': {'vpci': '0001:08:01.2'}}
94                     ]
95                 },
96             ],
97             'mgmt-interface': {
98                 'ip': 'test1',
99                 'tg-config': {
100                     'dut_result_dir': 'test2',
101                     'version': 'test3',
102                     'ixchassis': 'test4',
103                     'tcl_port': 'test5',
104                 },
105             }
106         }
107
108         expected = {
109             'machine': 'test1',
110             'port': 'test5',
111             'chassis': 'test4',
112             'cards': ['0000', '0001'],
113             'ports': ['07', '08'],
114             'output_dir': 'test2',
115             'version': 'test3',
116             'bidir': True,
117         }
118
119         result = ixnet_api.IxNextgen.get_config(tg_cfg)
120         self.assertEqual(result, expected)
121
122     def test__get_config_element_by_flow_group_name(self):
123         ixnet_gen = ixnet_api.IxNextgen()
124         ixnet_gen._ixnet = self.ixnet
125         ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
126                                                 ['fg_01']]
127         ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_01'
128         output = ixnet_gen._get_config_element_by_flow_group_name(
129             'flow_group_01')
130         self.assertEqual('traffic_item/configElement:flow_group_01', output)
131
132     def test__get_config_element_by_flow_group_name_no_match(self):
133         ixnet_gen = ixnet_api.IxNextgen()
134         ixnet_gen._ixnet = self.ixnet
135         ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
136                                                 ['fg_01']]
137         ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_02'
138         output = ixnet_gen._get_config_element_by_flow_group_name(
139             'flow_group_01')
140         self.assertIsNone(output)
141
142     def test__get_stack_item(self):
143         ixnet_gen = ixnet_api.IxNextgen()
144         ixnet_gen._ixnet = self.ixnet
145         ixnet_gen._ixnet.getList.return_value = ['tcp1', 'tcp2', 'udp']
146         with mock.patch.object(
147                 ixnet_gen, '_get_config_element_by_flow_group_name') as \
148                 mock_get_cfg_element:
149             mock_get_cfg_element.return_value = 'cfg_element'
150             output = ixnet_gen._get_stack_item(mock.ANY, ixnet_api.PROTO_TCP)
151         self.assertEqual(['tcp1', 'tcp2'], output)
152
153     def test__get_stack_item_no_config_element(self):
154         ixnet_gen = ixnet_api.IxNextgen()
155         ixnet_gen._ixnet = self.ixnet
156         with mock.patch.object(
157                 ixnet_gen, '_get_config_element_by_flow_group_name',
158                 return_value=None):
159             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
160                 ixnet_gen._get_stack_item(mock.ANY, mock.ANY)
161
162     def test__get_field_in_stack_item(self):
163         ixnet_gen = ixnet_api.IxNextgen()
164         ixnet_gen._ixnet = self.ixnet
165         ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
166         output = ixnet_gen._get_field_in_stack_item(mock.ANY, 'field2')
167         self.assertEqual('field2', output)
168
169     def test__get_field_in_stack_item_no_field_present(self):
170         ixnet_gen = ixnet_api.IxNextgen()
171         ixnet_gen._ixnet = self.ixnet
172         ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
173         with self.assertRaises(exceptions.IxNetworkFieldNotPresentInStackItem):
174             ixnet_gen._get_field_in_stack_item(mock.ANY, 'field3')
175
176     def test__parse_framesize(self):
177         ixnet_gen = ixnet_api.IxNextgen()
178         ixnet_gen._ixnet = self.ixnet
179         framesize = {'64B': '75', '512b': '25'}
180         output = ixnet_gen._parse_framesize(framesize)
181         self.assertEqual(2, len(output))
182         self.assertIn([64, 64, 75], output)
183         self.assertIn([512, 512, 25], output)
184
185     @mock.patch.object(IxNetwork, 'IxNet')
186     def test_connect(self, mock_ixnet):
187         mock_ixnet.return_value = self.ixnet
188         ixnet_gen = ixnet_api.IxNextgen()
189         with mock.patch.object(ixnet_gen, 'get_config') as mock_config:
190             mock_config.return_value = {'machine': 'machine_fake',
191                                         'port': 'port_fake',
192                                         'version': 12345}
193             ixnet_gen.connect(mock.ANY)
194
195         self.ixnet.connect.assert_called_once_with(
196             'machine_fake', '-port', 'port_fake', '-version', '12345')
197         mock_config.assert_called_once()
198
199     def test_connect_invalid_config_no_machine(self):
200         ixnet_gen = ixnet_api.IxNextgen()
201         ixnet_gen._ixnet = self.ixnet
202         ixnet_gen.get_config = mock.Mock(return_value={
203             'port': 'port_fake',
204             'version': '12345'})
205         self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
206         self.ixnet.connect.assert_not_called()
207
208     def test_connect_invalid_config_no_port(self):
209         ixnet_gen = ixnet_api.IxNextgen()
210         ixnet_gen._ixnet = self.ixnet
211         ixnet_gen.get_config = mock.Mock(return_value={
212             'machine': 'machine_fake',
213             'version': '12345'})
214         self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
215         self.ixnet.connect.assert_not_called()
216
217     def test_connect_invalid_config_no_version(self):
218         ixnet_gen = ixnet_api.IxNextgen()
219         ixnet_gen._ixnet = self.ixnet
220         ixnet_gen.get_config = mock.Mock(return_value={
221             'machine': 'machine_fake',
222             'port': 'port_fake'})
223         self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
224         self.ixnet.connect.assert_not_called()
225
226     def test_connect_no_config(self):
227         ixnet_gen = ixnet_api.IxNextgen()
228         ixnet_gen._ixnet = self.ixnet
229         ixnet_gen.get_config = mock.Mock(return_value={})
230         self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY)
231         self.ixnet.connect.assert_not_called()
232
233     def test_clear_config(self):
234         ixnet_gen = ixnet_api.IxNextgen()
235         ixnet_gen._ixnet = self.ixnet
236         ixnet_gen.clear_config()
237         self.ixnet.execute.assert_called_once_with('newConfig')
238
239     @mock.patch.object(ixnet_api, 'log')
240     def test_assign_ports_2_ports(self, *args):
241         self.ixnet.getAttribute.side_effect = ['up', 'down']
242         config = {
243             'chassis': '1.1.1.1',
244             'cards': ['1', '2'],
245             'ports': ['2', '2']}
246         ixnet_gen = ixnet_api.IxNextgen()
247         ixnet_gen._ixnet = self.ixnet
248         ixnet_gen._cfg = config
249
250         self.assertIsNone(ixnet_gen.assign_ports())
251         self.assertEqual(self.ixnet.execute.call_count, 2)
252         self.assertEqual(self.ixnet.commit.call_count, 4)
253         self.assertEqual(self.ixnet.getAttribute.call_count, 2)
254
255     @mock.patch.object(ixnet_api, 'log')
256     def test_assign_ports_port_down(self, mock_log):
257         self.ixnet.getAttribute.return_value = 'down'
258         config = {
259             'chassis': '1.1.1.1',
260             'cards': ['1', '2'],
261             'ports': ['3', '4']}
262         ixnet_gen = ixnet_api.IxNextgen()
263         ixnet_gen._ixnet = self.ixnet
264         ixnet_gen._cfg = config
265         ixnet_gen.assign_ports()
266         mock_log.warning.assert_called()
267
268     def test_assign_ports_no_config(self):
269         ixnet_gen = ixnet_api.IxNextgen()
270         ixnet_gen._ixnet = self.ixnet
271         ixnet_gen._cfg = {}
272         self.assertRaises(KeyError, ixnet_gen.assign_ports)
273
274     def test__create_traffic_item(self):
275         ixnet_gen = ixnet_api.IxNextgen()
276         ixnet_gen._ixnet = self.ixnet
277         self.ixnet.add.return_value = 'my_new_traffic_item'
278         self.ixnet.remapIds.return_value = ['my_traffic_item_id']
279
280         ixnet_gen._create_traffic_item()
281         self.ixnet.add.assert_called_once_with(
282             'my_root/traffic', 'trafficItem')
283         self.ixnet.setMultiAttribute.assert_called_once_with(
284             'my_new_traffic_item', '-name', 'RFC2544', '-trafficType', 'raw')
285         self.assertEqual(2, self.ixnet.commit.call_count)
286         self.ixnet.remapIds.assert_called_once_with('my_new_traffic_item')
287         self.ixnet.setAttribute('my_traffic_item_id/tracking',
288                                 '-trackBy', 'trafficGroupId0')
289
290     def test__create_flow_groups(self):
291         ixnet_gen = ixnet_api.IxNextgen()
292         ixnet_gen._ixnet = self.ixnet
293         ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
294         ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
295         ixnet_gen._create_flow_groups()
296         ixnet_gen.ixnet.add.assert_has_calls([
297             mock.call('traffic_item', 'endpointSet'),
298             mock.call('traffic_item', 'endpointSet')])
299         ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
300             mock.call('endp1', '-name', '1', '-sources', ['1/protocols'],
301                       '-destinations', ['2/protocols']),
302             mock.call('endp2', '-name', '2', '-sources', ['2/protocols'],
303                       '-destinations', ['1/protocols'])])
304
305     def test__append_protocol_to_stack(self):
306         ixnet_gen = ixnet_api.IxNextgen()
307         ixnet_gen._ixnet = self.ixnet
308
309         ixnet_gen._append_procotol_to_stack('my_protocol', 'prev_element')
310         self.ixnet.execute.assert_called_with(
311             'append', 'prev_element',
312             'my_root/traffic/protocolTemplate:"my_protocol"')
313
314     def test__setup_config_elements(self):
315         ixnet_gen = ixnet_api.IxNextgen()
316         ixnet_gen._ixnet = self.ixnet
317         ixnet_gen.ixnet.getList.side_effect = [['traffic_item'],
318                                                ['cfg_element']]
319         with mock.patch.object(ixnet_gen, '_append_procotol_to_stack') as \
320                 mock_append_proto:
321             ixnet_gen._setup_config_elements()
322         mock_append_proto.assert_has_calls([
323             mock.call(ixnet_api.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'),
324             mock.call(ixnet_api.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')])
325         ixnet_gen.ixnet.setAttribute.assert_has_calls([
326             mock.call('cfg_element/frameRateDistribution', '-portDistribution',
327                       'splitRateEvenly'),
328             mock.call('cfg_element/frameRateDistribution',
329                       '-streamDistribution', 'splitRateEvenly')])
330
331     @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
332     @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
333     @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
334     def test_create_traffic_model(self, mock__setup_config_elements,
335                                   mock__create_flow_groups,
336                                   mock__create_traffic_item):
337         ixnet_gen = ixnet_api.IxNextgen()
338         ixnet_gen._ixnet = self.ixnet
339
340         ixnet_gen.create_traffic_model()
341         mock__create_traffic_item.assert_called_once()
342         mock__create_flow_groups.assert_called_once()
343         mock__setup_config_elements.assert_called_once()
344
345     def test__update_frame_mac(self):
346         ixnet_gen = ixnet_api.IxNextgen()
347         ixnet_gen._ixnet = self.ixnet
348         with mock.patch.object(ixnet_gen, '_get_field_in_stack_item') as \
349                 mock_get_field:
350             mock_get_field.return_value = 'field_descriptor'
351             ixnet_gen._update_frame_mac('ethernet_descriptor', 'field', 'mac')
352         mock_get_field.assert_called_once_with('ethernet_descriptor', 'field')
353         ixnet_gen.ixnet.setMultiAttribute(
354             'field_descriptor', '-singleValue', 'mac', '-fieldValue', 'mac',
355             '-valueType', 'singleValue')
356         ixnet_gen.ixnet.commit.assert_called_once()
357
358     def test_update_frame(self):
359         ixnet_gen = ixnet_api.IxNextgen()
360         ixnet_gen._ixnet = self.ixnet
361         with mock.patch.object(
362                 ixnet_gen, '_get_config_element_by_flow_group_name',
363                 return_value='cfg_element'), \
364                 mock.patch.object(ixnet_gen, '_update_frame_mac') as \
365                 mock_update_frame, \
366                 mock.patch.object(ixnet_gen, '_get_stack_item') as \
367                 mock_get_stack_item:
368             mock_get_stack_item.side_effect = [['item1'], ['item2'],
369                                                ['item3'], ['item4']]
370             ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 50)
371
372         self.assertEqual(6, len(ixnet_gen.ixnet.setMultiAttribute.mock_calls))
373         self.assertEqual(4, len(mock_update_frame.mock_calls))
374         ixnet_gen.ixnet.setMultiAttribute.assert_has_calls(
375             [mock.call('cfg_element/frameRate', '-rate', 10000.5,
376                        '-type', 'framesPerSecond'),
377              mock.call('cfg_element/frameRate', '-rate', 75.2, '-type',
378                        'percentLineRate')],
379             any_order=True)
380
381     def test_update_frame_flow_not_present(self):
382         ixnet_gen = ixnet_api.IxNextgen()
383         ixnet_gen._ixnet = self.ixnet
384         with mock.patch.object(
385                 ixnet_gen, '_get_config_element_by_flow_group_name',
386                 return_value=None):
387             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
388                 ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 40)
389
390     def test_get_statistics(self):
391         ixnet_gen = ixnet_api.IxNextgen()
392         port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"'
393         flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"'
394         with mock.patch.object(ixnet_gen, '_build_stats_map') as \
395                 mock_build_stats:
396             ixnet_gen.get_statistics()
397
398         mock_build_stats.assert_has_calls([
399             mock.call(port_statistics, ixnet_gen.PORT_STATS_NAME_MAP),
400             mock.call(flow_statistics, ixnet_gen.LATENCY_NAME_MAP)])
401
402     def test__update_ipv4_address(self):
403         ixnet_gen = ixnet_api.IxNextgen()
404         ixnet_gen._ixnet = self.ixnet
405         with mock.patch.object(ixnet_gen, '_get_field_in_stack_item',
406                                return_value='field_desc'):
407             ixnet_gen._update_ipv4_address(mock.ANY, mock.ANY, '192.168.1.1',
408                                            100, 26, 25)
409         ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
410             'field_desc', '-seed', 100, '-fixedBits', '192.168.1.1',
411             '-randomMask', '0.0.0.63', '-valueType', 'random',
412             '-countValue', 25)
413
414     def test_update_ip_packet(self):
415         ixnet_gen = ixnet_api.IxNextgen()
416         ixnet_gen._ixnet = self.ixnet
417         with mock.patch.object(ixnet_gen, '_update_ipv4_address') as \
418                 mock_update_add, \
419                 mock.patch.object(ixnet_gen, '_get_stack_item'), \
420                 mock.patch.object(ixnet_gen,
421                 '_get_config_element_by_flow_group_name', return_value='celm'):
422             ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
423
424         self.assertEqual(4, len(mock_update_add.mock_calls))
425
426     def test_update_ip_packet_exception_no_config_element(self):
427         ixnet_gen = ixnet_api.IxNextgen()
428         ixnet_gen._ixnet = self.ixnet
429         with mock.patch.object(ixnet_gen,
430                                '_get_config_element_by_flow_group_name',
431                                return_value=None):
432             with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
433                 ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
434
435     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
436     def test_start_traffic(self, mock_ixnextgen_get_traffic_state):
437         ixnet_gen = ixnet_api.IxNextgen()
438         ixnet_gen._ixnet = self.ixnet
439         ixnet_gen._ixnet.getList.return_value = [0]
440
441         mock_ixnextgen_get_traffic_state.side_effect = [
442             'stopped', 'started', 'started', 'started']
443
444         result = ixnet_gen.start_traffic()
445         self.assertIsNone(result)
446         self.ixnet.getList.assert_called_once()
447         self.assertEqual(3, ixnet_gen._ixnet.execute.call_count)
448
449     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
450     def test_start_traffic_traffic_running(
451             self, mock_ixnextgen_get_traffic_state):
452         ixnet_gen = ixnet_api.IxNextgen()
453         ixnet_gen._ixnet = self.ixnet
454         ixnet_gen._ixnet.getList.return_value = [0]
455         mock_ixnextgen_get_traffic_state.side_effect = [
456             'started', 'stopped', 'started']
457
458         result = ixnet_gen.start_traffic()
459         self.assertIsNone(result)
460         self.ixnet.getList.assert_called_once()
461         self.assertEqual(4, ixnet_gen._ixnet.execute.call_count)
462
463     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
464     def test_start_traffic_wait_for_traffic_to_stop(
465             self, mock_ixnextgen_get_traffic_state):
466         ixnet_gen = ixnet_api.IxNextgen()
467         ixnet_gen._ixnet = self.ixnet
468         ixnet_gen._ixnet.getList.return_value = [0]
469         mock_ixnextgen_get_traffic_state.side_effect = [
470             'started', 'started', 'started', 'stopped', 'started']
471
472         result = ixnet_gen.start_traffic()
473         self.assertIsNone(result)
474         self.ixnet.getList.assert_called_once()
475         self.assertEqual(4, ixnet_gen._ixnet.execute.call_count)
476
477     @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
478     def test_start_traffic_wait_for_traffic_start(
479             self, mock_ixnextgen_get_traffic_state):
480         ixnet_gen = ixnet_api.IxNextgen()
481         ixnet_gen._ixnet = self.ixnet
482         ixnet_gen._ixnet.getList.return_value = [0]
483         mock_ixnextgen_get_traffic_state.side_effect = [
484             'stopped', 'stopped', 'stopped', 'started']
485
486         result = ixnet_gen.start_traffic()
487         self.assertIsNone(result)
488         self.ixnet.getList.assert_called_once()
489         self.assertEqual(3, ixnet_gen._ixnet.execute.call_count)