NFVBENCH-215 Fix wrong throughput ratio in latency tests
[nfvbench.git] / test / test_nfvbench.py
1 #!/usr/bin/env python
2 # Copyright 2016 Cisco Systems, Inc.  All rights reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15 #
16 import openstack
17 from keystoneauth1.exceptions import HTTPClientError
18 from mock import patch
19 import pytest
20
21 from .mock_trex import no_op
22
23 import json
24 import logging
25 import sys
26 from attrdict import AttrDict
27 from nfvbench.config import config_loads
28 from nfvbench.credentials import Credentials
29 from nfvbench.fluentd import FluentLogHandler
30 import nfvbench.log
31 import nfvbench.nfvbench
32 from nfvbench.traffic_client import Device
33 from nfvbench.traffic_client import GeneratorConfig
34 from nfvbench.traffic_client import IpBlock
35 from nfvbench.traffic_client import TrafficClient
36 from nfvbench.traffic_client import TrafficClientException
37 from nfvbench.traffic_gen import traffic_utils
38 from nfvbench import utils
39
40 # just to get rid of the unused function warning
41 no_op()
42
43 def setup_module(module):
44     """Enable log."""
45     nfvbench.log.setup(mute_stdout=True)
46
47 # =========================================================================
48 # Traffic client tests
49 # =========================================================================
50
51 def test_parse_rate_str():
52     parse_rate_str = traffic_utils.parse_rate_str
53     try:
54         assert parse_rate_str('100%') == {'rate_percent': '100.0'}
55         assert parse_rate_str('37.5%') == {'rate_percent': '37.5'}
56         assert parse_rate_str('100%') == {'rate_percent': '100.0'}
57         assert parse_rate_str('60pps') == {'rate_pps': '60'}
58         assert parse_rate_str('60kpps') == {'rate_pps': '60000'}
59         assert parse_rate_str('6Mpps') == {'rate_pps': '6000000'}
60         assert parse_rate_str('6gpps') == {'rate_pps': '6000000000'}
61         assert parse_rate_str('80bps') == {'rate_bps': '80'}
62         assert parse_rate_str('80bps') == {'rate_bps': '80'}
63         assert parse_rate_str('80kbps') == {'rate_bps': '80000'}
64         assert parse_rate_str('80kBps') == {'rate_bps': '640000'}
65         assert parse_rate_str('80Mbps') == {'rate_bps': '80000000'}
66         assert parse_rate_str('80 MBps') == {'rate_bps': '640000000'}
67         assert parse_rate_str('80Gbps') == {'rate_bps': '80000000000'}
68     except Exception as exc:
69         assert False, exc.message
70
71     def should_raise_error(str):
72         try:
73             parse_rate_str(str)
74         except Exception:
75             return True
76         else:
77             return False
78         return False
79
80     assert should_raise_error('101')
81     assert should_raise_error('201%')
82     assert should_raise_error('10Kbps')
83     assert should_raise_error('0kbps')
84     assert should_raise_error('0pps')
85     assert should_raise_error('-1bps')
86
87
88 def test_rate_conversion():
89     assert traffic_utils.load_to_bps(50, 10000000000) == pytest.approx(5000000000.0)
90     assert traffic_utils.load_to_bps(37, 10000000000) == pytest.approx(3700000000.0)
91     assert traffic_utils.load_to_bps(100, 10000000000) == pytest.approx(10000000000.0)
92
93     assert traffic_utils.bps_to_load(5000000000.0, 10000000000) == pytest.approx(50.0)
94     assert traffic_utils.bps_to_load(3700000000.0, 10000000000) == pytest.approx(37.0)
95     assert traffic_utils.bps_to_load(10000000000.0, 10000000000) == pytest.approx(100.0)
96
97     assert traffic_utils.bps_to_pps(500000, 64) == pytest.approx(744.047619048)
98     assert traffic_utils.bps_to_pps(388888, 1518) == pytest.approx(31.6066319896)
99     assert traffic_utils.bps_to_pps(9298322222, 340.3) == pytest.approx(3225895.85831)
100
101     assert traffic_utils.pps_to_bps(744.047619048, 64) == pytest.approx(500000)
102     assert traffic_utils.pps_to_bps(31.6066319896, 1518) == pytest.approx(388888)
103     assert traffic_utils.pps_to_bps(3225895.85831, 340.3) == pytest.approx(9298322222)
104
105
106 # pps at 10Gbps line rate for 64 byte frames
107 LR_64B_PPS = 14880952
108 LR_1518B_PPS = 812743
109
110 def assert_equivalence(reference, value, allowance_pct=1):
111     """Assert if a value is equivalent to a reference value with given margin.
112
113     :param float reference: reference value to compare to
114     :param float value: value to compare to reference
115     :param float allowance_pct: max allowed percentage of margin
116         0 : requires exact match
117         1 : must be equal within 1% of the reference value
118         ...
119         100: always true
120     """
121     if reference == 0:
122         assert value == 0
123     else:
124         assert abs(value - reference) * 100 / reference <= allowance_pct
125
126 def test_load_from_rate():
127     assert traffic_utils.get_load_from_rate('100%') == 100
128     assert_equivalence(100, traffic_utils.get_load_from_rate(str(LR_64B_PPS) + 'pps'))
129     assert_equivalence(50, traffic_utils.get_load_from_rate(str(LR_64B_PPS / 2) + 'pps'))
130     assert_equivalence(100, traffic_utils.get_load_from_rate('10Gbps'))
131     assert_equivalence(50, traffic_utils.get_load_from_rate('5000Mbps'))
132     assert_equivalence(1, traffic_utils.get_load_from_rate('100Mbps'))
133     assert_equivalence(100, traffic_utils.get_load_from_rate(str(LR_1518B_PPS) + 'pps',
134                                                              avg_frame_size=1518))
135     assert_equivalence(100, traffic_utils.get_load_from_rate(str(LR_1518B_PPS * 2) + 'pps',
136                                                              avg_frame_size=1518,
137                                                              line_rate='20Gbps'))
138
139 # =========================================================================
140 # Other tests
141 # =========================================================================
142
143 def test_no_credentials():
144     with patch.object(openstack, 'connect') as mock:
145         cred = Credentials('/completely/wrong/path/openrc', None, None, False)
146         if cred.rc_auth_url:
147             # shouldn't get valid data unless user set environment variables
148             assert False
149         else:
150             assert True
151     mock.assert_not_called()
152
153
154 def test_clouds_file_credentials():
155     with patch.object(openstack, 'connect') as mock:
156         Credentials(None, 'openstack', None, False)
157     mock.assert_called_once()
158
159
160 @patch('nfvbench.nfvbench.credentials')
161 def test_is_not_admin(mock_session):
162     mock_session.Session.return_value.get.return_value.raiseError.side_effect = HTTPClientError
163     cred = Credentials(None, 'openstack', None, False)
164     if cred.is_admin:
165         assert False
166     else:
167         assert True
168
169
170 def test_is_admin():
171     with patch.object(openstack, 'connect'):
172         cred = Credentials(None, 'openstack', None, False)
173         if cred.is_admin:
174             assert True
175         else:
176             assert False
177
178
179 def test_ip_block():
180     ipb = IpBlock('10.0.0.0', '0.0.0.1', 256)
181     assert ipb.get_ip() == '10.0.0.0'
182     assert ipb.get_ip(255) == '10.0.0.255'
183     with pytest.raises(IndexError):
184         ipb.get_ip(256)
185     ipb = IpBlock('10.0.0.0', '0.0.0.1', 1)
186     assert ipb.get_ip() == '10.0.0.0'
187     with pytest.raises(IndexError):
188         ipb.get_ip(1)
189
190     ipb = IpBlock('10.0.0.0', '0.0.0.2', 256)
191     assert ipb.get_ip() == '10.0.0.0'
192     assert ipb.get_ip(1) == '10.0.0.2'
193     assert ipb.get_ip(127) == '10.0.0.254'
194     assert ipb.get_ip(128) == '10.0.1.0'
195     with pytest.raises(IndexError):
196         ipb.get_ip(256)
197
198     # verify with step larger than 1
199     ipb = IpBlock('10.0.0.0', '0.0.0.2', 256)
200     assert ipb.get_ip() == '10.0.0.0'
201     assert ipb.get_ip(1) == '10.0.0.2'
202     assert ipb.get_ip(128) == '10.0.1.0'
203     assert ipb.get_ip(255) == '10.0.1.254'
204     with pytest.raises(IndexError):
205         ipb.get_ip(256)
206
207     ipb = IpBlock('10.0.0.0', '0.0.0.2', 128)
208     assert ipb.get_ip() == '10.0.0.0'
209     assert ipb.get_ip(1) == '10.0.0.2'
210     assert ipb.get_ip(127) == '10.0.0.254'
211     with pytest.raises(IndexError):
212         ipb.get_ip(128)
213
214     ipb = IpBlock('10.0.0.0', '0.0.0.4', 64)
215     assert ipb.get_ip() == '10.0.0.0'
216     assert ipb.get_ip(1) == '10.0.0.4'
217     assert ipb.get_ip(63) == '10.0.0.252'
218     with pytest.raises(IndexError):
219         ipb.get_ip(64)
220
221     ipb = IpBlock('10.0.0.0', '0.0.0.10', 1)
222     assert ipb.get_ip() == '10.0.0.0'
223     with pytest.raises(IndexError):
224         ipb.get_ip(1)
225
226
227 def test_lcm():
228     assert utils.lcm(10, 2) == 10
229     assert utils.lcm(1, 256) == 256
230     assert utils.lcm(10, 256) == 1280
231     assert utils.lcm(utils.lcm(10, 2), utils.lcm(1, 256))
232     with pytest.raises(TypeError):
233         utils.lcm(0, 0)
234
235
236 def test_flow_count_limit():
237     # lcm ip src and dst /32
238     lcm_ip = utils.lcm(1, 1) == 1
239     # port udp src = 1 port udp dst [1,29]
240     src_min = 1
241     src_max = 1
242     dst_min = 1
243     dst_max = 29
244     udp_step = 3
245     udp_src_size = Device.check_range_size(int(src_max) - int(src_min) + 1,
246                                            udp_step)
247     udp_dst_size = Device.check_range_size(int(dst_max) - int(dst_min) + 1,
248                                            udp_step)
249     lcm_port = utils.lcm(udp_src_size, udp_dst_size)
250     assert utils.lcm(lcm_ip, lcm_port) < 29
251
252
253 def test_check_range_size():
254     assert Device.check_range_size(256, 1) == 256
255     assert Device.check_range_size(256, 3) == 86
256     assert Device.check_range_size(256, 4) == 64
257     assert Device.check_range_size(16, 10) == 2
258     assert Device.check_range_size(1, 10) == 1
259     with pytest.raises(ZeroDivisionError):
260         Device.check_range_size(256, 0)
261
262
263 def test_reserve_ip_range():
264     ipb = IpBlock('10.0.0.0', '0.0.0.1', 256)
265     src_ip_first, src_ip_last = ipb.reserve_ip_range(256)
266     assert src_ip_first == "10.0.0.0"
267     assert src_ip_last == "10.0.0.255"
268     ipb = IpBlock('20.0.0.0', '0.0.0.1', 2)
269     src_ip_first, src_ip_last = ipb.reserve_ip_range(2)
270     assert src_ip_first == "20.0.0.0"
271     assert src_ip_last == "20.0.0.1"
272     ipb = IpBlock('30.0.0.0', '0.0.0.1', 2)
273     with pytest.raises(IndexError):
274         ipb.reserve_ip_range(256)
275
276
277 def check_stream_configs(gen_config):
278     """Verify that the range for each chain have adjacent IP ranges without holes between chains."""
279     config = gen_config.config
280     tgc = config['traffic_generator']
281     step = Device.ip_to_int(tgc['ip_addrs_step'])
282     cfc = 0
283     sip = Device.ip_to_int(tgc['ip_addrs'][0].split('/')[0])
284     dip = Device.ip_to_int(tgc['ip_addrs'][1].split('/')[0])
285     stream_configs = gen_config.devices[0].get_stream_configs()
286     for index in range(config['service_chain_count']):
287         stream_cfg = stream_configs[index]
288         # ip_src_static == True
289         assert stream_cfg['ip_src_count'] == 1
290         if index == 0:
291             assert stream_cfg['ip_dst_count'] == 4999
292         else:
293             assert stream_cfg['ip_dst_count'] == 5000
294         assert stream_cfg['ip_src_addr'] == Device.int_to_ip(sip)
295         assert Device.ip_to_int(stream_cfg['ip_src_addr']) == sip
296         assert Device.ip_to_int(stream_cfg['ip_dst_addr']) == dip
297         count = stream_cfg['ip_dst_count']
298         cfc += count
299         sip += step
300         dip += count * step
301     assert cfc == int(config['flow_count'] / 2)
302
303 def _check_device_flow_config(step_ip):
304     config = _get_dummy_tg_config('PVP', '1Mpps', scc=10, fc=99999, step_ip=step_ip)
305     gen_config = GeneratorConfig(config)
306     check_stream_configs(gen_config)
307
308 def test_device_flow_config():
309     _check_device_flow_config('0.0.0.1')
310     _check_device_flow_config('0.0.0.2')
311
312
313 def check_udp_stream_configs(gen_config, expected_cfg):
314     """Verify that the range for each chain have adjacent UDP ports without holes between chains."""
315     config = gen_config.config
316     stream_configs = gen_config.devices[0].get_stream_configs()
317     for index in range(config['service_chain_count']):
318         stream_cfg = stream_configs[index]
319         expected = expected_cfg[index]
320         assert stream_cfg['ip_src_addr'] == expected['ip_src_addr']
321         assert stream_cfg['ip_src_addr_max'] == expected['ip_src_addr_max']
322         assert stream_cfg['ip_src_count'] == expected['ip_src_count']
323
324         assert stream_cfg['ip_dst_addr'] == expected['ip_dst_addr']
325         assert stream_cfg['ip_dst_addr_max'] == expected['ip_dst_addr_max']
326         assert stream_cfg['ip_dst_count'] == expected['ip_dst_count']
327
328         assert stream_cfg['udp_src_port'] == expected['udp_src_port']
329         assert stream_cfg['udp_src_port_max'] == expected['udp_src_port_max']
330         assert stream_cfg['udp_src_count'] == expected['udp_src_count']
331
332         assert stream_cfg['udp_dst_port'] == expected['udp_dst_port']
333         assert stream_cfg['udp_dst_port_max'] == expected['udp_dst_port_max']
334         assert stream_cfg['udp_dst_count'] == expected['udp_dst_count']
335
336         lcm_ip = utils.lcm(stream_cfg['ip_src_count'], stream_cfg['ip_dst_count'])
337         udp_src_size = int(stream_cfg['udp_src_port_max']) - int(stream_cfg['udp_src_port']) + 1
338         udp_dst_size = int(stream_cfg['udp_dst_port_max']) - int(stream_cfg['udp_dst_port']) + 1
339         lcm_udp = utils.lcm(udp_src_size, udp_dst_size)
340         assert utils.lcm(lcm_ip, lcm_udp) >= stream_cfg['count']
341
342
343 def _check_device_udp_flow_config(param, expected_cfg):
344     config = _get_dummy_tg_config('PVP', '1Mpps',
345                                   scc=param['scc'],
346                                   ip_src_static=param['ip_src_static'],
347                                   fc=param['flow_count'],
348                                   ip0=param['ip_src_addr'],
349                                   ip1=param['ip_dst_addr'],
350                                   step_ip=param['ip_addrs_step'],
351                                   src_udp=param['udp_src_port'],
352                                   dst_udp=param['udp_dst_port'],
353                                   step_udp=param['udp_port_step'])
354     gen_config = GeneratorConfig(config)
355     check_udp_stream_configs(gen_config, expected_cfg)
356
357
358 def __get_udp_params():
359     param = {'ip_src_static': True,
360              'ip_src_addr': '110.0.0.0/32',
361              'ip_dst_addr': '120.0.0.0/32',
362              'ip_addrs_step': '0.0.0.1',
363              'udp_src_port': 53,
364              'udp_dst_port': 53,
365              'flow_count': 2,
366              'scc': 1,
367              'udp_port_step': '1'}
368     return param
369
370
371 def __get_udp_expected_list():
372     expected = {'ip_src_addr': '110.0.0.0',
373                 'ip_src_addr_max': '110.0.0.0',
374                 'ip_src_count': 1,
375                 'ip_dst_addr': '120.0.0.0',
376                 'ip_dst_addr_max': '120.0.0.0',
377                 'ip_dst_count': 1,
378                 'udp_src_port': 53,
379                 'udp_src_port_max': 53,
380                 'udp_src_count': 1,
381                 'udp_dst_port': 53,
382                 'udp_dst_port_max': 53,
383                 'udp_dst_count': 1}
384     return expected
385
386
387 def test_device_udp_flow_config_single_ip_single_port():
388     param = __get_udp_params()
389     expected = __get_udp_expected_list()
390     _check_device_udp_flow_config(param, [expected])
391
392
393 def test_device_udp_flow_config_single_ip_multiple_src_ports():
394     param = __get_udp_params()
395     expected = __get_udp_expected_list()
396     # Overwrite the udp_src_port value to define a large range of ports
397     # instead of a single port, in order to check if the imposed
398     # flow count is respected. Notice that udp range >> flow count.
399     param['udp_src_port'] = [53, 1024]
400     param['flow_count'] = 10
401     expected['udp_src_port_max'] = 57
402     expected['udp_src_count'] = 5
403     _check_device_udp_flow_config(param, [expected])
404
405
406 def test_device_udp_flow_config_multiple_ip_src_single_port():
407     param = __get_udp_params()
408     expected = __get_udp_expected_list()
409     # Re affect the default udp_src_port values and
410     # overwrite the ip_dst_addr value to define a large range of addresses
411     # instead of a single one, in order to check if the imposed
412     # flow count is respected. Notice that the netmask allows a very larger
413     # range of possible addresses than the flow count value.
414     param['udp_src_port'] = 53
415     param['flow_count'] = 10
416     param['ip_src_static'] = False
417     param['ip_dst_addr'] = '120.0.0.0/24'
418
419     expected['udp_src_port_max'] = 53
420     expected['udp_src_count'] = 1
421     expected['ip_dst_addr'] = '120.0.0.0'
422     expected['ip_dst_addr_max'] = '120.0.0.4'
423     expected['ip_dst_count'] = 5
424     _check_device_udp_flow_config(param, [expected])
425
426
427 def test_device_udp_flow_config_multiple_ip_src_dst_multiple_src_dst_ports():
428     param = __get_udp_params()
429     expected = __get_udp_expected_list()
430
431     param['udp_src_port'] = [49000, 49031]
432     param['udp_dst_port'] = [50000, 50033]
433     param['ip_src_static'] = False
434     param['flow_count'] = 1000
435     param['ip_src_addr'] = '110.0.0.0/16'
436     param['ip_dst_addr'] = '120.0.0.0/16'
437
438     expected['udp_src_port'] = 49000
439     expected['udp_src_port_max'] = 49024
440     expected['udp_dst_port'] = 50000
441     expected['udp_dst_port_max'] = 50024
442     expected['udp_src_count'] = 25
443     expected['udp_dst_count'] = 25
444     expected['ip_src_addr_max'] = '110.0.1.243'
445     expected['ip_src_count'] = 500
446     expected['ip_dst_addr'] = '120.0.0.0'
447     expected['ip_dst_addr_max'] = '120.0.1.243'
448     expected['ip_dst_count'] = 500
449     _check_device_udp_flow_config(param, [expected])
450
451
452
453
454 def test_device_udp_flow_config_random_multiple_ip_src_dst_multiple_src_dst_ports():
455     param = __get_udp_params()
456     expected = __get_udp_expected_list()
457
458     param['udp_src_port'] = [1025, 65000]
459     param['udp_dst_port'] = [1024, 65000]
460     param['ip_src_static'] = False
461     param['ip_addrs_step'] = 'random'
462     param['udp_port_step'] = 'random'
463     param['flow_count'] = 1000000
464     param['ip_src_addr'] = '110.0.0.0/16'
465     param['ip_dst_addr'] = '120.0.0.0/16'
466
467     expected['udp_src_port'] = 1025
468     expected['udp_src_port_max'] = 65000
469     expected['udp_dst_port'] = 1024
470     expected['udp_dst_port_max'] = 65000
471     expected['udp_src_count'] = 62500
472     expected['udp_dst_count'] = 62500
473     expected['ip_src_addr_max'] = '110.0.0.31'
474     expected['ip_src_count'] = 32
475     expected['ip_dst_addr'] = '120.0.0.0'
476     expected['ip_dst_addr_max'] = '120.0.0.31'
477     expected['ip_dst_count'] = 32
478     _check_device_udp_flow_config(param, [expected])
479
480 def test_device_udp_flow_config_random_multiple_ip_srcstatic_dst_multiple_src_dst_ports():
481     param = __get_udp_params()
482     expected = __get_udp_expected_list()
483
484     param['udp_src_port'] = [1025, 65000]
485     param['udp_dst_port'] = [1024, 65000]
486     param['ip_src_static'] = True
487     param['ip_addrs_step'] = 'random'
488     param['udp_port_step'] = 'random'
489     param['flow_count'] = 1000000
490     param['ip_src_addr'] = '110.0.0.0/16'
491     param['ip_dst_addr'] = '120.0.0.0/16'
492
493     expected['udp_src_port'] = 1025
494     expected['udp_src_port_max'] = 65000
495     expected['udp_dst_port'] = 1024
496     expected['udp_dst_port_max'] = 65000
497     expected['udp_src_count'] = 1
498     expected['udp_dst_count'] = 62500
499     expected['ip_src_addr_max'] = '110.0.0.0'
500     expected['ip_src_count'] = 1
501     expected['ip_dst_addr'] = '120.0.0.0'
502     expected['ip_dst_addr_max'] = '120.0.0.31'
503     expected['ip_dst_count'] = 32
504     _check_device_udp_flow_config(param, [expected])
505
506
507
508 def test_device_udp_flow_config_single_ip_src_dst_multiple_src_dst_ports():
509     param = __get_udp_params()
510     expected = __get_udp_expected_list()
511
512     param['udp_src_port'] = [49152, 49154]
513     param['udp_dst_port'] = [50001, 50005]
514     param['ip_src_static'] = False
515     param['flow_count'] = 10
516     param['ip_src_addr'] = '110.0.0.0/32'
517     param['ip_dst_addr'] = '120.0.0.0/32'
518
519     expected['udp_src_port'] = 49152
520     expected['udp_src_port_max'] = 49152
521     expected['udp_dst_port'] = 50001
522     expected['udp_dst_port_max'] = 50005
523     expected['udp_src_count'] = 1
524     expected['udp_dst_count'] = 5
525     expected['ip_src_addr_max'] = '110.0.0.0'
526     expected['ip_src_count'] = 1
527     expected['ip_dst_addr'] = '120.0.0.0'
528     expected['ip_dst_addr_max'] = '120.0.0.0'
529     expected['ip_dst_count'] = 1
530     _check_device_udp_flow_config(param, [expected])
531
532
533 def test_device_udp_flow_config_single_ip_src_dst_single_src_multiple_dst_ports():
534     param = __get_udp_params()
535     expected = __get_udp_expected_list()
536
537     param['udp_src_port'] = 49152
538     param['udp_dst_port'] = [50001, 50029]
539     param['udp_port_step'] = '3'
540     param['flow_count'] = 58
541     param['ip_src_addr'] = '110.0.0.0/32'
542     param['ip_dst_addr'] = '120.0.0.0/32'
543
544     expected['udp_src_port'] = 49152
545     expected['udp_src_port_max'] = 49152
546     expected['udp_dst_port'] = 50001
547     expected['udp_dst_port_max'] = 50029
548     expected['udp_src_count'] = 1
549     expected['udp_dst_count'] = 29
550     expected['ip_src_addr_max'] = '110.0.0.0'
551     expected['ip_src_count'] = 1
552     expected['ip_dst_addr'] = '120.0.0.0'
553     expected['ip_dst_addr_max'] = '120.0.0.0'
554     expected['ip_dst_count'] = 1
555     with pytest.raises(TrafficClientException):
556         _check_device_udp_flow_config(param, [expected])
557
558
559 def test_device_udp_flow_config_scc3():
560     param = __get_udp_params()
561     expected = __get_udp_expected_list()
562
563     param['scc'] = 3
564     param['udp_src_port'] = [49000, 49031]
565     param['udp_dst_port'] = [50000, 50033]
566     param['ip_src_static'] = False
567     param['flow_count'] = 10000
568     param['ip_src_addr'] = '110.0.0.0/16'
569     param['ip_dst_addr'] = '120.0.0.0/16'
570
571     expected_cfg = []
572     # chain 0
573     expected_scc0 = dict(expected)
574     expected_scc0['udp_src_port'] = 49000
575     expected_scc0['udp_src_port_max'] = 49016
576     expected_scc0['udp_dst_port'] = 50000
577     expected_scc0['udp_dst_port_max'] = 50033
578     expected_scc0['udp_src_count'] = 17
579     expected_scc0['udp_dst_count'] = 34
580     expected_scc0['ip_src_addr_max'] = '110.0.6.129'
581     expected_scc0['ip_src_count'] = 1666
582     expected_scc0['ip_dst_addr'] = '120.0.0.0'
583     expected_scc0['ip_dst_addr_max'] = '120.0.6.129'
584     expected_scc0['ip_dst_count'] = 1666
585     expected_cfg.append(expected_scc0)
586
587     # chain 1
588     expected_scc1 = dict(expected)
589     expected_scc1['udp_src_port'] = 49000
590     expected_scc1['udp_src_port_max'] = 49000
591     expected_scc1['udp_dst_port'] = 50000
592     expected_scc1['udp_dst_port_max'] = 50000
593     expected_scc1['udp_src_count'] = 1
594     expected_scc1['udp_dst_count'] = 1
595     expected_scc1['ip_src_addr'] = '110.0.6.130'
596     expected_scc1['ip_src_addr_max'] = '110.0.13.4'
597     expected_scc1['ip_src_count'] = 1667
598     expected_scc1['ip_dst_addr'] = '120.0.6.130'
599     expected_scc1['ip_dst_addr_max'] = '120.0.13.4'
600     expected_scc1['ip_dst_count'] = 1667
601     expected_cfg.append(expected_scc1)
602
603     # chain 2
604     expected_scc2 = dict(expected)
605     expected_scc2['udp_src_port'] = 49000
606     expected_scc2['udp_src_port_max'] = 49000
607     expected_scc2['udp_dst_port'] = 50000
608     expected_scc2['udp_dst_port_max'] = 50000
609     expected_scc2['udp_src_count'] = 1
610     expected_scc2['udp_dst_count'] = 1
611     expected_scc2['ip_src_addr'] = '110.0.13.5'
612     expected_scc2['ip_src_addr_max'] = '110.0.19.135'
613     expected_scc2['ip_src_count'] = 1667
614     expected_scc2['ip_dst_addr'] = '120.0.13.5'
615     expected_scc2['ip_dst_addr_max'] = '120.0.19.135'
616     expected_scc2['ip_dst_count'] = 1667
617     expected_cfg.append(expected_scc2)
618
619     _check_device_udp_flow_config(param, expected_cfg)
620
621
622 def test_device_udp_flow_config_doc_example1(caplog):
623     caplog.clear()
624     caplog.set_level(logging.INFO)
625     param = __get_udp_params()
626     expected = __get_udp_expected_list()
627
628     # Multiflow unitary test corresponding to first example in documentation
629     param['scc'] = 3
630     param['udp_src_port'] = 53
631     param['udp_dst_port'] = 53
632     param['ip_src_static'] = True
633     param['flow_count'] = 100
634     param['ip_src_addr'] = '110.0.0.0/8'
635     param['ip_dst_addr'] = '120.0.0.0/8'
636
637     expected_cfg = []
638     # chain 0
639     expected_scc0 = dict(expected)
640     expected_scc0['udp_src_port'] = 53
641     expected_scc0['udp_src_port_max'] = 53
642     expected_scc0['udp_dst_port'] = 53
643     expected_scc0['udp_dst_port_max'] = 53
644     expected_scc0['udp_src_count'] = 1
645     expected_scc0['udp_dst_count'] = 1
646     expected_scc0['ip_src_addr'] = '110.0.0.0'
647     expected_scc0['ip_src_addr_max'] = '110.0.0.0'
648     expected_scc0['ip_src_count'] = 1
649     expected_scc0['ip_dst_addr'] = '120.0.0.0'
650     expected_scc0['ip_dst_addr_max'] = '120.0.0.15'
651     expected_scc0['ip_dst_count'] = 16
652     expected_cfg.append(expected_scc0)
653
654     # chain 1
655     expected_scc1 = dict(expected)
656     expected_scc1['udp_src_port'] = 53
657     expected_scc1['udp_src_port_max'] = 53
658     expected_scc1['udp_dst_port'] = 53
659     expected_scc1['udp_dst_port_max'] = 53
660     expected_scc1['udp_src_count'] = 1
661     expected_scc1['udp_dst_count'] = 1
662     expected_scc1['ip_src_addr'] = '110.0.0.1'
663     expected_scc1['ip_src_addr_max'] = '110.0.0.1'
664     expected_scc1['ip_src_count'] = 1
665     expected_scc1['ip_dst_addr'] = '120.0.0.16'
666     expected_scc1['ip_dst_addr_max'] = '120.0.0.32'
667     expected_scc1['ip_dst_count'] = 17
668     expected_cfg.append(expected_scc1)
669
670     # chain 2
671     expected_scc2 = dict(expected)
672     expected_scc2['udp_src_port'] = 53
673     expected_scc2['udp_src_port_max'] = 53
674     expected_scc2['udp_dst_port'] = 53
675     expected_scc2['udp_dst_port_max'] = 53
676     expected_scc2['udp_src_count'] = 1
677     expected_scc2['udp_dst_count'] = 1
678     expected_scc2['ip_src_addr'] = '110.0.0.2'
679     expected_scc2['ip_src_addr_max'] = '110.0.0.2'
680     expected_scc2['ip_src_count'] = 1
681     expected_scc2['ip_dst_addr'] = '120.0.0.33'
682     expected_scc2['ip_dst_addr_max'] = '120.0.0.49'
683     expected_scc2['ip_dst_count'] = 17
684     expected_cfg.append(expected_scc2)
685
686     _check_device_udp_flow_config(param, expected_cfg)
687     assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text
688
689
690 def test_device_udp_flow_config_doc_example2(caplog):
691     caplog.clear()
692     caplog.set_level(logging.INFO)
693     param = __get_udp_params()
694     expected = __get_udp_expected_list()
695
696     # Multiflow unitary test corresponding to second example in documentation
697     param['scc'] = 3
698     param['udp_src_port'] = 53
699     param['udp_dst_port'] = 53
700     param['ip_src_static'] = True
701     param['ip_addrs_step'] = 'random'
702     param['flow_count'] = 100
703     param['ip_src_addr'] = '110.0.0.0/8'
704     param['ip_dst_addr'] = '120.0.0.0/8'
705
706     expected_cfg = []
707     # chain 0
708     expected_scc0 = dict(expected)
709     expected_scc0['udp_src_port'] = 53
710     expected_scc0['udp_src_port_max'] = 53
711     expected_scc0['udp_dst_port'] = 53
712     expected_scc0['udp_dst_port_max'] = 53
713     expected_scc0['udp_src_count'] = 1
714     expected_scc0['udp_dst_count'] = 1
715     expected_scc0['ip_src_addr'] = '110.0.0.0'
716     expected_scc0['ip_src_addr_max'] = '110.0.0.0'
717     expected_scc0['ip_src_count'] = 1
718     expected_scc0['ip_dst_addr'] = '120.0.0.0'
719     expected_scc0['ip_dst_addr_max'] = '120.0.0.15'
720     expected_scc0['ip_dst_count'] = 16
721     expected_cfg.append(expected_scc0)
722
723     # chain 1
724     expected_scc1 = dict(expected)
725     expected_scc1['udp_src_port'] = 53
726     expected_scc1['udp_src_port_max'] = 53
727     expected_scc1['udp_dst_port'] = 53
728     expected_scc1['udp_dst_port_max'] = 53
729     expected_scc1['udp_src_count'] = 1
730     expected_scc1['udp_dst_count'] = 1
731     expected_scc1['ip_src_addr'] = '110.0.0.1'
732     expected_scc1['ip_src_addr_max'] = '110.0.0.1'
733     expected_scc1['ip_src_count'] = 1
734     expected_scc1['ip_dst_addr'] = '120.0.0.16'
735     expected_scc1['ip_dst_addr_max'] = '120.0.0.32'
736     expected_scc1['ip_dst_count'] = 17
737     expected_cfg.append(expected_scc1)
738
739     # chain 2
740     expected_scc2 = dict(expected)
741     expected_scc2['udp_src_port'] = 53
742     expected_scc2['udp_src_port_max'] = 53
743     expected_scc2['udp_dst_port'] = 53
744     expected_scc2['udp_dst_port_max'] = 53
745     expected_scc2['udp_src_count'] = 1
746     expected_scc2['udp_dst_count'] = 1
747     expected_scc2['ip_src_addr'] = '110.0.0.2'
748     expected_scc2['ip_src_addr_max'] = '110.0.0.2'
749     expected_scc2['ip_src_count'] = 1
750     expected_scc2['ip_dst_addr'] = '120.0.0.33'
751     expected_scc2['ip_dst_addr_max'] = '120.0.0.49'
752     expected_scc2['ip_dst_count'] = 17
753     expected_cfg.append(expected_scc2)
754
755     _check_device_udp_flow_config(param, expected_cfg)
756     assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text
757
758
759 def test_device_udp_flow_config_doc_example3(caplog):
760     caplog.clear()
761     param = __get_udp_params()
762     expected = __get_udp_expected_list()
763
764     # Multiflow unitary test corresponding to third example in documentation
765     param['scc'] = 3
766     param['udp_src_port'] = 53
767     param['udp_dst_port'] = 53
768     param['ip_src_static'] = True
769     param['ip_addrs_step'] = '0.0.0.5'
770     param['flow_count'] = 100
771     param['ip_src_addr'] = '110.0.0.0/8'
772     param['ip_dst_addr'] = '120.0.0.0/8'
773
774     expected_cfg = []
775     # chain 0
776     expected_scc0 = dict(expected)
777     expected_scc0['udp_src_port'] = 53
778     expected_scc0['udp_src_port_max'] = 53
779     expected_scc0['udp_dst_port'] = 53
780     expected_scc0['udp_dst_port_max'] = 53
781     expected_scc0['udp_src_count'] = 1
782     expected_scc0['udp_dst_count'] = 1
783     expected_scc0['ip_src_addr'] = '110.0.0.0'
784     expected_scc0['ip_src_addr_max'] = '110.0.0.0'
785     expected_scc0['ip_src_count'] = 1
786     expected_scc0['ip_dst_addr'] = '120.0.0.0'
787     expected_scc0['ip_dst_addr_max'] = '120.0.0.75'
788     expected_scc0['ip_dst_count'] = 16
789     expected_cfg.append(expected_scc0)
790
791     # chain 1
792     expected_scc1 = dict(expected)
793     expected_scc1['udp_src_port'] = 53
794     expected_scc1['udp_src_port_max'] = 53
795     expected_scc1['udp_dst_port'] = 53
796     expected_scc1['udp_dst_port_max'] = 53
797     expected_scc1['udp_src_count'] = 1
798     expected_scc1['udp_dst_count'] = 1
799     expected_scc1['ip_src_addr'] = '110.0.0.5'
800     expected_scc1['ip_src_addr_max'] = '110.0.0.5'
801     expected_scc1['ip_src_count'] = 1
802     expected_scc1['ip_dst_addr'] = '120.0.0.80'
803     expected_scc1['ip_dst_addr_max'] = '120.0.0.160'
804     expected_scc1['ip_dst_count'] = 17
805     expected_cfg.append(expected_scc1)
806
807     # chain 2
808     expected_scc2 = dict(expected)
809     expected_scc2['udp_src_port'] = 53
810     expected_scc2['udp_src_port_max'] = 53
811     expected_scc2['udp_dst_port'] = 53
812     expected_scc2['udp_dst_port_max'] = 53
813     expected_scc2['udp_src_count'] = 1
814     expected_scc2['udp_dst_count'] = 1
815     expected_scc2['ip_src_addr'] = '110.0.0.10'
816     expected_scc2['ip_src_addr_max'] = '110.0.0.10'
817     expected_scc2['ip_src_count'] = 1
818     expected_scc2['ip_dst_addr'] = '120.0.0.165'
819     expected_scc2['ip_dst_addr_max'] = '120.0.0.245'
820     expected_scc2['ip_dst_count'] = 17
821     expected_cfg.append(expected_scc2)
822
823     caplog.set_level(logging.INFO)
824     _check_device_udp_flow_config(param, expected_cfg)
825     assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text
826
827
828 def test_device_udp_flow_config_doc_example4(caplog):
829     caplog.clear()
830     param = __get_udp_params()
831     expected = __get_udp_expected_list()
832
833     # Multiflow unitary test corresponding to fourth example in documentation
834     param['scc'] = 3
835     param['udp_src_port'] = [10, 14]
836     param['udp_dst_port'] = [20, 25]
837     param['ip_src_static'] = True
838     param['ip_addrs_step'] = '0.0.0.1'
839     param['udp_port_step'] = 'random'
840     param['flow_count'] = 100
841     param['ip_src_addr'] = '110.0.0.0/29'
842     param['ip_dst_addr'] = '120.0.0.0/30'
843
844     expected_cfg = []
845     # chain 0
846     expected_scc0 = dict(expected)
847     expected_scc0['udp_src_port'] = 10
848     expected_scc0['udp_src_port_max'] = 14
849     expected_scc0['udp_dst_port'] = 20
850     expected_scc0['udp_dst_port_max'] = 25
851     expected_scc0['udp_src_count'] = 5
852     expected_scc0['udp_dst_count'] = 6
853     expected_scc0['ip_src_addr'] = '110.0.0.0'
854     expected_scc0['ip_src_addr_max'] = '110.0.0.0'
855     expected_scc0['ip_src_count'] = 1
856     expected_scc0['ip_dst_addr'] = '120.0.0.0'
857     expected_scc0['ip_dst_addr_max'] = '120.0.0.0'
858     expected_scc0['ip_dst_count'] = 1
859     expected_cfg.append(expected_scc0)
860
861     # chain 1
862     expected_scc1 = dict(expected)
863     expected_scc1['udp_src_port'] = 10
864     expected_scc1['udp_src_port_max'] = 14
865     expected_scc1['udp_dst_port'] = 20
866     expected_scc1['udp_dst_port_max'] = 25
867     expected_scc1['udp_src_count'] = 5
868     expected_scc1['udp_dst_count'] = 6
869     expected_scc1['ip_src_addr'] = '110.0.0.1'
870     expected_scc1['ip_src_addr_max'] = '110.0.0.1'
871     expected_scc1['ip_src_count'] = 1
872     expected_scc1['ip_dst_addr'] = '120.0.0.1'
873     expected_scc1['ip_dst_addr_max'] = '120.0.0.1'
874     expected_scc1['ip_dst_count'] = 1
875     expected_cfg.append(expected_scc1)
876
877     # chain 2
878     expected_scc2 = dict(expected)
879     expected_scc2['udp_src_port'] = 10
880     expected_scc2['udp_src_port_max'] = 14
881     expected_scc2['udp_dst_port'] = 20
882     expected_scc2['udp_dst_port_max'] = 25
883     expected_scc2['udp_src_count'] = 5
884     expected_scc2['udp_dst_count'] = 6
885     expected_scc2['ip_src_addr'] = '110.0.0.2'
886     expected_scc2['ip_src_addr_max'] = '110.0.0.2'
887     expected_scc2['ip_src_count'] = 1
888     expected_scc2['ip_dst_addr'] = '120.0.0.2'
889     expected_scc2['ip_dst_addr_max'] = '120.0.0.2'
890     expected_scc2['ip_dst_count'] = 1
891     expected_cfg.append(expected_scc2)
892     caplog.set_level(logging.INFO)
893     _check_device_udp_flow_config(param, expected_cfg)
894     assert "Current values of ip_addrs_step and/or udp_port_step properties" in caplog.text
895     assert "udp_port_step='1' (previous value: udp_port_step='random'" in caplog.text
896
897
898 def test_device_udp_flow_config_no_random_steps_overridden(caplog):
899     caplog.clear()
900     param = __get_udp_params()
901     expected = __get_udp_expected_list()
902
903     # Multiflow unitary test corresponding to fifth example in documentation
904     param['scc'] = 3
905     param['udp_src_port'] = [10, 14]
906     param['udp_dst_port'] = [20, 25]
907     param['ip_src_static'] = True
908     param['ip_addrs_step'] = 'random'
909     param['udp_port_step'] = 'random'
910     param['flow_count'] = 100
911     param['ip_src_addr'] = '110.0.0.0/29'
912     param['ip_dst_addr'] = '120.0.0.0/30'
913
914     expected_cfg = []
915     # chain 0
916     expected_scc0 = dict(expected)
917     expected_scc0['udp_src_port'] = 10
918     expected_scc0['udp_src_port_max'] = 14
919     expected_scc0['udp_dst_port'] = 20
920     expected_scc0['udp_dst_port_max'] = 25
921     expected_scc0['udp_src_count'] = 5
922     expected_scc0['udp_dst_count'] = 6
923     expected_scc0['ip_src_addr'] = '110.0.0.0'
924     expected_scc0['ip_src_addr_max'] = '110.0.0.0'
925     expected_scc0['ip_src_count'] = 1
926     expected_scc0['ip_dst_addr'] = '120.0.0.0'
927     expected_scc0['ip_dst_addr_max'] = '120.0.0.0'
928     expected_scc0['ip_dst_count'] = 1
929     expected_cfg.append(expected_scc0)
930
931     # chain 1
932     expected_scc1 = dict(expected)
933     expected_scc1['udp_src_port'] = 10
934     expected_scc1['udp_src_port_max'] = 14
935     expected_scc1['udp_dst_port'] = 20
936     expected_scc1['udp_dst_port_max'] = 25
937     expected_scc1['udp_src_count'] = 5
938     expected_scc1['udp_dst_count'] = 6
939     expected_scc1['ip_src_addr'] = '110.0.0.1'
940     expected_scc1['ip_src_addr_max'] = '110.0.0.1'
941     expected_scc1['ip_src_count'] = 1
942     expected_scc1['ip_dst_addr'] = '120.0.0.1'
943     expected_scc1['ip_dst_addr_max'] = '120.0.0.1'
944     expected_scc1['ip_dst_count'] = 1
945     expected_cfg.append(expected_scc1)
946
947     # chain 2
948     expected_scc2 = dict(expected)
949     expected_scc2['udp_src_port'] = 10
950     expected_scc2['udp_src_port_max'] = 14
951     expected_scc2['udp_dst_port'] = 20
952     expected_scc2['udp_dst_port_max'] = 25
953     expected_scc2['udp_src_count'] = 5
954     expected_scc2['udp_dst_count'] = 6
955     expected_scc2['ip_src_addr'] = '110.0.0.2'
956     expected_scc2['ip_src_addr_max'] = '110.0.0.2'
957     expected_scc2['ip_src_count'] = 1
958     expected_scc2['ip_dst_addr'] = '120.0.0.2'
959     expected_scc2['ip_dst_addr_max'] = '120.0.0.2'
960     expected_scc2['ip_dst_count'] = 1
961     expected_cfg.append(expected_scc2)
962     caplog.set_level(logging.INFO)
963     _check_device_udp_flow_config(param, expected_cfg)
964     assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text
965
966
967 def test_config():
968     refcfg = {1: 100, 2: {21: 100, 22: 200}, 3: None}
969     res1 = {1: 10, 2: {21: 100, 22: 200}, 3: None}
970     res2 = {1: 100, 2: {21: 1000, 22: 200}, 3: None}
971     res3 = {1: 100, 2: {21: 100, 22: 200}, 3: "abc"}
972     assert config_loads("{}", refcfg) == refcfg
973     assert config_loads("{1: 10}", refcfg) == res1
974     assert config_loads("{2: {21: 1000}}", refcfg) == res2
975     assert config_loads('{3: "abc"}', refcfg) == res3
976
977     # correctly fails
978     # pairs of input string and expected subset (None if identical)
979     fail_pairs = [
980         ["{4: 0}", None],
981         ["{2: {21: 100, 30: 50}}", "{2: {30: 50}}"],
982         ["{2: {0: 1, 1: 2}, 5: 5}", None],
983         ["{1: 'abc', 2: {21: 0}}", "{1: 'abc'}"],
984         ["{2: 100}", None]
985     ]
986     for fail_pair in fail_pairs:
987         with pytest.raises(Exception) as e_info:
988             config_loads(fail_pair[0], refcfg)
989         expected = fail_pair[1]
990         if expected is None:
991             expected = fail_pair[0]
992         assert expected in str(e_info)
993
994     # whitelist keys
995     flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
996                          'extra_specs': {'hw:cpu_policy': 'dedicated'}}}
997     new_flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
998                              'extra_specs': {'hw:cpu_policy': 'dedicated', 'hw:numa_nodes': 2}}}
999     assert config_loads("{'flavor': {'extra_specs': {'hw:numa_nodes': 2}}}", flavor,
1000                         whitelist_keys=['alpha', 'extra_specs']) == new_flavor
1001
1002
1003 def test_fluentd():
1004     logger = logging.getLogger('fluent-logger')
1005
1006     class FluentdConfig(dict):
1007         def __getattr__(self, attr):
1008             return self.get(attr)
1009
1010     fluentd_configs = [
1011         FluentdConfig({
1012             'logging_tag': 'nfvbench',
1013             'result_tag': 'resultnfvbench',
1014             'ip': '127.0.0.1',
1015             'port': 7081
1016         }),
1017         FluentdConfig({
1018             'logging_tag': 'nfvbench',
1019             'result_tag': 'resultnfvbench',
1020             'ip': '127.0.0.1',
1021             'port': 24224
1022         }),
1023         FluentdConfig({
1024             'logging_tag': None,
1025             'result_tag': 'resultnfvbench',
1026             'ip': '127.0.0.1',
1027             'port': 7082
1028         }),
1029         FluentdConfig({
1030             'logging_tag': 'nfvbench',
1031             'result_tag': None,
1032             'ip': '127.0.0.1',
1033             'port': 7083
1034         })
1035     ]
1036
1037     handler = FluentLogHandler(fluentd_configs=fluentd_configs)
1038     logger.addHandler(handler)
1039     logger.setLevel(logging.INFO)
1040     logger.info('test')
1041     logger.warning('test %d', 100)
1042
1043     try:
1044         raise Exception("test")
1045     except Exception:
1046         logger.exception("got exception")
1047
1048 def assert_ndr_pdr(stats, ndr, ndr_dr, pdr, pdr_dr):
1049     assert stats['ndr']['rate_percent'] == ndr
1050     assert stats['ndr']['stats']['overall']['drop_percentage'] == ndr_dr
1051     assert_equivalence(pdr, stats['pdr']['rate_percent'])
1052     assert_equivalence(pdr_dr, stats['pdr']['stats']['overall']['drop_percentage'])
1053
1054 def _get_dummy_tg_config(chain_type, rate, scc=1, fc=10, step_ip='0.0.0.1',
1055                          ip0='10.0.0.0/8', ip1='20.0.0.0/8',
1056                          step_udp='1', src_udp=None, dst_udp=None, ip_src_static=True):
1057     return AttrDict({
1058         'traffic_generator': {'host_name': 'nfvbench_tg',
1059                               'default_profile': 'dummy',
1060                               'generator_profile': [{'name': 'dummy',
1061                                                      'tool': 'dummy',
1062                                                      'ip': '127.0.0.1',
1063                                                      'intf_speed': '10Gbps',
1064                                                      'interfaces': [{'port': 0, 'pci': '0.0'},
1065                                                                     {'port': 1, 'pci': '0.0'}]}],
1066                               'ip_addrs_step': step_ip,
1067                               'ip_addrs': [ip0, ip1],
1068                               'ip_src_static': ip_src_static,
1069                               'tg_gateway_ip_addrs': ['1.1.0.100', '2.2.0.100'],
1070                               'tg_gateway_ip_addrs_step': step_ip,
1071                               'gateway_ip_addrs': ['1.1.0.2', '2.2.0.2'],
1072                               'gateway_ip_addrs_step': step_ip,
1073                               'mac_addrs_left': None,
1074                               'mac_addrs_right': None,
1075                               'udp_src_port': src_udp,
1076                               'udp_dst_port': dst_udp,
1077                               'udp_port_step': step_udp},
1078         'traffic': {'profile': 'profile_64',
1079                     'bidirectional': True},
1080         'traffic_profile': [{'name': 'profile_64', 'l2frame_size': ['64']}],
1081         'generator_profile': None,
1082         'service_chain': chain_type,
1083         'service_chain_count': scc,
1084         'flow_count': fc,
1085         'vlan_tagging': True,
1086         'no_arp': False,
1087         'duration_sec': 1,
1088         'interval_sec': 1,
1089         'pause_sec': 1,
1090         'rate': rate,
1091         'check_traffic_time_sec': 200,
1092         'generic_poll_sec': 2,
1093         'measurement': {'NDR': 0.001, 'PDR': 0.1, 'load_epsilon': 0.1},
1094         'l2_loopback': False,
1095         'cores': None,
1096         'mbuf_factor': None,
1097         'disable_hdrh': None,
1098         'mbuf_64': None,
1099         'service_mode': False,
1100         'no_flow_stats': False,
1101         'no_latency_stats': False,
1102         'no_latency_streams': False,
1103         'intf_speed': '10Gbps',
1104         'periodic_gratuitous_arp': False,
1105         'gratuitous_arp_pps': 1
1106     })
1107
1108 def _get_traffic_client(user_info=None):
1109     config = _get_dummy_tg_config('PVP', 'ndr_pdr')
1110     config['vxlan'] = False
1111     config['mpls'] = False
1112     config['ndr_run'] = True
1113     config['pdr_run'] = True
1114     config['generator_profile'] = 'dummy'
1115     config['single_run'] = False
1116     if user_info:
1117         config['user_info'] = user_info
1118     traffic_client = TrafficClient(config)
1119     traffic_client.start_traffic_generator()
1120     traffic_client.set_traffic('64', True)
1121     return traffic_client
1122
1123 @patch.object(TrafficClient, 'skip_sleep', lambda x: True)
1124 def test_ndr_at_lr():
1125     """Test NDR at line rate."""
1126     traffic_client = _get_traffic_client()
1127     tg = traffic_client.gen
1128     # this is a perfect sut with no loss at LR
1129     tg.set_response_curve(lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100)
1130     # tx packets should be line rate for 64B and no drops...
1131     assert tg.get_tx_pps_dropped_pps(100) == (LR_64B_PPS, 0)
1132     # NDR and PDR should be at 100%
1133     # traffic_client.ensure_end_to_end()
1134     results = traffic_client.get_ndr_and_pdr()
1135     assert_ndr_pdr(results, 200.0, 0.0, 200.0, 0.0)
1136
1137 @patch.object(TrafficClient, 'skip_sleep', lambda x: True)
1138 def test_ndr_at_50():
1139     """Test NDR at 50% line rate.
1140
1141     This is a sut with an NDR of 50% and linear drop rate after NDR up to 20% drops at LR
1142     (meaning that if you send 100% TX, you will only receive 80% RX)
1143     the tg requested TX/actual TX ratio is up to 50%, after 50%
1144     is linear up 80% actuak TX when requesting 100%
1145     """
1146     traffic_client = _get_traffic_client()
1147     tg = traffic_client.gen
1148
1149     tg.set_response_curve(lr_dr=20, ndr=50, max_actual_tx=80, max_11_tx=50)
1150     # tx packets should be half line rate for 64B and no drops...
1151     assert tg.get_tx_pps_dropped_pps(50) == (LR_64B_PPS / 2, 0)
1152     # at 100% TX requested, actual TX is 80% where the drop rate is 3/5 of 20% of the actual TX
1153     assert tg.get_tx_pps_dropped_pps(100) == (int(LR_64B_PPS * 0.8),
1154                                               int(LR_64B_PPS * 0.8 * 0.6 * 0.2))
1155     results = traffic_client.get_ndr_and_pdr()
1156     assert_ndr_pdr(results, 100.0, 0.0, 100.781, 0.09374)
1157
1158 @patch.object(TrafficClient, 'skip_sleep', lambda x: True)
1159 def test_ndr_pdr_low_cpu():
1160     """Test NDR and PDR with too low cpu.
1161
1162     This test is for the case where the TG is underpowered and cannot send fast enough for the NDR
1163     true NDR=40%, actual TX at 50% = 30%, actual measured DR is 0%
1164     The ndr/pdr should bail out with a warning and a best effort measured NDR of 30%
1165     """
1166     traffic_client = _get_traffic_client()
1167     tg = traffic_client.gen
1168     tg.set_response_curve(lr_dr=50, ndr=40, max_actual_tx=60, max_11_tx=0)
1169     # tx packets should be 30% at requested half line rate for 64B and no drops...
1170     assert tg.get_tx_pps_dropped_pps(50) == (int(LR_64B_PPS * 0.3), 0)
1171     results = traffic_client.get_ndr_and_pdr()
1172     assert results
1173     # import pprint
1174     # pp = pprint.PrettyPrinter(indent=4)
1175     # pp.pprint(results)
1176
1177 @patch.object(TrafficClient, 'skip_sleep', lambda x: True)
1178 def test_ndr_at_lr_sdn_gw_encapsulation():
1179     """Test NDR at line rate with traffic gen outside SUT and connected via SDN GW."""
1180     user_info = {'extra_encapsulation_bytes': 28}
1181     traffic_client = _get_traffic_client(user_info)
1182     tg = traffic_client.gen
1183     # this is a perfect sut with no loss at LR
1184     tg.set_response_curve(lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100)
1185     # tx packets should be line rate for 64B and no drops...
1186     assert tg.get_tx_pps_dropped_pps(100) == (LR_64B_PPS, 0)
1187     # NDR and PDR should be at 100%
1188     # traffic_client.ensure_end_to_end()
1189     results = traffic_client.get_ndr_and_pdr()
1190     assert results['ndr']['stats']['theoretical_tx_rate_bps'] == 15000000000.0
1191     assert_ndr_pdr(results, 200.0, 0.0, 200.0, 0.0)
1192
1193 @patch.object(TrafficClient, 'skip_sleep', lambda x: True)
1194 def test_no_openstack():
1195     """Test nfvbench using main."""
1196     config = _get_dummy_tg_config('EXT', '1000pps')
1197     config.openrc_file = None
1198     config.vlans = [[100], [200]]
1199     config['traffic_generator']['mac_addrs_left'] = ['00:00:00:00:00:00']
1200     config['traffic_generator']['mac_addrs_right'] = ['00:00:00:00:01:00']
1201     del config['generator_profile']
1202     old_argv = sys.argv
1203     sys.argv = [old_argv[0], '-c', json.dumps(config)]
1204     nfvbench.nfvbench.main()
1205     sys.argv = old_argv