From 21261ea231082d76caf2c21f70e9550061f15d6f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 12:16:56 +0900 Subject: [PATCH 01/10] network/qdisc: introduce is_ready() in qdisc vtable Preparation for next commit. --- src/network/tc/qdisc.c | 13 ++++++++++--- src/network/tc/qdisc.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 6aef268d1f..8f8a7408a5 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -353,10 +353,17 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) { if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return false; - if (IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT)) /* TC_H_CLSACT == TC_H_INGRESS */ - return true; + /* TC_H_CLSACT == TC_H_INGRESS */ + if (!IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT) && + link_find_tclass(link, qdisc->parent, NULL) < 0) + return false; - return link_find_tclass(link, qdisc->parent, NULL) >= 0; + if (QDISC_VTABLE(qdisc) && + QDISC_VTABLE(qdisc)->is_ready && + QDISC_VTABLE(qdisc)->is_ready(qdisc, link) <= 0) + return false; + + return true; } static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index adaaf260c4..155e2adf24 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -56,6 +56,7 @@ typedef struct QDiscVTable { int (*init)(QDisc *qdisc); int (*fill_message)(Link *link, QDisc *qdisc, sd_netlink_message *m); int (*verify)(QDisc *qdisc); + int (*is_ready)(QDisc *qdisc, Link *link); } QDiscVTable; extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX]; From 9b2a2e06c470df1af01f636bc549103968b6275c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 12:32:23 +0900 Subject: [PATCH 02/10] network/teql: wait for corresponding teql interface to be available --- src/network/tc/teql.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/network/tc/teql.c b/src/network/tc/teql.c index 1422860f55..9fd9e09006 100644 --- a/src/network/tc/teql.c +++ b/src/network/tc/teql.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "macro.h" +#include "networkd-link.h" #include "parse-util.h" #include "string-util.h" #include "teql.h" @@ -17,9 +18,24 @@ static int trivial_link_equalizer_verify(QDisc *qdisc) { return free_and_replace(qdisc->tca_kind, tca_kind); } +static int trivial_link_equalizer_is_ready(QDisc *qdisc, Link *link) { + Link *teql; + + assert(qdisc); + assert(qdisc->tca_kind); + assert(link); + assert(link->manager); + + if (link_get_by_name(link->manager, qdisc->tca_kind, &teql) < 0) + return false; + + return link_is_ready_to_configure(teql, /* allow_unmanaged = */ true); +} + const QDiscVTable teql_vtable = { .object_size = sizeof(TrivialLinkEqualizer), .verify = trivial_link_equalizer_verify, + .is_ready = trivial_link_equalizer_is_ready, }; int config_parse_trivial_link_equalizer_id( From 67a9b3ec94829d1dd26cdcc6490d9d4e1fde0efd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Jul 2022 09:47:41 +0900 Subject: [PATCH 03/10] test-network: use timedatectl in build directory --- test/test-network/systemd-networkd-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 9266441944..0ead5c8e64 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -497,14 +497,14 @@ def flush_l2tp_tunnels(): def save_timezone(): global saved_timezone - r = run('timedatectl show --value --property Timezone') + r = run(*timedatectl_cmd, 'show', '--value', '--property', 'Timezone', env=env) if r.returncode == 0: saved_timezone = r.stdout.rstrip() print(f'### Saved timezone: {saved_timezone}') def restore_timezone(): if saved_timezone: - call(f'timedatectl set-timezone {saved_timezone}') + call(*timedatectl_cmd, 'set-timezone', f'{saved_timezone}', env=env) def read_link_attr(*args): with open(os.path.join('/sys/class/net', *args), encoding='utf-8') as f: From b05c4d6bbfab37476d74054e92e57ba243c29ac7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Jul 2022 11:00:29 +0900 Subject: [PATCH 04/10] test-network: also run timesyncd under sanitizer or valgrind --- test/test-network/systemd-networkd-tests.py | 173 ++++++++++---------- 1 file changed, 84 insertions(+), 89 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0ead5c8e64..e0587bc89d 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -38,13 +38,16 @@ which_paths = ':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip( networkd_bin = shutil.which('systemd-networkd', path=which_paths) resolved_bin = shutil.which('systemd-resolved', path=which_paths) +timesyncd_bin = shutil.which('systemd-timesyncd', path=which_paths) udevd_bin = shutil.which('systemd-udevd', path=which_paths) wait_online_bin = shutil.which('systemd-networkd-wait-online', path=which_paths) networkctl_bin = shutil.which('networkctl', path=which_paths) resolvectl_bin = shutil.which('resolvectl', path=which_paths) timedatectl_bin = shutil.which('timedatectl', path=which_paths) +udevadm_bin = shutil.which('udevadm', path=which_paths) use_valgrind = False +valgrind_cmd = '' enable_debug = True env = {} wait_online_env = {} @@ -277,7 +280,7 @@ def expectedFailureIfFQPIEIsNotAvailable(): return f def udev_reload(): - check_output('udevadm control --reload') + check_output(*udevadm_cmd, 'control', '--reload') def copy_network_unit(*units, copy_dropins=True): """ @@ -371,7 +374,7 @@ def clear_udev_rules(): def save_active_units(): for u in ['systemd-networkd.socket', 'systemd-networkd.service', - 'systemd-resolved.service', + 'systemd-resolved.service', 'systemd-timesyncd.service', 'firewalld.service']: if call(f'systemctl is-active --quiet {u}') == 0: call(f'systemctl stop {u}') @@ -383,6 +386,46 @@ def restore_active_units(): for u in active_units: call(f'systemctl restart {u}') +def create_service_dropin(service, command, reload_command=None, additional_settings=None): + drop_in = [ + '[Service]', + 'ExecStart=', + f'ExecStart=!!{valgrind_cmd}{command}', + ] + if reload_command: + drop_in += [ + 'ExecReload=', + f'ExecReload={valgrind_cmd}{reload_command}', + ] + if enable_debug: + drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] + if asan_options: + drop_in += [f'Environment=ASAN_OPTIONS="{asan_options}"'] + if lsan_options: + drop_in += [f'Environment=LSAN_OPTIONS="{lsan_options}"'] + if ubsan_options: + drop_in += [f'Environment=UBSAN_OPTIONS="{ubsan_options}"'] + if asan_options or lsan_options or ubsan_options: + drop_in += ['SystemCallFilter='] + if use_valgrind or asan_options or lsan_options or ubsan_options: + drop_in += ['MemoryDenyWriteExecute=no'] + if use_valgrind: + drop_in += [ + 'Environment=SYSTEMD_MEMPOOL=0', + 'PrivateTmp=yes', + ] + if with_coverage: + drop_in += [ + 'ProtectSystem=no', + 'ProtectHome=no', + ] + if additional_settings: + drop_in += additional_settings + + mkdir_p(f'/run/systemd/system/{service}.service.d') + with open(f'/run/systemd/system/{service}.service.d/00-override.conf', mode='w', encoding='utf-8') as f: + f.write('\n'.join(drop_in)) + def link_exists(link): return os.path.exists(os.path.join('/sys/class/net', link, 'ifindex')) @@ -657,82 +700,21 @@ def setUpModule(): save_routing_policy_rules() save_timezone() + create_service_dropin('systemd-networkd', networkd_bin, + f'{networkctl_bin} reload', + ['[Service]', 'Restart=no', '[Unit]', 'StartLimitIntervalSec=0']) + create_service_dropin('systemd-resolved', resolved_bin) + create_service_dropin('systemd-timesyncd', timesyncd_bin) + + # TODO: also run udevd with sanitizers, valgrind, or coverage + #create_service_dropin('systemd-udevd', udevd_bin, + # f'{udevadm_bin} control --reload --timeout 0') drop_in = [ - '[Unit]', - 'StartLimitIntervalSec=0', '[Service]', - 'Restart=no', 'ExecStart=', + f'ExecStart=!!{udevd_bin}', 'ExecReload=', - ] - if use_valgrind: - drop_in += [ - 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin, - f'ExecReload=valgrind {networkctl_bin} reload', - 'PrivateTmp=yes' - ] - else: - drop_in += [ - 'ExecStart=!!' + networkd_bin, - f'ExecReload={networkctl_bin} reload', - ] - if enable_debug: - drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] - if asan_options: - drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] - if lsan_options: - drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] - if ubsan_options: - drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] - if asan_options or lsan_options or ubsan_options: - drop_in += ['SystemCallFilter='] - if use_valgrind or asan_options or lsan_options or ubsan_options: - drop_in += ['MemoryDenyWriteExecute=no'] - if with_coverage: - drop_in += [ - 'ProtectSystem=no', - 'ProtectHome=no', - ] - - mkdir_p('/run/systemd/system/systemd-networkd.service.d') - with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w', encoding='utf-8') as f: - f.write('\n'.join(drop_in)) - - drop_in = [ - '[Service]', - 'Restart=no', - 'ExecStart=', - ] - if use_valgrind: - drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin] - else: - drop_in += ['ExecStart=!!' + resolved_bin] - if enable_debug: - drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] - if asan_options: - drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] - if lsan_options: - drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] - if ubsan_options: - drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] - if asan_options or lsan_options or ubsan_options: - drop_in += ['SystemCallFilter='] - if use_valgrind or asan_options or lsan_options or ubsan_options: - drop_in += ['MemoryDenyWriteExecute=no'] - if with_coverage: - drop_in += [ - 'ProtectSystem=no', - 'ProtectHome=no', - ] - - mkdir_p('/run/systemd/system/systemd-resolved.service.d') - with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w', encoding='utf-8') as f: - f.write('\n'.join(drop_in)) - - drop_in = [ - '[Service]', - 'ExecStart=', - 'ExecStart=!!' + udevd_bin, + f'ExecReload={udevadm_bin} control --reload --timeout 0', ] mkdir_p('/run/systemd/system/systemd-udevd.service.d') @@ -742,8 +724,10 @@ def setUpModule(): check_output('systemctl daemon-reload') print(check_output('systemctl cat systemd-networkd.service')) print(check_output('systemctl cat systemd-resolved.service')) + print(check_output('systemctl cat systemd-timesyncd.service')) print(check_output('systemctl cat systemd-udevd.service')) check_output('systemctl restart systemd-resolved.service') + check_output('systemctl restart systemd-timesyncd.service') check_output('systemctl restart systemd-udevd.service') def tearDownModule(): @@ -756,6 +740,7 @@ def tearDownModule(): rm_rf('/run/systemd/system/systemd-networkd.service.d') rm_rf('/run/systemd/system/systemd-resolved.service.d') + rm_rf('/run/systemd/system/systemd-timesyncd.service.d') rm_rf('/run/systemd/system/systemd-udevd.service.d') check_output('systemctl daemon-reload') check_output('systemctl restart systemd-udevd.service') @@ -3952,7 +3937,7 @@ class NetworkdSRIOVTests(unittest.TestCase, Utilities): f.write('[Link]\nSR-IOVVirtualFunctions=4\n') udev_reload() - call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') + call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1') output = check_output('ip link show dev eni99np1') print(output) @@ -3968,7 +3953,7 @@ class NetworkdSRIOVTests(unittest.TestCase, Utilities): f.write('[Link]\nSR-IOVVirtualFunctions=\n') udev_reload() - call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') + call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1') output = check_output('ip link show dev eni99np1') print(output) @@ -3984,7 +3969,7 @@ class NetworkdSRIOVTests(unittest.TestCase, Utilities): f.write('[Link]\nSR-IOVVirtualFunctions=2\n') udev_reload() - call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') + call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1') output = check_output('ip link show dev eni99np1') print(output) @@ -4000,7 +3985,7 @@ class NetworkdSRIOVTests(unittest.TestCase, Utilities): f.write('[Link]\nSR-IOVVirtualFunctions=\n') udev_reload() - call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') + call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1') output = check_output('ip link show dev eni99np1') print(output) @@ -5307,11 +5292,13 @@ if __name__ == '__main__': parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir') parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin') parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin') + parser.add_argument('--timesyncd', help='Path to systemd-timesyncd', dest='timesyncd_bin') parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin') parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin') parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin') parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin') parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin') + parser.add_argument('--udevadm', help='Path to udevadm', dest='udevadm_bin') parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind) parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug) parser.add_argument('--asan-options', help='ASAN options', dest='asan_options') @@ -5321,20 +5308,25 @@ if __name__ == '__main__': ns, unknown_args = parser.parse_known_args(namespace=unittest) if ns.build_dir: - if ns.networkd_bin or ns.resolved_bin or ns.udevd_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin: - print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.') + if ns.networkd_bin or ns.resolved_bin or ns.timesyncd_bin or ns.udevd_bin or \ + ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin or ns.udevadm_bin: + print('WARNING: --networkd, --resolved, --timesyncd, --udevd, --wait-online, --networkctl, --resolvectl, --timedatectl, or --udevadm options are ignored when --build-dir is specified.') networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd') resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved') + timesyncd_bin = os.path.join(ns.build_dir, 'systemd-timesyncd') udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd') wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online') networkctl_bin = os.path.join(ns.build_dir, 'networkctl') resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl') timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl') + udevadm_bin = os.path.join(ns.build_dir, 'udevadm') else: if ns.networkd_bin: networkd_bin = ns.networkd_bin if ns.resolved_bin: resolved_bin = ns.resolved_bin + if ns.timesyncd_bin: + timesyncd_bin = ns.timesyncd_bin if ns.udevd_bin: udevd_bin = ns.udevd_bin if ns.wait_online_bin: @@ -5345,6 +5337,8 @@ if __name__ == '__main__': resolvectl_bin = ns.resolvectl_bin if ns.timedatectl_bin: timedatectl_bin = ns.timedatectl_bin + if ns.udevadm_bin: + udevadm_bin = ns.udevadm_bin use_valgrind = ns.use_valgrind enable_debug = ns.enable_debug @@ -5354,15 +5348,14 @@ if __name__ == '__main__': with_coverage = ns.with_coverage if use_valgrind: - networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin] - resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin] - timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin] - wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin] - else: - networkctl_cmd = [networkctl_bin] - resolvectl_cmd = [resolvectl_bin] - timedatectl_cmd = [timedatectl_bin] - wait_online_cmd = [wait_online_bin] + # Do not forget the trailing space. + valgrind_cmd = 'valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + + networkctl_cmd = valgrind_cmd.split() + [networkctl_bin] + resolvectl_cmd = valgrind_cmd.split() + [resolvectl_bin] + timedatectl_cmd = valgrind_cmd.split() + [timedatectl_bin] + udevadm_cmd = valgrind_cmd.split() + [udevadm_bin] + wait_online_cmd = valgrind_cmd.split() + [wait_online_bin] if asan_options: env.update({'ASAN_OPTIONS': asan_options}) @@ -5370,6 +5363,8 @@ if __name__ == '__main__': env.update({'LSAN_OPTIONS': lsan_options}) if ubsan_options: env.update({'UBSAN_OPTIONS': ubsan_options}) + if use_valgrind: + env.update({'SYSTEMD_MEMPOOL': '0'}) wait_online_env = env.copy() if enable_debug: From 66504b22e25c7e879b95431ecfc94dc238cc98c9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 06:20:28 +0900 Subject: [PATCH 05/10] test-network: drop unused text= arguments --- test/test-network/systemd-networkd-tests.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index e0587bc89d..cb014d67f3 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -95,24 +95,24 @@ def mkdir_p(path): def touch(path): pathlib.Path(path).touch() -def check_output(*command, text=True, **kwargs): +def check_output(*command, **kwargs): # This checks the result and returns stdout (and stderr) on success. command = command[0].split() + list(command[1:]) - return subprocess.run(command, check=True, universal_newlines=text, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs).stdout.rstrip() + return subprocess.run(command, check=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs).stdout.rstrip() -def call(*command, text=True, **kwargs): +def call(*command, **kwargs): # This returns returncode. stdout and stderr are merged and shown in console command = command[0].split() + list(command[1:]) - return subprocess.run(command, check=False, universal_newlines=text, stderr=subprocess.STDOUT, **kwargs).returncode + return subprocess.run(command, check=False, universal_newlines=True, stderr=subprocess.STDOUT, **kwargs).returncode -def call_quiet(*command, text=True, **kwargs): +def call_quiet(*command, **kwargs): command = command[0].split() + list(command[1:]) - return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode + return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode -def run(*command, text=True, **kwargs): +def run(*command, **kwargs): # This returns CompletedProcess instance. command = command[0].split() + list(command[1:]) - return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) def is_module_available(module_name): lsmod_output = check_output('lsmod') From 17479d51ccf05499405507b9e19ac1f026e8268b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 06:40:46 +0900 Subject: [PATCH 06/10] test-network: show stdout and stderr on failure in check_output() --- test/test-network/systemd-networkd-tests.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index cb014d67f3..60ed22291c 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -98,7 +98,12 @@ def touch(path): def check_output(*command, **kwargs): # This checks the result and returns stdout (and stderr) on success. command = command[0].split() + list(command[1:]) - return subprocess.run(command, check=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs).stdout.rstrip() + ret = subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs) + if ret.returncode == 0: + return ret.stdout.rstrip() + # When returncode != 0, print stdout and stderr, then trigger CalledProcessError. + print(ret.stdout) + ret.check_returncode() def call(*command, **kwargs): # This returns returncode. stdout and stderr are merged and shown in console @@ -871,7 +876,7 @@ class Utilities(): try: check_output(*args, env=wait_online_env) except subprocess.CalledProcessError as e: - print(e.stdout) # show logs only on failure + # show detailed status on failure for link in links_with_operstate: name = link.split(':')[0] if link_exists(name): From 5cdc7c89cb437eb46fb24ad62b9792c1b8aa4d69 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 07:04:19 +0900 Subject: [PATCH 07/10] test-network: rename tun99 and tap99 The names seem to be used in AWS. This also merges test_tun() and test_tap(). --- test/test-network/conf/25-tap.netdev | 2 +- test/test-network/conf/25-tun.netdev | 2 +- test/test-network/systemd-networkd-tests.py | 16 +++++----------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/test/test-network/conf/25-tap.netdev b/test/test-network/conf/25-tap.netdev index 5c1f97be9e..f52d255560 100644 --- a/test/test-network/conf/25-tap.netdev +++ b/test/test-network/conf/25-tap.netdev @@ -1,6 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later [NetDev] -Name=tap99 +Name=testtap99 Kind=tap [Tap] diff --git a/test/test-network/conf/25-tun.netdev b/test/test-network/conf/25-tun.netdev index ed25026a95..8ab2f5a038 100644 --- a/test/test-network/conf/25-tun.netdev +++ b/test/test-network/conf/25-tun.netdev @@ -1,6 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later [NetDev] -Name=tun99 +Name=testtun99 Kind=tun [Tun] diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 60ed22291c..9bff088a18 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1352,24 +1352,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertRegex(output, 'link/ether 12:34:56:78:9a:bf') self.assertRegex(output, 'mtu 1800') - def test_tun(self): - copy_network_unit('25-tun.netdev') + def test_tuntap(self): + copy_network_unit('25-tun.netdev', '25-tap.netdev') start_networkd() - self.wait_online(['tun99:off'], setup_state='unmanaged') + self.wait_online(['testtun99:off', 'testtap99:off'], setup_state='unmanaged') - output = check_output('ip -d link show tun99') + output = check_output('ip -d link show testtun99') print(output) # Old ip command does not support IFF_ flags self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ') - def test_tap(self): - copy_network_unit('25-tap.netdev') - start_networkd() - - self.wait_online(['tap99:off'], setup_state='unmanaged') - - output = check_output('ip -d link show tap99') + output = check_output('ip -d link show testtap99') print(output) # Old ip command does not support IFF_ flags self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ') From 854f98995813669c9fa2951506899ca3896b6316 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 08:22:52 +0900 Subject: [PATCH 08/10] test-network: check qdisc feature by module existence --- test/test-network/systemd-networkd-tests.py | 55 ++------------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 9bff088a18..3302939626 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -239,51 +239,6 @@ def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable(): return f -def expectedFailureIfCAKEIsNotAvailable(): - def f(func): - call_quiet('ip link add dummy98 type dummy') - rc = call_quiet('tc qdisc add dev dummy98 parent root cake') - remove_link('dummy98') - return func if rc == 0 else unittest.expectedFailure(func) - - return f - -def expectedFailureIfPIEIsNotAvailable(): - def f(func): - call_quiet('ip link add dummy98 type dummy') - rc = call_quiet('tc qdisc add dev dummy98 parent root pie') - remove_link('dummy98') - return func if rc == 0 else unittest.expectedFailure(func) - - return f - -def expectedFailureIfHHFIsNotAvailable(): - def f(func): - call_quiet('ip link add dummy98 type dummy') - rc = call_quiet('tc qdisc add dev dummy98 parent root hhf') - remove_link('dummy98') - return func if rc == 0 else unittest.expectedFailure(func) - - return f - -def expectedFailureIfETSIsNotAvailable(): - def f(func): - call_quiet('ip link add dummy98 type dummy') - rc = call_quiet('tc qdisc add dev dummy98 parent root ets bands 10') - remove_link('dummy98') - return func if rc == 0 else unittest.expectedFailure(func) - - return f - -def expectedFailureIfFQPIEIsNotAvailable(): - def f(func): - call_quiet('ip link add dummy98 type dummy') - rc = call_quiet('tc qdisc add dev dummy98 parent root fq_pie') - remove_link('dummy98') - return func if rc == 0 else unittest.expectedFailure(func) - - return f - def udev_reload(): check_output(*udevadm_cmd, 'control', '--reload') @@ -3367,7 +3322,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000') self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000') - @expectedFailureIfCAKEIsNotAvailable() + @expectedFailureIfModuleIsNotAvailable('sch_cake') def test_qdisc_cake(self): copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev') start_networkd() @@ -3389,7 +3344,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertIn('mpu 20', output) self.assertIn('fwmark 0xff00', output) - @expectedFailureIfPIEIsNotAvailable() + @expectedFailureIfModuleIsNotAvailable('sch_pie') def test_qdisc_pie(self): copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev') start_networkd() @@ -3400,7 +3355,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'qdisc pie 3a: root') self.assertRegex(output, 'limit 200000') - @expectedFailureIfHHFIsNotAvailable() + @expectedFailureIfModuleIsNotAvailable('sch_hhf') def test_qdisc_hhf(self): copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev') start_networkd() @@ -3411,7 +3366,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'qdisc hhf 3a: root') self.assertRegex(output, 'limit 1022p') - @expectedFailureIfETSIsNotAvailable() + @expectedFailureIfModuleIsNotAvailable('sch_ets') def test_qdisc_ets(self): copy_network_unit('25-qdisc-ets.network', '12-dummy.netdev') start_networkd() @@ -3425,7 +3380,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'quanta 1 2 3 4 5') self.assertRegex(output, 'priomap 3 4 5 6 7') - @expectedFailureIfFQPIEIsNotAvailable() + @expectedFailureIfModuleIsNotAvailable('sch_fq_pie') def test_qdisc_fq_pie(self): copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev') start_networkd() From 4c7d13f4b2180ae03c63814f4793b099722daaaf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 11:22:06 +0900 Subject: [PATCH 09/10] test-network: split test_qdisc() and test_qdisc2() And check module availability in each tests. This also sorts qdisc tests. --- .../conf/25-qdisc-clsact-and-htb.network | 204 ------------ .../test-network/conf/25-qdisc-clsact.network | 10 + test/test-network/conf/25-qdisc-codel.network | 16 + test/test-network/conf/25-qdisc-fq.network | 20 ++ .../conf/25-qdisc-fq_codel.network | 19 ++ test/test-network/conf/25-qdisc-gred.network | 14 + .../conf/25-qdisc-htb-fifo.network | 65 ++++ .../conf/25-qdisc-ingress.network | 10 + ....network => 25-qdisc-netem-compat.network} | 3 - test/test-network/conf/25-qdisc-netem.network | 15 + test/test-network/conf/25-qdisc-qfq.network | 4 +- test/test-network/conf/25-qdisc-sfb.network | 12 + test/test-network/conf/25-qdisc-sfq.network | 12 + test/test-network/conf/25-qdisc-tbf.network | 16 + test/test-network/conf/25-qdisc-teql.network | 12 + test/test-network/systemd-networkd-tests.py | 307 +++++++++++------- 16 files changed, 418 insertions(+), 321 deletions(-) delete mode 100644 test/test-network/conf/25-qdisc-clsact-and-htb.network create mode 100644 test/test-network/conf/25-qdisc-clsact.network create mode 100644 test/test-network/conf/25-qdisc-codel.network create mode 100644 test/test-network/conf/25-qdisc-fq.network create mode 100644 test/test-network/conf/25-qdisc-fq_codel.network create mode 100644 test/test-network/conf/25-qdisc-gred.network create mode 100644 test/test-network/conf/25-qdisc-htb-fifo.network create mode 100644 test/test-network/conf/25-qdisc-ingress.network rename test/test-network/conf/{25-qdisc-ingress-netem-compat.network => 25-qdisc-netem-compat.network} (84%) create mode 100644 test/test-network/conf/25-qdisc-netem.network create mode 100644 test/test-network/conf/25-qdisc-sfb.network create mode 100644 test/test-network/conf/25-qdisc-sfq.network create mode 100644 test/test-network/conf/25-qdisc-tbf.network create mode 100644 test/test-network/conf/25-qdisc-teql.network diff --git a/test/test-network/conf/25-qdisc-clsact-and-htb.network b/test/test-network/conf/25-qdisc-clsact-and-htb.network deleted file mode 100644 index c91666d323..0000000000 --- a/test/test-network/conf/25-qdisc-clsact-and-htb.network +++ /dev/null @@ -1,204 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Match] -Name=dummy98 - -[Network] -IPv6AcceptRA=no -Address=10.1.2.3/16 - -[QDisc] -Parent=clsact - -[HierarchyTokenBucket] -Parent=root -Handle=0002 -DefaultClass=30 -RateToQuantum=20 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0030 -Priority=1 -QuantumBytes=4000 -MTUBytes=1700 -OverheadBytes=100 -Rate=1M -BufferBytes=123456 -CeilRate=0.5M -CeilBufferBytes=123457 - -[NetworkEmulator] -Parent=2:30 -Handle=0030 -DelaySec=50ms -DelayJitterSec=10ms -LossRate=20% -PacketLimit=100 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0031 -Priority=1 -Rate=1M -CeilRate=0.5M - -[TrivialLinkEqualizer] -Parent=2:31 -Handle=0031 -Id=1 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0032 -Priority=1 -Rate=1M -CeilRate=0.5M - -[FairQueueing] -Parent=2:32 -Handle=0032 -PacketLimit=1000 -FlowLimit=200 -QuantumBytes=1500 -InitialQuantumBytes=13000 -MaximumRate=1M -Buckets=512 -OrphanMask=511 -Pacing=yes -CEThresholdSec=100ms - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0033 -Priority=1 -Rate=1M -CeilRate=0.5M - -[ControlledDelay] -Parent=2:33 -Handle=0033 -PacketLimit=2000 -TargetSec=10ms -IntervalSec=50ms -ECN=yes -CEThresholdSec=100ms - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0034 -Priority=1 -Rate=1M -CeilRate=0.5M - -[FairQueueingControlledDelay] -Parent=2:34 -Handle=0034 -PacketLimit=20480 -MemoryLimitBytes=64M -Flows=2048 -TargetSec=10ms -IntervalSec=200ms -QuantumBytes=1400 -ECN=yes -CEThresholdSec=100ms - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0035 -Priority=1 -Rate=1M -CeilRate=0.5M - -[TokenBucketFilter] -Parent=2:35 -Handle=0035 -Rate=1G -BurstBytes=5000 -LatencySec=70msec -PeakRate=100G -MTUBytes=1000000 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0036 -Priority=1 -Rate=1M -CeilRate=0.5M - -[StochasticFairnessQueueing] -Parent=2:36 -Handle=0036 -PerturbPeriodSec=5sec - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0037 -Priority=1 -Rate=1M -CeilRate=0.5M - -[PFIFO] -Parent=2:37 -Handle=0037 -PacketLimit=100000 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0038 -Priority=1 -Rate=1M -CeilRate=0.5M - -[GenericRandomEarlyDetection] -Parent=2:38 -Handle=0038 -VirtualQueues=12 -DefaultVirtualQueue=10 -GenericRIO=yes - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:0039 -Priority=1 -Rate=1M -CeilRate=0.5M - -[StochasticFairBlue] -Parent=2:39 -Handle=0039 -PacketLimit=200000 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:003a -Priority=1 -Rate=1M -CeilRate=0.5M - -[BFIFO] -Parent=2:3a -Handle=003a -LimitBytes=1000000 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:003b -Priority=1 -Rate=1M -CeilRate=0.5M - -[PFIFOHeadDrop] -Parent=2:3b -Handle=003b -PacketLimit=1023 - -[HierarchyTokenBucketClass] -Parent=root -ClassId=0002:003c -Priority=1 -Rate=1M -CeilRate=0.5M - -[PFIFOFast] -Parent=2:3c -Handle=003c diff --git a/test/test-network/conf/25-qdisc-clsact.network b/test/test-network/conf/25-qdisc-clsact.network new file mode 100644 index 0000000000..8a1661878b --- /dev/null +++ b/test/test-network/conf/25-qdisc-clsact.network @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[QDisc] +Parent=clsact diff --git a/test/test-network/conf/25-qdisc-codel.network b/test/test-network/conf/25-qdisc-codel.network new file mode 100644 index 0000000000..a332fa8ebf --- /dev/null +++ b/test/test-network/conf/25-qdisc-codel.network @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[ControlledDelay] +Parent=root +Handle=0033 +PacketLimit=2000 +TargetSec=10ms +IntervalSec=50ms +ECN=yes +CEThresholdSec=100ms diff --git a/test/test-network/conf/25-qdisc-fq.network b/test/test-network/conf/25-qdisc-fq.network new file mode 100644 index 0000000000..5539a642f6 --- /dev/null +++ b/test/test-network/conf/25-qdisc-fq.network @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[FairQueueing] +Parent=root +Handle=0032 +PacketLimit=1000 +FlowLimit=200 +QuantumBytes=1500 +InitialQuantumBytes=13000 +MaximumRate=1M +Buckets=512 +OrphanMask=511 +Pacing=yes +CEThresholdSec=100ms diff --git a/test/test-network/conf/25-qdisc-fq_codel.network b/test/test-network/conf/25-qdisc-fq_codel.network new file mode 100644 index 0000000000..0e7d62db49 --- /dev/null +++ b/test/test-network/conf/25-qdisc-fq_codel.network @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[FairQueueingControlledDelay] +Parent=root +Handle=0034 +PacketLimit=20480 +MemoryLimitBytes=64M +Flows=2048 +TargetSec=10ms +IntervalSec=200ms +QuantumBytes=1400 +ECN=yes +CEThresholdSec=100ms diff --git a/test/test-network/conf/25-qdisc-gred.network b/test/test-network/conf/25-qdisc-gred.network new file mode 100644 index 0000000000..a49955f165 --- /dev/null +++ b/test/test-network/conf/25-qdisc-gred.network @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[GenericRandomEarlyDetection] +Parent=root +Handle=0038 +VirtualQueues=12 +DefaultVirtualQueue=10 +GenericRIO=yes diff --git a/test/test-network/conf/25-qdisc-htb-fifo.network b/test/test-network/conf/25-qdisc-htb-fifo.network new file mode 100644 index 0000000000..1e092a9e02 --- /dev/null +++ b/test/test-network/conf/25-qdisc-htb-fifo.network @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[HierarchyTokenBucket] +Parent=root +Handle=0002 +DefaultClass=30 +RateToQuantum=20 + +[HierarchyTokenBucketClass] +Parent=root +ClassId=0002:0037 +Priority=1 +Rate=1M +CeilRate=0.5M +QuantumBytes=4000 +MTUBytes=1700 +OverheadBytes=100 +BufferBytes=123456 +CeilBufferBytes=123457 + +[PFIFO] +Parent=2:37 +Handle=0037 +PacketLimit=100000 + +[HierarchyTokenBucketClass] +Parent=root +ClassId=0002:003a +Priority=1 +Rate=1M +CeilRate=0.5M + +[BFIFO] +Parent=2:3a +Handle=003a +LimitBytes=1000000 + +[HierarchyTokenBucketClass] +Parent=root +ClassId=0002:003b +Priority=1 +Rate=1M +CeilRate=0.5M + +[PFIFOHeadDrop] +Parent=2:3b +Handle=003b +PacketLimit=1023 + +[HierarchyTokenBucketClass] +Parent=root +ClassId=0002:003c +Priority=1 +Rate=1M +CeilRate=0.5M + +[PFIFOFast] +Parent=2:3c +Handle=003c diff --git a/test/test-network/conf/25-qdisc-ingress.network b/test/test-network/conf/25-qdisc-ingress.network new file mode 100644 index 0000000000..6fb5fef77d --- /dev/null +++ b/test/test-network/conf/25-qdisc-ingress.network @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=test1 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.4/16 + +[QDisc] +Parent=ingress diff --git a/test/test-network/conf/25-qdisc-ingress-netem-compat.network b/test/test-network/conf/25-qdisc-netem-compat.network similarity index 84% rename from test/test-network/conf/25-qdisc-ingress-netem-compat.network rename to test/test-network/conf/25-qdisc-netem-compat.network index d895f7f34f..15e0f7f367 100644 --- a/test/test-network/conf/25-qdisc-ingress-netem-compat.network +++ b/test/test-network/conf/25-qdisc-netem-compat.network @@ -12,6 +12,3 @@ NetworkEmulatorDelaySec=50ms NetworkEmulatorDelayJitterSec=10ms NetworkEmulatorLossRate=20% NetworkEmulatorPacketLimit=100 - -[TrafficControlQueueingDiscipline] -Parent=ingress diff --git a/test/test-network/conf/25-qdisc-netem.network b/test/test-network/conf/25-qdisc-netem.network new file mode 100644 index 0000000000..9848788235 --- /dev/null +++ b/test/test-network/conf/25-qdisc-netem.network @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[NetworkEmulator] +Parent=root +Handle=0030 +DelaySec=50ms +DelayJitterSec=10ms +LossRate=20% +PacketLimit=100 diff --git a/test/test-network/conf/25-qdisc-qfq.network b/test/test-network/conf/25-qdisc-qfq.network index 1c8dbc2461..b09e99c4f2 100644 --- a/test/test-network/conf/25-qdisc-qfq.network +++ b/test/test-network/conf/25-qdisc-qfq.network @@ -1,10 +1,10 @@ # SPDX-License-Identifier: LGPL-2.1-or-later [Match] -Name=test1 +Name=dummy98 [Network] IPv6AcceptRA=no -Address=10.1.2.4/16 +Address=10.1.2.3/16 [QuickFairQueueing] Parent=root diff --git a/test/test-network/conf/25-qdisc-sfb.network b/test/test-network/conf/25-qdisc-sfb.network new file mode 100644 index 0000000000..bfcda007a6 --- /dev/null +++ b/test/test-network/conf/25-qdisc-sfb.network @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[StochasticFairBlue] +Parent=root +Handle=0039 +PacketLimit=200000 diff --git a/test/test-network/conf/25-qdisc-sfq.network b/test/test-network/conf/25-qdisc-sfq.network new file mode 100644 index 0000000000..263cd6dfbe --- /dev/null +++ b/test/test-network/conf/25-qdisc-sfq.network @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[StochasticFairnessQueueing] +Parent=root +Handle=0036 +PerturbPeriodSec=5sec diff --git a/test/test-network/conf/25-qdisc-tbf.network b/test/test-network/conf/25-qdisc-tbf.network new file mode 100644 index 0000000000..c5f28fb63c --- /dev/null +++ b/test/test-network/conf/25-qdisc-tbf.network @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[TokenBucketFilter] +Parent=root +Handle=0035 +Rate=1G +BurstBytes=5000 +LatencySec=70msec +PeakRate=100G +MTUBytes=1000000 diff --git a/test/test-network/conf/25-qdisc-teql.network b/test/test-network/conf/25-qdisc-teql.network new file mode 100644 index 0000000000..ed7e21fd9a --- /dev/null +++ b/test/test-network/conf/25-qdisc-teql.network @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[TrivialLinkEqualizer] +Parent=root +Handle=0031 +Id=1 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 3302939626..209f5a565c 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3220,108 +3220,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertEqual(output, '') - def test_qdisc(self): - copy_network_unit('25-qdisc-clsact-and-htb.network', '12-dummy.netdev', - '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev') - check_output('modprobe sch_teql max_equalizers=2') - start_networkd() - self.wait_online(['dummy98:routable', 'test1:routable']) - - output = check_output('tc qdisc show dev test1') - print(output) - self.assertRegex(output, 'qdisc netem') - self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') - self.assertRegex(output, 'qdisc ingress') - - output = check_output('tc qdisc show dev dummy98') - print(output) - self.assertRegex(output, 'qdisc clsact') - - self.assertRegex(output, 'qdisc htb 2: root') - self.assertRegex(output, r'default (0x30|30)') - - self.assertRegex(output, 'qdisc netem 30: parent 2:30') - self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') - self.assertRegex(output, 'qdisc fq_codel') - self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn') - - self.assertRegex(output, 'qdisc teql1 31: parent 2:31') - - self.assertRegex(output, 'qdisc fq 32: parent 2:32') - self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511') - self.assertRegex(output, 'quantum 1500') - self.assertRegex(output, 'initial_quantum 13000') - self.assertRegex(output, 'maxrate 1Mbit') - - self.assertRegex(output, 'qdisc codel 33: parent 2:33') - self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn') - - self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34') - self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn') - - self.assertRegex(output, 'qdisc tbf 35: parent 2:35') - self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms') - - self.assertRegex(output, 'qdisc sfq 36: parent 2:36') - self.assertRegex(output, 'perturb 5sec') - - self.assertRegex(output, 'qdisc pfifo 37: parent 2:37') - self.assertRegex(output, 'limit 100000p') - - self.assertRegex(output, 'qdisc gred 38: parent 2:38') - self.assertRegex(output, 'vqs 12 default 10 grio') - - self.assertRegex(output, 'qdisc sfb 39: parent 2:39') - self.assertRegex(output, 'limit 200000') - - self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a') - self.assertRegex(output, 'limit 1000000') - - self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b') - self.assertRegex(output, 'limit 1023p') - - self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c') - - output = check_output('tc -d class show dev dummy98') - print(output) - self.assertRegex(output, 'class htb 2:30 root leaf 30:') - self.assertRegex(output, 'class htb 2:31 root leaf 31:') - self.assertRegex(output, 'class htb 2:32 root leaf 32:') - self.assertRegex(output, 'class htb 2:33 root leaf 33:') - self.assertRegex(output, 'class htb 2:34 root leaf 34:') - self.assertRegex(output, 'class htb 2:35 root leaf 35:') - self.assertRegex(output, 'class htb 2:36 root leaf 36:') - self.assertRegex(output, 'class htb 2:37 root leaf 37:') - self.assertRegex(output, 'class htb 2:38 root leaf 38:') - self.assertRegex(output, 'class htb 2:39 root leaf 39:') - self.assertRegex(output, 'class htb 2:3a root leaf 3a:') - self.assertRegex(output, 'class htb 2:3b root leaf 3b:') - self.assertRegex(output, 'class htb 2:3c root leaf 3c:') - self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit') - self.assertRegex(output, 'burst 123456') - self.assertRegex(output, 'cburst 123457') - - def test_qdisc2(self): - copy_network_unit('25-qdisc-drr.network', '12-dummy.netdev', - '25-qdisc-qfq.network', '11-dummy.netdev') - start_networkd() - self.wait_online(['dummy98:routable', 'test1:routable']) - - output = check_output('tc qdisc show dev dummy98') - print(output) - self.assertRegex(output, 'qdisc drr 2: root') - output = check_output('tc class show dev dummy98') - print(output) - self.assertRegex(output, 'class drr 2:30 root quantum 2000b') - - output = check_output('tc qdisc show dev test1') - print(output) - self.assertRegex(output, 'qdisc qfq 2: root') - output = check_output('tc class show dev test1') - print(output) - self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000') - self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000') - @expectedFailureIfModuleIsNotAvailable('sch_cake') def test_qdisc_cake(self): copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev') @@ -3344,27 +3242,29 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertIn('mpu 20', output) self.assertIn('fwmark 0xff00', output) - @expectedFailureIfModuleIsNotAvailable('sch_pie') - def test_qdisc_pie(self): - copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev') + @expectedFailureIfModuleIsNotAvailable('sch_codel') + def test_qdisc_codel(self): + copy_network_unit('25-qdisc-codel.network', '12-dummy.netdev') start_networkd() self.wait_online(['dummy98:routable']) output = check_output('tc qdisc show dev dummy98') print(output) - self.assertRegex(output, 'qdisc pie 3a: root') - self.assertRegex(output, 'limit 200000') + self.assertRegex(output, 'qdisc codel 33: root') + self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn') - @expectedFailureIfModuleIsNotAvailable('sch_hhf') - def test_qdisc_hhf(self): - copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev') + @expectedFailureIfModuleIsNotAvailable('sch_drr') + def test_qdisc_drr(self): + copy_network_unit('25-qdisc-drr.network', '12-dummy.netdev') start_networkd() self.wait_online(['dummy98:routable']) output = check_output('tc qdisc show dev dummy98') print(output) - self.assertRegex(output, 'qdisc hhf 3a: root') - self.assertRegex(output, 'limit 1022p') + self.assertRegex(output, 'qdisc drr 2: root') + output = check_output('tc class show dev dummy98') + print(output) + self.assertRegex(output, 'class drr 2:30 root quantum 2000b') @expectedFailureIfModuleIsNotAvailable('sch_ets') def test_qdisc_ets(self): @@ -3380,6 +3280,31 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'quanta 1 2 3 4 5') self.assertRegex(output, 'priomap 3 4 5 6 7') + @expectedFailureIfModuleIsNotAvailable('sch_fq') + def test_qdisc_fq(self): + copy_network_unit('25-qdisc-fq.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc fq 32: root') + self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511') + self.assertRegex(output, 'quantum 1500') + self.assertRegex(output, 'initial_quantum 13000') + self.assertRegex(output, 'maxrate 1Mbit') + + @expectedFailureIfModuleIsNotAvailable('sch_fq_codel') + def test_qdisc_fq_codel(self): + copy_network_unit('25-qdisc-fq_codel.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc fq_codel 34: root') + self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn') + @expectedFailureIfModuleIsNotAvailable('sch_fq_pie') def test_qdisc_fq_pie(self): copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev') @@ -3392,6 +3317,164 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'qdisc fq_pie 3a: root') self.assertRegex(output, 'limit 200000p') + @expectedFailureIfModuleIsNotAvailable('sch_gred') + def test_qdisc_gred(self): + copy_network_unit('25-qdisc-gred.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc gred 38: root') + self.assertRegex(output, 'vqs 12 default 10 grio') + + @expectedFailureIfModuleIsNotAvailable('sch_hhf') + def test_qdisc_hhf(self): + copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc hhf 3a: root') + self.assertRegex(output, 'limit 1022p') + + @expectedFailureIfModuleIsNotAvailable('sch_htb') + def test_qdisc_htb_fifo(self): + copy_network_unit('25-qdisc-htb-fifo.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc htb 2: root') + self.assertRegex(output, r'default (0x30|30)') + + self.assertRegex(output, 'qdisc pfifo 37: parent 2:37') + self.assertRegex(output, 'limit 100000p') + + self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a') + self.assertRegex(output, 'limit 1000000') + + self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b') + self.assertRegex(output, 'limit 1023p') + + self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c') + + output = check_output('tc -d class show dev dummy98') + print(output) + self.assertRegex(output, 'class htb 2:37 root leaf 37:') + self.assertRegex(output, 'class htb 2:3a root leaf 3a:') + self.assertRegex(output, 'class htb 2:3b root leaf 3b:') + self.assertRegex(output, 'class htb 2:3c root leaf 3c:') + self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit') + self.assertRegex(output, 'burst 123456') + self.assertRegex(output, 'cburst 123457') + + @expectedFailureIfModuleIsNotAvailable('sch_ingress') + def test_qdisc_ingress(self): + copy_network_unit('25-qdisc-clsact.network', '12-dummy.netdev', + '25-qdisc-ingress.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable', 'test1:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc clsact') + + output = check_output('tc qdisc show dev test1') + print(output) + self.assertRegex(output, 'qdisc ingress') + + @expectedFailureIfModuleIsNotAvailable('sch_netem') + def test_qdisc_netem(self): + copy_network_unit('25-qdisc-netem.network', '12-dummy.netdev', + '25-qdisc-netem-compat.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable', 'test1:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc netem 30: root') + self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') + + output = check_output('tc qdisc show dev test1') + print(output) + self.assertRegex(output, 'qdisc netem [0-9a-f]*: root') + self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') + + @expectedFailureIfModuleIsNotAvailable('sch_pie') + def test_qdisc_pie(self): + copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc pie 3a: root') + self.assertRegex(output, 'limit 200000') + + @expectedFailureIfModuleIsNotAvailable('sch_qfq') + def test_qdisc_qfq(self): + copy_network_unit('25-qdisc-qfq.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc qfq 2: root') + output = check_output('tc class show dev dummy98') + print(output) + self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000') + self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000') + + @expectedFailureIfModuleIsNotAvailable('sch_sfb') + def test_qdisc_sfb(self): + copy_network_unit('25-qdisc-sfb.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc sfb 39: root') + self.assertRegex(output, 'limit 200000') + + @expectedFailureIfModuleIsNotAvailable('sch_sfq') + def test_qdisc_sfq(self): + copy_network_unit('25-qdisc-sfq.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc sfq 36: root') + self.assertRegex(output, 'perturb 5sec') + + @expectedFailureIfModuleIsNotAvailable('sch_tbf') + def test_qdisc_tbf(self): + copy_network_unit('25-qdisc-tbf.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc tbf 35: root') + self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms') + + @expectedFailureIfModuleIsNotAvailable('sch_teql') + def test_qdisc_teql(self): + call_quiet('rmmod sch_teql') + + copy_network_unit('25-qdisc-teql.network', '12-dummy.netdev') + start_networkd() + self.wait_links('dummy98') + check_output('modprobe sch_teql max_equalizers=2') + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'qdisc teql1 31: root') + def test_wait_online_ipv4(self): copy_network_unit('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network') start_networkd() From 23b38192095706c5581c9a7502d24234d410aa40 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 6 Aug 2022 12:36:41 +0900 Subject: [PATCH 10/10] test-network: split out qdisc and wait-online tests from NetworkdNetworkTests --- test/test-network/systemd-networkd-tests.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 209f5a565c..fddae84259 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3220,6 +3220,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertEqual(output, '') +class NetworkdTCTests(unittest.TestCase, Utilities): + + def setUp(self): + setup_common() + + def tearDown(self): + tear_down_common() + @expectedFailureIfModuleIsNotAvailable('sch_cake') def test_qdisc_cake(self): copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev') @@ -3475,6 +3483,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'qdisc teql1 31: root') +class NetworkWaitOnlineTests(unittest.TestCase, Utilities): + + def setUp(self): + setup_common() + + def tearDown(self): + tear_down_common() + def test_wait_online_ipv4(self): copy_network_unit('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network') start_networkd()