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