X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=test%2Ftest_nfvbench.py;h=e48fbda9ebbde87cb14c9fb71cbfec610a2864fe;hb=refs%2Fchanges%2F09%2F73709%2F6;hp=4603ae1ddb6715e265e3ffb68c6f2c3b7dc79c97;hpb=5aae8e338ab2a71e89c1a9b442c895c72685f585;p=nfvbench.git diff --git a/test/test_nfvbench.py b/test/test_nfvbench.py index 4603ae1..e48fbda 100644 --- a/test/test_nfvbench.py +++ b/test/test_nfvbench.py @@ -13,259 +13,36 @@ # License for the specific language governing permissions and limitations # under the License. # +import openstack +from keystoneauth1.exceptions import HTTPClientError +from mock import patch +import pytest + +from .mock_trex import no_op + import json import logging -import os import sys - -import pytest - from attrdict import AttrDict from nfvbench.config import config_loads from nfvbench.credentials import Credentials from nfvbench.fluentd import FluentLogHandler import nfvbench.log -from nfvbench.network import Interface -from nfvbench.network import Network -from nfvbench.specs import ChainType -from nfvbench.specs import Encaps -import nfvbench.traffic_gen.traffic_utils as traffic_utils - -__location__ = os.path.realpath(os.path.join(os.getcwd(), - os.path.dirname(__file__))) - - -@pytest.fixture -def openstack_vxlan_spec(): - return AttrDict( - { - 'openstack': AttrDict({ - 'vswitch': "VTS", - 'encaps': Encaps.VxLAN}), - 'run_spec': AttrDict({ - 'use_vpp': True - }) - } - ) - - -# ========================================================================= -# PVP Chain tests -# ========================================================================= - -def test_chain_interface(): - iface = Interface('testname', 'vpp', tx_packets=1234, rx_packets=4321) - assert iface.name == 'testname' - assert iface.device == 'vpp' - assert iface.get_packet_count('tx') == 1234 - assert iface.get_packet_count('rx') == 4321 - assert iface.get_packet_count('wrong_key') == 0 - - -# pylint: disable=redefined-outer-name -@pytest.fixture(scope='session') -def iface1(): - return Interface('iface1', 'trex', tx_packets=10000, rx_packets=1234) - - -@pytest.fixture(scope='session') -def iface2(): - return Interface('iface2', 'n9k', tx_packets=1234, rx_packets=9901) - - -@pytest.fixture(scope='session') -def iface3(): - return Interface('iface3', 'n9k', tx_packets=9900, rx_packets=1234) - - -@pytest.fixture(scope='session') -def iface4(): - return Interface('iface4', 'vpp', tx_packets=1234, rx_packets=9801) - - -@pytest.fixture(scope='session') -def net1(iface1, iface2, iface3, iface4): - return Network([iface1, iface2, iface3, iface4], reverse=False) - - -@pytest.fixture(scope='session') -def net2(iface1, iface2, iface3): - return Network([iface1, iface2, iface3], reverse=True) - - -def test_chain_network(net1, net2, iface1, iface2, iface3, iface4): - assert [iface1, iface2, iface3, iface4] == net1.get_interfaces() - assert [iface3, iface2, iface1] == net2.get_interfaces() - net2.add_interface(iface4) - assert [iface4, iface3, iface2, iface1] == net2.get_interfaces() - - -# pylint: enable=redefined-outer-name - -# pylint: disable=pointless-string-statement -""" -def test_chain_analysis(net1, monkeypatch, openstack_vxlan_spec): - def mock_empty(self, *args, **kwargs): - pass - - monkeypatch.setattr(ServiceChain, '_setup', mock_empty) - - f = ServiceChain(AttrDict({'service_chain': 'DUMMY'}), [], {'tor': {}}, openstack_vxlan_spec, - lambda x, y, z: None) - result = f.get_analysis([net1]) - assert result[1]['packet_drop_count'] == 99 - assert result[1]['packet_drop_percentage'] == 0.99 - assert result[2]['packet_drop_count'] == 1 - assert result[2]['packet_drop_percentage'] == 0.01 - assert result[3]['packet_drop_count'] == 99 - assert result[3]['packet_drop_percentage'] == 0.99 - - net1.reverse = True - result = f.get_analysis([net1]) - assert result[1]['packet_drop_count'] == 0 - assert result[1]['packet_drop_percentage'] == 0.0 - assert result[2]['packet_drop_count'] == 0 - assert result[2]['packet_drop_percentage'] == 0.0 - assert result[3]['packet_drop_count'] == 0 - assert result[3]['packet_drop_percentage'] == 0.0 - - -@pytest.fixture -def pvp_chain(monkeypatch, openstack_vxlan_spec): - tor_vni1 = Interface('vni-4097', 'n9k', 50, 77) - vsw_vni1 = Interface('vxlan_tunnel0', 'vpp', 77, 48) - vsw_vif1 = Interface('VirtualEthernet0/0/2', 'vpp', 48, 77) - vsw_vif2 = Interface('VirtualEthernet0/0/3', 'vpp', 77, 47) - vsw_vni2 = Interface('vxlan_tunnel1', 'vpp', 43, 77) - tor_vni2 = Interface('vni-4098', 'n9k', 77, 40) - - def mock_init(self, *args, **kwargs): - self.vni_ports = [4097, 4098] - self.specs = openstack_vxlan_spec - self.clients = { - 'vpp': AttrDict({ - 'set_interface_counters': lambda: None, - }) - } - self.worker = AttrDict({ - 'run': lambda: None, - }) +import nfvbench.nfvbench +from nfvbench.traffic_client import Device +from nfvbench.traffic_client import GeneratorConfig +from nfvbench.traffic_client import IpBlock +from nfvbench.traffic_client import TrafficClient +from nfvbench.traffic_client import TrafficClientException +from nfvbench.traffic_gen import traffic_utils +from nfvbench import utils - def mock_empty(self, *args, **kwargs): - pass +# just to get rid of the unused function warning +no_op() - def mock_get_network(self, traffic_port, vni_id, reverse=False): - if vni_id == 0: - return Network([tor_vni1, vsw_vni1, vsw_vif1], reverse) - else: - return Network([tor_vni2, vsw_vni2, vsw_vif2], reverse) - - def mock_get_data(self): - return {} - - monkeypatch.setattr(PVPChain, '_get_network', mock_get_network) - monkeypatch.setattr(PVPChain, '_get_data', mock_get_data) - monkeypatch.setattr(PVPChain, '_setup', mock_empty) - monkeypatch.setattr(VxLANWorker, '_clear_interfaces', mock_empty) - monkeypatch.setattr(PVPChain, '_generate_traffic', mock_empty) - monkeypatch.setattr(PVPChain, '__init__', mock_init) - return PVPChain(None, None, {'vm': None, 'vpp': None, 'tor': None, 'traffic': None}, None) - - -def test_pvp_chain_run(pvp_chain): - result = pvp_chain.run() - expected_result = { - 'raw_data': {}, - 'stats': None, - 'packet_analysis': { - 'direction-forward': [ - OrderedDict([ - ('interface', 'vni-4097'), - ('device', 'n9k'), - ('packet_count', 50) - ]), - OrderedDict([ - ('interface', 'vxlan_tunnel0'), - ('device', 'vpp'), - ('packet_count', 48), - ('packet_drop_count', 2), - ('packet_drop_percentage', 4.0) - ]), - OrderedDict([ - ('interface', 'VirtualEthernet0/0/2'), - ('device', 'vpp'), - ('packet_count', 48), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]), - OrderedDict([ - ('interface', 'VirtualEthernet0/0/3'), - ('device', 'vpp'), - ('packet_count', 47), - ('packet_drop_count', 1), - ('packet_drop_percentage', 2.0) - ]), - OrderedDict([ - ('interface', 'vxlan_tunnel1'), - ('device', 'vpp'), - ('packet_count', 43), - ('packet_drop_count', 4), - ('packet_drop_percentage', 8.0) - ]), - OrderedDict([ - ('interface', 'vni-4098'), - ('device', 'n9k'), - ('packet_count', 40), - ('packet_drop_count', 3), - ('packet_drop_percentage', 6.0) - ]) - ], - 'direction-reverse': [ - OrderedDict([ - ('interface', 'vni-4098'), - ('device', 'n9k'), - ('packet_count', 77) - ]), - OrderedDict([ - ('interface', 'vxlan_tunnel1'), - ('device', 'vpp'), - ('packet_count', 77), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]), - OrderedDict([ - ('interface', 'VirtualEthernet0/0/3'), - ('device', 'vpp'), - ('packet_count', 77), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]), - OrderedDict([ - ('interface', 'VirtualEthernet0/0/2'), - ('device', 'vpp'), - ('packet_count', 77), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]), - OrderedDict([ - ('interface', 'vxlan_tunnel0'), - ('device', 'vpp'), - ('packet_count', 77), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]), - OrderedDict([ - ('interface', 'vni-4097'), - ('device', 'n9k'), - ('packet_count', 77), - ('packet_drop_count', 0), - ('packet_drop_percentage', 0.0) - ]) - ] - } - } - assert result == expected_result -""" +def setup_module(module): + """Enable log.""" + nfvbench.log.setup(mute_stdout=True) # ========================================================================= # Traffic client tests @@ -298,7 +75,6 @@ def test_parse_rate_str(): return True else: return False - return False assert should_raise_error('101') @@ -326,12 +102,13 @@ def test_rate_conversion(): assert traffic_utils.pps_to_bps(31.6066319896, 1518) == pytest.approx(388888) assert traffic_utils.pps_to_bps(3225895.85831, 340.3) == pytest.approx(9298322222) + # pps at 10Gbps line rate for 64 byte frames LR_64B_PPS = 14880952 LR_1518B_PPS = 812743 def assert_equivalence(reference, value, allowance_pct=1): - '''Asserts if a value is equivalent to a reference value with given margin + """Assert if a value is equivalent to a reference value with given margin. :param float reference: reference value to compare to :param float value: value to compare to reference @@ -340,7 +117,7 @@ def assert_equivalence(reference, value, allowance_pct=1): 1 : must be equal within 1% of the reference value ... 100: always true - ''' + """ if reference == 0: assert value == 0 else: @@ -359,75 +136,45 @@ def test_load_from_rate(): avg_frame_size=1518, line_rate='20Gbps')) -""" -@pytest.fixture -def traffic_client(monkeypatch): - - def mock_init(self, *args, **kwargs): - self.run_config = { - 'bidirectional': False, - 'l2frame_size': '64', - 'duration_sec': 30, - 'rates': [{'rate_percent': '10'}, {'rate_pps': '1'}] - } - - def mock_modify_load(self, load): - self.run_config['rates'][0] = {'rate_percent': str(load)} - self.current_load = load - - monkeypatch.setattr(TrafficClient, '__init__', mock_init) - monkeypatch.setattr(TrafficClient, 'modify_load', mock_modify_load) - - return TrafficClient() -""" - - -# pylint: enable=pointless-string-statement - # ========================================================================= # Other tests # ========================================================================= -def setup_module(module): - nfvbench.log.setup(mute_stdout=True) - def test_no_credentials(): - cred = Credentials('/completely/wrong/path/openrc', None, False) - if cred.rc_auth_url: - # shouldn't get valid data unless user set environment variables - assert False - else: - assert True + with patch.object(openstack, 'connect') as mock: + cred = Credentials('/completely/wrong/path/openrc', None, None, False) + if cred.rc_auth_url: + # shouldn't get valid data unless user set environment variables + assert False + else: + assert True + mock.assert_not_called() -# Because trex_stl_lib may not be installed when running unit test -# nfvbench.traffic_client will try to import STLError: -# from trex_stl_lib.api import STLError -# will raise ImportError: No module named trex_stl_lib.api -try: - import trex_stl_lib.api +def test_clouds_file_credentials(): + with patch.object(openstack, 'connect') as mock: + Credentials(None, 'openstack', None, False) + mock.assert_called_once() - assert trex_stl_lib.api -except ImportError: - # Make up a trex_stl_lib.api.STLError class - class STLError(Exception): - pass +@patch('nfvbench.nfvbench.credentials') +def test_is_not_admin(mock_session): + mock_session.Session.return_value.get.return_value.raiseError.side_effect = HTTPClientError + cred = Credentials(None, 'openstack', None, False) + if cred.is_admin: + assert False + else: + assert True - from types import ModuleType - stl_lib_mod = ModuleType('trex_stl_lib') - sys.modules['trex_stl_lib'] = stl_lib_mod - api_mod = ModuleType('trex_stl_lib.api') - stl_lib_mod.api = api_mod - sys.modules['trex_stl_lib.api'] = api_mod - api_mod.STLError = STLError +def test_is_admin(): + with patch.object(openstack, 'connect'): + cred = Credentials(None, 'openstack', None, False) + if cred.is_admin: + assert True + else: + assert False -# pylint: disable=wrong-import-position,ungrouped-imports -from nfvbench.traffic_client import Device -from nfvbench.traffic_client import IpBlock -from nfvbench.traffic_client import TrafficClient -from nfvbench.traffic_client import TrafficGeneratorFactory def test_ip_block(): ipb = IpBlock('10.0.0.0', '0.0.0.1', 256) @@ -435,6 +182,19 @@ def test_ip_block(): assert ipb.get_ip(255) == '10.0.0.255' with pytest.raises(IndexError): ipb.get_ip(256) + ipb = IpBlock('10.0.0.0', '0.0.0.1', 1) + assert ipb.get_ip() == '10.0.0.0' + with pytest.raises(IndexError): + ipb.get_ip(1) + + ipb = IpBlock('10.0.0.0', '0.0.0.2', 256) + assert ipb.get_ip() == '10.0.0.0' + assert ipb.get_ip(1) == '10.0.0.2' + assert ipb.get_ip(127) == '10.0.0.254' + assert ipb.get_ip(128) == '10.0.1.0' + with pytest.raises(IndexError): + ipb.get_ip(256) + # verify with step larger than 1 ipb = IpBlock('10.0.0.0', '0.0.0.2', 256) assert ipb.get_ip() == '10.0.0.0' @@ -444,69 +204,764 @@ def test_ip_block(): with pytest.raises(IndexError): ipb.get_ip(256) + ipb = IpBlock('10.0.0.0', '0.0.0.2', 128) + assert ipb.get_ip() == '10.0.0.0' + assert ipb.get_ip(1) == '10.0.0.2' + assert ipb.get_ip(127) == '10.0.0.254' + with pytest.raises(IndexError): + ipb.get_ip(128) -def check_config(configs, cc, fc, src_ip, dst_ip, step_ip): - '''Verify that the range configs for each chain have adjacent IP ranges - of the right size and without holes between chains - ''' - step = Device.ip_to_int(step_ip) - cfc = 0 - sip = Device.ip_to_int(src_ip) - dip = Device.ip_to_int(dst_ip) - for index in range(cc): - config = configs[index] - assert config['ip_src_count'] == config['ip_dst_count'] - assert Device.ip_to_int(config['ip_src_addr']) == sip - assert Device.ip_to_int(config['ip_dst_addr']) == dip - count = config['ip_src_count'] - cfc += count - sip += count * step - dip += count * step - assert cfc == fc - + ipb = IpBlock('10.0.0.0', '0.0.0.4', 64) + assert ipb.get_ip() == '10.0.0.0' + assert ipb.get_ip(1) == '10.0.0.4' + assert ipb.get_ip(63) == '10.0.0.252' + with pytest.raises(IndexError): + ipb.get_ip(64) -def create_device(fc, cc, ip, gip, tggip, step_ip, mac): - return Device(0, 0, flow_count=fc, chain_count=cc, ip=ip, gateway_ip=gip, tg_gateway_ip=tggip, - ip_addrs_step=step_ip, - tg_gateway_ip_addrs_step=step_ip, - gateway_ip_addrs_step=step_ip, - dst_mac=mac) + ipb = IpBlock('10.0.0.0', '0.0.0.10', 1) + assert ipb.get_ip() == '10.0.0.0' + with pytest.raises(IndexError): + ipb.get_ip(1) + + +def test_lcm(): + assert utils.lcm(10, 2) == 10 + assert utils.lcm(1, 256) == 256 + assert utils.lcm(10, 256) == 1280 + assert utils.lcm(utils.lcm(10, 2), utils.lcm(1, 256)) + with pytest.raises(TypeError): + utils.lcm(0, 0) + + +def test_flow_count_limit(): + # lcm ip src and dst /32 + lcm_ip = utils.lcm(1, 1) == 1 + # port udp src = 1 port udp dst [1,29] + src_min = 1 + src_max = 1 + dst_min = 1 + dst_max = 29 + udp_step = 3 + udp_src_size = Device.check_range_size(int(src_max) - int(src_min) + 1, + udp_step) + udp_dst_size = Device.check_range_size(int(dst_max) - int(dst_min) + 1, + udp_step) + lcm_port = utils.lcm(udp_src_size, udp_dst_size) + assert utils.lcm(lcm_ip, lcm_port) < 29 + + +def test_check_range_size(): + assert Device.check_range_size(256, 1) == 256 + assert Device.check_range_size(256, 3) == 86 + assert Device.check_range_size(256, 4) == 64 + assert Device.check_range_size(16, 10) == 2 + assert Device.check_range_size(1, 10) == 1 + with pytest.raises(ZeroDivisionError): + Device.check_range_size(256, 0) + + +def test_reserve_ip_range(): + ipb = IpBlock('10.0.0.0', '0.0.0.1', 256) + src_ip_first, src_ip_last = ipb.reserve_ip_range(256) + assert src_ip_first == "10.0.0.0" + assert src_ip_last == "10.0.0.255" + ipb = IpBlock('20.0.0.0', '0.0.0.1', 2) + src_ip_first, src_ip_last = ipb.reserve_ip_range(2) + assert src_ip_first == "20.0.0.0" + assert src_ip_last == "20.0.0.1" + ipb = IpBlock('30.0.0.0', '0.0.0.1', 2) + with pytest.raises(IndexError): + ipb.reserve_ip_range(256) -def check_device_flow_config(step_ip): - fc = 99999 - cc = 10 - ip0 = '10.0.0.0' - ip1 = '20.0.0.0' - tggip = '50.0.0.0' - gip = '60.0.0.0' - mac = ['00:11:22:33:44:55'] * cc - dev0 = create_device(fc, cc, ip0, gip, tggip, step_ip, mac) - dev1 = create_device(fc, cc, ip1, gip, tggip, step_ip, mac) - dev0.set_destination(dev1) - configs = dev0.get_stream_configs(ChainType.EXT) - check_config(configs, cc, fc, ip0, ip1, step_ip) +def check_stream_configs(gen_config): + """Verify that the range for each chain have adjacent IP ranges without holes between chains.""" + config = gen_config.config + tgc = config['traffic_generator'] + step = Device.ip_to_int(tgc['ip_addrs_step']) + cfc = 0 + sip = Device.ip_to_int(tgc['ip_addrs'][0].split('/')[0]) + dip = Device.ip_to_int(tgc['ip_addrs'][1].split('/')[0]) + stream_configs = gen_config.devices[0].get_stream_configs() + for index in range(config['service_chain_count']): + stream_cfg = stream_configs[index] + # ip_src_static == True + assert stream_cfg['ip_src_count'] == 1 + if index == 0: + assert stream_cfg['ip_dst_count'] == 4999 + else: + assert stream_cfg['ip_dst_count'] == 5000 + assert stream_cfg['ip_src_addr'] == Device.int_to_ip(sip) + assert Device.ip_to_int(stream_cfg['ip_src_addr']) == sip + assert Device.ip_to_int(stream_cfg['ip_dst_addr']) == dip + count = stream_cfg['ip_dst_count'] + cfc += count + sip += step + dip += count * step + assert cfc == int(config['flow_count'] / 2) +def _check_device_flow_config(step_ip): + config = _get_dummy_tg_config('PVP', '1Mpps', scc=10, fc=99999, step_ip=step_ip) + gen_config = GeneratorConfig(config) + check_stream_configs(gen_config) def test_device_flow_config(): - check_device_flow_config('0.0.0.1') - check_device_flow_config('0.0.0.2') - - -def test_device_ip_range(): - def ip_range_overlaps(ip0, ip1, flows): - tggip = '50.0.0.0' - gip = '60.0.0.0' - mac = ['00:11:22:33:44:55'] * 10 - dev0 = create_device(flows, 10, ip0, gip, tggip, '0.0.0.1', mac) - dev1 = create_device(flows, 10, ip1, gip, tggip, '0.0.0.1', mac) - dev0.set_destination(dev1) - return dev0.ip_range_overlaps() - - assert not ip_range_overlaps('10.0.0.0', '20.0.0.0', 10000) - assert ip_range_overlaps('10.0.0.0', '10.0.1.0', 10000) - assert ip_range_overlaps('10.0.0.0', '10.0.1.0', 257) - assert ip_range_overlaps('10.0.1.0', '10.0.0.0', 257) + _check_device_flow_config('0.0.0.1') + _check_device_flow_config('0.0.0.2') + + +def check_udp_stream_configs(gen_config, expected_cfg): + """Verify that the range for each chain have adjacent UDP ports without holes between chains.""" + config = gen_config.config + stream_configs = gen_config.devices[0].get_stream_configs() + for index in range(config['service_chain_count']): + stream_cfg = stream_configs[index] + expected = expected_cfg[index] + assert stream_cfg['ip_src_addr'] == expected['ip_src_addr'] + assert stream_cfg['ip_src_addr_max'] == expected['ip_src_addr_max'] + assert stream_cfg['ip_src_count'] == expected['ip_src_count'] + + assert stream_cfg['ip_dst_addr'] == expected['ip_dst_addr'] + assert stream_cfg['ip_dst_addr_max'] == expected['ip_dst_addr_max'] + assert stream_cfg['ip_dst_count'] == expected['ip_dst_count'] + + assert stream_cfg['udp_src_port'] == expected['udp_src_port'] + assert stream_cfg['udp_src_port_max'] == expected['udp_src_port_max'] + assert stream_cfg['udp_src_count'] == expected['udp_src_count'] + + assert stream_cfg['udp_dst_port'] == expected['udp_dst_port'] + assert stream_cfg['udp_dst_port_max'] == expected['udp_dst_port_max'] + assert stream_cfg['udp_dst_count'] == expected['udp_dst_count'] + + lcm_ip = utils.lcm(stream_cfg['ip_src_count'], stream_cfg['ip_dst_count']) + udp_src_size = int(stream_cfg['udp_src_port_max']) - int(stream_cfg['udp_src_port']) + 1 + udp_dst_size = int(stream_cfg['udp_dst_port_max']) - int(stream_cfg['udp_dst_port']) + 1 + lcm_udp = utils.lcm(udp_src_size, udp_dst_size) + assert utils.lcm(lcm_ip, lcm_udp) >= stream_cfg['count'] + + +def _check_device_udp_flow_config(param, expected_cfg): + config = _get_dummy_tg_config('PVP', '1Mpps', + scc=param['scc'], + ip_src_static=param['ip_src_static'], + fc=param['flow_count'], + ip0=param['ip_src_addr'], + ip1=param['ip_dst_addr'], + step_ip=param['ip_addrs_step'], + src_udp=param['udp_src_port'], + dst_udp=param['udp_dst_port'], + step_udp=param['udp_port_step']) + gen_config = GeneratorConfig(config) + check_udp_stream_configs(gen_config, expected_cfg) + + +def __get_udp_params(): + param = {'ip_src_static': True, + 'ip_src_addr': '110.0.0.0/32', + 'ip_dst_addr': '120.0.0.0/32', + 'ip_addrs_step': '0.0.0.1', + 'udp_src_port': 53, + 'udp_dst_port': 53, + 'flow_count': 2, + 'scc': 1, + 'udp_port_step': '1'} + return param + + +def __get_udp_expected_list(): + expected = {'ip_src_addr': '110.0.0.0', + 'ip_src_addr_max': '110.0.0.0', + 'ip_src_count': 1, + 'ip_dst_addr': '120.0.0.0', + 'ip_dst_addr_max': '120.0.0.0', + 'ip_dst_count': 1, + 'udp_src_port': 53, + 'udp_src_port_max': 53, + 'udp_src_count': 1, + 'udp_dst_port': 53, + 'udp_dst_port_max': 53, + 'udp_dst_count': 1} + return expected + + +def test_device_udp_flow_config_single_ip_single_port(): + param = __get_udp_params() + expected = __get_udp_expected_list() + _check_device_udp_flow_config(param, [expected]) + + +def test_device_udp_flow_config_single_ip_multiple_src_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + # Overwrite the udp_src_port value to define a large range of ports + # instead of a single port, in order to check if the imposed + # flow count is respected. Notice that udp range >> flow count. + param['udp_src_port'] = [53, 1024] + param['flow_count'] = 10 + expected['udp_src_port_max'] = 57 + expected['udp_src_count'] = 5 + _check_device_udp_flow_config(param, [expected]) + + +def test_device_udp_flow_config_multiple_ip_src_single_port(): + param = __get_udp_params() + expected = __get_udp_expected_list() + # Re affect the default udp_src_port values and + # overwrite the ip_dst_addr value to define a large range of addresses + # instead of a single one, in order to check if the imposed + # flow count is respected. Notice that the netmask allows a very larger + # range of possible addresses than the flow count value. + param['udp_src_port'] = 53 + param['flow_count'] = 10 + param['ip_src_static'] = False + param['ip_dst_addr'] = '120.0.0.0/24' + + expected['udp_src_port_max'] = 53 + expected['udp_src_count'] = 1 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.0.4' + expected['ip_dst_count'] = 5 + _check_device_udp_flow_config(param, [expected]) + + +def test_device_udp_flow_config_multiple_ip_src_dst_multiple_src_dst_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['udp_src_port'] = [49000, 49031] + param['udp_dst_port'] = [50000, 50033] + param['ip_src_static'] = False + param['flow_count'] = 1000 + param['ip_src_addr'] = '110.0.0.0/16' + param['ip_dst_addr'] = '120.0.0.0/16' + + expected['udp_src_port'] = 49000 + expected['udp_src_port_max'] = 49024 + expected['udp_dst_port'] = 50000 + expected['udp_dst_port_max'] = 50024 + expected['udp_src_count'] = 25 + expected['udp_dst_count'] = 25 + expected['ip_src_addr_max'] = '110.0.1.243' + expected['ip_src_count'] = 500 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.1.243' + expected['ip_dst_count'] = 500 + _check_device_udp_flow_config(param, [expected]) + + + + +def test_device_udp_flow_config_random_multiple_ip_src_dst_multiple_src_dst_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['udp_src_port'] = [1025, 65000] + param['udp_dst_port'] = [1024, 65000] + param['ip_src_static'] = False + param['ip_addrs_step'] = 'random' + param['udp_port_step'] = 'random' + param['flow_count'] = 1000000 + param['ip_src_addr'] = '110.0.0.0/16' + param['ip_dst_addr'] = '120.0.0.0/16' + + expected['udp_src_port'] = 1025 + expected['udp_src_port_max'] = 65000 + expected['udp_dst_port'] = 1024 + expected['udp_dst_port_max'] = 65000 + expected['udp_src_count'] = 62500 + expected['udp_dst_count'] = 62500 + expected['ip_src_addr_max'] = '110.0.0.31' + expected['ip_src_count'] = 32 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.0.31' + expected['ip_dst_count'] = 32 + _check_device_udp_flow_config(param, [expected]) + +def test_device_udp_flow_config_random_multiple_ip_srcstatic_dst_multiple_src_dst_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['udp_src_port'] = [1025, 65000] + param['udp_dst_port'] = [1024, 65000] + param['ip_src_static'] = True + param['ip_addrs_step'] = 'random' + param['udp_port_step'] = 'random' + param['flow_count'] = 1000000 + param['ip_src_addr'] = '110.0.0.0/16' + param['ip_dst_addr'] = '120.0.0.0/16' + + expected['udp_src_port'] = 1025 + expected['udp_src_port_max'] = 65000 + expected['udp_dst_port'] = 1024 + expected['udp_dst_port_max'] = 65000 + expected['udp_src_count'] = 1 + expected['udp_dst_count'] = 62500 + expected['ip_src_addr_max'] = '110.0.0.0' + expected['ip_src_count'] = 1 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.0.31' + expected['ip_dst_count'] = 32 + _check_device_udp_flow_config(param, [expected]) + + + +def test_device_udp_flow_config_single_ip_src_dst_multiple_src_dst_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['udp_src_port'] = [49152, 49154] + param['udp_dst_port'] = [50001, 50005] + param['ip_src_static'] = False + param['flow_count'] = 10 + param['ip_src_addr'] = '110.0.0.0/32' + param['ip_dst_addr'] = '120.0.0.0/32' + + expected['udp_src_port'] = 49152 + expected['udp_src_port_max'] = 49152 + expected['udp_dst_port'] = 50001 + expected['udp_dst_port_max'] = 50005 + expected['udp_src_count'] = 1 + expected['udp_dst_count'] = 5 + expected['ip_src_addr_max'] = '110.0.0.0' + expected['ip_src_count'] = 1 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.0.0' + expected['ip_dst_count'] = 1 + _check_device_udp_flow_config(param, [expected]) + + +def test_device_udp_flow_config_single_ip_src_dst_single_src_multiple_dst_ports(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['udp_src_port'] = 49152 + param['udp_dst_port'] = [50001, 50029] + param['udp_port_step'] = '3' + param['flow_count'] = 58 + param['ip_src_addr'] = '110.0.0.0/32' + param['ip_dst_addr'] = '120.0.0.0/32' + + expected['udp_src_port'] = 49152 + expected['udp_src_port_max'] = 49152 + expected['udp_dst_port'] = 50001 + expected['udp_dst_port_max'] = 50029 + expected['udp_src_count'] = 1 + expected['udp_dst_count'] = 29 + expected['ip_src_addr_max'] = '110.0.0.0' + expected['ip_src_count'] = 1 + expected['ip_dst_addr'] = '120.0.0.0' + expected['ip_dst_addr_max'] = '120.0.0.0' + expected['ip_dst_count'] = 1 + with pytest.raises(TrafficClientException): + _check_device_udp_flow_config(param, [expected]) + + +def test_device_udp_flow_config_scc3(): + param = __get_udp_params() + expected = __get_udp_expected_list() + + param['scc'] = 3 + param['udp_src_port'] = [49000, 49031] + param['udp_dst_port'] = [50000, 50033] + param['ip_src_static'] = False + param['flow_count'] = 10000 + param['ip_src_addr'] = '110.0.0.0/16' + param['ip_dst_addr'] = '120.0.0.0/16' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 49000 + expected_scc0['udp_src_port_max'] = 49016 + expected_scc0['udp_dst_port'] = 50000 + expected_scc0['udp_dst_port_max'] = 50033 + expected_scc0['udp_src_count'] = 17 + expected_scc0['udp_dst_count'] = 34 + expected_scc0['ip_src_addr_max'] = '110.0.6.129' + expected_scc0['ip_src_count'] = 1666 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.6.129' + expected_scc0['ip_dst_count'] = 1666 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 49000 + expected_scc1['udp_src_port_max'] = 49000 + expected_scc1['udp_dst_port'] = 50000 + expected_scc1['udp_dst_port_max'] = 50000 + expected_scc1['udp_src_count'] = 1 + expected_scc1['udp_dst_count'] = 1 + expected_scc1['ip_src_addr'] = '110.0.6.130' + expected_scc1['ip_src_addr_max'] = '110.0.13.4' + expected_scc1['ip_src_count'] = 1667 + expected_scc1['ip_dst_addr'] = '120.0.6.130' + expected_scc1['ip_dst_addr_max'] = '120.0.13.4' + expected_scc1['ip_dst_count'] = 1667 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 49000 + expected_scc2['udp_src_port_max'] = 49000 + expected_scc2['udp_dst_port'] = 50000 + expected_scc2['udp_dst_port_max'] = 50000 + expected_scc2['udp_src_count'] = 1 + expected_scc2['udp_dst_count'] = 1 + expected_scc2['ip_src_addr'] = '110.0.13.5' + expected_scc2['ip_src_addr_max'] = '110.0.19.135' + expected_scc2['ip_src_count'] = 1667 + expected_scc2['ip_dst_addr'] = '120.0.13.5' + expected_scc2['ip_dst_addr_max'] = '120.0.19.135' + expected_scc2['ip_dst_count'] = 1667 + expected_cfg.append(expected_scc2) + + _check_device_udp_flow_config(param, expected_cfg) + + +def test_device_udp_flow_config_doc_example1(caplog): + caplog.clear() + caplog.set_level(logging.INFO) + param = __get_udp_params() + expected = __get_udp_expected_list() + + # Multiflow unitary test corresponding to first example in documentation + param['scc'] = 3 + param['udp_src_port'] = 53 + param['udp_dst_port'] = 53 + param['ip_src_static'] = True + param['flow_count'] = 100 + param['ip_src_addr'] = '110.0.0.0/8' + param['ip_dst_addr'] = '120.0.0.0/8' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 53 + expected_scc0['udp_src_port_max'] = 53 + expected_scc0['udp_dst_port'] = 53 + expected_scc0['udp_dst_port_max'] = 53 + expected_scc0['udp_src_count'] = 1 + expected_scc0['udp_dst_count'] = 1 + expected_scc0['ip_src_addr'] = '110.0.0.0' + expected_scc0['ip_src_addr_max'] = '110.0.0.0' + expected_scc0['ip_src_count'] = 1 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.0.15' + expected_scc0['ip_dst_count'] = 16 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 53 + expected_scc1['udp_src_port_max'] = 53 + expected_scc1['udp_dst_port'] = 53 + expected_scc1['udp_dst_port_max'] = 53 + expected_scc1['udp_src_count'] = 1 + expected_scc1['udp_dst_count'] = 1 + expected_scc1['ip_src_addr'] = '110.0.0.1' + expected_scc1['ip_src_addr_max'] = '110.0.0.1' + expected_scc1['ip_src_count'] = 1 + expected_scc1['ip_dst_addr'] = '120.0.0.16' + expected_scc1['ip_dst_addr_max'] = '120.0.0.32' + expected_scc1['ip_dst_count'] = 17 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 53 + expected_scc2['udp_src_port_max'] = 53 + expected_scc2['udp_dst_port'] = 53 + expected_scc2['udp_dst_port_max'] = 53 + expected_scc2['udp_src_count'] = 1 + expected_scc2['udp_dst_count'] = 1 + expected_scc2['ip_src_addr'] = '110.0.0.2' + expected_scc2['ip_src_addr_max'] = '110.0.0.2' + expected_scc2['ip_src_count'] = 1 + expected_scc2['ip_dst_addr'] = '120.0.0.33' + expected_scc2['ip_dst_addr_max'] = '120.0.0.49' + expected_scc2['ip_dst_count'] = 17 + expected_cfg.append(expected_scc2) + + _check_device_udp_flow_config(param, expected_cfg) + assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text + + +def test_device_udp_flow_config_doc_example2(caplog): + caplog.clear() + caplog.set_level(logging.INFO) + param = __get_udp_params() + expected = __get_udp_expected_list() + + # Multiflow unitary test corresponding to second example in documentation + param['scc'] = 3 + param['udp_src_port'] = 53 + param['udp_dst_port'] = 53 + param['ip_src_static'] = True + param['ip_addrs_step'] = 'random' + param['flow_count'] = 100 + param['ip_src_addr'] = '110.0.0.0/8' + param['ip_dst_addr'] = '120.0.0.0/8' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 53 + expected_scc0['udp_src_port_max'] = 53 + expected_scc0['udp_dst_port'] = 53 + expected_scc0['udp_dst_port_max'] = 53 + expected_scc0['udp_src_count'] = 1 + expected_scc0['udp_dst_count'] = 1 + expected_scc0['ip_src_addr'] = '110.0.0.0' + expected_scc0['ip_src_addr_max'] = '110.0.0.0' + expected_scc0['ip_src_count'] = 1 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.0.15' + expected_scc0['ip_dst_count'] = 16 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 53 + expected_scc1['udp_src_port_max'] = 53 + expected_scc1['udp_dst_port'] = 53 + expected_scc1['udp_dst_port_max'] = 53 + expected_scc1['udp_src_count'] = 1 + expected_scc1['udp_dst_count'] = 1 + expected_scc1['ip_src_addr'] = '110.0.0.1' + expected_scc1['ip_src_addr_max'] = '110.0.0.1' + expected_scc1['ip_src_count'] = 1 + expected_scc1['ip_dst_addr'] = '120.0.0.16' + expected_scc1['ip_dst_addr_max'] = '120.0.0.32' + expected_scc1['ip_dst_count'] = 17 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 53 + expected_scc2['udp_src_port_max'] = 53 + expected_scc2['udp_dst_port'] = 53 + expected_scc2['udp_dst_port_max'] = 53 + expected_scc2['udp_src_count'] = 1 + expected_scc2['udp_dst_count'] = 1 + expected_scc2['ip_src_addr'] = '110.0.0.2' + expected_scc2['ip_src_addr_max'] = '110.0.0.2' + expected_scc2['ip_src_count'] = 1 + expected_scc2['ip_dst_addr'] = '120.0.0.33' + expected_scc2['ip_dst_addr_max'] = '120.0.0.49' + expected_scc2['ip_dst_count'] = 17 + expected_cfg.append(expected_scc2) + + _check_device_udp_flow_config(param, expected_cfg) + assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text + + +def test_device_udp_flow_config_doc_example3(caplog): + caplog.clear() + param = __get_udp_params() + expected = __get_udp_expected_list() + + # Multiflow unitary test corresponding to third example in documentation + param['scc'] = 3 + param['udp_src_port'] = 53 + param['udp_dst_port'] = 53 + param['ip_src_static'] = True + param['ip_addrs_step'] = '0.0.0.5' + param['flow_count'] = 100 + param['ip_src_addr'] = '110.0.0.0/8' + param['ip_dst_addr'] = '120.0.0.0/8' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 53 + expected_scc0['udp_src_port_max'] = 53 + expected_scc0['udp_dst_port'] = 53 + expected_scc0['udp_dst_port_max'] = 53 + expected_scc0['udp_src_count'] = 1 + expected_scc0['udp_dst_count'] = 1 + expected_scc0['ip_src_addr'] = '110.0.0.0' + expected_scc0['ip_src_addr_max'] = '110.0.0.0' + expected_scc0['ip_src_count'] = 1 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.0.75' + expected_scc0['ip_dst_count'] = 16 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 53 + expected_scc1['udp_src_port_max'] = 53 + expected_scc1['udp_dst_port'] = 53 + expected_scc1['udp_dst_port_max'] = 53 + expected_scc1['udp_src_count'] = 1 + expected_scc1['udp_dst_count'] = 1 + expected_scc1['ip_src_addr'] = '110.0.0.5' + expected_scc1['ip_src_addr_max'] = '110.0.0.5' + expected_scc1['ip_src_count'] = 1 + expected_scc1['ip_dst_addr'] = '120.0.0.80' + expected_scc1['ip_dst_addr_max'] = '120.0.0.160' + expected_scc1['ip_dst_count'] = 17 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 53 + expected_scc2['udp_src_port_max'] = 53 + expected_scc2['udp_dst_port'] = 53 + expected_scc2['udp_dst_port_max'] = 53 + expected_scc2['udp_src_count'] = 1 + expected_scc2['udp_dst_count'] = 1 + expected_scc2['ip_src_addr'] = '110.0.0.10' + expected_scc2['ip_src_addr_max'] = '110.0.0.10' + expected_scc2['ip_src_count'] = 1 + expected_scc2['ip_dst_addr'] = '120.0.0.165' + expected_scc2['ip_dst_addr_max'] = '120.0.0.245' + expected_scc2['ip_dst_count'] = 17 + expected_cfg.append(expected_scc2) + + caplog.set_level(logging.INFO) + _check_device_udp_flow_config(param, expected_cfg) + assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text + + +def test_device_udp_flow_config_doc_example4(caplog): + caplog.clear() + param = __get_udp_params() + expected = __get_udp_expected_list() + + # Multiflow unitary test corresponding to fourth example in documentation + param['scc'] = 3 + param['udp_src_port'] = [10, 14] + param['udp_dst_port'] = [20, 25] + param['ip_src_static'] = True + param['ip_addrs_step'] = '0.0.0.1' + param['udp_port_step'] = 'random' + param['flow_count'] = 100 + param['ip_src_addr'] = '110.0.0.0/29' + param['ip_dst_addr'] = '120.0.0.0/30' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 10 + expected_scc0['udp_src_port_max'] = 14 + expected_scc0['udp_dst_port'] = 20 + expected_scc0['udp_dst_port_max'] = 25 + expected_scc0['udp_src_count'] = 5 + expected_scc0['udp_dst_count'] = 6 + expected_scc0['ip_src_addr'] = '110.0.0.0' + expected_scc0['ip_src_addr_max'] = '110.0.0.0' + expected_scc0['ip_src_count'] = 1 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.0.0' + expected_scc0['ip_dst_count'] = 1 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 10 + expected_scc1['udp_src_port_max'] = 14 + expected_scc1['udp_dst_port'] = 20 + expected_scc1['udp_dst_port_max'] = 25 + expected_scc1['udp_src_count'] = 5 + expected_scc1['udp_dst_count'] = 6 + expected_scc1['ip_src_addr'] = '110.0.0.1' + expected_scc1['ip_src_addr_max'] = '110.0.0.1' + expected_scc1['ip_src_count'] = 1 + expected_scc1['ip_dst_addr'] = '120.0.0.1' + expected_scc1['ip_dst_addr_max'] = '120.0.0.1' + expected_scc1['ip_dst_count'] = 1 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 10 + expected_scc2['udp_src_port_max'] = 14 + expected_scc2['udp_dst_port'] = 20 + expected_scc2['udp_dst_port_max'] = 25 + expected_scc2['udp_src_count'] = 5 + expected_scc2['udp_dst_count'] = 6 + expected_scc2['ip_src_addr'] = '110.0.0.2' + expected_scc2['ip_src_addr_max'] = '110.0.0.2' + expected_scc2['ip_src_count'] = 1 + expected_scc2['ip_dst_addr'] = '120.0.0.2' + expected_scc2['ip_dst_addr_max'] = '120.0.0.2' + expected_scc2['ip_dst_count'] = 1 + expected_cfg.append(expected_scc2) + caplog.set_level(logging.INFO) + _check_device_udp_flow_config(param, expected_cfg) + assert "Current values of ip_addrs_step and/or udp_port_step properties" in caplog.text + assert "udp_port_step='1' (previous value: udp_port_step='random'" in caplog.text + + +def test_device_udp_flow_config_no_random_steps_overridden(caplog): + caplog.clear() + param = __get_udp_params() + expected = __get_udp_expected_list() + + # Multiflow unitary test corresponding to fifth example in documentation + param['scc'] = 3 + param['udp_src_port'] = [10, 14] + param['udp_dst_port'] = [20, 25] + param['ip_src_static'] = True + param['ip_addrs_step'] = 'random' + param['udp_port_step'] = 'random' + param['flow_count'] = 100 + param['ip_src_addr'] = '110.0.0.0/29' + param['ip_dst_addr'] = '120.0.0.0/30' + + expected_cfg = [] + # chain 0 + expected_scc0 = dict(expected) + expected_scc0['udp_src_port'] = 10 + expected_scc0['udp_src_port_max'] = 14 + expected_scc0['udp_dst_port'] = 20 + expected_scc0['udp_dst_port_max'] = 25 + expected_scc0['udp_src_count'] = 5 + expected_scc0['udp_dst_count'] = 6 + expected_scc0['ip_src_addr'] = '110.0.0.0' + expected_scc0['ip_src_addr_max'] = '110.0.0.0' + expected_scc0['ip_src_count'] = 1 + expected_scc0['ip_dst_addr'] = '120.0.0.0' + expected_scc0['ip_dst_addr_max'] = '120.0.0.0' + expected_scc0['ip_dst_count'] = 1 + expected_cfg.append(expected_scc0) + + # chain 1 + expected_scc1 = dict(expected) + expected_scc1['udp_src_port'] = 10 + expected_scc1['udp_src_port_max'] = 14 + expected_scc1['udp_dst_port'] = 20 + expected_scc1['udp_dst_port_max'] = 25 + expected_scc1['udp_src_count'] = 5 + expected_scc1['udp_dst_count'] = 6 + expected_scc1['ip_src_addr'] = '110.0.0.1' + expected_scc1['ip_src_addr_max'] = '110.0.0.1' + expected_scc1['ip_src_count'] = 1 + expected_scc1['ip_dst_addr'] = '120.0.0.1' + expected_scc1['ip_dst_addr_max'] = '120.0.0.1' + expected_scc1['ip_dst_count'] = 1 + expected_cfg.append(expected_scc1) + + # chain 2 + expected_scc2 = dict(expected) + expected_scc2['udp_src_port'] = 10 + expected_scc2['udp_src_port_max'] = 14 + expected_scc2['udp_dst_port'] = 20 + expected_scc2['udp_dst_port_max'] = 25 + expected_scc2['udp_src_count'] = 5 + expected_scc2['udp_dst_count'] = 6 + expected_scc2['ip_src_addr'] = '110.0.0.2' + expected_scc2['ip_src_addr_max'] = '110.0.0.2' + expected_scc2['ip_src_count'] = 1 + expected_scc2['ip_dst_addr'] = '120.0.0.2' + expected_scc2['ip_dst_addr_max'] = '120.0.0.2' + expected_scc2['ip_dst_count'] = 1 + expected_cfg.append(expected_scc2) + caplog.set_level(logging.INFO) + _check_device_udp_flow_config(param, expected_cfg) + assert "Current values of ip_addrs_step and/or udp_port_step properties" not in caplog.text def test_config(): @@ -534,7 +989,7 @@ def test_config(): expected = fail_pair[1] if expected is None: expected = fail_pair[0] - assert expected in e_info.value.message + assert expected in str(e_info) # whitelist keys flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0, @@ -596,7 +1051,9 @@ def assert_ndr_pdr(stats, ndr, ndr_dr, pdr, pdr_dr): assert_equivalence(pdr, stats['pdr']['rate_percent']) assert_equivalence(pdr_dr, stats['pdr']['stats']['overall']['drop_percentage']) -def get_dummy_tg_config(chain_type, rate): +def _get_dummy_tg_config(chain_type, rate, scc=1, fc=10, step_ip='0.0.0.1', + ip0='10.0.0.0/8', ip1='20.0.0.0/8', + step_udp='1', src_udp=None, dst_udp=None, ip_src_static=True): return AttrDict({ 'traffic_generator': {'host_name': 'nfvbench_tg', 'default_profile': 'dummy', @@ -606,19 +1063,25 @@ def get_dummy_tg_config(chain_type, rate): 'intf_speed': '10Gbps', 'interfaces': [{'port': 0, 'pci': '0.0'}, {'port': 1, 'pci': '0.0'}]}], - 'ip_addrs_step': '0.0.0.1', - 'ip_addrs': ['10.0.0.0/8', '20.0.0.0/8'], + 'ip_addrs_step': step_ip, + 'ip_addrs': [ip0, ip1], + 'ip_src_static': ip_src_static, 'tg_gateway_ip_addrs': ['1.1.0.100', '2.2.0.100'], - 'tg_gateway_ip_addrs_step': '0.0.0.1', + 'tg_gateway_ip_addrs_step': step_ip, 'gateway_ip_addrs': ['1.1.0.2', '2.2.0.2'], - 'gateway_ip_addrs_step': '0.0.0.1', + 'gateway_ip_addrs_step': step_ip, 'mac_addrs_left': None, 'mac_addrs_right': None, - 'udp_src_port': None, - 'udp_dst_port': None}, + 'udp_src_port': src_udp, + 'udp_dst_port': dst_udp, + 'udp_port_step': step_udp}, + 'traffic': {'profile': 'profile_64', + 'bidirectional': True}, + 'traffic_profile': [{'name': 'profile_64', 'l2frame_size': ['64']}], + 'generator_profile': None, 'service_chain': chain_type, - 'service_chain_count': 1, - 'flow_count': 10, + 'service_chain_count': scc, + 'flow_count': fc, 'vlan_tagging': True, 'no_arp': False, 'duration_sec': 1, @@ -628,43 +1091,61 @@ def get_dummy_tg_config(chain_type, rate): 'check_traffic_time_sec': 200, 'generic_poll_sec': 2, 'measurement': {'NDR': 0.001, 'PDR': 0.1, 'load_epsilon': 0.1}, - 'l2_loopback': False + 'l2_loopback': False, + 'cores': None, + 'mbuf_factor': None, + 'disable_hdrh': None, + 'mbuf_64': None, + 'service_mode': False, + 'no_flow_stats': False, + 'no_latency_stats': False, + 'no_latency_streams': False, + 'intf_speed': '10Gbps', + 'periodic_gratuitous_arp': False, + 'gratuitous_arp_pps': 1 }) -def get_traffic_client(): - config = get_dummy_tg_config('PVP', 'ndr_pdr') +def _get_traffic_client(user_info=None): + config = _get_dummy_tg_config('PVP', 'ndr_pdr') + config['vxlan'] = False + config['mpls'] = False config['ndr_run'] = True config['pdr_run'] = True config['generator_profile'] = 'dummy' config['single_run'] = False - generator_factory = TrafficGeneratorFactory(config) - config.generator_config = generator_factory.get_generator_config(config.generator_profile) - traffic_client = TrafficClient(config, skip_sleep=True) + if user_info: + config['user_info'] = user_info + traffic_client = TrafficClient(config) traffic_client.start_traffic_generator() traffic_client.set_traffic('64', True) return traffic_client +@patch.object(TrafficClient, 'skip_sleep', lambda x: True) def test_ndr_at_lr(): - traffic_client = get_traffic_client() + """Test NDR at line rate.""" + traffic_client = _get_traffic_client() tg = traffic_client.gen - # this is a perfect sut with no loss at LR tg.set_response_curve(lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100) # tx packets should be line rate for 64B and no drops... assert tg.get_tx_pps_dropped_pps(100) == (LR_64B_PPS, 0) # NDR and PDR should be at 100% - traffic_client.ensure_end_to_end() + # traffic_client.ensure_end_to_end() results = traffic_client.get_ndr_and_pdr() - assert_ndr_pdr(results, 200.0, 0.0, 200.0, 0.0) +@patch.object(TrafficClient, 'skip_sleep', lambda x: True) def test_ndr_at_50(): - traffic_client = get_traffic_client() + """Test NDR at 50% line rate. + + This is a sut with an NDR of 50% and linear drop rate after NDR up to 20% drops at LR + (meaning that if you send 100% TX, you will only receive 80% RX) + the tg requested TX/actual TX ratio is up to 50%, after 50% + is linear up 80% actuak TX when requesting 100% + """ + traffic_client = _get_traffic_client() tg = traffic_client.gen - # this is a sut with an NDR of 50% and linear drop rate after NDR up to 20% drops at LR - # (meaning that if you send 100% TX, you will only receive 80% RX) - # the tg requested TX/actual TX ratio is 1up to 50%, after 50% - # is linear up 80% actuak TX when requesting 100% + tg.set_response_curve(lr_dr=20, ndr=50, max_actual_tx=80, max_11_tx=50) # tx packets should be half line rate for 64B and no drops... assert tg.get_tx_pps_dropped_pps(50) == (LR_64B_PPS / 2, 0) @@ -674,12 +1155,16 @@ def test_ndr_at_50(): results = traffic_client.get_ndr_and_pdr() assert_ndr_pdr(results, 100.0, 0.0, 100.781, 0.09374) +@patch.object(TrafficClient, 'skip_sleep', lambda x: True) def test_ndr_pdr_low_cpu(): - traffic_client = get_traffic_client() + """Test NDR and PDR with too low cpu. + + This test is for the case where the TG is underpowered and cannot send fast enough for the NDR + true NDR=40%, actual TX at 50% = 30%, actual measured DR is 0% + The ndr/pdr should bail out with a warning and a best effort measured NDR of 30% + """ + traffic_client = _get_traffic_client() tg = traffic_client.gen - # This test is for the case where the TG is underpowered and cannot send fast enough for the NDR - # true NDR=40%, actual TX at 50% = 30%, actual measured DR is 0% - # The ndr/pdr should bail out with a warning and a best effort measured NDR of 30% tg.set_response_curve(lr_dr=50, ndr=40, max_actual_tx=60, max_11_tx=0) # tx packets should be 30% at requested half line rate for 64B and no drops... assert tg.get_tx_pps_dropped_pps(50) == (int(LR_64B_PPS * 0.3), 0) @@ -689,11 +1174,31 @@ def test_ndr_pdr_low_cpu(): # pp = pprint.PrettyPrinter(indent=4) # pp.pprint(results) -import nfvbench.nfvbench +@patch.object(TrafficClient, 'skip_sleep', lambda x: True) +def test_ndr_at_lr_sdn_gw_encapsulation(): + """Test NDR at line rate with traffic gen outside SUT and connected via SDN GW.""" + user_info = {'extra_encapsulation_bytes': 28} + traffic_client = _get_traffic_client(user_info) + tg = traffic_client.gen + # this is a perfect sut with no loss at LR + tg.set_response_curve(lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100) + # tx packets should be line rate for 64B and no drops... + assert tg.get_tx_pps_dropped_pps(100) == (LR_64B_PPS, 0) + # NDR and PDR should be at 100% + # traffic_client.ensure_end_to_end() + results = traffic_client.get_ndr_and_pdr() + assert results['ndr']['stats']['theoretical_tx_rate_bps'] == 15000000000.0 + assert_ndr_pdr(results, 200.0, 0.0, 200.0, 0.0) +@patch.object(TrafficClient, 'skip_sleep', lambda x: True) def test_no_openstack(): - config = get_dummy_tg_config('EXT', '1000pps') + """Test nfvbench using main.""" + config = _get_dummy_tg_config('EXT', '1000pps') config.openrc_file = None + config.vlans = [[100], [200]] + config['traffic_generator']['mac_addrs_left'] = ['00:00:00:00:00:00'] + config['traffic_generator']['mac_addrs_right'] = ['00:00:00:00:01:00'] + del config['generator_profile'] old_argv = sys.argv sys.argv = [old_argv[0], '-c', json.dumps(config)] nfvbench.nfvbench.main()