import errno
import itertools
import os
+import pathlib
import re
import shutil
import signal
import sys
import time
import unittest
-from shutil import copytree
-from pathlib import Path
-
-network_unit_file_path='/run/systemd/network'
-networkd_runtime_directory='/run/systemd/netif'
-networkd_conf_dropin_path='/run/systemd/networkd.conf.d'
-networkd_ci_path='/run/networkd-ci'
-network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
-network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
-
-udev_rules_dir='/run/udev/rules.d'
-
-dnsmasq_pid_file='/run/networkd-ci/test-dnsmasq.pid'
-dnsmasq_log_file='/run/networkd-ci/test-dnsmasq.log'
-dnsmasq_lease_file='/run/networkd-ci/test-dnsmasq.lease'
-
-isc_dhcpd_pid_file='/run/networkd-ci/test-isc-dhcpd.pid'
-isc_dhcpd_lease_file='/run/networkd-ci/test-isc-dhcpd.lease'
-
-systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
-which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
-
-networkd_bin=shutil.which('systemd-networkd', path=which_paths)
-resolved_bin=shutil.which('systemd-resolved', 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)
-
-use_valgrind=False
-enable_debug=True
+
+network_unit_dir = '/run/systemd/network'
+networkd_conf_dropin_dir = '/run/systemd/networkd.conf.d'
+networkd_ci_temp_dir = '/run/networkd-ci'
+udev_rules_dir = '/run/udev/rules.d'
+
+dnsmasq_pid_file = '/run/networkd-ci/test-dnsmasq.pid'
+dnsmasq_log_file = '/run/networkd-ci/test-dnsmasq.log'
+dnsmasq_lease_file = '/run/networkd-ci/test-dnsmasq.lease'
+
+isc_dhcpd_pid_file = '/run/networkd-ci/test-isc-dhcpd.pid'
+isc_dhcpd_lease_file = '/run/networkd-ci/test-isc-dhcpd.lease'
+
+systemd_lib_paths = ['/usr/lib/systemd', '/lib/systemd']
+which_paths = ':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
+
+networkd_bin = shutil.which('systemd-networkd', path=which_paths)
+resolved_bin = shutil.which('systemd-resolved', 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)
+
+use_valgrind = False
+enable_debug = True
env = {}
wait_online_env = {}
-asan_options=None
-lsan_options=None
-ubsan_options=None
-with_coverage=False
-
-running_units = []
+asan_options = None
+lsan_options = None
+ubsan_options = None
+with_coverage = False
+
+active_units = []
+protected_links = {
+ 'erspan0',
+ 'gre0',
+ 'gretap0',
+ 'ifb0',
+ 'ifb1',
+ 'ip6_vti0',
+ 'ip6gre0',
+ 'ip6tnl0',
+ 'ip_vti0',
+ 'lo',
+ 'sit0',
+ 'tunl0',
+}
+saved_routes = None
+saved_ipv4_rules = None
+saved_ipv6_rules = None
+
+def rm_f(path):
+ if os.path.exists(path):
+ os.remove(path)
+
+def rm_rf(path):
+ shutil.rmtree(path, ignore_errors=True)
+
+def cp(src, dst):
+ shutil.copy(src, dst)
+
+def cp_r(src, dst):
+ shutil.copytree(src, dst, copy_function=shutil.copy)
+
+def mkdir_p(path):
+ os.makedirs(path, exist_ok=True)
+
+def touch(path):
+ pathlib.Path(path).touch()
+
+def check_output(*command, text=True, **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()
-def check_output(*command, **kwargs):
- # This replaces both check_output and check_call (output can be ignored)
+def call(*command, text=True, **kwargs):
+ # This returns returncode. stdout and stderr are shown in console
command = command[0].split() + list(command[1:])
- return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
+ return subprocess.run(command, check=False, universal_newlines=text, **kwargs).returncode
-def call(*command, **kwargs):
+def call_quiet(*command, text=True, **kwargs):
command = command[0].split() + list(command[1:])
- return subprocess.call(command, universal_newlines=True, **kwargs)
+ return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode
-def run(*command, **kwargs):
+def run(*command, text=True, **kwargs):
+ # This returns CompletedProcess instance.
command = command[0].split() + list(command[1:])
- return subprocess.run(command, universal_newlines=True, check=False, **kwargs)
+ return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
def is_module_available(module_name):
lsmod_output = check_output('lsmod')
module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
- return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
+ return module_re.search(lsmod_output) or call_quiet('modprobe', module_name) == 0
def expectedFailureIfModuleIsNotAvailable(module_name):
def f(func):
- if not is_module_available(module_name):
- return unittest.expectedFailure(func)
- return func
+ return func if is_module_available(module_name) else unittest.expectedFailure(func)
return f
def expectedFailureIfERSPANv0IsNotSupported():
# erspan version 0 is supported since f989d546a2d5a9f001f6f8be49d98c10ab9b1897 (v5.8)
def f(func):
- rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 0', stderr=subprocess.DEVNULL)
- if rc == 0:
- call('ip link del erspan99')
- return func
-
- return unittest.expectedFailure(func)
+ rc = call_quiet('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 0')
+ remove_link('erspan99')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfERSPANv2IsNotSupported():
# erspan version 2 is supported since f551c91de262ba36b20c3ac19538afb4f4507441 (v4.16)
def f(func):
- rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 2', stderr=subprocess.DEVNULL)
- if rc == 0:
- call('ip link del erspan99')
- return func
-
- return unittest.expectedFailure(func)
+ rc = call_quiet('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 2')
+ remove_link('erspan99')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
def f(func):
- rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
- if rc == 0:
- call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
- return func
-
- return unittest.expectedFailure(func)
+ rc = call_quiet('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
+ call_quiet('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
def f(func):
- rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
- if rc == 0:
- call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
- return func
-
- return unittest.expectedFailure(func)
+ rc = call_quiet('ip rule add not from 192.168.100.19 ipproto tcp table 7')
+ call_quiet('ip rule del not from 192.168.100.19 ipproto tcp table 7')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
def f(func):
- support = False
- rc = call('ip rule add from 192.168.100.19 table 7 uidrange 200-300', stderr=subprocess.DEVNULL)
- if rc == 0:
- ret = run('ip rule list from 192.168.100.19 table 7', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- if ret.returncode == 0 and 'uidrange 200-300' in ret.stdout.rstrip():
- support = True
- call('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
-
- if support:
- return func
-
- return unittest.expectedFailure(func)
+ supported = False
+ if call_quiet('ip rule add from 192.168.100.19 table 7 uidrange 200-300') == 0:
+ ret = run('ip rule list from 192.168.100.19 table 7')
+ supported = ret.returncode == 0 and 'uidrange 200-300' in ret.stdout
+ call_quiet('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
+ return func if supported else unittest.expectedFailure(func)
return f
def expectedFailureIfLinkFileFieldIsNotSet():
def f(func):
- support = False
- rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
- if rc == 0:
- ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
- support = True
- call('ip link del dummy99')
-
- if support:
- return func
-
- return unittest.expectedFailure(func)
+ call_quiet('ip link add name dummy99 type dummy')
+ ret = run('udevadm info -w10s /sys/class/net/dummy99')
+ supported = ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout
+ remove_link('dummy99')
+ return func if supported else unittest.expectedFailure(func)
return f
def expectedFailureIfNexthopIsNotAvailable():
def f(func):
- rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(func)
+ rc = call_quiet('ip nexthop list')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfRTA_VIAIsNotSupported():
def f(func):
- call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- call('ip link set up dev dummy98', stderr=subprocess.DEVNULL)
- call('ip route add 2001:1234:5:8fff:ff:ff:ff:fe/128 dev dummy98', stderr=subprocess.DEVNULL)
- rc = call('ip route add 10.10.10.10 via inet6 2001:1234:5:8fff:ff:ff:ff:fe dev dummy98', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(func)
+ call_quiet('ip link add dummy98 type dummy')
+ call_quiet('ip link set up dev dummy98')
+ call_quiet('ip route add 2001:1234:5:8fff:ff:ff:ff:fe/128 dev dummy98')
+ rc = call_quiet('ip route add 10.10.10.10 via inet6 2001:1234:5:8fff:ff:ff:ff:fe dev dummy98')
+ remove_link('dummy98')
+ return func if rc == 0 else unittest.expectedFailure(func)
return f
def expectedFailureIfAlternativeNameIsNotAvailable():
def f(func):
- supported = False
- call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
- if rc == 0:
- rc = call('ip link show dev hogehogehogehogehoge', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- if rc == 0:
- supported = True
-
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if supported:
- return func
-
- return unittest.expectedFailure(func)
+ call_quiet('ip link add dummy98 type dummy')
+ supported = \
+ call_quiet('ip link prop add dev dummy98 altname hogehogehogehogehoge') == 0 and \
+ call_quiet('ip link show dev hogehogehogehogehoge') == 0
+ remove_link('dummy98')
+ return func if supported else unittest.expectedFailure(func)
return f
def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable():
def f(func):
- call('rmmod netdevsim', stderr=subprocess.DEVNULL)
- rc = call('modprobe netdevsim', stderr=subprocess.DEVNULL)
- if rc != 0:
- return unittest.expectedFailure(func)
+ def finalize(func, supported):
+ call_quiet('rmmod netdevsim')
+ return func if supported else unittest.expectedFailure(func)
+
+ call_quiet('rmmod netdevsim')
+ if call_quiet('modprobe netdevsim') != 0:
+ return finalize(func, False)
try:
with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
f.write('99 1')
except OSError:
- return unittest.expectedFailure(func)
+ return finalize(func, False)
- call('udevadm settle')
- call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
- try:
- with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w', encoding='utf-8') as f:
- f.write('3')
- except OSError:
- call('rmmod netdevsim', stderr=subprocess.DEVNULL)
- return unittest.expectedFailure(func)
+ if not os.path.exists('/sys/bus/netdevsim/devices/netdevsim99/sriov_numvfs'):
+ return finalize(func, False)
- call('rmmod netdevsim', stderr=subprocess.DEVNULL)
- return func
+ # Also checks if udevd supports .link files, as it seems disabled on CentOS CI (Arch).
+ rc = call_quiet('udevadm info -w10s /sys/class/net/eni99np1')
+ return finalize(func, rc == 0)
return f
def expectedFailureIfCAKEIsNotAvailable():
def f(func):
- call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('tc qdisc add dev dummy98 parent root cake', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(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('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('tc qdisc add dev dummy98 parent root pie', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(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('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('tc qdisc add dev dummy98 parent root hhf', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(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('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('tc qdisc add dev dummy98 parent root ets bands 10', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(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('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
- rc = call('tc qdisc add dev dummy98 parent root fq_pie', stderr=subprocess.DEVNULL)
- call('ip link del dummy98', stderr=subprocess.DEVNULL)
- if rc == 0:
- return func
-
- return unittest.expectedFailure(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 setUpModule():
- os.makedirs(network_unit_file_path, exist_ok=True)
- os.makedirs(networkd_conf_dropin_path, exist_ok=True)
- os.makedirs(networkd_ci_path, exist_ok=True)
- os.makedirs(udev_rules_dir, exist_ok=True)
+def copy_network_unit(*units, copy_dropins=True):
+ """
+ Copy networkd unit files into the testbed.
- shutil.rmtree(networkd_ci_path)
- copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
+ Any networkd unit file type can be specified, as well as drop-in files.
- shutil.copy(os.path.join(networkd_ci_path, '00-debug-net.rules'), udev_rules_dir)
+ By default, all drop-ins for a specified unit file are copied in;
+ to avoid that specify dropins=False.
- for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service',
- 'systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service',
+ When a drop-in file is specified, its unit file is also copied in automatically.
+ """
+ mkdir_p(network_unit_dir)
+ for unit in units:
+ if copy_dropins and os.path.exists(os.path.join(networkd_ci_temp_dir, unit + '.d')):
+ cp_r(os.path.join(networkd_ci_temp_dir, unit + '.d'), os.path.join(network_unit_dir, unit + '.d'))
+ if unit.endswith('.conf'):
+ dropin = unit
+ unit = os.path.dirname(dropin).rstrip('.d')
+ dropindir = os.path.join(network_unit_dir, unit + '.d')
+ mkdir_p(dropindir)
+ cp(os.path.join(networkd_ci_temp_dir, dropin), dropindir)
+ cp(os.path.join(networkd_ci_temp_dir, unit), network_unit_dir)
+
+def remove_network_unit(*units):
+ """
+ Remove previously copied unit files from the testbed.
+
+ Drop-ins will be removed automatically.
+ """
+ for unit in units:
+ rm_f(os.path.join(network_unit_dir, unit))
+ rm_rf(os.path.join(network_unit_dir, unit + '.d'))
+
+def clear_network_units():
+ rm_rf(network_unit_dir)
+
+def copy_networkd_conf_dropin(*dropins):
+ """Copy networkd.conf dropin files into the testbed."""
+ mkdir_p(networkd_conf_dropin_dir)
+ for dropin in dropins:
+ cp(os.path.join(networkd_ci_temp_dir, dropin), networkd_conf_dropin_dir)
+
+def remove_networkd_conf_dropin(*dropins):
+ """Remove previously copied networkd.conf dropin files from the testbed."""
+ for dropin in dropins:
+ rm_f(os.path.join(networkd_conf_dropin_dir, dropin))
+
+def clear_networkd_conf_dropins():
+ rm_rf(networkd_conf_dropin_dir)
+
+def copy_udev_rule(*rules):
+ """Copy udev rules"""
+ mkdir_p(udev_rules_dir)
+ for rule in rules:
+ cp(os.path.join(networkd_ci_temp_dir, rule), udev_rules_dir)
+
+def remove_udev_rule(*rules):
+ """Remove previously copied udev rules"""
+ for rule in rules:
+ rm_f(os.path.join(udev_rules_dir, rule))
+
+def clear_udev_rules():
+ rm_rf(udev_rules_dir)
+
+def save_active_units():
+ for u in ['systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service',
+ 'systemd-networkd.socket', 'systemd-networkd.service',
+ 'systemd-resolved.service',
'firewalld.service']:
if call(f'systemctl is-active --quiet {u}') == 0:
- check_output(f'systemctl stop {u}')
- running_units.append(u)
+ call(f'systemctl stop {u}')
+ active_units.append(u)
+
+def restore_active_units():
+ if 'systemd-networkd.socket' in active_units:
+ call('systemctl stop systemd-networkd.socket systemd-networkd.service')
+ if 'systemd-udevd-kernel.socket' in active_units or 'systemd-udevd-control.socket' in active_units:
+ call('systemctl stop systemd-udevd-kernel.socket systemd-udevd-control.socket systemd-udevd.service')
+ for u in active_units:
+ call(f'systemctl restart {u}')
+
+def link_exists(link):
+ return os.path.exists(os.path.join('/sys/class/net', link, 'ifindex'))
+
+def remove_link(*links, protect=False):
+ for link in links:
+ if protect and link in protected_links:
+ continue
+ if link_exists(link):
+ call(f'ip link del dev {link}')
+
+def save_existing_links():
+ links = os.listdir('/sys/class/net')
+ for link in links:
+ if link_exists(link):
+ protected_links.add(link)
+
+ print('### The following links will be protected:')
+ print(', '.join(sorted(list(protected_links))))
+
+def flush_links():
+ links = os.listdir('/sys/class/net')
+ remove_link(*links, protect=True)
+
+def flush_nexthops():
+ # Currently, the 'ip nexthop' command does not have 'save' and 'restore'.
+ # Hence, we cannot restore nexthops in a simple way.
+ # Let's assume there is no nexthop used in the system
+ call_quiet('ip nexthop flush')
+
+def save_routes():
+ # pylint: disable=global-statement
+ global saved_routes
+ saved_routes = check_output('ip route show table all')
+ print('### The following routes will be protected:')
+ print(saved_routes)
+
+def flush_routes():
+ have = False
+ output = check_output('ip route show table all')
+ for line in output.splitlines():
+ if line in saved_routes:
+ continue
+ if 'proto kernel' in line:
+ continue
+ if ' dev ' in line and not ' dev lo ' in line:
+ continue
+ if not have:
+ have = True
+ print('### Removing routes that did not exist when the test started.')
+ print(f'# {line}')
+ call(f'ip route del {line}')
+
+def save_routing_policy_rules():
+ # pylint: disable=global-statement
+ global saved_ipv4_rules, saved_ipv6_rules
+ def save(ipv):
+ output = check_output(f'ip -{ipv} rule show')
+ print(f'### The following IPv{ipv} routing policy rules will be protected:')
+ print(output)
+ return output
+
+ saved_ipv4_rules = save(4)
+ saved_ipv6_rules = save(6)
+
+def flush_routing_policy_rules():
+ def flush(ipv, saved_rules):
+ have = False
+ output = check_output(f'ip -{ipv} rule show')
+ for line in output.splitlines():
+ if line in saved_rules:
+ continue
+ if not have:
+ have = True
+ print(f'### Removing IPv{ipv} routing policy rules that did not exist when the test started.')
+ print(f'# {line}')
+ words = line.split()
+ priority = words[0].rstrip(':')
+ call(f'ip -{ipv} rule del priority {priority} ' + ' '.join(words[1:]))
+
+ flush(4, saved_ipv4_rules)
+ flush(6, saved_ipv6_rules)
+
+def flush_fou_ports():
+ ret = run('ip fou show')
+ if ret.returncode != 0:
+ return # fou may not be supported
+ for line in ret.stdout.splitlines():
+ port = line.split()[1]
+ call(f'ip fou del port {port}')
+
+def flush_l2tp_tunnels():
+ output = check_output('ip l2tp show tunnel')
+ for line in output.splitlines():
+ words = line.split()
+ if words[0] == 'Tunnel':
+ tid = words[1].rstrip(',')
+ call(f'ip l2tp del tunnel tunnel_id {tid}')
+
+def read_link_attr(*args):
+ with open(os.path.join('/sys/class/net', *args), encoding='utf-8') as f:
+ return f.readline().strip()
+
+def read_link_state_file(link):
+ ifindex = read_link_attr(link, 'ifindex')
+ path = os.path.join('/run/systemd/netif/links', ifindex)
+ with open(path, encoding='utf-8') as f:
+ return f.read()
+
+def read_ip_sysctl_attr(link, attribute, ipv):
+ with open(os.path.join('/proc/sys/net', ipv, 'conf', link, attribute), encoding='utf-8') as f:
+ return f.readline().strip()
+
+def read_ipv6_sysctl_attr(link, attribute):
+ return read_ip_sysctl_attr(link, attribute, 'ipv6')
+
+def read_ipv4_sysctl_attr(link, attribute):
+ return read_ip_sysctl_attr(link, attribute, 'ipv4')
+
+def start_dnsmasq(*additional_options, interface='veth-peer', lease_time='2m', ipv4_range='192.168.5.10,192.168.5.200', ipv4_router='192.168.5.1', ipv6_range='2600::10,2600::20'):
+ command = (
+ 'dnsmasq',
+ f'--log-facility={dnsmasq_log_file}',
+ '--log-queries=extra',
+ '--log-dhcp',
+ f'--pid-file={dnsmasq_pid_file}',
+ '--conf-file=/dev/null',
+ '--bind-interfaces',
+ f'--interface={interface}',
+ f'--dhcp-leasefile={dnsmasq_lease_file}',
+ '--enable-ra',
+ f'--dhcp-range={ipv6_range},{lease_time}',
+ f'--dhcp-range={ipv4_range},{lease_time}',
+ '--dhcp-option=option:mtu,1492',
+ f'--dhcp-option=option:router,{ipv4_router}',
+ '--port=0',
+ '--no-resolv',
+ ) + additional_options
+ check_output(*command)
+
+def stop_by_pid_file(pid_file):
+ if not os.path.exists(pid_file):
+ return
+ with open(pid_file, 'r', encoding='utf-8') as f:
+ pid = f.read().rstrip(' \t\r\n\0')
+ os.kill(int(pid), signal.SIGTERM)
+ for _ in range(25):
+ try:
+ os.kill(int(pid), 0)
+ print(f"PID {pid} is still alive, waiting...")
+ time.sleep(.2)
+ except OSError as e:
+ if e.errno == errno.ESRCH:
+ break
+ print(f"Unexpected exception when waiting for {pid} to die: {e.errno}")
+ os.remove(pid_file)
+
+def stop_dnsmasq():
+ stop_by_pid_file(dnsmasq_pid_file)
+ rm_f(dnsmasq_lease_file)
+ rm_f(dnsmasq_log_file)
+
+def read_dnsmasq_log_file():
+ with open(dnsmasq_log_file, encoding='utf-8') as f:
+ return f.read()
+
+def start_isc_dhcpd(conf_file, ipv, interface='veth-peer'):
+ conf_file_path = os.path.join(networkd_ci_temp_dir, conf_file)
+ isc_dhcpd_command = f'dhcpd {ipv} -cf {conf_file_path} -lf {isc_dhcpd_lease_file} -pf {isc_dhcpd_pid_file} {interface}'
+ touch(isc_dhcpd_lease_file)
+ check_output(isc_dhcpd_command)
+
+def stop_isc_dhcpd():
+ stop_by_pid_file(isc_dhcpd_pid_file)
+ rm_f(isc_dhcpd_lease_file)
+
+def stop_networkd(show_logs=True):
+ if show_logs:
+ invocation_id = check_output('systemctl show systemd-networkd.service -p InvocationID --value')
+ check_output('systemctl stop systemd-networkd.socket')
+ check_output('systemctl stop systemd-networkd.service')
+ if show_logs:
+ print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
+
+def start_networkd():
+ check_output('systemctl start systemd-networkd')
+
+def restart_networkd(show_logs=True):
+ stop_networkd(show_logs)
+ start_networkd()
+
+def networkctl_reconfigure(*links):
+ check_output(*networkctl_cmd, 'reconfigure', *links, env=env)
+
+def networkctl_reload(sleep_time=1):
+ check_output(*networkctl_cmd, 'reload', env=env)
+ # 'networkctl reload' asynchronously reconfigure links.
+ # Hence, we need to wait for a short time for link to be in configuring state.
+ if sleep_time > 0:
+ time.sleep(sleep_time)
+
+def setup_common():
+ print()
+
+def tear_down_common():
+ # 1. stop DHCP servers
+ stop_dnsmasq()
+ stop_isc_dhcpd()
+
+ # 2. remove modules
+ call_quiet('rmmod netdevsim')
+ call_quiet('rmmod sch_teql')
+
+ # 3. remove network namespace
+ call_quiet('ip netns del ns99')
+
+ # 4. remove links
+ flush_links()
+
+ # 5. stop networkd
+ stop_networkd(show_logs=True)
+
+ # 6. remove configs
+ clear_network_units()
+ clear_networkd_conf_dropins()
+
+ # 7. flush settings
+ flush_fou_ports()
+ flush_l2tp_tunnels()
+ flush_nexthops()
+ flush_routing_policy_rules()
+ flush_routes()
+
+def setUpModule():
+ rm_rf(networkd_ci_temp_dir)
+ cp_r(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_temp_dir)
+
+ clear_network_units()
+ clear_networkd_conf_dropins()
+ clear_udev_rules()
+
+ copy_udev_rule('00-debug-net.rules')
+
+ # Save current state
+ save_active_units()
+ save_existing_links()
+ save_routes()
+ save_routing_policy_rules()
drop_in = [
'[Unit]',
]
else:
drop_in += [
- 'ExecStart=!!' + networkd_bin,
- f'ExecReload={networkctl_bin} reload',
+ 'ExecStart=!!' + networkd_bin,
+ f'ExecReload={networkctl_bin} reload',
]
if enable_debug:
drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
'ProtectHome=no',
]
- os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
+ 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))
'ProtectHome=no',
]
- os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True)
+ 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))
'ExecStart=!!' + udevd_bin,
]
- os.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok=True)
+ mkdir_p('/run/systemd/system/systemd-udevd.service.d')
with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w', encoding='utf-8') as f:
f.write('\n'.join(drop_in))
print(check_output('systemctl cat systemd-networkd.service'))
print(check_output('systemctl cat systemd-resolved.service'))
print(check_output('systemctl cat systemd-udevd.service'))
- check_output('systemctl restart systemd-resolved')
- check_output('systemctl restart systemd-udevd')
+ check_output('systemctl restart systemd-resolved.service')
+ check_output('systemctl restart systemd-udevd.service')
def tearDownModule():
- shutil.rmtree(networkd_ci_path)
- os.remove(os.path.join(udev_rules_dir, '00-debug-net.rules'))
-
- for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service']:
- check_output(f'systemctl stop {u}')
-
- shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
- shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
- shutil.rmtree('/run/systemd/system/systemd-udevd.service.d')
+ rm_rf(networkd_ci_temp_dir)
+ clear_udev_rules()
+ clear_network_units()
+ clear_networkd_conf_dropins()
+
+ rm_rf('/run/systemd/system/systemd-networkd.service.d')
+ rm_rf('/run/systemd/system/systemd-resolved.service.d')
+ rm_rf('/run/systemd/system/systemd-udevd.service.d')
check_output('systemctl daemon-reload')
- check_output('systemctl restart systemd-udevd.service')
-
- for u in running_units:
- check_output(f'systemctl start {u}')
-
-def read_link_attr(*args):
- with open(os.path.join('/sys/class/net/', *args), encoding='utf-8') as f:
- return f.readline().strip()
-
-def get_ifindex_by_name(link):
- return read_link_attr(f'{link}/ifindex')
-
-def read_link_state_file(link):
- ifindex = get_ifindex_by_name(link)
- path = os.path.join('/run/systemd/netif/links/', ifindex)
- with open(path, encoding='utf-8') as f:
- return f.read()
-
-def read_bridge_port_attr(bridge, link, attribute):
- path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
- path_port = 'lower_' + link + '/brport'
- path = os.path.join(path_bridge, path_port)
-
- with open(os.path.join(path, attribute), encoding='utf-8') as f:
- return f.readline().strip()
-
-def link_exists(link):
- return os.path.exists(os.path.join('/sys/class/net', link))
-
-def remove_links(links):
- for link in links:
- if link_exists(link):
- call('ip link del dev', link)
- time.sleep(1)
-
-def remove_fou_ports(ports):
- for port in ports:
- call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
-
-def remove_routing_policy_rule_tables(tables):
- for table in tables:
- rc = 0
- while rc == 0:
- rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- rc = 0
- while rc == 0:
- rc = call('ip -6 rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
-
-def remove_routes(routes):
- for route_type, addr in routes:
- call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
-
-def remove_blackhole_nexthops():
- ret = run('ip nexthop show dev lo', stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
- if ret.returncode == 0:
- for line in ret.stdout.rstrip().splitlines():
- dev_id = line.split()[1]
- call(f'ip nexthop del id {dev_id}')
-
-def remove_l2tp_tunnels(tunnel_ids):
- output = check_output('ip l2tp show tunnel')
- for tid in tunnel_ids:
- words='Tunnel ' + tid + ', encap'
- if words in output:
- call('ip l2tp del tunnel tid', tid)
- time.sleep(1)
-
-def read_ipv6_sysctl_attr(link, attribute):
- with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute), encoding='utf-8') as f:
- return f.readline().strip()
-
-def read_ipv4_sysctl_attr(link, attribute):
- with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute), encoding='utf-8') as f:
- return f.readline().strip()
+ restore_active_units()
-def copy_unit_to_networkd_unit_path(*units, dropins=True):
- """Copy networkd unit files into the testbed.
-
- Any networkd unit file type can be specified, as well as drop-in files.
-
- By default, all drop-ins for a specified unit file are copied in;
- to avoid that specify dropins=False.
-
- When a drop-in file is specified, its unit file is also copied in automatically.
- """
- print()
- for unit in units:
- if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')):
- copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
- if unit.endswith('.conf'):
- dropin = unit
- dropindir = os.path.join(network_unit_file_path, os.path.dirname(dropin))
- os.makedirs(dropindir, exist_ok=True)
- shutil.copy(os.path.join(networkd_ci_path, dropin), dropindir)
- unit = os.path.dirname(dropin).rstrip('.d')
- shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
-
-def remove_unit_from_networkd_path(units):
- """Remove previously copied unit files from the testbed.
-
- Drop-ins will be removed automatically.
- """
- for unit in units:
- if os.path.exists(os.path.join(network_unit_file_path, unit)):
- os.remove(os.path.join(network_unit_file_path, unit))
- if os.path.exists(os.path.join(network_unit_file_path, unit + '.d')):
- shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
-
-def copy_networkd_conf_dropin(*dropins):
- """Copy networkd.conf dropin files into the testbed."""
- for dropin in dropins:
- shutil.copy(os.path.join(networkd_ci_path, dropin), networkd_conf_dropin_path)
-
-def remove_networkd_conf_dropin(dropins):
- """Remove previously copied networkd.conf dropin files from the testbed."""
- for dropin in dropins:
- if os.path.exists(os.path.join(networkd_conf_dropin_path, dropin)):
- os.remove(os.path.join(networkd_conf_dropin_path, dropin))
-
-def start_dnsmasq(additional_options='', interface='veth-peer', ipv4_range='192.168.5.10,192.168.5.200', ipv4_router='192.168.5.1', ipv6_range='2600::10,2600::20', lease_time='1h'):
- dnsmasq_command = f'dnsmasq -8 {dnsmasq_log_file} --log-queries=extra --log-dhcp --pid-file={dnsmasq_pid_file} --conf-file=/dev/null --bind-interfaces --interface={interface} --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile={dnsmasq_lease_file} --dhcp-option=26,1492 --dhcp-option=option:router,{ipv4_router} --port=0 ' + additional_options
- check_output(dnsmasq_command)
-
-def stop_by_pid_file(pid_file):
- if os.path.exists(pid_file):
- with open(pid_file, 'r', encoding='utf-8') as f:
- pid = f.read().rstrip(' \t\r\n\0')
- os.kill(int(pid), signal.SIGTERM)
- for _ in range(25):
- try:
- os.kill(int(pid), 0)
- print(f"PID {pid} is still alive, waiting...")
- time.sleep(.2)
- except OSError as e:
- if e.errno == errno.ESRCH:
- break
- print(f"Unexpected exception when waiting for {pid} to die: {e.errno}")
-
- os.remove(pid_file)
-
-def stop_dnsmasq():
- stop_by_pid_file(dnsmasq_pid_file)
-
-def read_dnsmasq_log_file():
- if os.path.exists(dnsmasq_log_file):
- with open(dnsmasq_log_file, encoding='utf-8') as f:
- return f.read()
-
-def remove_dnsmasq_lease_file():
- if os.path.exists(dnsmasq_lease_file):
- os.remove(dnsmasq_lease_file)
-
-def remove_dnsmasq_log_file():
- if os.path.exists(dnsmasq_log_file):
- os.remove(dnsmasq_log_file)
-
-def start_isc_dhcpd(interface, conf_file, ip):
- conf_file_path = os.path.join(networkd_ci_path, conf_file)
- isc_dhcpd_command = f'dhcpd {ip} -cf {conf_file_path} -lf {isc_dhcpd_lease_file} -pf {isc_dhcpd_pid_file} {interface}'
- Path(isc_dhcpd_lease_file).touch()
- check_output(isc_dhcpd_command)
+class Utilities():
+ # pylint: disable=no-member
-def stop_isc_dhcpd():
- stop_by_pid_file(isc_dhcpd_pid_file)
- if os.path.exists(isc_dhcpd_lease_file):
- os.remove(isc_dhcpd_lease_file)
+ def check_link_exists(self, link, expected=True):
+ if expected:
+ self.assertTrue(link_exists(link))
+ else:
+ self.assertFalse(link_exists(link))
-def remove_networkd_state_files():
- if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
- os.remove(os.path.join(networkd_runtime_directory, 'state'))
+ def check_link_attr(self, *args):
+ self.assertEqual(read_link_attr(*args[:-1]), args[-1])
-def stop_networkd(show_logs=True, remove_state_files=True):
- if show_logs:
- invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
- check_output('systemctl stop systemd-networkd.socket')
- check_output('systemctl stop systemd-networkd.service')
- if show_logs:
- print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
- if remove_state_files:
- remove_networkd_state_files()
+ def check_bridge_port_attr(self, master, port, attribute, expected, allow_enoent=False):
+ path = os.path.join('/sys/devices/virtual/net', master, 'lower_' + port, 'brport', attribute)
+ if allow_enoent and not os.path.exists(path):
+ return
+ with open(path, encoding='utf-8') as f:
+ self.assertEqual(f.readline().strip(), expected)
-def start_networkd(sleep_sec=0):
- check_output('systemctl start systemd-networkd')
- if sleep_sec > 0:
- time.sleep(sleep_sec)
+ def check_ipv4_sysctl_attr(self, link, attribute, expected):
+ self.assertEqual(read_ipv4_sysctl_attr(link, attribute), expected)
-def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
- stop_networkd(show_logs, remove_state_files)
- start_networkd(sleep_sec)
+ def check_ipv6_sysctl_attr(self, link, attribute, expected):
+ self.assertEqual(read_ipv6_sysctl_attr(link, attribute), expected)
-class Utilities():
- # pylint: disable=no-member
+ def wait_links(self, *links, timeout=20, fail_assert=True):
+ def links_exist(*links):
+ for link in links:
+ if not link_exists(link):
+ return False
+ return True
- def check_link_exists(self, link):
- self.assertTrue(link_exists(link))
+ for iteration in range(timeout + 1):
+ if iteration > 0:
+ time.sleep(1)
- def check_link_attr(self, *args):
- self.assertEqual(read_link_attr(*args[:-1]), args[-1])
+ if links_exist(*links):
+ return True
+ if fail_assert:
+ self.fail('Timed out waiting for all links to be created: ' + ', '.join(list(links)))
+ return False
def wait_activated(self, link, state='down', timeout=20, fail_assert=True):
# wait for the interface is activated.
invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
needle = f'{link}: Bringing link {state}'
flag = state.upper()
- for iteration in range(timeout+1):
+ for iteration in range(timeout + 1):
if iteration != 0:
time.sleep(1)
if not link_exists(link):
args += ['--ipv6']
try:
check_output(*args, env=wait_online_env)
- except subprocess.CalledProcessError:
+ except subprocess.CalledProcessError as e:
+ print(e.stdout) # show logs only on failure
for link in links_with_operstate:
name = link.split(':')[0]
if link_exists(name):
- output = check_output(*networkctl_cmd, '-n', '0', 'status', name, env=env)
- print(output)
+ call(*networkctl_cmd, '-n', '0', 'status', name, env=env)
raise
if not bool_any and setup_state:
for link in links_with_operstate:
class NetworkctlTests(unittest.TestCase, Utilities):
- links = [
- 'dummy98',
- 'test1',
- 'veth99',
- ]
-
- units = [
- '11-dummy.netdev',
- '11-dummy-mtu.netdev',
- '11-dummy.network',
- '12-dummy.netdev',
- '12-dummy.link',
- '25-address-static.network',
- '25-veth.netdev',
- '26-netdev-link-local-addressing-yes.network',
- ]
-
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
@expectedFailureIfAlternativeNameIsNotAvailable()
def test_altname(self):
- copy_unit_to_networkd_unit_path('26-netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
+ copy_network_unit('26-netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
check_output('udevadm control --reload')
start_networkd()
self.wait_online(['dummy98:degraded'])
self.assertRegex(output, 'hogehogehogehogehogehoge')
def test_reconfigure(self):
- copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
+ copy_network_unit('25-address-static.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
check_output('ip address del 10.1.2.4/16 dev dummy98')
check_output('ip address del 10.2.2.4/16 dev dummy98')
- check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
+ networkctl_reconfigure('dummy98')
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dev dummy98')
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
- remove_unit_from_networkd_path(['25-address-static.network'])
+ remove_network_unit('25-address-static.network')
- check_output(*networkctl_cmd, 'reload', env=env)
+ networkctl_reload()
self.wait_operstate('dummy98', 'degraded', setup_state='unmanaged')
output = check_output('ip -4 address show dev dummy98')
self.assertNotIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertNotIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
- copy_unit_to_networkd_unit_path('25-address-static.network')
- check_output(*networkctl_cmd, 'reload', env=env)
+ copy_network_unit('25-address-static.network')
+ networkctl_reload()
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dev dummy98')
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
def test_reload(self):
- start_networkd(3)
+ start_networkd()
- copy_unit_to_networkd_unit_path('11-dummy.netdev')
- check_output(*networkctl_cmd, 'reload', env=env)
+ copy_network_unit('11-dummy.netdev')
+ networkctl_reload()
self.wait_operstate('test1', 'off', setup_state='unmanaged')
- copy_unit_to_networkd_unit_path('11-dummy.network')
- check_output(*networkctl_cmd, 'reload', env=env)
+ copy_network_unit('11-dummy.network')
+ networkctl_reload()
self.wait_online(['test1:degraded'])
- remove_unit_from_networkd_path(['11-dummy.network'])
- check_output(*networkctl_cmd, 'reload', env=env)
+ remove_network_unit('11-dummy.network')
+ networkctl_reload()
self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
- remove_unit_from_networkd_path(['11-dummy.netdev'])
- check_output(*networkctl_cmd, 'reload', env=env)
+ remove_network_unit('11-dummy.netdev')
+ networkctl_reload()
self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
- check_output(*networkctl_cmd, 'reload', env=env)
+ copy_network_unit('11-dummy.netdev', '11-dummy.network')
+ networkctl_reload()
self.wait_operstate('test1', 'degraded')
def test_glob(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+ copy_network_unit('11-dummy.netdev', '11-dummy.network')
start_networkd()
self.wait_online(['test1:degraded'])
self.assertRegex(output, 'test1')
def test_mtu(self):
- copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
+ copy_network_unit('11-dummy-mtu.netdev', '11-dummy.network')
start_networkd()
self.wait_online(['test1:degraded'])
self.assertRegex(output, 'MTU: 1600')
def test_type(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+ copy_network_unit('11-dummy.netdev', '11-dummy.network')
start_networkd()
self.wait_online(['test1:degraded'])
@expectedFailureIfLinkFileFieldIsNotSet()
def test_udev_link_file(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+ copy_network_unit('11-dummy.netdev', '11-dummy.network')
start_networkd()
self.wait_online(['test1:degraded'])
self.assertRegex(output, r'Network File: n/a')
def test_delete_links(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
- '25-veth.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('11-dummy.netdev', '11-dummy.network',
+ '25-veth.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
- self.assertFalse(link_exists('test1'))
- self.assertFalse(link_exists('veth99'))
- self.assertFalse(link_exists('veth-peer'))
+ self.check_link_exists('test1', expected=False)
+ self.check_link_exists('veth99', expected=False)
+ self.check_link_exists('veth-peer', expected=False)
class NetworkdNetDevTests(unittest.TestCase, Utilities):
- links_remove_earlier = [
- 'xfrm98',
- 'xfrm99',
- ]
-
- links = [
- '6rdtun99',
- 'bareudp99',
- 'batadv99',
- 'bond98',
- 'bond99',
- 'bridge99',
- 'dropin-test',
- 'dummy98',
- 'erspan98',
- 'erspan99',
- 'geneve99',
- 'gretap96',
- 'gretap98',
- 'gretap99',
- 'gretun96',
- 'gretun97',
- 'gretun98',
- 'gretun99',
- 'ifb99',
- 'ip6gretap98',
- 'ip6gretap99',
- 'ip6gretun96',
- 'ip6gretun97',
- 'ip6gretun98',
- 'ip6gretun99',
- 'ip6tnl-external',
- 'ip6tnl-slaac',
- 'ip6tnl97',
- 'ip6tnl98',
- 'ip6tnl99',
- 'ipiptun96',
- 'ipiptun97',
- 'ipiptun98',
- 'ipiptun99',
- 'ipvlan99',
- 'ipvtap99',
- 'isataptun99',
- 'macvlan99',
- 'macvtap99',
- 'nlmon99',
- 'sittun96',
- 'sittun97',
- 'sittun98',
- 'sittun99',
- 'tap99',
- 'test1',
- 'tun99',
- 'vcan99',
- 'veth-mtu',
- 'veth99',
- 'vlan99',
- 'vrf99',
- 'vti6tun97',
- 'vti6tun98',
- 'vti6tun99',
- 'vtitun96',
- 'vtitun97',
- 'vtitun98',
- 'vtitun99',
- 'vxcan99',
- 'vxlan-slaac',
- 'vxlan97',
- 'vxlan98',
- 'vxlan99',
- 'wg97',
- 'wg98',
- 'wg99',
- ]
-
- units = [
- '10-dropin-test.netdev',
- '11-dummy.netdev',
- '11-dummy.network',
- '12-dummy.netdev',
- '13-not-match-udev-property.network',
- '14-match-udev-property.network',
- '15-name-conflict-test.netdev',
- '21-macvlan.netdev',
- '21-macvtap.netdev',
- '21-vlan-test1.network',
- '21-vlan.netdev',
- '21-vlan.network',
- '25-6rd-tunnel.netdev',
- '25-bareudp.netdev',
- '25-batadv.netdev',
- '25-bond.netdev',
- '25-bond-balanced-tlb.netdev',
- '25-bridge.netdev',
- '25-bridge-configure-without-carrier.network',
- '25-bridge.network',
- '25-erspan0-tunnel-local-any.netdev',
- '25-erspan0-tunnel.netdev',
- '25-erspan1-tunnel-local-any.netdev',
- '25-erspan1-tunnel.netdev',
- '25-erspan2-tunnel-local-any.netdev',
- '25-erspan2-tunnel.netdev',
- '25-fou-gretap.netdev',
- '25-fou-gre.netdev',
- '25-fou-ipip.netdev',
- '25-fou-ipproto-gre.netdev',
- '25-fou-ipproto-ipip.netdev',
- '25-fou-sit.netdev',
- '25-geneve.netdev',
- '25-gretap-tunnel-local-any.netdev',
- '25-gretap-tunnel.netdev',
- '25-gre-tunnel-any-any.netdev',
- '25-gre-tunnel-local-any.netdev',
- '25-gre-tunnel-remote-any.netdev',
- '25-gre-tunnel.netdev',
- '25-ifb.netdev',
- '25-ip6gretap-tunnel-local-any.netdev',
- '25-ip6gretap-tunnel.netdev',
- '25-ip6gre-tunnel-any-any.netdev',
- '25-ip6gre-tunnel-local-any.netdev',
- '25-ip6gre-tunnel-remote-any.netdev',
- '25-ip6gre-tunnel.netdev',
- '25-ip6tnl-tunnel-external.netdev',
- '25-ip6tnl-tunnel-local-any.netdev',
- '25-ip6tnl-tunnel-local-slaac.netdev',
- '25-ip6tnl-tunnel-local-slaac.network',
- '25-ip6tnl-tunnel-remote-any.netdev',
- '25-ip6tnl-tunnel.netdev',
- '25-ipip-tunnel-any-any.netdev',
- '25-ipip-tunnel-independent.netdev',
- '25-ipip-tunnel-independent-loopback.netdev',
- '25-ipip-tunnel-local-any.netdev',
- '25-ipip-tunnel-remote-any.netdev',
- '25-ipip-tunnel.netdev',
- '25-ipvlan.netdev',
- '25-ipvtap.netdev',
- '25-isatap-tunnel.netdev',
- '25-macsec.key',
- '25-macsec.netdev',
- '25-macsec.network',
- '25-nlmon.netdev',
- '25-sit-tunnel-any-any.netdev',
- '25-sit-tunnel-local-any.netdev',
- '25-sit-tunnel-remote-any.netdev',
- '25-sit-tunnel.netdev',
- '25-tap.netdev',
- '25-tun.netdev',
- '25-tunnel-any-any.network',
- '25-tunnel-local-any.network',
- '25-tunnel-remote-any.network',
- '25-tunnel.network',
- '25-vcan.netdev',
- '25-veth-mtu.netdev',
- '25-veth.netdev',
- '25-vrf.netdev',
- '25-vti6-tunnel-any-any.netdev',
- '25-vti6-tunnel-local-any.netdev',
- '25-vti6-tunnel-remote-any.netdev',
- '25-vti6-tunnel.netdev',
- '25-vti-tunnel-any-any.netdev',
- '25-vti-tunnel-local-any.netdev',
- '25-vti-tunnel-remote-any.netdev',
- '25-vti-tunnel.netdev',
- '25-vxcan.netdev',
- '25-vxlan-independent.netdev',
- '25-vxlan-ipv6.netdev',
- '25-vxlan-local-slaac.netdev',
- '25-vxlan-local-slaac.network',
- '25-vxlan-veth99.network',
- '25-vxlan.netdev',
- '25-wireguard-23-peers.netdev',
- '25-wireguard-23-peers.network',
- '25-wireguard-no-peer.netdev',
- '25-wireguard-no-peer.network',
- '25-wireguard-preshared-key.txt',
- '25-wireguard-private-key.txt',
- '25-wireguard.netdev',
- '25-wireguard.network',
- '25-xfrm.netdev',
- '25-xfrm-independent.netdev',
- '25-6rd.network',
- '25-erspan.network',
- '25-gre.network',
- '25-gretap.network',
- '25-gretun.network',
- '25-ip6gretap.network',
- '25-ip6gretun.network',
- '25-ip6tnl-slaac.network',
- '25-ip6tnl.network',
- '25-ipip.network',
- '25-ipv6-prefix.network',
- '25-ipvlan.network',
- '25-ipvtap.network',
- '25-isatap.network',
- '26-macsec.network',
- '25-macvlan.network',
- '25-macvtap.network',
- '26-netdev-link-local-addressing-yes.network',
- '25-sit.network',
- '25-vti6.network',
- '25-vti.network',
- '25-vxlan-ipv6.network',
- '25-vxlan-test1.network',
- '25-vxlan.network',
- '25-xfrm.network',
- ]
-
- fou_ports = [
- '55555',
- '55556']
-
def setUp(self):
- remove_fou_ports(self.fou_ports)
- remove_links(self.links_remove_earlier)
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_fou_ports(self.fou_ports)
- remove_links(self.links_remove_earlier)
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_dropin_and_name_conflict(self):
- copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
+ copy_network_unit('10-dropin-test.netdev', '15-name-conflict-test.netdev')
start_networkd()
self.wait_online(['dropin-test:off'], setup_state='unmanaged')
self.assertRegex(output, '00:50:56:c0:00:28')
def test_match_udev_property(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
+ copy_network_unit('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
start_networkd()
self.wait_online(['dummy98:routable'])
self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
def test_wait_online_any(self):
- copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
+ copy_network_unit('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
start_networkd()
self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
@expectedFailureIfModuleIsNotAvailable('bareudp')
def test_bareudp(self):
- copy_unit_to_networkd_unit_path('25-bareudp.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-bareudp.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['bareudp99:degraded'])
@expectedFailureIfModuleIsNotAvailable('batman-adv')
def test_batadv(self):
- copy_unit_to_networkd_unit_path('25-batadv.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-batadv.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['batadv99:degraded'])
self.assertRegex(output, 'batadv')
def test_bridge(self):
- copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
+ copy_network_unit('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
start_networkd()
self.wait_online(['bridge99:no-carrier'])
self.assertIn('vlan_default_pvid 9 ', output)
def test_bond(self):
- copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
+ copy_network_unit('25-bond.netdev', '25-bond-balanced-tlb.netdev')
start_networkd()
self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
- self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
- self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
- self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
- self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
- self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
- self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
- self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
- self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
- self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
- self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
- self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
-
- self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
- self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
+ self.check_link_attr('bond99', 'bonding', 'mode', '802.3ad 4')
+ self.check_link_attr('bond99', 'bonding', 'xmit_hash_policy', 'layer3+4 1')
+ self.check_link_attr('bond99', 'bonding', 'miimon', '1000')
+ self.check_link_attr('bond99', 'bonding', 'lacp_rate', 'fast 1')
+ self.check_link_attr('bond99', 'bonding', 'updelay', '2000')
+ self.check_link_attr('bond99', 'bonding', 'downdelay', '2000')
+ self.check_link_attr('bond99', 'bonding', 'resend_igmp', '4')
+ self.check_link_attr('bond99', 'bonding', 'min_links', '1')
+ self.check_link_attr('bond99', 'bonding', 'ad_actor_sys_prio', '1218')
+ self.check_link_attr('bond99', 'bonding', 'ad_user_port_key', '811')
+ self.check_link_attr('bond99', 'bonding', 'ad_actor_system', '00:11:22:33:44:55')
+
+ self.check_link_attr('bond98', 'bonding', 'mode', 'balance-tlb 5')
+ self.check_link_attr('bond98', 'bonding', 'tlb_dynamic_lb', '1')
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bond99', env=env)
print(output)
self.assertIn('Mode: balance-tlb', output)
def test_vlan(self):
- copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
- '21-vlan.network', '21-vlan-test1.network')
+ copy_network_unit('21-vlan.netdev', '11-dummy.netdev',
+ '21-vlan.network', '21-vlan-test1.network')
start_networkd()
self.wait_online(['test1:degraded', 'vlan99:routable'])
self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
def test_macvtap(self):
+ first = True
for mode in ['private', 'vepa', 'bridge', 'passthru']:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_macvtap(mode={mode})')
with self.subTest(mode=mode):
- if mode != 'private':
- self.tearDown()
- copy_unit_to_networkd_unit_path('21-macvtap.netdev', '26-netdev-link-local-addressing-yes.network',
- '11-dummy.netdev', '25-macvtap.network')
- with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a', encoding='utf-8') as f:
+ copy_network_unit('21-macvtap.netdev', '26-netdev-link-local-addressing-yes.network',
+ '11-dummy.netdev', '25-macvtap.network')
+ with open(os.path.join(network_unit_dir, '21-macvtap.netdev'), mode='a', encoding='utf-8') as f:
f.write('[MACVTAP]\nMode=' + mode)
start_networkd()
self.assertRegex(output, 'macvtap mode ' + mode + ' ')
def test_macvlan(self):
+ first = True
for mode in ['private', 'vepa', 'bridge', 'passthru']:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_macvlan(mode={mode})')
with self.subTest(mode=mode):
- if mode != 'private':
- self.tearDown()
- copy_unit_to_networkd_unit_path('21-macvlan.netdev', '26-netdev-link-local-addressing-yes.network',
- '11-dummy.netdev', '25-macvlan.network')
- with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a', encoding='utf-8') as f:
+ copy_network_unit('21-macvlan.netdev', '26-netdev-link-local-addressing-yes.network',
+ '11-dummy.netdev', '25-macvlan.network')
+ with open(os.path.join(network_unit_dir, '21-macvlan.netdev'), mode='a', encoding='utf-8') as f:
f.write('[MACVLAN]\nMode=' + mode)
start_networkd()
self.assertRegex(output, ' mtu 2000 ')
self.assertRegex(output, 'macvlan mode ' + mode + ' ')
- rc = call("ip link del test1")
- self.assertEqual(rc, 0)
- time.sleep(1)
-
- rc = call("ip link add test1 type dummy")
- self.assertEqual(rc, 0)
+ remove_link('test1')
time.sleep(1)
+ check_output("ip link add test1 type dummy")
self.wait_online(['macvlan99:degraded',
'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
@expectedFailureIfModuleIsNotAvailable('ipvlan')
def test_ipvlan(self):
+ first = True
for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_ipvlan(mode={mode}, flag={flag})')
with self.subTest(mode=mode, flag=flag):
- if mode != 'L2':
- self.tearDown()
- copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '26-netdev-link-local-addressing-yes.network',
- '11-dummy.netdev', '25-ipvlan.network')
- with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a', encoding='utf-8') as f:
+ copy_network_unit('25-ipvlan.netdev', '26-netdev-link-local-addressing-yes.network',
+ '11-dummy.netdev', '25-ipvlan.network')
+ with open(os.path.join(network_unit_dir, '25-ipvlan.netdev'), mode='a', encoding='utf-8') as f:
f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
start_networkd()
@expectedFailureIfModuleIsNotAvailable('ipvtap')
def test_ipvtap(self):
+ first = True
for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_ipvtap(mode={mode}, flag={flag})')
with self.subTest(mode=mode, flag=flag):
- if mode != 'L2':
- self.tearDown()
- copy_unit_to_networkd_unit_path('25-ipvtap.netdev', '26-netdev-link-local-addressing-yes.network',
- '11-dummy.netdev', '25-ipvtap.network')
- with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a', encoding='utf-8') as f:
+ copy_network_unit('25-ipvtap.netdev', '26-netdev-link-local-addressing-yes.network',
+ '11-dummy.netdev', '25-ipvtap.network')
+ with open(os.path.join(network_unit_dir, '25-ipvtap.netdev'), mode='a', encoding='utf-8') as f:
f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
start_networkd()
self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
def test_veth(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '26-netdev-link-local-addressing-yes.network',
- '25-veth-mtu.netdev')
+ copy_network_unit('25-veth.netdev', '26-netdev-link-local-addressing-yes.network',
+ '25-veth-mtu.netdev')
start_networkd()
self.wait_online(['veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded'])
self.assertRegex(output, 'mtu 1800')
def test_tun(self):
- copy_unit_to_networkd_unit_path('25-tun.netdev')
+ copy_network_unit('25-tun.netdev')
start_networkd()
self.wait_online(['tun99:off'], setup_state='unmanaged')
self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
def test_tap(self):
- copy_unit_to_networkd_unit_path('25-tap.netdev')
+ copy_network_unit('25-tap.netdev')
start_networkd()
self.wait_online(['tap99:off'], setup_state='unmanaged')
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_vrf(self):
- copy_unit_to_networkd_unit_path('25-vrf.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-vrf.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['vrf99:carrier'])
@expectedFailureIfModuleIsNotAvailable('vcan')
def test_vcan(self):
- copy_unit_to_networkd_unit_path('25-vcan.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-vcan.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['vcan99:carrier'])
@expectedFailureIfModuleIsNotAvailable('vxcan')
def test_vxcan(self):
- copy_unit_to_networkd_unit_path('25-vxcan.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-vxcan.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
@expectedFailureIfModuleIsNotAvailable('wireguard')
def test_wireguard(self):
- copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
- '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
- '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
- '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
+ copy_network_unit('25-wireguard.netdev', '25-wireguard.network',
+ '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
+ '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
+ '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
start_networkd()
self.wait_online(['wg99:routable', 'wg98:routable', 'wg97:carrier'])
self.assertEqual(output, '0x4d3')
def test_geneve(self):
- copy_unit_to_networkd_unit_path('25-geneve.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-geneve.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['geneve99:degraded'])
self.assertRegex(output, 'udp6zerocsumrx')
def test_ipip_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip.network',
- '25-ipip-tunnel.netdev', '25-tunnel.network',
- '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
+ copy_network_unit('12-dummy.netdev', '25-ipip.network',
+ '25-ipip-tunnel.netdev', '25-tunnel.network',
+ '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
def test_gre_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretun.network',
- '25-gre-tunnel.netdev', '25-tunnel.network',
- '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
+ copy_network_unit('12-dummy.netdev', '25-gretun.network',
+ '25-gre-tunnel.netdev', '25-tunnel.network',
+ '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
self.assertNotRegex(output, 'oseq')
def test_ip6gre_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretun.network',
- '25-ip6gre-tunnel.netdev', '25-tunnel.network',
- '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
- start_networkd(5)
+ copy_network_unit('12-dummy.netdev', '25-ip6gretun.network',
+ '25-ip6gre-tunnel.netdev', '25-tunnel.network',
+ '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
+ start_networkd()
# Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
- self.check_link_exists('dummy98')
- self.check_link_exists('ip6gretun99')
- self.check_link_exists('ip6gretun98')
- self.check_link_exists('ip6gretun97')
- self.check_link_exists('ip6gretun96')
+ self.wait_links('dummy98', 'ip6gretun99', 'ip6gretun98', 'ip6gretun97', 'ip6gretun96')
output = check_output('ip -d link show ip6gretun99')
print(output)
self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
def test_gretap_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap.network',
- '25-gretap-tunnel.netdev', '25-tunnel.network',
- '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+ copy_network_unit('12-dummy.netdev', '25-gretap.network',
+ '25-gretap-tunnel.netdev', '25-tunnel.network',
+ '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
self.assertRegex(output, 'oseq')
def test_ip6gretap_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretap.network',
- '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
- '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+ copy_network_unit('12-dummy.netdev', '25-ip6gretap.network',
+ '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
+ '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
def test_vti_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti.network',
- '25-vti-tunnel.netdev', '25-tunnel.network',
- '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
+ copy_network_unit('12-dummy.netdev', '25-vti.network',
+ '25-vti-tunnel.netdev', '25-tunnel.network',
+ '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
self.assertRegex(output, 'vti remote any local any dev dummy98')
def test_vti6_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6.network',
- '25-vti6-tunnel.netdev', '25-tunnel.network',
- '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+ copy_network_unit('12-dummy.netdev', '25-vti6.network',
+ '25-vti6-tunnel.netdev', '25-tunnel.network',
+ '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
start_networkd()
self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
def test_ip6tnl_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl.network',
- '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
- '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network',
- '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network',
- '25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('12-dummy.netdev', '25-ip6tnl.network',
+ '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
+ '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network',
+ '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network',
+ '25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable',
'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded',
self.assertIn('default dev ip6tnl-slaac proto static', output)
def test_sit_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit.network',
- '25-sit-tunnel.netdev', '25-tunnel.network',
- '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
- '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
- '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
+ copy_network_unit('12-dummy.netdev', '25-sit.network',
+ '25-sit-tunnel.netdev', '25-tunnel.network',
+ '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+ '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
+ '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
def test_isatap_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap.network',
- '25-isatap-tunnel.netdev', '25-tunnel.network')
+ copy_network_unit('12-dummy.netdev', '25-isatap.network',
+ '25-isatap-tunnel.netdev', '25-tunnel.network')
start_networkd()
self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
self.assertRegex(output, "isatap ")
def test_6rd_tunnel(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd.network',
- '25-6rd-tunnel.netdev', '25-tunnel.network')
+ copy_network_unit('12-dummy.netdev', '25-6rd.network',
+ '25-6rd-tunnel.netdev', '25-tunnel.network')
start_networkd()
self.wait_online(['sittun99:routable', 'dummy98:degraded'])
@expectedFailureIfERSPANv0IsNotSupported()
def test_erspan_tunnel_v0(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network',
- '25-erspan0-tunnel.netdev', '25-tunnel.network',
- '25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+ copy_network_unit('12-dummy.netdev', '25-erspan.network',
+ '25-erspan0-tunnel.netdev', '25-tunnel.network',
+ '25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
self.assertIn('iseq', output)
def test_erspan_tunnel_v1(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network',
- '25-erspan1-tunnel.netdev', '25-tunnel.network',
- '25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+ copy_network_unit('12-dummy.netdev', '25-erspan.network',
+ '25-erspan1-tunnel.netdev', '25-tunnel.network',
+ '25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
@expectedFailureIfERSPANv2IsNotSupported()
def test_erspan_tunnel_v2(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network',
- '25-erspan2-tunnel.netdev', '25-tunnel.network',
- '25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+ copy_network_unit('12-dummy.netdev', '25-erspan.network',
+ '25-erspan2-tunnel.netdev', '25-tunnel.network',
+ '25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
self.assertIn('oseq', output)
def test_tunnel_independent(self):
- copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['ipiptun99:carrier'])
def test_tunnel_independent_loopback(self):
- copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['ipiptun99:carrier'])
@expectedFailureIfModuleIsNotAvailable('xfrm_interface')
def test_xfrm(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-xfrm.network',
- '25-xfrm.netdev', '25-xfrm-independent.netdev',
- '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('12-dummy.netdev', '25-xfrm.network',
+ '25-xfrm.netdev', '25-xfrm-independent.netdev',
+ '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded'])
# Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
self.assertTrue(is_module_available('fou'))
- copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
- '25-fou-ipip.netdev', '25-fou-sit.netdev',
- '25-fou-gre.netdev', '25-fou-gretap.netdev')
+ copy_network_unit('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
+ '25-fou-ipip.netdev', '25-fou-sit.netdev',
+ '25-fou-gre.netdev', '25-fou-gretap.netdev')
start_networkd()
self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
def test_vxlan(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-vxlan-test1.network',
- '25-vxlan.netdev', '25-vxlan.network',
- '25-vxlan-ipv6.netdev', '25-vxlan-ipv6.network',
- '25-vxlan-independent.netdev', '26-netdev-link-local-addressing-yes.network',
- '25-veth.netdev', '25-vxlan-veth99.network', '25-ipv6-prefix.network',
- '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
+ copy_network_unit('11-dummy.netdev', '25-vxlan-test1.network',
+ '25-vxlan.netdev', '25-vxlan.network',
+ '25-vxlan-ipv6.netdev', '25-vxlan-ipv6.network',
+ '25-vxlan-independent.netdev', '26-netdev-link-local-addressing-yes.network',
+ '25-veth.netdev', '25-vxlan-veth99.network', '25-ipv6-prefix.network',
+ '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
start_networkd()
self.wait_online(['test1:degraded', 'veth99:routable', 'veth-peer:degraded',
@unittest.skip(reason="Causes kernel panic on recent kernels: https://bugzilla.kernel.org/show_bug.cgi?id=208315")
def test_macsec(self):
- copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
- '26-macsec.network', '12-dummy.netdev')
+ copy_network_unit('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
+ '26-macsec.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded', 'macsec99:routable'])
self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
def test_nlmon(self):
- copy_unit_to_networkd_unit_path('25-nlmon.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-nlmon.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['nlmon99:carrier'])
@expectedFailureIfModuleIsNotAvailable('ifb')
def test_ifb(self):
- copy_unit_to_networkd_unit_path('25-ifb.netdev', '26-netdev-link-local-addressing-yes.network')
+ copy_network_unit('25-ifb.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online(['ifb99:degraded'])
class NetworkdL2TPTests(unittest.TestCase, Utilities):
- links =[
- 'l2tp-ses1',
- 'l2tp-ses2',
- 'l2tp-ses3',
- 'l2tp-ses4',
- 'test1']
-
- units = [
- '11-dummy.netdev',
- '25-l2tp-dummy.network',
- '25-l2tp.network',
- '25-l2tp-ip.netdev',
- '25-l2tp-udp.netdev']
-
- l2tp_tunnel_ids = [ '10' ]
-
def setUp(self):
- remove_l2tp_tunnels(self.l2tp_tunnel_ids)
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_l2tp_tunnels(self.l2tp_tunnel_ids)
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
@expectedFailureIfModuleIsNotAvailable('l2tp_eth')
def test_l2tp_udp(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
- '25-l2tp-udp.netdev', '25-l2tp.network')
+ copy_network_unit('11-dummy.netdev', '25-l2tp-dummy.network',
+ '25-l2tp-udp.netdev', '25-l2tp.network')
start_networkd()
self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
@expectedFailureIfModuleIsNotAvailable('l2tp_ip')
def test_l2tp_ip(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
- '25-l2tp-ip.netdev', '25-l2tp.network')
+ copy_network_unit('11-dummy.netdev', '25-l2tp-dummy.network',
+ '25-l2tp-ip.netdev', '25-l2tp.network')
start_networkd()
self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
self.assertRegex(output, "interface name: l2tp-ses4")
class NetworkdNetworkTests(unittest.TestCase, Utilities):
- links = [
- 'bond199',
- 'dummy98',
- 'dummy99',
- 'gretun97',
- 'ip6gretun97',
- 'test1',
- 'veth-peer',
- 'veth99',
- 'vlan99',
- 'vrf99',
- ]
-
- units = [
- '11-dummy.netdev',
- '12-dummy.netdev',
- '12-dummy.network',
- '21-vlan.netdev',
- '21-vlan-test1.network',
- '23-active-slave.network',
- '24-keep-configuration-static.network',
- '24-search-domain.network',
- '25-address-ipv4acd-veth99.network',
- '25-address-link-section.network',
- '25-address-peer-ipv4.network',
- '25-address-static.network',
- '25-activation-policy.network',
- '25-bind-carrier.network',
- '25-bond-active-backup-slave.netdev',
- '25-fibrule-invert.network',
- '25-fibrule-port-range.network',
- '25-fibrule-uidrange.network',
- '25-gre-tunnel-remote-any.netdev',
- '25-ip6gre-tunnel-remote-any.netdev',
- '25-ipv6-address-label-section.network',
- '25-ipv6-proxy-ndp.network',
- '25-link-local-addressing-no.network',
- '25-link-local-addressing-yes.network',
- '25-link-section-unmanaged.network',
- '25-neighbor-section.network',
- '25-neighbor-next.network',
- '25-neighbor-ipv6.network',
- '25-neighbor-ip-dummy.network',
- '25-neighbor-ip.network',
- '25-nexthop-dummy.network',
- '25-nexthop-nothing.network',
- '25-nexthop.network',
- '25-qdisc-cake.network',
- '25-qdisc-clsact-and-htb.network',
- '25-qdisc-drr.network',
- '25-qdisc-ets.network',
- '25-qdisc-fq_pie.network',
- '25-qdisc-hhf.network',
- '25-qdisc-ingress-netem-compat.network',
- '25-qdisc-pie.network',
- '25-qdisc-qfq.network',
- '25-prefix-route-with-vrf.network',
- '25-prefix-route-without-vrf.network',
- '25-route-ipv6-src.network',
- '25-route-static.network',
- '25-route-via-ipv6.network',
- '25-route-vrf.network',
- '25-gateway-static.network',
- '25-gateway-next-static.network',
- '25-sysctl-disable-ipv6.network',
- '25-sysctl.network',
- '25-test1.network',
- '25-veth-peer.network',
- '25-veth.netdev',
- '25-vrf.netdev',
- '25-vrf.network',
- '26-link-local-addressing-ipv6.network',
- '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network',
- '25-dhcp-server-with-ipv6-prefix.network',
- '25-ipv6ra-prefix-client-with-static-ipv4-address.network',
- '25-ipv6-prefix-with-delay.network',
- '25-routing-policy-rule-dummy98.network',
- '25-routing-policy-rule-test1.network',
- '25-routing-policy-rule-reconfigure1.network',
- '25-routing-policy-rule-reconfigure2.network',
- ]
-
- networkd_conf_dropins = [
- 'networkd-manage-foreign-routes-no.conf',
- ]
-
- routing_policy_rule_tables = ['7', '8', '9', '10', '1011']
- routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
def setUp(self):
- remove_blackhole_nexthops()
- remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
- remove_routes(self.routes)
- remove_links(self.links)
- stop_networkd(show_logs=False)
- call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ setup_common()
def tearDown(self):
- remove_blackhole_nexthops()
- remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
- remove_routes(self.routes)
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- remove_networkd_conf_dropin(self.networkd_conf_dropins)
- stop_networkd(show_logs=True)
- call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ tear_down_common()
def test_address_static(self):
# test for #22515. The address will be removed and replaced with /64 prefix.
- rc = call('ip link add dummy98 type dummy')
- self.assertEqual(rc, 0)
- rc = call('ip link set dev dummy98 up')
- self.assertEqual(rc, 0)
- rc = call('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98')
- self.assertEqual(rc, 0)
+ check_output('ip link add dummy98 type dummy')
+ check_output('ip link set dev dummy98 up')
+ check_output('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98')
self.wait_address('dummy98', '2001:db8:0:f101::15/128', ipv='-6')
- rc = call('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98')
- self.assertEqual(rc, 0)
+ check_output('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98')
self.wait_address('dummy98', '10.3.2.3/16 brd 10.3.255.250', ipv='-4')
- copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
+ copy_network_unit('25-address-static.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
self.assertRegex(output, 'inet 10.9.0.1/16 (metric 128 |)brd 10.9.255.255 scope global dummy98')
# test for ENOBUFS issue #17012
- for i in range(1,254):
+ for i in range(1, 254):
self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
# invalid sections
# Tests for #20891.
# 1. set preferred lifetime forever to drop the deprecated flag for testing #20891.
- self.assertEqual(call('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever'), 0)
- self.assertEqual(call('ip address change 2001:db8:1:f101::1/64 dev dummy98 preferred_lft forever'), 0)
+ check_output('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever')
+ check_output('ip address change 2001:db8:1:f101::1/64 dev dummy98 preferred_lft forever')
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertNotIn('deprecated', output)
self.assertNotIn('deprecated', output)
# 2. reconfigure the interface.
- check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
+ networkctl_reconfigure('dummy98')
self.wait_online(['dummy98:routable'])
# 3. check the deprecated flag is set for the address configured with PreferredLifetime=0
# test for ENOBUFS issue #17012
output = check_output('ip -4 address show dev dummy98')
- for i in range(1,254):
+ for i in range(1, 254):
self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
# TODO: check json string
check_output('ip netns exec ns99 ip link set veth-peer up')
check_output('ip netns exec ns99 ip address add 192.168.100.10/24 dev veth-peer')
- copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network', dropins=False)
+ copy_network_unit('25-address-ipv4acd-veth99.network', copy_dropins=False)
start_networkd()
self.wait_online(['veth99:routable'])
self.assertNotIn('192.168.100.10/24', output)
self.assertIn('192.168.100.11/24', output)
- copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network.d/conflict-address.conf')
- run(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ copy_network_unit('25-address-ipv4acd-veth99.network.d/conflict-address.conf')
+ networkctl_reload()
self.wait_operstate('veth99', operstate='routable', setup_state='configuring', setup_timeout=10)
output = check_output('ip -4 address show dev veth99')
def test_address_peer_ipv4(self):
# test for issue #17304
- copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev')
+ copy_network_unit('25-address-peer-ipv4.network', '12-dummy.netdev')
for trial in range(2):
if trial == 0:
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_prefix_route(self):
- copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
- '25-prefix-route-without-vrf.network', '11-dummy.netdev',
- '25-vrf.netdev', '25-vrf.network')
+ copy_network_unit('25-prefix-route-with-vrf.network', '12-dummy.netdev',
+ '25-prefix-route-without-vrf.network', '11-dummy.netdev',
+ '25-vrf.netdev', '25-vrf.network')
for trial in range(2):
if trial == 0:
start_networkd()
else:
- restart_networkd(3)
+ restart_networkd()
self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
def test_configure_without_carrier(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev')
+ copy_network_unit('11-dummy.netdev')
start_networkd()
self.wait_operstate('test1', 'off', '')
check_output('ip link set dev test1 up carrier off')
- copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
+ copy_network_unit('25-test1.network.d/configure-without-carrier.conf', copy_dropins=False)
restart_networkd()
self.wait_online(['test1:no-carrier'])
self.assertRegex(output, routable_map[carrier])
def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev')
+ copy_network_unit('11-dummy.netdev')
start_networkd()
self.wait_operstate('test1', 'off', '')
check_output('ip link set dev test1 up carrier off')
- copy_unit_to_networkd_unit_path('25-test1.network')
+ copy_network_unit('25-test1.network')
restart_networkd()
self.wait_online(['test1:no-carrier'])
self.assertRegex(output, routable_map[carrier])
def test_routing_policy_rule(self):
- copy_unit_to_networkd_unit_path('25-routing-policy-rule-test1.network', '11-dummy.netdev')
+ copy_network_unit('25-routing-policy-rule-test1.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded'])
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
def test_routing_policy_rule_issue_11280(self):
- copy_unit_to_networkd_unit_path('25-routing-policy-rule-test1.network', '11-dummy.netdev',
- '25-routing-policy-rule-dummy98.network', '12-dummy.netdev')
+ copy_network_unit('25-routing-policy-rule-test1.network', '11-dummy.netdev',
+ '25-routing-policy-rule-dummy98.network', '12-dummy.netdev')
- for _ in range(3):
- # Remove state files only first time
- start_networkd(3)
+ for trial in range(3):
+ restart_networkd(show_logs=(trial > 0))
self.wait_online(['test1:degraded', 'dummy98:degraded'])
- time.sleep(1)
output = check_output('ip rule list table 7')
print(output)
print(output)
self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
- stop_networkd(remove_state_files=False)
-
def test_routing_policy_rule_reconfigure(self):
- copy_unit_to_networkd_unit_path('25-routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
+ copy_network_unit('25-routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded'])
print(output)
self.assertIn('10112: from all oif test1 lookup 1011', output)
- copy_unit_to_networkd_unit_path('25-routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
- run(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ copy_network_unit('25-routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
+ networkctl_reload()
self.wait_online(['test1:degraded'])
output = check_output('ip rule list table 1011')
self.assertNotIn('10112: from all oif test1 lookup 1011', output)
self.assertIn('10113: from all iif test1 lookup 1011', output)
- run('ip rule delete priority 10111')
- run('ip rule delete priority 10112')
- run('ip rule delete priority 10113')
- run('ip rule delete priority 10114')
- run('ip -6 rule delete priority 10113')
+ call('ip rule delete priority 10111')
+ call('ip rule delete priority 10112')
+ call('ip rule delete priority 10113')
+ call('ip rule delete priority 10114')
+ call('ip -6 rule delete priority 10113')
output = check_output('ip rule list table 1011')
print(output)
print(output)
self.assertEqual(output, '')
- run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
+ networkctl_reconfigure('test1')
self.wait_online(['test1:degraded'])
output = check_output('ip rule list table 1011')
@expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
def test_routing_policy_rule_port_range(self):
- copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
+ copy_network_unit('25-fibrule-port-range.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded'])
@expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
def test_routing_policy_rule_invert(self):
- copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
+ copy_network_unit('25-fibrule-invert.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded'])
@expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
def test_routing_policy_rule_uidrange(self):
- copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
+ copy_network_unit('25-fibrule-uidrange.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded'])
if not manage_foreign_routes:
copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf')
- copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
+ copy_network_unit('25-route-static.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
# TODO: check json string
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
- copy_unit_to_networkd_unit_path('25-address-static.network')
- check_output(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ copy_network_unit('25-address-static.network')
+ networkctl_reload()
self.wait_online(['dummy98:routable'])
# check all routes managed by Manager are removed
print(output)
self.assertEqual(output, '')
- remove_unit_from_networkd_path(['25-address-static.network'])
- check_output(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ remove_network_unit('25-address-static.network')
+ networkctl_reload()
self.wait_online(['dummy98:routable'])
# check all routes managed by Manager are reconfigured
print(output)
self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
- rc = call("ip link del dummy98")
- self.assertEqual(rc, 0)
+ remove_link('dummy98')
time.sleep(2)
# check all routes managed by Manager are removed
self.tearDown()
def test_route_static(self):
+ first = True
for manage_foreign_routes in [True, False]:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_route_static(manage_foreign_routes={manage_foreign_routes})')
with self.subTest(manage_foreign_routes=manage_foreign_routes):
self._test_route_static(manage_foreign_routes)
@expectedFailureIfRTA_VIAIsNotSupported()
def test_route_via_ipv6(self):
- copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
+ copy_network_unit('25-route-via-ipv6.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_route_vrf(self):
- copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
- '25-vrf.netdev', '25-vrf.network')
+ copy_network_unit('25-route-vrf.network', '12-dummy.netdev',
+ '25-vrf.netdev', '25-vrf.network')
start_networkd()
self.wait_online(['dummy98:routable', 'vrf99:carrier'])
self.assertNotRegex(output, 'default via 192.168.100.1')
def test_gateway_reconfigure(self):
- copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
+ copy_network_unit('25-gateway-static.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
print('### ip -4 route show dev dummy98 default')
output = check_output('ip -4 route show dev dummy98 default')
print(output)
- self.assertRegex(output, 'default via 149.10.124.59 proto static')
- self.assertNotRegex(output, '149.10.124.60')
+ self.assertIn('default via 149.10.124.59 proto static', output)
+ self.assertNotIn('149.10.124.60', output)
- remove_unit_from_networkd_path(['25-gateway-static.network'])
- copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
- restart_networkd(3)
+ remove_network_unit('25-gateway-static.network')
+ copy_network_unit('25-gateway-next-static.network')
+ networkctl_reload()
self.wait_online(['dummy98:routable'])
print('### ip -4 route show dev dummy98 default')
output = check_output('ip -4 route show dev dummy98 default')
print(output)
- self.assertNotRegex(output, '149.10.124.59')
- self.assertRegex(output, 'default via 149.10.124.60 proto static')
+ self.assertNotIn('149.10.124.59', output)
+ self.assertIn('default via 149.10.124.60 proto static', output)
def test_ip_route_ipv6_src_route(self):
# a dummy device does not make the addresses go through tentative state, so we
# reuse a bond from an earlier test, which does make the addresses go through
# tentative state, and do our test on that
- copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
+ copy_network_unit('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:enslaved', 'bond199:routable'])
self.assertRegex(output, '2001:1234:56:8f63::2')
def test_ip_link_mac_address(self):
- copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
+ copy_network_unit('25-address-link-section.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'])
self.assertRegex(output, '00:01:02:aa:bb:cc')
def test_ip_link_unmanaged(self):
- copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
- start_networkd(5)
-
- self.check_link_exists('dummy98')
+ copy_network_unit('25-link-section-unmanaged.network', '12-dummy.netdev')
+ start_networkd()
self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
def test_ipv6_address_label(self):
- copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
+ copy_network_unit('25-ipv6-address-label-section.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'])
self.assertRegex(output, '2004:da8:1::/64')
def test_ipv6_proxy_ndp(self):
- copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
+ copy_network_unit('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('ip neighbor show proxy dev dummy98')
print(output)
- for i in range(1,5):
+ for i in range(1, 5):
self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
def test_neighbor_section(self):
- copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
+ copy_network_unit('25-neighbor-section.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'], timeout='40s')
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
def test_neighbor_reconfigure(self):
- copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
+ copy_network_unit('25-neighbor-section.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'], timeout='40s')
self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
- remove_unit_from_networkd_path(['25-neighbor-section.network'])
- copy_unit_to_networkd_unit_path('25-neighbor-next.network')
- restart_networkd(3)
+ remove_network_unit('25-neighbor-section.network')
+ copy_network_unit('25-neighbor-next.network')
+ networkctl_reload()
self.wait_online(['dummy98:degraded'], timeout='40s')
print('### ip neigh list dev dummy98')
output = check_output('ip neigh list dev dummy98')
self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
def test_neighbor_gre(self):
- copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
- '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
+ copy_network_unit('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
+ '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
start_networkd()
self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
def test_link_local_addressing(self):
- copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
- '25-link-local-addressing-no.network', '12-dummy.netdev')
+ copy_network_unit('25-link-local-addressing-yes.network', '11-dummy.netdev',
+ '25-link-local-addressing-no.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['test1:degraded', 'dummy98:carrier'])
# stable_secret (RFC7217)
# 3: generate stable privacy addresses, using a random secret if unset
- self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
- self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
+ self.check_ipv6_sysctl_attr('test1', 'stable_secret', '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
+ self.check_ipv6_sysctl_attr('test1', 'addr_gen_mode', '2')
+ self.check_ipv6_sysctl_attr('dummy98', 'addr_gen_mode', '1')
def test_link_local_addressing_ipv6ll(self):
- copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
+ copy_network_unit('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'])
print(output)
self.assertRegex(output, 'inet6 .* scope link')
- copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
- check_output(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ copy_network_unit('25-link-local-addressing-no.network')
+ networkctl_reload()
self.wait_online(['dummy98:carrier'])
# Check if the IPv6LL address is removed.
print(output)
self.assertNotRegex(output, 'inet6 .* scope link')
- remove_unit_from_networkd_path(['25-link-local-addressing-no.network'])
- check_output(*networkctl_cmd, 'reload', env=env)
- time.sleep(1)
+ remove_network_unit('25-link-local-addressing-no.network')
+ networkctl_reload()
self.wait_online(['dummy98:degraded'])
# Check if a new IPv6LL address is assigned.
self.assertRegex(output, 'inet6 .* scope link')
def test_sysctl(self):
- copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
+ copy_network_unit('25-sysctl.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:degraded'])
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
- self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
- self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
- self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
+ self.check_ipv6_sysctl_attr('dummy98', 'forwarding', '1')
+ self.check_ipv6_sysctl_attr('dummy98', 'use_tempaddr', '2')
+ self.check_ipv6_sysctl_attr('dummy98', 'dad_transmits', '3')
+ self.check_ipv6_sysctl_attr('dummy98', 'hop_limit', '5')
+ self.check_ipv6_sysctl_attr('dummy98', 'proxy_ndp', '1')
+ self.check_ipv4_sysctl_attr('dummy98', 'forwarding', '1')
+ self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1')
+ self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1')
def test_sysctl_disable_ipv6(self):
- copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
+ copy_network_unit('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
print('## Disable ipv6')
check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
self.assertRegex(output, 'default')
self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
- check_output('ip link del dummy98')
+ remove_link('dummy98')
print('## Enable ipv6')
check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
- restart_networkd(3)
+ restart_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dummy98')
check_output('ip link set dummy98 up')
time.sleep(2)
- copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
+ copy_network_unit('25-bind-carrier.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['test1:routable'])
self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
self.wait_operstate('test1', 'routable')
- check_output('ip link del dummy98')
+ remove_link('dummy98')
time.sleep(2)
output = check_output('ip address show test1')
print(output)
self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
self.wait_operstate('test1', 'routable')
- def _test_activation_policy(self, test, interface):
+ def _test_activation_policy(self, interface, test):
conffile = '25-activation-policy.network'
if test:
conffile = f'{conffile}.d/{test}.conf'
if interface == 'vlan99':
- copy_unit_to_networkd_unit_path('21-vlan.netdev', '21-vlan-test1.network')
- copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
+ copy_network_unit('21-vlan.netdev', '21-vlan-test1.network')
+ copy_network_unit('11-dummy.netdev', conffile, copy_dropins=False)
start_networkd()
always = test.startswith('always')
time.sleep(1)
def test_activation_policy(self):
+ first = True
for interface in ['test1', 'vlan99']:
- with self.subTest(interface=interface):
- for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
- with self.subTest(test=test):
- self.setUp()
- self._test_activation_policy(test, interface)
- self.tearDown()
+ for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_activation_policy(interface={interface}, test={test})')
+ with self.subTest(interface=interface, test=test):
+ self._test_activation_policy(interface, test)
def _test_activation_policy_required_for_online(self, policy, required):
conffile = '25-activation-policy.network'
units += [f'{conffile}.d/{policy}.conf']
if required:
units += [f'{conffile}.d/required-{required}.conf']
- copy_unit_to_networkd_unit_path(*units, dropins=False)
+ copy_network_unit(*units, copy_dropins=False)
start_networkd()
if policy.endswith('down'):
self.assertRegex(output, f'Required For Online: {yesno}')
def test_activation_policy_required_for_online(self):
+ first = True
for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']:
for required in ['yes', 'no', '']:
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_activation_policy_required_for_online(policy={policy}, required={required})')
with self.subTest(policy=policy, required=required):
- self.setUp()
self._test_activation_policy_required_for_online(policy, required)
- self.tearDown()
def test_domain(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
+ copy_network_unit('12-dummy.netdev', '24-search-domain.network')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('ip route show dev dummy98')
print(output)
- copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
+ copy_network_unit('24-keep-configuration-static.network')
start_networkd()
self.wait_online(['dummy98:routable'])
# TODO: check json string
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
- copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
- '12-dummy.netdev', '25-nexthop-dummy.network')
+ copy_network_unit('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
+ '12-dummy.netdev', '25-nexthop-dummy.network')
start_networkd()
check_nexthop(self)
- remove_unit_from_networkd_path(['25-nexthop.network'])
- copy_unit_to_networkd_unit_path('25-nexthop-nothing.network')
- rc = call(*networkctl_cmd, 'reload', env=env)
- self.assertEqual(rc, 0)
- time.sleep(1)
-
+ remove_network_unit('25-nexthop.network')
+ copy_network_unit('25-nexthop-nothing.network')
+ networkctl_reload()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip nexthop list dev veth99')
print(output)
self.assertEqual(output, '')
- remove_unit_from_networkd_path(['25-nexthop-nothing.network'])
- copy_unit_to_networkd_unit_path('25-nexthop.network')
- rc = call(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
- self.assertEqual(rc, 0)
- rc = call(*networkctl_cmd, 'reload', env=env)
- self.assertEqual(rc, 0)
- time.sleep(1)
+ remove_network_unit('25-nexthop-nothing.network')
+ copy_network_unit('25-nexthop.network')
+ networkctl_reconfigure('dummy98')
+ networkctl_reload()
check_nexthop(self)
- rc = call('ip link del veth99')
- self.assertEqual(rc, 0)
+ remove_link('veth99')
time.sleep(2)
output = check_output('ip nexthop list dev lo')
self.assertEqual(output, '')
def test_qdisc(self):
- copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
- '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
+ 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')
self.assertRegex(output, 'cburst 123457')
def test_qdisc2(self):
- copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
- '25-qdisc-qfq.network', '11-dummy.netdev')
+ 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')
@expectedFailureIfCAKEIsNotAvailable()
def test_qdisc_cake(self):
- copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
+ copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
@expectedFailureIfPIEIsNotAvailable()
def test_qdisc_pie(self):
- copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
+ copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
@expectedFailureIfHHFIsNotAvailable()
def test_qdisc_hhf(self):
- copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev')
+ copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
@expectedFailureIfETSIsNotAvailable()
def test_qdisc_ets(self):
- copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev')
+ copy_network_unit('25-qdisc-ets.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
@expectedFailureIfFQPIEIsNotAvailable()
def test_qdisc_fq_pie(self):
- copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev')
+ copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
self.assertRegex(output, 'limit 200000p')
def test_wait_online_ipv4(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
+ 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()
self.wait_online(['veth99:routable'], ipv4=True)
self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1)
def test_wait_online_ipv6(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix-with-delay.network', '25-ipv6ra-prefix-client-with-static-ipv4-address.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6-prefix-with-delay.network', '25-ipv6ra-prefix-client-with-static-ipv4-address.network')
start_networkd()
self.wait_online(['veth99:routable'], ipv6=True)
self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1)
class NetworkdStateFileTests(unittest.TestCase, Utilities):
- links = [
- 'dummy98',
- ]
-
- units = [
- '12-dummy.netdev',
- '25-state-file-tests.network',
- ]
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_state_file(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-state-file-tests.network')
+ copy_network_unit('12-dummy.netdev', '25-state-file-tests.network')
start_networkd()
self.wait_online(['dummy98:routable'])
self.assertIn('DNSSEC=no', output)
class NetworkdBondTests(unittest.TestCase, Utilities):
- links = [
- 'bond199',
- 'bond99',
- 'dummy98',
- 'test1']
-
- units = [
- '11-dummy.netdev',
- '12-dummy.netdev',
- '23-active-slave.network',
- '23-bond199.network',
- '23-keep-master.network',
- '23-primary-slave.network',
- '25-bond-active-backup-slave.netdev',
- '25-bond.netdev',
- '25-bond99.network',
- '25-bond-slave.network']
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_bond_keep_master(self):
check_output('ip link add bond199 type bond mode active-backup')
check_output('ip link add dummy98 type dummy')
check_output('ip link set dummy98 master bond199')
- copy_unit_to_networkd_unit_path('23-keep-master.network')
+ copy_network_unit('23-keep-master.network')
start_networkd()
self.wait_online(['dummy98:enslaved'])
self.assertRegex(output, 'master bond199')
def test_bond_active_slave(self):
- copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
+ copy_network_unit('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
self.assertRegex(output, 'active_slave dummy98')
def test_bond_primary_slave(self):
- copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
+ copy_network_unit('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
self.assertRegex(output, 'primary dummy98')
def test_bond_operstate(self):
- copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
- '25-bond99.network','25-bond-slave.network')
+ copy_network_unit('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
+ '25-bond99.network', '25-bond-slave.network')
start_networkd()
self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
self.assertNotRegex(output, 'NO-CARRIER')
class NetworkdBridgeTests(unittest.TestCase, Utilities):
- links = [
- 'bridge99',
- 'dummy98',
- 'test1',
- 'vlan99',
- ]
-
- units = [
- '11-dummy.netdev',
- '12-dummy.netdev',
- '21-vlan.netdev',
- '21-vlan.network',
- '23-keep-master.network',
- '26-bridge.netdev',
- '26-bridge-configure-without-carrier.network',
- '26-bridge-issue-20373.netdev',
- '26-bridge-mdb-master.network',
- '26-bridge-mdb-slave.network',
- '26-bridge-slave-interface-1.network',
- '26-bridge-slave-interface-2.network',
- '26-bridge-vlan-master-issue-20373.network',
- '26-bridge-vlan-master.network',
- '26-bridge-vlan-slave-issue-20373.network',
- '26-bridge-vlan-slave.network',
- '25-bridge99-ignore-carrier-loss.network',
- '25-bridge99.network'
- ]
-
- routing_policy_rule_tables = ['100']
def setUp(self):
- remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_bridge_vlan(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
- '26-bridge.netdev', '26-bridge-vlan-master.network')
+ copy_network_unit('11-dummy.netdev', '26-bridge-vlan-slave.network',
+ '26-bridge.netdev', '26-bridge-vlan-master.network')
start_networkd()
self.wait_online(['test1:enslaved', 'bridge99:degraded'])
self.assertNotRegex(output, '4095')
def test_bridge_vlan_issue_20373(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network',
- '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network',
- '21-vlan.netdev', '21-vlan.network')
+ copy_network_unit('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network',
+ '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network',
+ '21-vlan.netdev', '21-vlan.network')
start_networkd()
self.wait_online(['test1:enslaved', 'bridge99:degraded', 'vlan99:routable'])
self.assertIn('600', output)
def test_bridge_mdb(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network',
- '26-bridge.netdev', '26-bridge-mdb-master.network')
+ copy_network_unit('11-dummy.netdev', '26-bridge-mdb-slave.network',
+ '26-bridge.netdev', '26-bridge-mdb-master.network')
start_networkd()
self.wait_online(['test1:enslaved', 'bridge99:degraded'])
self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065')
# Old kernel may not support bridge MDB entries on bridge master
- if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0:
+ if call_quiet('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068') == 0:
self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
check_output('ip link add dummy98 type dummy')
check_output('ip link set dummy98 master bridge99')
- copy_unit_to_networkd_unit_path('23-keep-master.network')
+ copy_network_unit('23-keep-master.network')
start_networkd()
self.wait_online(['dummy98:enslaved'])
output = check_output('bridge -d link show dummy98')
print(output)
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'path_cost', '400')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood', '0')
# CONFIG_BRIDGE_IGMP_SNOOPING=y
- if os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast'):
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
- if os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress'):
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast', '1', allow_enoent=True)
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '1')
def test_bridge_property(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
- '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
- '25-bridge99.network')
+ copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
+ '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
+ '25-bridge99.network')
start_networkd()
self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
output = check_output('bridge -d link show dummy98')
print(output)
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'isolated'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'path_cost', '400')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'isolated', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood', '0')
# CONFIG_BRIDGE_IGMP_SNOOPING=y
- if os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast'):
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
- if os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress'):
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
- self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast', '1', allow_enoent=True)
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '1')
output = check_output('bridge -d link show test1')
print(output)
- self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
+ self.check_bridge_port_attr('bridge99', 'test1', 'priority', '0')
check_output('ip address add 192.168.0.16/24 dev bridge99')
- time.sleep(1)
-
output = check_output('ip addr show bridge99')
print(output)
self.assertRegex(output, '192.168.0.16/24')
print(output)
self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
- self.assertEqual(call('ip link del test1'), 0)
+ remove_link('test1')
self.wait_operstate('bridge99', 'degraded-carrier')
- check_output('ip link del dummy98')
+ remove_link('dummy98')
self.wait_operstate('bridge99', 'no-carrier')
self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
def test_bridge_configure_without_carrier(self):
- copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
- '11-dummy.netdev')
+ copy_network_unit('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
+ '11-dummy.netdev')
start_networkd()
# With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
self.assertRegex(output, '10.1.2.1')
def test_bridge_ignore_carrier_loss(self):
- copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
- '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
- '25-bridge99-ignore-carrier-loss.network')
+ copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
+ '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
+ '25-bridge99-ignore-carrier-loss.network')
start_networkd()
self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
check_output('ip address add 192.168.0.16/24 dev bridge99')
- time.sleep(1)
-
- check_output('ip link del test1')
- check_output('ip link del dummy98')
+ remove_link('test1', 'dummy98')
time.sleep(3)
output = check_output('ip address show bridge99')
self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
- copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
- '25-bridge99-ignore-carrier-loss.network')
+ copy_network_unit('26-bridge.netdev', '26-bridge-slave-interface-1.network',
+ '25-bridge99-ignore-carrier-loss.network')
start_networkd()
self.wait_online(['bridge99:no-carrier'])
check_output('ip link add dummy98 type dummy')
check_output('ip link set dummy98 up')
if trial < 3:
- check_output('ip link del dummy98')
+ remove_link('dummy98')
self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
self.assertIn('from all to 8.8.8.8 lookup 100', output)
class NetworkdSRIOVTests(unittest.TestCase, Utilities):
- units = [
- '25-sriov-udev.network',
- '25-sriov.link',
- '25-sriov.network',
- ]
def setUp(self):
- stop_networkd(show_logs=False)
- call('rmmod netdevsim', stderr=subprocess.DEVNULL)
+ setup_common()
def tearDown(self):
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
- call('rmmod netdevsim', stderr=subprocess.DEVNULL)
+ tear_down_common()
@expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
def test_sriov(self):
- call('modprobe netdevsim', stderr=subprocess.DEVNULL)
+ call('modprobe netdevsim')
with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
f.write('99 1')
- call('udevadm settle')
- call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
- with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w', encoding='utf-8') as f:
+ with open('/sys/bus/netdevsim/devices/netdevsim99/sriov_numvfs', mode='w', encoding='utf-8') as f:
f.write('3')
- copy_unit_to_networkd_unit_path('25-sriov.network')
+ copy_network_unit('25-sriov.network')
start_networkd()
self.wait_online(['eni99np1:routable'])
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
- )
+ )
@expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
def test_sriov_udev(self):
- call('modprobe netdevsim', stderr=subprocess.DEVNULL)
-
- copy_unit_to_networkd_unit_path('25-sriov.link', '25-sriov-udev.network')
+ copy_network_unit('25-sriov.link', '25-sriov-udev.network')
call('udevadm control --reload')
+ call('modprobe netdevsim')
+
with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
f.write('99 1')
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
- )
+ )
self.assertNotIn('vf 3', output)
self.assertNotIn('vf 4', output)
- with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
f.write('[Link]\nSR-IOVVirtualFunctions=4\n')
call('udevadm control --reload')
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
'vf 3'
- )
+ )
self.assertNotIn('vf 4', output)
- with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
call('udevadm control --reload')
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
'vf 3'
- )
+ )
self.assertNotIn('vf 4', output)
- with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
f.write('[Link]\nSR-IOVVirtualFunctions=2\n')
call('udevadm control --reload')
self.assertRegex(output,
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off'
- )
+ )
self.assertNotIn('vf 2', output)
self.assertNotIn('vf 3', output)
self.assertNotIn('vf 4', output)
- with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
call('udevadm control --reload')
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
- )
+ )
self.assertNotIn('vf 3', output)
self.assertNotIn('vf 4', output)
class NetworkdLLDPTests(unittest.TestCase, Utilities):
- links = ['veth99']
-
- units = [
- '23-emit-lldp.network',
- '24-lldp.network',
- '25-veth.netdev']
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_lldp(self):
- copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
+ copy_network_unit('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
start_networkd()
self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
self.fail()
class NetworkdRATests(unittest.TestCase, Utilities):
- links = ['veth99']
-
- units = [
- '25-veth.netdev',
- '25-ipv6-prefix.network',
- '25-ipv6-prefix-veth.network',
- '25-ipv6-prefix-veth-token-static.network',
- '25-ipv6-prefix-veth-token-prefixstable.network',
- '25-ipv6-prefix-veth-token-prefixstable-without-address.network']
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_ipv6_prefix_delegation(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:degraded'])
self.assertRegex(output, '2002:da8:1:0')
def test_ipv6_token_static(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:degraded'])
self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe')
def test_ipv6_token_prefixstable(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:degraded'])
self.assertIn('2002:da8:2:0:1034:56ff:fe78:9abc', output) # EUI64
def test_ipv6_token_prefixstable_without_address(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable-without-address.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable-without-address.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:degraded'])
self.assertIn('2002:da8:2:0:f689:561a:8eda:7443', output)
class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
- links = [
- 'dummy98',
- 'veth99',
- ]
-
- units = [
- '12-dummy.netdev',
- '25-veth.netdev',
- '25-dhcp-client.network',
- '25-dhcp-client-static-lease.network',
- '25-dhcp-client-timezone-router.network',
- '25-dhcp-server.network',
- '25-dhcp-server-downstream.network',
- '25-dhcp-server-static-lease.network',
- '25-dhcp-server-timezone-router.network',
- '25-dhcp-server-uplink.network',
- ]
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_dhcp_server(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
self.assertRegex(output, 'NTP: 192.168.5.1\n *192.168.5.11')
def test_dhcp_server_with_uplink(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-downstream.network',
- '12-dummy.netdev', '25-dhcp-server-uplink.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-downstream.network',
+ '12-dummy.netdev', '25-dhcp-server-uplink.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
self.assertIn('NTP: 192.168.5.1', output)
def test_emit_router_timezone(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client-timezone-router.network', '25-dhcp-server-timezone-router.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-client-timezone-router.network', '25-dhcp-server-timezone-router.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
self.assertIn('Time Zone: Europe/Berlin', output)
def test_dhcp_server_static_lease(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client-static-lease.network', '25-dhcp-server-static-lease.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-client-static-lease.network', '25-dhcp-server-static-lease.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
self.assertIn('Address: 10.1.1.200 (DHCP4 via 10.1.1.1)', output)
class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
- links = [
- 'client',
- 'server',
- 'client-peer',
- 'server-peer',
- ]
-
- units = [
- '25-agent-veth-client.netdev',
- '25-agent-veth-server.netdev',
- '25-agent-client.network',
- '25-agent-server.network',
- '25-agent-client-peer.network',
- '25-agent-server-peer.network',
- ]
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_relay_agent(self):
- copy_unit_to_networkd_unit_path(*self.units)
+ copy_network_unit('25-agent-veth-client.netdev',
+ '25-agent-veth-server.netdev',
+ '25-agent-client.network',
+ '25-agent-server.network',
+ '25-agent-client-peer.network',
+ '25-agent-server-peer.network')
start_networkd()
self.wait_online(['client:routable'])
self.assertRegex(output, r'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
- links = [
- 'veth99',
- 'vrf99']
-
- units = [
- '25-veth.netdev',
- '25-vrf.netdev',
- '25-vrf.network',
- '25-dhcp-client-anonymize.network',
- '25-dhcp-client-gateway-onlink-implicit.network',
- '25-dhcp-client-ipv4-only.network',
- '25-dhcp-client-ipv4-use-routes-use-gateway.network',
- '25-dhcp-client-ipv6-only.network',
- '25-dhcp-client-keep-configuration-dhcp-on-stop.network',
- '25-dhcp-client-keep-configuration-dhcp.network',
- '25-dhcp-client-vrf.network',
- '25-dhcp-client-with-ipv4ll.network',
- '25-dhcp-client.network',
- '25-dhcp-server-veth-peer.network',
- '25-static.network']
def setUp(self):
- stop_dnsmasq()
- remove_dnsmasq_lease_file()
- remove_dnsmasq_log_file()
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- stop_dnsmasq()
- remove_dnsmasq_lease_file()
- remove_dnsmasq_log_file()
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_dhcp_client_ipv6_only(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
self.assertRegex(output, 'token :: dev veth99')
def test_dhcp_client_ipv4_only(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
- start_dnsmasq(ipv4_range='192.168.5.110,192.168.5.119',
- additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7 --dhcp-option=option:domain-search,example.com --dhcp-alternate-port=67,5555',
- lease_time='2m')
+ start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7',
+ '--dhcp-option=option:domain-search,example.com',
+ '--dhcp-alternate-port=67,5555',
+ ipv4_range='192.168.5.110,192.168.5.119')
self.wait_online(['veth99:routable', 'veth-peer:routable'])
print('## ip address show dev veth99 scope global')
# change address range, DNS servers, and Domains
stop_dnsmasq()
- remove_dnsmasq_log_file()
- start_dnsmasq(ipv4_range='192.168.5.120,192.168.5.129',
- additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8 --dhcp-option=option:domain-search,foo.example.com --dhcp-alternate-port=67,5555',
- lease_time='2m')
+ start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8',
+ '--dhcp-option=option:domain-search,foo.example.com',
+ '--dhcp-alternate-port=67,5555',
+ ipv4_range='192.168.5.120,192.168.5.129',)
# Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
print('Wait for the DHCP lease to be expired')
self.assertIn('26:mtu', output)
def test_dhcp_client_ipv4_use_routes_gateway(self):
+ first = True
for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
- self.setUp()
+ if first:
+ first = False
+ else:
+ self.tearDown()
+
+ print(f'### test_dhcp_client_ipv4_use_routes_gateway(routes={routes}, gateway={gateway}, dns_and_ntp_routes={dns_and_ntp_routes}, classless={classless})')
with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
- self.tearDown()
def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
testunit = '25-dhcp-client-ipv4-use-routes-use-gateway.network'
testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf')
testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf')
testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf')
- copy_unit_to_networkd_unit_path(*testunits, dropins=False)
+ copy_network_unit(*testunits, copy_dropins=False)
start_networkd()
self.wait_online(['veth-peer:carrier'])
- additional_options = '--dhcp-option=option:dns-server,192.168.5.10,8.8.8.8 --dhcp-option=option:ntp-server,192.168.5.11,9.9.9.9 --dhcp-option=option:static-route,192.168.5.100,192.168.5.2,8.8.8.8,192.168.5.3'
+ additional_options = [
+ '--dhcp-option=option:dns-server,192.168.5.10,8.8.8.8',
+ '--dhcp-option=option:ntp-server,192.168.5.11,9.9.9.9',
+ '--dhcp-option=option:static-route,192.168.5.100,192.168.5.2,8.8.8.8,192.168.5.3'
+ ]
if classless:
- additional_options += ' --dhcp-option=option:classless-static-route,0.0.0.0/0,192.168.5.4,8.0.0.0/8,192.168.5.5'
- start_dnsmasq(additional_options=additional_options, lease_time='2m')
+ additional_options += [
+ '--dhcp-option=option:classless-static-route,0.0.0.0/0,192.168.5.4,8.0.0.0/8,192.168.5.5'
+ ]
+ start_dnsmasq(*additional_options)
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip -4 route show dev veth99')
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
def test_dhcp_client_settings_anonymize(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-anonymize.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-anonymize.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
start_dnsmasq()
self.assertNotIn('26:mtu', output)
def test_dhcp_keep_configuration_dhcp(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev',
- '25-dhcp-server-veth-peer.network',
- '25-dhcp-client-keep-configuration-dhcp.network')
+ copy_network_unit('25-veth.netdev',
+ '25-dhcp-server-veth-peer.network',
+ '25-dhcp-client-keep-configuration-dhcp.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
- start_dnsmasq(lease_time='2m')
+ start_dnsmasq()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip address show dev veth99 scope global')
self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global veth99\n *'
'valid_lft forever preferred_lft forever')
- with open(os.path.join(network_unit_file_path, '25-dhcp-client-keep-configuration-dhcp.network'), mode='a', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-dhcp-client-keep-configuration-dhcp.network'), mode='a', encoding='utf-8') as f:
f.write('[Network]\nDHCP=no\n')
start_networkd()
'valid_lft forever preferred_lft forever')
def test_dhcp_keep_configuration_dhcp_on_stop(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev',
- '25-dhcp-server-veth-peer.network',
- '25-dhcp-client-keep-configuration-dhcp-on-stop.network')
+ copy_network_unit('25-veth.netdev',
+ '25-dhcp-server-veth-peer.network',
+ '25-dhcp-client-keep-configuration-dhcp-on-stop.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
- start_dnsmasq(lease_time='2m')
+ start_dnsmasq()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip address show dev veth99 scope global')
print(output)
self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
- start_networkd(3)
+ start_networkd()
self.wait_online(['veth-peer:routable'])
output = check_output('ip address show dev veth99 scope global')
self.assertNotIn('192.168.5.', output)
def test_dhcp_client_reuse_address_as_static(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
start_dnsmasq()
static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address, 'Address=' + ipv6_address])
print(static_network)
- remove_unit_from_networkd_path(['25-dhcp-client.network'])
+ remove_network_unit('25-dhcp-client.network')
- with open(os.path.join(network_unit_file_path, '25-static.network'), mode='w', encoding='utf-8') as f:
+ with open(os.path.join(network_unit_dir, '25-static.network'), mode='w', encoding='utf-8') as f:
f.write(static_network)
restart_networkd()
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_dhcp_client_vrf(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-vrf.network',
- '25-vrf.netdev', '25-vrf.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-vrf.network',
+ '25-vrf.netdev', '25-vrf.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
start_dnsmasq()
self.assertEqual(output, '')
def test_dhcp_client_gateway_onlink_implicit(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network',
- '25-dhcp-client-gateway-onlink-implicit.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network',
+ '25-dhcp-client-gateway-onlink-implicit.network')
start_networkd()
self.wait_online(['veth-peer:carrier'])
start_dnsmasq()
self.assertRegex(output, 'onlink')
def test_dhcp_client_with_ipv4ll(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network',
- '25-dhcp-client-with-ipv4ll.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network',
+ '25-dhcp-client-with-ipv4ll.network')
start_networkd()
# we need to increase timeout above default, as this will need to wait for
# systemd-networkd to get the dhcpv4 transient failure event
self.assertNotIn('192.168.5.', output)
self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
- start_dnsmasq(lease_time='2m')
+ start_dnsmasq()
print('Wait for a DHCP lease to be acquired and the IPv4LL address to be dropped')
self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link', scope='link', ipv='-4')
def test_dhcp_client_use_dns(self):
def check(self, ipv4, ipv6):
- os.makedirs(os.path.join(network_unit_file_path, '25-dhcp-client.network.d'), exist_ok=True)
- with open(os.path.join(network_unit_file_path, '25-dhcp-client.network.d/override.conf'), mode='w', encoding='utf-8') as f:
+ os.makedirs(os.path.join(network_unit_dir, '25-dhcp-client.network.d'), exist_ok=True)
+ with open(os.path.join(network_unit_dir, '25-dhcp-client.network.d/override.conf'), mode='w', encoding='utf-8') as f:
f.write('[DHCPv4]\nUseDNS=')
f.write('yes' if ipv4 else 'no')
f.write('\n[DHCPv6]\nUseDNS=')
f.write('yes' if ipv6 else 'no')
f.write('\n[IPv6AcceptRA]\nUseDNS=no')
- check_output(*networkctl_cmd, 'reload', env=env)
- # 'networkctl reload' asynchronously reconfigure links.
- # Hence, we need to wait for a short time for the link to be in configuring state.
- time.sleep(1)
+ networkctl_reload()
self.wait_online(['veth99:routable'])
# link becomes 'routable' when at least one protocol provide an valid address. Hence, we need to explicitly wait for both addresses.
# TODO: check json string
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network', dropins=False)
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network', copy_dropins=False)
start_networkd()
self.wait_online(['veth-peer:carrier'])
- start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
+ start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1',
+ '--dhcp-option=option6:dns-server,[2600::1]')
check(self, True, True)
check(self, True, False)
check(self, False, False)
class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
- links = [
- 'dummy97',
- 'dummy98',
- 'dummy99',
- 'test1',
- 'veth97',
- 'veth98',
- 'veth99',
- ]
-
- units = [
- '11-dummy.netdev',
- '12-dummy.netdev',
- '13-dummy.netdev',
- '25-veth.netdev',
- '25-veth-downstream-veth97.netdev',
- '25-veth-downstream-veth98.netdev',
- '80-6rd-tunnel.network',
- '25-dhcp-pd-downstream-dummy97.network',
- '25-dhcp-pd-downstream-dummy98.network',
- '25-dhcp-pd-downstream-dummy99.network',
- '25-dhcp-pd-downstream-test1.network',
- '25-dhcp-pd-downstream-veth97.network',
- '25-dhcp-pd-downstream-veth97-peer.network',
- '25-dhcp-pd-downstream-veth98.network',
- '25-dhcp-pd-downstream-veth98-peer.network',
- '25-dhcp4-6rd-server.network',
- '25-dhcp4-6rd-upstream.network',
- '25-dhcp6pd-server.network',
- '25-dhcp6pd-upstream.network',
- ]
def setUp(self):
- stop_isc_dhcpd()
- stop_dnsmasq()
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- stop_isc_dhcpd()
- stop_dnsmasq()
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_dhcp6pd(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp6pd-server.network', '25-dhcp6pd-upstream.network',
- '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
- '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
- '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
- '25-dhcp-pd-downstream-dummy97.network',
- '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
- '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp6pd-server.network', '25-dhcp6pd-upstream.network',
+ '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
+ '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
+ '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
+ '25-dhcp-pd-downstream-dummy97.network',
+ '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
+ '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network')
start_networkd()
self.wait_online(['veth-peer:routable'])
- start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf', ip='-6')
+ start_isc_dhcpd(conf_file='isc-dhcpd-dhcp6pd.conf', ipv='-6')
self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires')
# Test case for reconfigure
- check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env)
+ networkctl_reconfigure('dummy98', 'dummy99')
self.wait_online(['dummy98:routable'])
print('### ip -6 address show dev dummy98 scope global')
self.assertIn(f'via ::10.0.0.1 dev {tunnel_name}', output)
def test_dhcp4_6rd(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp4-6rd-server.network', '25-dhcp4-6rd-upstream.network',
- '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
- '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
- '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
- '25-dhcp-pd-downstream-dummy97.network',
- '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
- '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network',
- '80-6rd-tunnel.network')
+ copy_network_unit('25-veth.netdev', '25-dhcp4-6rd-server.network', '25-dhcp4-6rd-upstream.network',
+ '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
+ '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
+ '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
+ '25-dhcp-pd-downstream-dummy97.network',
+ '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
+ '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network',
+ '80-6rd-tunnel.network')
start_networkd()
self.wait_online(['veth-peer:routable'])
# 6rd-prefix: 2001:db8::/32
# br-addresss: 10.0.0.1
- start_dnsmasq(additional_options='--dhcp-option=212,08:20:20:01:0d:b8:00:00:00:00:00:00:00:00:00:00:00:00:0a:00:00:01', ipv4_range='10.100.100.100,10.100.100.200', ipv4_router='10.0.0.1', lease_time='2m')
+ start_dnsmasq('--dhcp-option=212,08:20:20:01:0d:b8:00:00:00:00:00:00:00:00:00:00:00:00:0a:00:00:01',
+ ipv4_range='10.100.100.100,10.100.100.200',
+ ipv4_router='10.0.0.1')
self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
self.verify_dhcp4_6rd(tunnel_name)
# Test case for reconfigure
- check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env)
+ networkctl_reconfigure('dummy98', 'dummy99')
self.wait_online(['dummy98:routable', 'dummy99:degraded'])
self.verify_dhcp4_6rd(tunnel_name)
self.verify_dhcp4_6rd(tunnel_name)
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
- links = [
- 'dummy98',
- 'veth99',
- ]
-
- units = [
- '12-dummy.netdev',
- '25-veth.netdev',
- '25-ipv6ra-prefix-client-deny-list.network',
- '25-ipv6ra-prefix-client.network',
- '25-ipv6ra-prefix.network',
- '25-ipv6ra-uplink.network',
- ]
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def test_ipv6_route_prefix(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6ra-prefix-client.network', '25-ipv6ra-prefix.network',
- '12-dummy.netdev', '25-ipv6ra-uplink.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6ra-prefix-client.network', '25-ipv6ra-prefix.network',
+ '12-dummy.netdev', '25-ipv6ra-uplink.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
def test_ipv6_route_prefix_deny_list(self):
- copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6ra-prefix-client-deny-list.network', '25-ipv6ra-prefix.network',
- '12-dummy.netdev', '25-ipv6ra-uplink.network')
+ copy_network_unit('25-veth.netdev', '25-ipv6ra-prefix-client-deny-list.network', '25-ipv6ra-prefix.network',
+ '12-dummy.netdev', '25-ipv6ra-uplink.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
self.assertIn('example.com', output)
class NetworkdMTUTests(unittest.TestCase, Utilities):
- links = ['dummy98']
-
- units = [
- '12-dummy.netdev',
- '12-dummy-mtu.netdev',
- '12-dummy-mtu.link',
- '12-dummy.network',
- ]
def setUp(self):
- remove_links(self.links)
- stop_networkd(show_logs=False)
+ setup_common()
def tearDown(self):
- remove_links(self.links)
- remove_unit_from_networkd_path(self.units)
- stop_networkd(show_logs=True)
+ tear_down_common()
def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
if not ipv6_mtu:
# test normal start
start_networkd()
self.wait_online(['dummy98:routable'])
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
- self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
+ self.check_link_attr('dummy98', 'mtu', mtu)
+ self.check_ipv6_sysctl_attr('dummy98', 'mtu', ipv6_mtu)
# test normal restart
restart_networkd()
self.wait_online(['dummy98:routable'])
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
- self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
+ self.check_link_attr('dummy98', 'mtu', mtu)
+ self.check_ipv6_sysctl_attr('dummy98', 'mtu', ipv6_mtu)
if reset:
self.reset_check_mtu(mtu, ipv6_mtu)
stop_networkd()
# note - changing the device mtu resets the ipv6 mtu
- run('ip link set up mtu 1501 dev dummy98')
- run('ip link set up mtu 1500 dev dummy98')
- self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
- self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
+ check_output('ip link set up mtu 1501 dev dummy98')
+ check_output('ip link set up mtu 1500 dev dummy98')
+ self.check_link_attr('dummy98', 'mtu', '1500')
+ self.check_ipv6_sysctl_attr('dummy98', 'mtu', '1500')
self.check_mtu(mtu, ipv6_mtu, reset=False)
def test_mtu_network(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
+ copy_network_unit('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
self.check_mtu('1600')
def test_mtu_netdev(self):
- copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
+ copy_network_unit('12-dummy-mtu.netdev', '12-dummy.network', copy_dropins=False)
# note - MTU set by .netdev happens ONLY at device creation!
self.check_mtu('1600', reset=False)
def test_mtu_link(self):
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
+ copy_network_unit('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', copy_dropins=False)
# must reload udev because it only picks up new files after 3 second delay
call('udevadm control --reload')
# note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
def test_ipv6_mtu(self):
''' set ipv6 mtu without setting device mtu '''
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
+ copy_network_unit('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
self.check_mtu('1500', '1400')
def test_ipv6_mtu_toolarge(self):
''' try set ipv6 mtu over device mtu (it shouldn't work) '''
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
+ copy_network_unit('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
self.check_mtu('1500', '1500')
def test_mtu_network_ipv6_mtu(self):
''' set ipv6 mtu and set device mtu via network file '''
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
+ copy_network_unit('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
self.check_mtu('1600', '1550')
def test_mtu_netdev_ipv6_mtu(self):
''' set ipv6 mtu and set device mtu via netdev file '''
- copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
+ copy_network_unit('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
self.check_mtu('1600', '1550', reset=False)
def test_mtu_link_ipv6_mtu(self):
''' set ipv6 mtu and set device mtu via link file '''
- copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
+ copy_network_unit('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
# must reload udev because it only picks up new files after 3 second delay
call('udevadm control --reload')
self.check_mtu('1600', '1550', reset=False)
wait_online_cmd = [wait_online_bin]
if asan_options:
- env.update({ 'ASAN_OPTIONS' : asan_options })
+ env.update({'ASAN_OPTIONS': asan_options})
if lsan_options:
- env.update({ 'LSAN_OPTIONS' : lsan_options })
+ env.update({'LSAN_OPTIONS': lsan_options})
if ubsan_options:
- env.update({ 'UBSAN_OPTIONS' : ubsan_options })
+ env.update({'UBSAN_OPTIONS': ubsan_options})
wait_online_env = env.copy()
if enable_debug:
- wait_online_env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
+ wait_online_env.update({'SYSTEMD_LOG_LEVEL': 'debug'})
sys.argv[1:] = unknown_args
unittest.main(verbosity=3)