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