2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
14 from shutil
import copytree
16 network_unit_file_path
='/run/systemd/network'
17 networkd_runtime_directory
='/run/systemd/netif'
18 networkd_ci_path
='/run/networkd-ci'
19 network_sysctl_ipv6_path
='/proc/sys/net/ipv6/conf'
20 network_sysctl_ipv4_path
='/proc/sys/net/ipv4/conf'
22 dnsmasq_pid_file
='/run/networkd-ci/test-test-dnsmasq.pid'
23 dnsmasq_log_file
='/run/networkd-ci/test-dnsmasq-log-file'
25 systemd_lib_paths
=['/usr/lib/systemd', '/lib/systemd']
26 which_paths
=':'.join(systemd_lib_paths
+ os
.getenv('PATH', os
.defpath
).lstrip(':').split(':'))
28 networkd_bin
=shutil
.which('systemd-networkd', path
=which_paths
)
29 resolved_bin
=shutil
.which('systemd-resolved', path
=which_paths
)
30 udevd_bin
=shutil
.which('systemd-udevd', path
=which_paths
)
31 wait_online_bin
=shutil
.which('systemd-networkd-wait-online', path
=which_paths
)
32 networkctl_bin
=shutil
.which('networkctl', path
=which_paths
)
33 resolvectl_bin
=shutil
.which('resolvectl', path
=which_paths
)
34 timedatectl_bin
=shutil
.which('timedatectl', path
=which_paths
)
45 def check_output(*command
, **kwargs
):
46 # This replaces both check_output and check_call (output can be ignored)
47 command
= command
[0].split() + list(command
[1:])
48 return subprocess
.check_output(command
, universal_newlines
=True, **kwargs
).rstrip()
50 def call(*command
, **kwargs
):
51 command
= command
[0].split() + list(command
[1:])
52 return subprocess
.call(command
, universal_newlines
=True, **kwargs
)
54 def run(*command
, **kwargs
):
55 command
= command
[0].split() + list(command
[1:])
56 return subprocess
.run(command
, universal_newlines
=True, **kwargs
)
58 def is_module_available(module_name
):
59 lsmod_output
= check_output('lsmod')
60 module_re
= re
.compile(rf
'^{re.escape(module_name)}\b', re
.MULTILINE
)
61 return module_re
.search(lsmod_output
) or not call('modprobe', module_name
, stderr
=subprocess
.DEVNULL
)
63 def expectedFailureIfModuleIsNotAvailable(module_name
):
65 if not is_module_available(module_name
):
66 return unittest
.expectedFailure(func
)
71 def expectedFailureIfERSPANModuleIsNotAvailable():
73 rc
= call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr
=subprocess
.DEVNULL
)
75 call('ip link del erspan99')
78 return unittest
.expectedFailure(func
)
82 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
84 rc
= call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr
=subprocess
.DEVNULL
)
86 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
89 return unittest
.expectedFailure(func
)
93 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
95 rc
= call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr
=subprocess
.DEVNULL
)
97 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
100 return unittest
.expectedFailure(func
)
104 def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
107 rc
= call('ip rule add from 192.168.100.19 table 7 uidrange 200-300', stderr
=subprocess
.DEVNULL
)
109 ret
= run('ip rule list from 192.168.100.19 table 7', stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
110 if ret
.returncode
== 0 and 'uidrange 200-300' in ret
.stdout
.rstrip():
112 call('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
117 return unittest
.expectedFailure(func
)
121 def expectedFailureIfLinkFileFieldIsNotSet():
124 rc
= call('ip link add name dummy99 type dummy', stderr
=subprocess
.DEVNULL
)
126 ret
= run('udevadm info -w10s /sys/class/net/dummy99', stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
127 if ret
.returncode
== 0 and 'E: ID_NET_LINK_FILE=' in ret
.stdout
.rstrip():
129 call('ip link del dummy99')
134 return unittest
.expectedFailure(func
)
138 def expectedFailureIfNexthopIsNotAvailable():
140 rc
= call('ip nexthop list', stderr
=subprocess
.DEVNULL
)
144 return unittest
.expectedFailure(func
)
148 def expectedFailureIfAlternativeNameIsNotAvailable():
150 call('ip link add dummy98 type dummy', stderr
=subprocess
.DEVNULL
)
151 rc
= call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr
=subprocess
.DEVNULL
)
152 call('ip link del dummy98', stderr
=subprocess
.DEVNULL
)
156 return unittest
.expectedFailure(func
)
160 def expectedFailureIfCAKEIsNotAvailable():
162 call('ip link add dummy98 type dummy', stderr
=subprocess
.DEVNULL
)
163 rc
= call('tc qdisc add dev dummy98 parent root cake', stderr
=subprocess
.DEVNULL
)
164 call('ip link del dummy98', stderr
=subprocess
.DEVNULL
)
168 return unittest
.expectedFailure(func
)
172 def expectedFailureIfPIEIsNotAvailable():
174 call('ip link add dummy98 type dummy', stderr
=subprocess
.DEVNULL
)
175 rc
= call('tc qdisc add dev dummy98 parent root pie', stderr
=subprocess
.DEVNULL
)
176 call('ip link del dummy98', stderr
=subprocess
.DEVNULL
)
180 return unittest
.expectedFailure(func
)
187 os
.makedirs(network_unit_file_path
, exist_ok
=True)
188 os
.makedirs(networkd_ci_path
, exist_ok
=True)
190 shutil
.rmtree(networkd_ci_path
)
191 copytree(os
.path
.join(os
.path
.dirname(os
.path
.abspath(__file__
)), 'conf'), networkd_ci_path
)
193 for u
in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service',
194 'systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service',
195 'firewalld.service']:
196 if call(f
'systemctl is-active --quiet {u}') == 0:
197 check_output(f
'systemctl stop {u}')
198 running_units
.append(u
)
202 'StartLimitIntervalSec=0',
209 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin
,
213 drop_in
+= ['ExecStart=!!' + networkd_bin
]
215 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
217 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
219 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
221 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
222 if asan_options
or lsan_options
or ubsan_options
:
223 drop_in
+= ['SystemCallFilter=']
224 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
225 drop_in
+= ['MemoryDenyWriteExecute=no']
227 os
.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok
=True)
228 with
open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode
='w') as f
:
229 f
.write('\n'.join(drop_in
))
237 drop_in
+= ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin
]
239 drop_in
+= ['ExecStart=!!' + resolved_bin
]
241 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
243 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
245 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
247 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
248 if asan_options
or lsan_options
or ubsan_options
:
249 drop_in
+= ['SystemCallFilter=']
250 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
251 drop_in
+= ['MemoryDenyWriteExecute=no']
253 os
.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok
=True)
254 with
open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode
='w') as f
:
255 f
.write('\n'.join(drop_in
))
260 'ExecStart=!!' + udevd_bin
,
263 os
.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok
=True)
264 with
open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode
='w') as f
:
265 f
.write('\n'.join(drop_in
))
267 check_output('systemctl daemon-reload')
268 print(check_output('systemctl cat systemd-networkd.service'))
269 print(check_output('systemctl cat systemd-resolved.service'))
270 print(check_output('systemctl cat systemd-udevd.service'))
271 check_output('systemctl restart systemd-resolved')
272 check_output('systemctl restart systemd-udevd')
274 def tearDownModule():
277 shutil
.rmtree(networkd_ci_path
)
279 for u
in ['systemd-networkd.service', 'systemd-resolved.service']:
280 check_output(f
'systemctl stop {u}')
282 shutil
.rmtree('/run/systemd/system/systemd-networkd.service.d')
283 shutil
.rmtree('/run/systemd/system/systemd-resolved.service.d')
284 shutil
.rmtree('/run/systemd/system/systemd-udevd.service.d')
285 check_output('systemctl daemon-reload')
286 check_output('systemctl restart systemd-udevd.service')
288 for u
in running_units
:
289 check_output(f
'systemctl start {u}')
291 def read_link_attr(*args
):
292 with
open(os
.path
.join('/sys/class/net/', *args
)) as f
:
293 return f
.readline().strip()
295 def read_bridge_port_attr(bridge
, link
, attribute
):
296 path_bridge
= os
.path
.join('/sys/devices/virtual/net', bridge
)
297 path_port
= 'lower_' + link
+ '/brport'
298 path
= os
.path
.join(path_bridge
, path_port
)
300 with
open(os
.path
.join(path
, attribute
)) as f
:
301 return f
.readline().strip()
303 def link_exists(link
):
304 return os
.path
.exists(os
.path
.join('/sys/class/net', link
))
306 def remove_links(links
):
308 if link_exists(link
):
309 call('ip link del dev', link
)
312 def remove_fou_ports(ports
):
314 call('ip fou del port', port
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
316 def remove_routing_policy_rule_tables(tables
):
320 rc
= call('ip rule del table', table
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
322 def remove_routes(routes
):
323 for route_type
, addr
in routes
:
324 call('ip route del', route_type
, addr
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
326 def remove_l2tp_tunnels(tunnel_ids
):
327 output
= check_output('ip l2tp show tunnel')
328 for tid
in tunnel_ids
:
329 words
='Tunnel ' + tid
+ ', encap'
331 call('ip l2tp del tunnel tid', tid
)
334 def read_ipv6_sysctl_attr(link
, attribute
):
335 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, link
), attribute
)) as f
:
336 return f
.readline().strip()
338 def read_ipv4_sysctl_attr(link
, attribute
):
339 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv4_path
, link
), attribute
)) as f
:
340 return f
.readline().strip()
342 def copy_unit_to_networkd_unit_path(*units
, dropins
=True):
343 """Copy networkd unit files into the testbed.
345 Any networkd unit file type can be specified, as well as drop-in files.
347 By default, all drop-ins for a specified unit file are copied in;
348 to avoid that specify dropins=False.
350 When a drop-in file is specified, its unit file is also copied in automatically.
354 if dropins
and os
.path
.exists(os
.path
.join(networkd_ci_path
, unit
+ '.d')):
355 copytree(os
.path
.join(networkd_ci_path
, unit
+ '.d'), os
.path
.join(network_unit_file_path
, unit
+ '.d'))
356 if unit
.endswith('.conf'):
358 dropindir
= os
.path
.join(network_unit_file_path
, os
.path
.dirname(dropin
))
359 os
.makedirs(dropindir
, exist_ok
=True)
360 shutil
.copy(os
.path
.join(networkd_ci_path
, dropin
), dropindir
)
361 unit
= os
.path
.dirname(dropin
).rstrip('.d')
362 shutil
.copy(os
.path
.join(networkd_ci_path
, unit
), network_unit_file_path
)
364 def remove_unit_from_networkd_path(units
):
365 """Remove previously copied unit files from the testbed.
367 Drop-ins will be removed automatically.
370 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
))):
371 os
.remove(os
.path
.join(network_unit_file_path
, unit
))
372 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
+ '.d'))):
373 shutil
.rmtree(os
.path
.join(network_unit_file_path
, unit
+ '.d'))
375 def start_dnsmasq(additional_options
='', ipv4_range
='192.168.5.10,192.168.5.200', ipv6_range
='2600::10,2600::20', lease_time
='1h'):
376 dnsmasq_command
= f
'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
377 check_output(dnsmasq_command
)
379 def stop_dnsmasq(pid_file
):
380 if os
.path
.exists(pid_file
):
381 with
open(pid_file
, 'r') as f
:
382 pid
= f
.read().rstrip(' \t\r\n\0')
383 os
.kill(int(pid
), signal
.SIGTERM
)
387 def search_words_in_dnsmasq_log(words
, show_all
=False):
388 if os
.path
.exists(dnsmasq_log_file
):
389 with
open (dnsmasq_log_file
) as in_file
:
390 contents
= in_file
.read()
393 for line
in contents
.splitlines():
396 print("%s, %s" % (words
, line
))
400 def remove_lease_file():
401 if os
.path
.exists(os
.path
.join(networkd_ci_path
, 'lease')):
402 os
.remove(os
.path
.join(networkd_ci_path
, 'lease'))
404 def remove_log_file():
405 if os
.path
.exists(dnsmasq_log_file
):
406 os
.remove(dnsmasq_log_file
)
408 def remove_networkd_state_files():
409 if os
.path
.exists(os
.path
.join(networkd_runtime_directory
, 'state')):
410 os
.remove(os
.path
.join(networkd_runtime_directory
, 'state'))
412 def stop_networkd(show_logs
=True, remove_state_files
=True):
414 invocation_id
= check_output('systemctl show systemd-networkd -p InvocationID --value')
415 check_output('systemctl stop systemd-networkd')
417 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id
))
418 if remove_state_files
:
419 remove_networkd_state_files()
421 def start_networkd(sleep_sec
=0):
422 check_output('systemctl start systemd-networkd')
424 time
.sleep(sleep_sec
)
426 def restart_networkd(sleep_sec
=0, show_logs
=True, remove_state_files
=True):
427 stop_networkd(show_logs
, remove_state_files
)
428 start_networkd(sleep_sec
)
432 def check_link_exists(self
, link
):
433 self
.assertTrue(link_exists(link
))
435 def wait_operstate(self
, link
, operstate
='degraded', setup_state
='configured', setup_timeout
=5, fail_assert
=True):
436 """Wait for the link to reach the specified operstate and/or setup state.
438 Specify None or '' for either operstate or setup_state to ignore that state.
439 This will recheck until the state conditions are met or the timeout expires.
441 If the link successfully matches the requested state, this returns True.
442 If this times out waiting for the link to match, the behavior depends on the
443 'fail_assert' parameter; if True, this causes a test assertion failure,
444 otherwise this returns False. The default is to cause assertion failure.
446 Note that this function matches on *exactly* the given operstate and setup_state.
447 To wait for a link to reach *or exceed* a given operstate, use wait_online().
454 for secs
in range(setup_timeout
+ 1):
455 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', link
, env
=env
)
457 if re
.search(rf
'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output
):
459 # don't bother sleeping if time is up
460 if secs
< setup_timeout
:
463 self
.fail(f
'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
466 def wait_online(self
, links_with_operstate
, timeout
='20s', bool_any
=False, setup_state
='configured', setup_timeout
=5):
467 """Wait for the link(s) to reach the specified operstate and/or setup state.
469 This is similar to wait_operstate() but can be used for multiple links,
470 and it also calls systemd-networkd-wait-online to wait for the given operstate.
471 The operstate should be specified in the link name, like 'eth0:degraded'.
472 If just a link name is provided, wait-online's default operstate to wait for is degraded.
474 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the
475 'setup_timeout' controls the per-link timeout waiting for the setup_state.
477 Set 'bool_any' to True to wait for any (instead of all) of the given links.
478 If this is set, no setup_state checks are done.
480 Note that this function waits for the link(s) to reach *or exceed* the given operstate.
481 However, the setup_state, if specified, must be matched *exactly*.
483 This returns if the link(s) reached the requested operstate/setup_state; otherwise it
484 raises CalledProcessError or fails test assertion.
486 args
= wait_online_cmd
+ [f
'--timeout={timeout}'] + [f
'--interface={link}' for link
in links_with_operstate
]
490 check_output(*args
, env
=env
)
491 except subprocess
.CalledProcessError
:
492 for link
in links_with_operstate
:
493 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', link
.split(':')[0], env
=env
)
496 if not bool_any
and setup_state
:
497 for link
in links_with_operstate
:
498 self
.wait_operstate(link
.split(':')[0], None, setup_state
, setup_timeout
)
500 def wait_address(self
, link
, address_regex
, scope
='global', ipv
='', timeout_sec
=100):
501 for i
in range(timeout_sec
):
504 output
= check_output(f
'ip {ipv} address show dev {link} scope {scope}')
505 if re
.search(address_regex
, output
):
508 self
.assertRegex(output
, address_regex
)
510 class NetworkctlTests(unittest
.TestCase
, Utilities
):
520 '11-dummy-mtu.netdev',
524 '25-address-static.network',
526 'netdev-link-local-addressing-yes.network',
530 remove_links(self
.links
)
531 stop_networkd(show_logs
=False)
534 remove_links(self
.links
)
535 remove_unit_from_networkd_path(self
.units
)
536 stop_networkd(show_logs
=True)
538 @expectedFailureIfAlternativeNameIsNotAvailable()
539 def test_altname(self
):
540 copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
541 check_output('udevadm control --reload')
543 self
.wait_online(['dummy98:degraded'])
545 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'dummy98', env
=env
)
546 self
.assertRegex(output
, 'hogehogehogehogehogehoge')
548 def test_reconfigure(self
):
549 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
551 self
.wait_online(['dummy98:routable'])
553 output
= check_output('ip -4 address show dev dummy98')
555 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
556 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
557 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
559 check_output('ip address del 10.1.2.3/16 dev dummy98')
560 check_output('ip address del 10.1.2.4/16 dev dummy98')
561 check_output('ip address del 10.2.2.4/16 dev dummy98')
563 check_output(*networkctl_cmd
, 'reconfigure', 'dummy98', env
=env
)
564 self
.wait_online(['dummy98:routable'])
566 output
= check_output('ip -4 address show dev dummy98')
568 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
569 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
570 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
572 def test_reload(self
):
575 copy_unit_to_networkd_unit_path('11-dummy.netdev')
576 check_output(*networkctl_cmd
, 'reload', env
=env
)
577 self
.wait_operstate('test1', 'off', setup_state
='unmanaged')
579 copy_unit_to_networkd_unit_path('11-dummy.network')
580 check_output(*networkctl_cmd
, 'reload', env
=env
)
581 self
.wait_online(['test1:degraded'])
583 remove_unit_from_networkd_path(['11-dummy.network'])
584 check_output(*networkctl_cmd
, 'reload', env
=env
)
585 self
.wait_operstate('test1', 'degraded', setup_state
='unmanaged')
587 remove_unit_from_networkd_path(['11-dummy.netdev'])
588 check_output(*networkctl_cmd
, 'reload', env
=env
)
589 self
.wait_operstate('test1', 'degraded', setup_state
='unmanaged')
591 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
592 check_output(*networkctl_cmd
, 'reload', env
=env
)
593 self
.wait_operstate('test1', 'degraded')
596 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
599 self
.wait_online(['test1:degraded'])
601 output
= check_output(*networkctl_cmd
, 'list', env
=env
)
602 self
.assertRegex(output
, '1 lo ')
603 self
.assertRegex(output
, 'test1')
605 output
= check_output(*networkctl_cmd
, 'list', 'test1', env
=env
)
606 self
.assertNotRegex(output
, '1 lo ')
607 self
.assertRegex(output
, 'test1')
609 output
= check_output(*networkctl_cmd
, 'list', 'te*', env
=env
)
610 self
.assertNotRegex(output
, '1 lo ')
611 self
.assertRegex(output
, 'test1')
613 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'te*', env
=env
)
614 self
.assertNotRegex(output
, '1: lo ')
615 self
.assertRegex(output
, 'test1')
617 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'tes[a-z][0-9]', env
=env
)
618 self
.assertNotRegex(output
, '1: lo ')
619 self
.assertRegex(output
, 'test1')
622 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
625 self
.wait_online(['test1:degraded'])
627 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'test1', env
=env
)
628 self
.assertRegex(output
, 'MTU: 1600')
631 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
633 self
.wait_online(['test1:degraded'])
635 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'test1', env
=env
)
637 self
.assertRegex(output
, 'Type: ether')
639 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'lo', env
=env
)
641 self
.assertRegex(output
, 'Type: loopback')
643 @expectedFailureIfLinkFileFieldIsNotSet()
644 def test_udev_link_file(self
):
645 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
647 self
.wait_online(['test1:degraded'])
649 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'test1', env
=env
)
651 self
.assertRegex(output
, r
'Link File: (/usr)?/lib/systemd/network/99-default.link')
652 self
.assertRegex(output
, r
'Network File: /run/systemd/network/11-dummy.network')
654 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'lo', env
=env
)
656 self
.assertRegex(output
, r
'Link File: (/usr)?/lib/systemd/network/99-default.link')
657 self
.assertRegex(output
, r
'Network File: n/a')
659 def test_delete_links(self
):
660 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
661 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
664 self
.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
666 check_output(*networkctl_cmd
, 'delete', 'test1', 'veth99', env
=env
)
667 self
.assertFalse(link_exists('test1'))
668 self
.assertFalse(link_exists('veth99'))
669 self
.assertFalse(link_exists('veth-peer'))
671 class NetworkdNetDevTests(unittest
.TestCase
, Utilities
):
673 links_remove_earlier
= [
738 '10-dropin-test.netdev',
742 '13-not-match-udev-property.network',
743 '14-match-udev-property.network',
744 '15-name-conflict-test.netdev',
747 '21-vlan-test1.network',
750 '25-6rd-tunnel.netdev',
752 '25-bond-balanced-tlb.netdev',
754 '25-bridge-configure-without-carrier.network',
756 '25-erspan-tunnel-local-any.netdev',
757 '25-erspan-tunnel.netdev',
758 '25-fou-gretap.netdev',
760 '25-fou-ipip.netdev',
761 '25-fou-ipproto-gre.netdev',
762 '25-fou-ipproto-ipip.netdev',
765 '25-gretap-tunnel-local-any.netdev',
766 '25-gretap-tunnel.netdev',
767 '25-gre-tunnel-any-any.netdev',
768 '25-gre-tunnel-local-any.netdev',
769 '25-gre-tunnel-remote-any.netdev',
770 '25-gre-tunnel.netdev',
772 '25-ip6gretap-tunnel-local-any.netdev',
773 '25-ip6gretap-tunnel.netdev',
774 '25-ip6gre-tunnel-any-any.netdev',
775 '25-ip6gre-tunnel-local-any.netdev',
776 '25-ip6gre-tunnel-remote-any.netdev',
777 '25-ip6gre-tunnel.netdev',
778 '25-ip6tnl-tunnel-any-any.netdev',
779 '25-ip6tnl-tunnel-local-any.netdev',
780 '25-ip6tnl-tunnel-remote-any.netdev',
781 '25-ip6tnl-tunnel.netdev',
782 '25-ipip-tunnel-any-any.netdev',
783 '25-ipip-tunnel-independent.netdev',
784 '25-ipip-tunnel-independent-loopback.netdev',
785 '25-ipip-tunnel-local-any.netdev',
786 '25-ipip-tunnel-remote-any.netdev',
787 '25-ipip-tunnel.netdev',
790 '25-isatap-tunnel.netdev',
795 '25-sit-tunnel-any-any.netdev',
796 '25-sit-tunnel-local-any.netdev',
797 '25-sit-tunnel-remote-any.netdev',
798 '25-sit-tunnel.netdev',
801 '25-tunnel-local-any.network',
802 '25-tunnel-remote-any.network',
807 '25-vti6-tunnel-any-any.netdev',
808 '25-vti6-tunnel-local-any.netdev',
809 '25-vti6-tunnel-remote-any.netdev',
810 '25-vti6-tunnel.netdev',
811 '25-vti-tunnel-any-any.netdev',
812 '25-vti-tunnel-local-any.netdev',
813 '25-vti-tunnel-remote-any.netdev',
814 '25-vti-tunnel.netdev',
817 '25-wireguard-23-peers.netdev',
818 '25-wireguard-23-peers.network',
819 '25-wireguard-preshared-key.txt',
820 '25-wireguard-private-key.txt',
821 '25-wireguard.netdev',
822 '25-wireguard.network',
824 '25-xfrm-independent.netdev',
840 'netdev-link-local-addressing-yes.network',
844 'vxlan-test1.network',
854 remove_fou_ports(self
.fou_ports
)
855 remove_links(self
.links_remove_earlier
)
856 remove_links(self
.links
)
857 stop_networkd(show_logs
=False)
860 remove_fou_ports(self
.fou_ports
)
861 remove_links(self
.links_remove_earlier
)
862 remove_links(self
.links
)
863 remove_unit_from_networkd_path(self
.units
)
864 stop_networkd(show_logs
=True)
866 def test_dropin_and_name_conflict(self
):
867 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
870 self
.wait_online(['dropin-test:off'], setup_state
='unmanaged')
872 output
= check_output('ip link show dropin-test')
874 self
.assertRegex(output
, '00:50:56:c0:00:28')
876 def test_match_udev_property(self
):
877 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
879 self
.wait_online(['dummy98:routable'])
881 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'dummy98', env
=env
)
883 self
.assertRegex(output
, 'Network File: /run/systemd/network/14-match-udev-property')
885 def test_wait_online_any(self
):
886 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
889 self
.wait_online(['bridge99', 'test1:degraded'], bool_any
=True)
891 self
.wait_operstate('bridge99', '(off|no-carrier)', setup_state
='configuring')
892 self
.wait_operstate('test1', 'degraded')
894 def test_bridge(self
):
895 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
898 self
.wait_online(['bridge99:no-carrier'])
900 tick
= os
.sysconf('SC_CLK_TCK')
901 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick
))
902 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick
))
903 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick
))
904 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick
))
905 self
.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
906 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
907 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
908 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
909 self
.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
911 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'bridge99', env
=env
)
913 self
.assertRegex(output
, 'Priority: 9')
914 self
.assertRegex(output
, 'STP: yes')
915 self
.assertRegex(output
, 'Multicast IGMP Version: 3')
918 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
921 self
.wait_online(['bond99:off', 'bond98:off'], setup_state
='unmanaged')
923 self
.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
924 self
.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
925 self
.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
926 self
.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
927 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
928 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
929 self
.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
930 self
.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
931 self
.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
932 self
.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
933 self
.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
935 self
.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
936 self
.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
939 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
940 '21-vlan.network', '21-vlan-test1.network')
943 self
.wait_online(['test1:degraded', 'vlan99:routable'])
945 output
= check_output('ip -d link show test1')
947 self
.assertRegex(output
, ' mtu 2000 ')
949 output
= check_output('ip -d link show vlan99')
951 self
.assertRegex(output
, ' mtu 2000 ')
952 self
.assertRegex(output
, 'REORDER_HDR')
953 self
.assertRegex(output
, 'LOOSE_BINDING')
954 self
.assertRegex(output
, 'GVRP')
955 self
.assertRegex(output
, 'MVRP')
956 self
.assertRegex(output
, ' id 99 ')
958 output
= check_output('ip -4 address show dev test1')
960 self
.assertRegex(output
, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
961 self
.assertRegex(output
, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
963 output
= check_output('ip -4 address show dev vlan99')
965 self
.assertRegex(output
, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
967 def test_macvtap(self
):
968 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
969 with self
.subTest(mode
=mode
):
970 if mode
!= 'private':
972 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
973 '11-dummy.netdev', 'macvtap.network')
974 with
open(os
.path
.join(network_unit_file_path
, '21-macvtap.netdev'), mode
='a') as f
:
975 f
.write('[MACVTAP]\nMode=' + mode
)
978 self
.wait_online(['macvtap99:degraded', 'test1:degraded'])
980 output
= check_output('ip -d link show macvtap99')
982 self
.assertRegex(output
, 'macvtap mode ' + mode
+ ' ')
984 def test_macvlan(self
):
985 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
986 with self
.subTest(mode
=mode
):
987 if mode
!= 'private':
989 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
990 '11-dummy.netdev', 'macvlan.network')
991 with
open(os
.path
.join(network_unit_file_path
, '21-macvlan.netdev'), mode
='a') as f
:
992 f
.write('[MACVLAN]\nMode=' + mode
)
995 self
.wait_online(['macvlan99:degraded', 'test1:degraded'])
997 output
= check_output('ip -d link show test1')
999 self
.assertRegex(output
, ' mtu 2000 ')
1001 output
= check_output('ip -d link show macvlan99')
1003 self
.assertRegex(output
, ' mtu 2000 ')
1004 self
.assertRegex(output
, 'macvlan mode ' + mode
+ ' ')
1006 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1007 def test_ipvlan(self
):
1008 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1009 with self
.subTest(mode
=mode
, flag
=flag
):
1012 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1013 '11-dummy.netdev', 'ipvlan.network')
1014 with
open(os
.path
.join(network_unit_file_path
, '25-ipvlan.netdev'), mode
='a') as f
:
1015 f
.write('[IPVLAN]\nMode=' + mode
+ '\nFlags=' + flag
)
1018 self
.wait_online(['ipvlan99:degraded', 'test1:degraded'])
1020 output
= check_output('ip -d link show ipvlan99')
1022 self
.assertRegex(output
, 'ipvlan *mode ' + mode
.lower() + ' ' + flag
)
1024 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1025 def test_ipvtap(self
):
1026 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1027 with self
.subTest(mode
=mode
, flag
=flag
):
1030 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1031 '11-dummy.netdev', 'ipvtap.network')
1032 with
open(os
.path
.join(network_unit_file_path
, '25-ipvtap.netdev'), mode
='a') as f
:
1033 f
.write('[IPVTAP]\nMode=' + mode
+ '\nFlags=' + flag
)
1036 self
.wait_online(['ipvtap99:degraded', 'test1:degraded'])
1038 output
= check_output('ip -d link show ipvtap99')
1040 self
.assertRegex(output
, 'ipvtap *mode ' + mode
.lower() + ' ' + flag
)
1042 def test_veth(self
):
1043 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
1046 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1048 output
= check_output('ip -d link show veth99')
1050 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bc')
1051 output
= check_output('ip -d link show veth-peer')
1053 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bd')
1056 copy_unit_to_networkd_unit_path('25-tun.netdev')
1059 self
.wait_online(['tun99:off'], setup_state
='unmanaged')
1061 output
= check_output('ip -d link show tun99')
1063 # Old ip command does not support IFF_ flags
1064 self
.assertRegex(output
, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
1067 copy_unit_to_networkd_unit_path('25-tap.netdev')
1070 self
.wait_online(['tap99:off'], setup_state
='unmanaged')
1072 output
= check_output('ip -d link show tap99')
1074 # Old ip command does not support IFF_ flags
1075 self
.assertRegex(output
, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
1077 @expectedFailureIfModuleIsNotAvailable('vrf')
1079 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
1082 self
.wait_online(['vrf99:carrier'])
1084 @expectedFailureIfModuleIsNotAvailable('vcan')
1085 def test_vcan(self
):
1086 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
1089 self
.wait_online(['vcan99:carrier'])
1091 @expectedFailureIfModuleIsNotAvailable('vxcan')
1092 def test_vxcan(self
):
1093 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
1096 self
.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
1098 @expectedFailureIfModuleIsNotAvailable('wireguard')
1099 def test_wireguard(self
):
1100 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1101 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
1102 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
1104 self
.wait_online(['wg99:carrier', 'wg98:routable'])
1106 if shutil
.which('wg'):
1109 output
= check_output('wg show wg99 listen-port')
1110 self
.assertRegex(output
, '51820')
1111 output
= check_output('wg show wg99 fwmark')
1112 self
.assertRegex(output
, '0x4d2')
1113 output
= check_output('wg show wg99 allowed-ips')
1114 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
1115 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
1116 output
= check_output('wg show wg99 persistent-keepalive')
1117 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
1118 output
= check_output('wg show wg99 endpoints')
1119 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
1120 output
= check_output('wg show wg99 private-key')
1121 self
.assertRegex(output
, r
'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
1122 output
= check_output('wg show wg99 preshared-keys')
1123 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
1124 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
1126 output
= check_output('wg show wg98 private-key')
1127 self
.assertRegex(output
, r
'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
1129 def test_geneve(self
):
1130 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
1133 self
.wait_online(['geneve99:degraded'])
1135 output
= check_output('ip -d link show geneve99')
1137 self
.assertRegex(output
, '192.168.22.1')
1138 self
.assertRegex(output
, '6082')
1139 self
.assertRegex(output
, 'udpcsum')
1140 self
.assertRegex(output
, 'udp6zerocsumrx')
1142 def test_ipip_tunnel(self
):
1143 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1144 '25-ipip-tunnel.netdev', '25-tunnel.network',
1145 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1146 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1147 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1149 self
.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1151 output
= check_output('ip -d link show ipiptun99')
1153 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1154 output
= check_output('ip -d link show ipiptun98')
1156 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
1157 output
= check_output('ip -d link show ipiptun97')
1159 self
.assertRegex(output
, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
1160 output
= check_output('ip -d link show ipiptun96')
1162 self
.assertRegex(output
, 'ipip (ipip )?remote any local any dev dummy98')
1164 def test_gre_tunnel(self
):
1165 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1166 '25-gre-tunnel.netdev', '25-tunnel.network',
1167 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1168 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1169 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1171 self
.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1173 output
= check_output('ip -d link show gretun99')
1175 self
.assertRegex(output
, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1176 self
.assertRegex(output
, 'ikey 1.2.3.103')
1177 self
.assertRegex(output
, 'okey 1.2.4.103')
1178 self
.assertRegex(output
, 'iseq')
1179 self
.assertRegex(output
, 'oseq')
1180 output
= check_output('ip -d link show gretun98')
1182 self
.assertRegex(output
, 'gre remote 10.65.223.239 local any dev dummy98')
1183 self
.assertRegex(output
, 'ikey 0.0.0.104')
1184 self
.assertRegex(output
, 'okey 0.0.0.104')
1185 self
.assertNotRegex(output
, 'iseq')
1186 self
.assertNotRegex(output
, 'oseq')
1187 output
= check_output('ip -d link show gretun97')
1189 self
.assertRegex(output
, 'gre remote any local 10.65.223.238 dev dummy98')
1190 self
.assertRegex(output
, 'ikey 0.0.0.105')
1191 self
.assertRegex(output
, 'okey 0.0.0.105')
1192 self
.assertNotRegex(output
, 'iseq')
1193 self
.assertNotRegex(output
, 'oseq')
1194 output
= check_output('ip -d link show gretun96')
1196 self
.assertRegex(output
, 'gre remote any local any dev dummy98')
1197 self
.assertRegex(output
, 'ikey 0.0.0.106')
1198 self
.assertRegex(output
, 'okey 0.0.0.106')
1199 self
.assertNotRegex(output
, 'iseq')
1200 self
.assertNotRegex(output
, 'oseq')
1202 def test_ip6gre_tunnel(self
):
1203 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1204 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1205 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1206 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1207 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1210 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1212 self
.check_link_exists('dummy98')
1213 self
.check_link_exists('ip6gretun99')
1214 self
.check_link_exists('ip6gretun98')
1215 self
.check_link_exists('ip6gretun97')
1216 self
.check_link_exists('ip6gretun96')
1218 output
= check_output('ip -d link show ip6gretun99')
1220 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1221 output
= check_output('ip -d link show ip6gretun98')
1223 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1224 output
= check_output('ip -d link show ip6gretun97')
1226 self
.assertRegex(output
, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1227 output
= check_output('ip -d link show ip6gretun96')
1229 self
.assertRegex(output
, 'ip6gre remote any local any dev dummy98')
1231 def test_gretap_tunnel(self
):
1232 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1233 '25-gretap-tunnel.netdev', '25-tunnel.network',
1234 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1236 self
.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1238 output
= check_output('ip -d link show gretap99')
1240 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1241 self
.assertRegex(output
, 'ikey 0.0.0.106')
1242 self
.assertRegex(output
, 'okey 0.0.0.106')
1243 self
.assertRegex(output
, 'iseq')
1244 self
.assertRegex(output
, 'oseq')
1245 output
= check_output('ip -d link show gretap98')
1247 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local any dev dummy98')
1248 self
.assertRegex(output
, 'ikey 0.0.0.107')
1249 self
.assertRegex(output
, 'okey 0.0.0.107')
1250 self
.assertRegex(output
, 'iseq')
1251 self
.assertRegex(output
, 'oseq')
1253 def test_ip6gretap_tunnel(self
):
1254 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1255 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1256 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1258 self
.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1260 output
= check_output('ip -d link show ip6gretap99')
1262 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1263 output
= check_output('ip -d link show ip6gretap98')
1265 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1267 def test_vti_tunnel(self
):
1268 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1269 '25-vti-tunnel.netdev', '25-tunnel.network',
1270 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1271 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1272 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1274 self
.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1276 output
= check_output('ip -d link show vtitun99')
1278 self
.assertRegex(output
, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1279 output
= check_output('ip -d link show vtitun98')
1281 self
.assertRegex(output
, 'vti remote 10.65.223.239 local any dev dummy98')
1282 output
= check_output('ip -d link show vtitun97')
1284 self
.assertRegex(output
, 'vti remote any local 10.65.223.238 dev dummy98')
1285 output
= check_output('ip -d link show vtitun96')
1287 self
.assertRegex(output
, 'vti remote any local any dev dummy98')
1289 def test_vti6_tunnel(self
):
1290 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1291 '25-vti6-tunnel.netdev', '25-tunnel.network',
1292 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1293 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1295 self
.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1297 output
= check_output('ip -d link show vti6tun99')
1299 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1300 output
= check_output('ip -d link show vti6tun98')
1302 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1303 output
= check_output('ip -d link show vti6tun97')
1305 self
.assertRegex(output
, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1307 def test_ip6tnl_tunnel(self
):
1308 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1309 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1310 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1311 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1313 self
.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1315 output
= check_output('ip -d link show ip6tnl99')
1317 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1318 output
= check_output('ip -d link show ip6tnl98')
1320 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1321 output
= check_output('ip -d link show ip6tnl97')
1323 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1325 def test_sit_tunnel(self
):
1326 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1327 '25-sit-tunnel.netdev', '25-tunnel.network',
1328 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1329 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1330 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1332 self
.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1334 output
= check_output('ip -d link show sittun99')
1336 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1337 output
= check_output('ip -d link show sittun98')
1339 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
1340 output
= check_output('ip -d link show sittun97')
1342 self
.assertRegex(output
, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
1343 output
= check_output('ip -d link show sittun96')
1345 self
.assertRegex(output
, "sit (ip6ip )?remote any local any dev dummy98")
1347 def test_isatap_tunnel(self
):
1348 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1349 '25-isatap-tunnel.netdev', '25-tunnel.network')
1351 self
.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1353 output
= check_output('ip -d link show isataptun99')
1355 self
.assertRegex(output
, "isatap ")
1357 def test_6rd_tunnel(self
):
1358 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1359 '25-6rd-tunnel.netdev', '25-tunnel.network')
1361 self
.wait_online(['sittun99:routable', 'dummy98:degraded'])
1363 output
= check_output('ip -d link show sittun99')
1365 self
.assertRegex(output
, '6rd-prefix 2602::/24')
1367 @expectedFailureIfERSPANModuleIsNotAvailable()
1368 def test_erspan_tunnel(self
):
1369 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1370 '25-erspan-tunnel.netdev', '25-tunnel.network',
1371 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1373 self
.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1375 output
= check_output('ip -d link show erspan99')
1377 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local 172.16.1.200')
1378 self
.assertRegex(output
, 'ikey 0.0.0.101')
1379 self
.assertRegex(output
, 'okey 0.0.0.101')
1380 self
.assertRegex(output
, 'iseq')
1381 self
.assertRegex(output
, 'oseq')
1382 output
= check_output('ip -d link show erspan98')
1384 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local any')
1385 self
.assertRegex(output
, '102')
1386 self
.assertRegex(output
, 'ikey 0.0.0.102')
1387 self
.assertRegex(output
, 'okey 0.0.0.102')
1388 self
.assertRegex(output
, 'iseq')
1389 self
.assertRegex(output
, 'oseq')
1391 def test_tunnel_independent(self
):
1392 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1395 self
.wait_online(['ipiptun99:carrier'])
1397 def test_tunnel_independent_loopback(self
):
1398 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1401 self
.wait_online(['ipiptun99:carrier'])
1403 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1404 def test_xfrm(self
):
1405 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1406 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1409 self
.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1411 output
= check_output('ip link show dev xfrm99')
1414 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1415 def test_xfrm_independent(self
):
1416 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1419 self
.wait_online(['xfrm99:degraded'])
1421 @expectedFailureIfModuleIsNotAvailable('fou')
1423 # The following redundant check is necessary for CentOS CI.
1424 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1425 self
.assertTrue(is_module_available('fou'))
1427 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1428 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1429 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1432 self
.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state
='unmanaged')
1434 output
= check_output('ip fou show')
1436 self
.assertRegex(output
, 'port 55555 ipproto 4')
1437 self
.assertRegex(output
, 'port 55556 ipproto 47')
1439 output
= check_output('ip -d link show ipiptun96')
1441 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1442 output
= check_output('ip -d link show sittun96')
1444 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1445 output
= check_output('ip -d link show gretun96')
1447 self
.assertRegex(output
, 'encap fou encap-sport 1001 encap-dport 55556')
1448 output
= check_output('ip -d link show gretap96')
1450 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55556')
1452 def test_vxlan(self
):
1453 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1454 '11-dummy.netdev', 'vxlan-test1.network')
1457 self
.wait_online(['test1:degraded', 'vxlan99:degraded'])
1459 output
= check_output('ip -d link show vxlan99')
1461 self
.assertRegex(output
, '999')
1462 self
.assertRegex(output
, '5555')
1463 self
.assertRegex(output
, 'l2miss')
1464 self
.assertRegex(output
, 'l3miss')
1465 self
.assertRegex(output
, 'udpcsum')
1466 self
.assertRegex(output
, 'udp6zerocsumtx')
1467 self
.assertRegex(output
, 'udp6zerocsumrx')
1468 self
.assertRegex(output
, 'remcsumtx')
1469 self
.assertRegex(output
, 'remcsumrx')
1470 self
.assertRegex(output
, 'gbp')
1472 output
= check_output('bridge fdb show dev vxlan99')
1474 self
.assertRegex(output
, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1475 self
.assertRegex(output
, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1476 self
.assertRegex(output
, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1478 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'vxlan99', env
=env
)
1480 self
.assertRegex(output
, 'VNI: 999')
1481 self
.assertRegex(output
, 'Destination Port: 5555')
1482 self
.assertRegex(output
, 'Underlying Device: test1')
1484 def test_macsec(self
):
1485 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1486 'macsec.network', '12-dummy.netdev')
1489 self
.wait_online(['dummy98:degraded', 'macsec99:routable'])
1491 output
= check_output('ip -d link show macsec99')
1493 self
.assertRegex(output
, 'macsec99@dummy98')
1494 self
.assertRegex(output
, 'macsec sci [0-9a-f]*000b')
1495 self
.assertRegex(output
, 'encrypt on')
1497 output
= check_output('ip macsec show macsec99')
1499 self
.assertRegex(output
, 'encrypt on')
1500 self
.assertRegex(output
, 'TXSC: [0-9a-f]*000b on SA 1')
1501 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1502 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1503 self
.assertRegex(output
, 'RXSC: c619528fe6a00100, state on')
1504 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1505 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1506 self
.assertRegex(output
, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1507 self
.assertRegex(output
, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1508 self
.assertNotRegex(output
, 'key 02030405067080900000000000000000')
1509 self
.assertRegex(output
, 'RXSC: 8c16456c83a90002, state on')
1510 self
.assertRegex(output
, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1512 def test_nlmon(self
):
1513 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1516 self
.wait_online(['nlmon99:carrier'])
1518 @expectedFailureIfModuleIsNotAvailable('ifb')
1520 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1523 self
.wait_online(['ifb99:degraded'])
1525 class NetworkdL2TPTests(unittest
.TestCase
, Utilities
):
1536 '25-l2tp-dummy.network',
1538 '25-l2tp-ip.netdev',
1539 '25-l2tp-udp.netdev']
1541 l2tp_tunnel_ids
= [ '10' ]
1544 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1545 remove_links(self
.links
)
1546 stop_networkd(show_logs
=False)
1549 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1550 remove_links(self
.links
)
1551 remove_unit_from_networkd_path(self
.units
)
1552 stop_networkd(show_logs
=True)
1554 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1555 def test_l2tp_udp(self
):
1556 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1557 '25-l2tp-udp.netdev', '25-l2tp.network')
1560 self
.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1562 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1564 self
.assertRegex(output
, "Tunnel 10, encap UDP")
1565 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1566 self
.assertRegex(output
, "Peer tunnel 11")
1567 self
.assertRegex(output
, "UDP source / dest ports: 3000/4000")
1568 self
.assertRegex(output
, "UDP checksum: enabled")
1570 output
= check_output('ip l2tp show session tid 10 session_id 15')
1572 self
.assertRegex(output
, "Session 15 in tunnel 10")
1573 self
.assertRegex(output
, "Peer session 16, tunnel 11")
1574 self
.assertRegex(output
, "interface name: l2tp-ses1")
1576 output
= check_output('ip l2tp show session tid 10 session_id 17')
1578 self
.assertRegex(output
, "Session 17 in tunnel 10")
1579 self
.assertRegex(output
, "Peer session 18, tunnel 11")
1580 self
.assertRegex(output
, "interface name: l2tp-ses2")
1582 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1583 def test_l2tp_ip(self
):
1584 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1585 '25-l2tp-ip.netdev', '25-l2tp.network')
1588 self
.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1590 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1592 self
.assertRegex(output
, "Tunnel 10, encap IP")
1593 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1594 self
.assertRegex(output
, "Peer tunnel 12")
1596 output
= check_output('ip l2tp show session tid 10 session_id 25')
1598 self
.assertRegex(output
, "Session 25 in tunnel 10")
1599 self
.assertRegex(output
, "Peer session 26, tunnel 12")
1600 self
.assertRegex(output
, "interface name: l2tp-ses3")
1602 output
= check_output('ip l2tp show session tid 10 session_id 27')
1604 self
.assertRegex(output
, "Session 27 in tunnel 10")
1605 self
.assertRegex(output
, "Peer session 28, tunnel 12")
1606 self
.assertRegex(output
, "interface name: l2tp-ses4")
1608 class NetworkdNetworkTests(unittest
.TestCase
, Utilities
):
1623 '23-active-slave.network',
1624 '24-keep-configuration-static.network',
1625 '24-search-domain.network',
1626 '25-address-dad-veth-peer.network',
1627 '25-address-dad-veth99.network',
1628 '25-address-link-section.network',
1629 '25-address-preferred-lifetime-zero.network',
1630 '25-address-static.network',
1631 '25-bind-carrier.network',
1632 '25-bond-active-backup-slave.netdev',
1633 '25-fibrule-invert.network',
1634 '25-fibrule-port-range.network',
1635 '25-fibrule-uidrange.network',
1636 '25-gre-tunnel-remote-any.netdev',
1637 '25-ip6gre-tunnel-remote-any.netdev',
1638 '25-ipv6-address-label-section.network',
1639 '25-link-local-addressing-no.network',
1640 '25-link-local-addressing-yes.network',
1641 '25-link-section-unmanaged.network',
1642 '25-neighbor-section.network',
1643 '25-neighbor-next.network',
1644 '25-neighbor-ipv6.network',
1645 '25-neighbor-ip-dummy.network',
1646 '25-neighbor-ip.network',
1647 '25-nexthop.network',
1648 '25-qdisc-cake.network',
1649 '25-qdisc-clsact-and-htb.network',
1650 '25-qdisc-drr.network',
1651 '25-qdisc-ingress-netem-compat.network',
1652 '25-qdisc-pie.network',
1653 '25-route-ipv6-src.network',
1654 '25-route-static.network',
1655 '25-route-vrf.network',
1656 '25-gateway-static.network',
1657 '25-gateway-next-static.network',
1658 '25-sysctl-disable-ipv6.network',
1659 '25-sysctl.network',
1660 '25-veth-peer.network',
1663 '26-link-local-addressing-ipv6.network',
1664 'configure-without-carrier.network',
1665 'routing-policy-rule-dummy98.network',
1666 'routing-policy-rule-test1.network']
1668 routing_policy_rule_tables
= ['7', '8', '9']
1669 routes
= [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1672 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1673 remove_routes(self
.routes
)
1674 remove_links(self
.links
)
1675 stop_networkd(show_logs
=False)
1678 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1679 remove_routes(self
.routes
)
1680 remove_links(self
.links
)
1681 remove_unit_from_networkd_path(self
.units
)
1682 stop_networkd(show_logs
=True)
1684 def test_address_static(self
):
1685 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1688 self
.wait_online(['dummy98:routable'])
1690 output
= check_output('ip -4 address show dev dummy98')
1692 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1693 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1694 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1697 self
.assertNotRegex(output
, '10.10.0.1/16')
1698 self
.assertNotRegex(output
, '10.10.0.2/16')
1700 output
= check_output('ip -4 address show dev dummy98 label 32')
1701 self
.assertRegex(output
, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1703 output
= check_output('ip -4 address show dev dummy98 label 33')
1704 self
.assertRegex(output
, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1706 output
= check_output('ip -4 address show dev dummy98 label 34')
1707 self
.assertRegex(output
, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1709 output
= check_output('ip -4 address show dev dummy98 label 35')
1710 self
.assertRegex(output
, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1712 output
= check_output('ip -6 address show dev dummy98')
1714 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::15/64 scope global')
1715 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::16/64 scope global')
1716 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::15/64 scope global')
1717 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::16/64 scope global')
1718 self
.assertRegex(output
, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1719 self
.assertRegex(output
, 'inet6 fd[0-9a-f:]*1/64 scope global')
1721 def test_address_preferred_lifetime_zero_ipv6(self
):
1722 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1725 self
.wait_online(['dummy98:routable'])
1727 output
= check_output('ip address show dummy98')
1729 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1730 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::1/64 scope global')
1732 output
= check_output('ip route show dev dummy98')
1734 self
.assertRegex(output
, 'default via 20.20.20.1 proto static')
1736 def test_address_dad(self
):
1737 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1740 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
1742 output
= check_output('ip -4 address show dev veth99')
1744 self
.assertRegex(output
, '192.168.100.10/24')
1746 output
= check_output('ip -4 address show dev veth-peer')
1748 self
.assertNotRegex(output
, '192.168.100.10/24')
1750 def test_configure_without_carrier(self
):
1751 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1753 self
.wait_online(['test1:routable'])
1755 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'test1', env
=env
)
1757 self
.assertRegex(output
, '192.168.0.15')
1758 self
.assertRegex(output
, '192.168.0.1')
1759 self
.assertRegex(output
, 'routable')
1761 def test_routing_policy_rule(self
):
1762 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1764 self
.wait_online(['test1:degraded'])
1766 output
= check_output('ip rule list iif test1 priority 111')
1768 self
.assertRegex(output
, '111:')
1769 self
.assertRegex(output
, 'from 192.168.100.18')
1770 self
.assertRegex(output
, r
'tos (0x08|throughput)\s')
1771 self
.assertRegex(output
, 'iif test1')
1772 self
.assertRegex(output
, 'oif test1')
1773 self
.assertRegex(output
, 'lookup 7')
1775 output
= check_output('ip rule list iif test1 priority 101')
1777 self
.assertRegex(output
, '101:')
1778 self
.assertRegex(output
, 'from all')
1779 self
.assertRegex(output
, 'iif test1')
1780 self
.assertRegex(output
, 'lookup 9')
1782 output
= check_output('ip -6 rule list iif test1 priority 100')
1784 self
.assertRegex(output
, '100:')
1785 self
.assertRegex(output
, 'from all')
1786 self
.assertRegex(output
, 'iif test1')
1787 self
.assertRegex(output
, 'lookup 8')
1789 output
= check_output('ip -6 rule list iif test1 priority 101')
1791 self
.assertRegex(output
, '101:')
1792 self
.assertRegex(output
, 'from all')
1793 self
.assertRegex(output
, 'iif test1')
1794 self
.assertRegex(output
, 'lookup 9')
1796 def test_routing_policy_rule_issue_11280(self
):
1797 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1798 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1800 for trial
in range(3):
1801 # Remove state files only first time
1803 self
.wait_online(['test1:degraded', 'dummy98:degraded'])
1806 output
= check_output('ip rule list table 7')
1808 self
.assertRegex(output
, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1810 output
= check_output('ip rule list table 8')
1812 self
.assertRegex(output
, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1814 stop_networkd(remove_state_files
=False)
1816 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1817 def test_routing_policy_rule_port_range(self
):
1818 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1820 self
.wait_online(['test1:degraded'])
1822 output
= check_output('ip rule')
1824 self
.assertRegex(output
, '111')
1825 self
.assertRegex(output
, 'from 192.168.100.18')
1826 self
.assertRegex(output
, '1123-1150')
1827 self
.assertRegex(output
, '3224-3290')
1828 self
.assertRegex(output
, 'tcp')
1829 self
.assertRegex(output
, 'lookup 7')
1831 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1832 def test_routing_policy_rule_invert(self
):
1833 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1835 self
.wait_online(['test1:degraded'])
1837 output
= check_output('ip rule')
1839 self
.assertRegex(output
, '111')
1840 self
.assertRegex(output
, 'not.*?from.*?192.168.100.18')
1841 self
.assertRegex(output
, 'tcp')
1842 self
.assertRegex(output
, 'lookup 7')
1844 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
1845 def test_routing_policy_rule_uidrange(self
):
1846 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
1848 self
.wait_online(['test1:degraded'])
1850 output
= check_output('ip rule')
1852 self
.assertRegex(output
, '111')
1853 self
.assertRegex(output
, 'from 192.168.100.18')
1854 self
.assertRegex(output
, 'lookup 7')
1855 self
.assertRegex(output
, 'uidrange 100-200')
1857 def test_route_static(self
):
1858 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1860 self
.wait_online(['dummy98:routable'])
1862 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'dummy98', env
=env
)
1865 print('### ip -6 route show dev dummy98')
1866 output
= check_output('ip -6 route show dev dummy98')
1868 self
.assertRegex(output
, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1869 self
.assertRegex(output
, '2001:1234:5:8f63::1 proto kernel')
1871 print('### ip -6 route show dev dummy98 default')
1872 output
= check_output('ip -6 route show dev dummy98 default')
1874 self
.assertRegex(output
, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1876 print('### ip -4 route show dev dummy98')
1877 output
= check_output('ip -4 route show dev dummy98')
1879 self
.assertRegex(output
, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1880 self
.assertRegex(output
, '149.10.124.64 proto static scope link')
1881 self
.assertRegex(output
, '169.254.0.0/16 proto static scope link metric 2048')
1882 self
.assertRegex(output
, '192.168.1.1 proto static initcwnd 20')
1883 self
.assertRegex(output
, '192.168.1.2 proto static initrwnd 30')
1884 self
.assertRegex(output
, 'multicast 149.10.123.4 proto static')
1886 print('### ip -4 route show dev dummy98 default')
1887 output
= check_output('ip -4 route show dev dummy98 default')
1889 self
.assertRegex(output
, 'default via 149.10.125.65 proto static onlink')
1890 self
.assertRegex(output
, 'default via 149.10.124.64 proto static')
1891 self
.assertRegex(output
, 'default proto static')
1893 print('### ip -4 route show table local dev dummy98')
1894 output
= check_output('ip -4 route show table local dev dummy98')
1896 self
.assertRegex(output
, 'local 149.10.123.1 proto static scope host')
1897 self
.assertRegex(output
, 'anycast 149.10.123.2 proto static scope link')
1898 self
.assertRegex(output
, 'broadcast 149.10.123.3 proto static scope link')
1900 print('### ip route show type blackhole')
1901 output
= check_output('ip route show type blackhole')
1903 self
.assertRegex(output
, 'blackhole 202.54.1.2 proto static')
1905 print('### ip route show type unreachable')
1906 output
= check_output('ip route show type unreachable')
1908 self
.assertRegex(output
, 'unreachable 202.54.1.3 proto static')
1910 print('### ip route show type prohibit')
1911 output
= check_output('ip route show type prohibit')
1913 self
.assertRegex(output
, 'prohibit 202.54.1.4 proto static')
1915 print('### ip route show 192.168.10.1')
1916 output
= check_output('ip route show 192.168.10.1')
1918 self
.assertRegex(output
, '192.168.10.1 proto static')
1919 self
.assertRegex(output
, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1920 self
.assertRegex(output
, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1922 print('### ip route show 192.168.10.2')
1923 output
= check_output('ip route show 192.168.10.2')
1925 # old ip command does not show IPv6 gateways...
1926 self
.assertRegex(output
, '192.168.10.2 proto static')
1927 self
.assertRegex(output
, 'nexthop')
1928 self
.assertRegex(output
, 'dev dummy98 weight 10')
1929 self
.assertRegex(output
, 'dev dummy98 weight 5')
1931 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1932 output
= check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1934 # old ip command does not show 'nexthop' keyword and weight...
1935 self
.assertRegex(output
, '2001:1234:5:7fff:ff:ff:ff:ff')
1936 self
.assertRegex(output
, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
1937 self
.assertRegex(output
, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
1939 @expectedFailureIfModuleIsNotAvailable('vrf')
1940 def test_route_vrf(self
):
1941 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
1942 '25-vrf.netdev', '25-vrf.network')
1944 self
.wait_online(['dummy98:routable', 'vrf99:carrier'])
1946 output
= check_output('ip route show vrf vrf99')
1948 self
.assertRegex(output
, 'default via 192.168.100.1')
1950 output
= check_output('ip route show')
1952 self
.assertNotRegex(output
, 'default via 192.168.100.1')
1954 def test_gateway_reconfigure(self
):
1955 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1957 self
.wait_online(['dummy98:routable'])
1958 print('### ip -4 route show dev dummy98 default')
1959 output
= check_output('ip -4 route show dev dummy98 default')
1961 self
.assertRegex(output
, 'default via 149.10.124.59 proto static')
1962 self
.assertNotRegex(output
, '149.10.124.60')
1964 remove_unit_from_networkd_path(['25-gateway-static.network'])
1965 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1967 self
.wait_online(['dummy98:routable'])
1968 print('### ip -4 route show dev dummy98 default')
1969 output
= check_output('ip -4 route show dev dummy98 default')
1971 self
.assertNotRegex(output
, '149.10.124.59')
1972 self
.assertRegex(output
, 'default via 149.10.124.60 proto static')
1974 def test_ip_route_ipv6_src_route(self
):
1975 # a dummy device does not make the addresses go through tentative state, so we
1976 # reuse a bond from an earlier test, which does make the addresses go through
1977 # tentative state, and do our test on that
1978 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1980 self
.wait_online(['dummy98:enslaved', 'bond199:routable'])
1982 output
= check_output('ip -6 route list dev bond199')
1984 self
.assertRegex(output
, 'abcd::/16')
1985 self
.assertRegex(output
, 'src')
1986 self
.assertRegex(output
, '2001:1234:56:8f63::2')
1988 def test_ip_link_mac_address(self
):
1989 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1991 self
.wait_online(['dummy98:degraded'])
1993 output
= check_output('ip link show dummy98')
1995 self
.assertRegex(output
, '00:01:02:aa:bb:cc')
1997 def test_ip_link_unmanaged(self
):
1998 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
2001 self
.check_link_exists('dummy98')
2003 self
.wait_operstate('dummy98', 'off', setup_state
='unmanaged')
2005 def test_ipv6_address_label(self
):
2006 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2008 self
.wait_online(['dummy98:degraded'])
2010 output
= check_output('ip addrlabel list')
2012 self
.assertRegex(output
, '2004:da8:1::/64')
2014 def test_neighbor_section(self
):
2015 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2017 self
.wait_online(['dummy98:degraded'], timeout
='40s')
2019 print('### ip neigh list dev dummy98')
2020 output
= check_output('ip neigh list dev dummy98')
2022 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2023 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2025 def test_neighbor_reconfigure(self
):
2026 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2028 self
.wait_online(['dummy98:degraded'], timeout
='40s')
2030 print('### ip neigh list dev dummy98')
2031 output
= check_output('ip neigh list dev dummy98')
2033 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2034 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2036 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2037 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2039 self
.wait_online(['dummy98:degraded'], timeout
='40s')
2040 print('### ip neigh list dev dummy98')
2041 output
= check_output('ip neigh list dev dummy98')
2043 self
.assertNotRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2044 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2045 self
.assertNotRegex(output
, '2004:da8:1::1.*PERMANENT')
2047 def test_neighbor_gre(self
):
2048 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2049 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
2051 self
.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout
='40s')
2053 output
= check_output('ip neigh list dev gretun97')
2055 self
.assertRegex(output
, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
2057 output
= check_output('ip neigh list dev ip6gretun97')
2059 self
.assertRegex(output
, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
2061 def test_link_local_addressing(self
):
2062 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2063 '25-link-local-addressing-no.network', '12-dummy.netdev')
2065 self
.wait_online(['test1:degraded', 'dummy98:carrier'])
2067 output
= check_output('ip address show dev test1')
2069 self
.assertRegex(output
, 'inet .* scope link')
2070 self
.assertRegex(output
, 'inet6 .* scope link')
2072 output
= check_output('ip address show dev dummy98')
2074 self
.assertNotRegex(output
, 'inet6* .* scope link')
2077 Documentation/networking/ip-sysctl.txt
2079 addr_gen_mode - INTEGER
2080 Defines how link-local and autoconf addresses are generated.
2082 0: generate address based on EUI64 (default)
2083 1: do no generate a link-local address, use EUI64 for addresses generated
2085 2: generate stable privacy addresses, using the secret from
2086 stable_secret (RFC7217)
2087 3: generate stable privacy addresses, using a random secret if unset
2090 test1_addr_gen_mode
= ''
2091 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')):
2092 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')) as f
:
2096 # if stable_secret is unset, then EIO is returned
2097 test1_addr_gen_mode
= '0'
2099 test1_addr_gen_mode
= '2'
2101 test1_addr_gen_mode
= '0'
2103 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'addr_gen_mode')):
2104 self
.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode
)
2106 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'dummy98'), 'addr_gen_mode')):
2107 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
2109 def test_link_local_addressing_remove_ipv6ll(self
):
2110 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2112 self
.wait_online(['dummy98:degraded'])
2114 output
= check_output('ip address show dev dummy98')
2116 self
.assertRegex(output
, 'inet6 .* scope link')
2118 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2120 self
.wait_online(['dummy98:carrier'])
2122 output
= check_output('ip address show dev dummy98')
2124 self
.assertNotRegex(output
, 'inet6* .* scope link')
2126 def test_sysctl(self
):
2127 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2129 self
.wait_online(['dummy98:degraded'])
2131 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2132 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2133 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2134 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2135 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2136 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2137 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
2139 def test_sysctl_disable_ipv6(self
):
2140 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
2142 print('## Disable ipv6')
2143 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2144 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
2147 self
.wait_online(['dummy98:routable'])
2149 output
= check_output('ip -4 address show dummy98')
2151 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2152 output
= check_output('ip -6 address show dummy98')
2154 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
2155 self
.assertRegex(output
, 'inet6 .* scope link')
2156 output
= check_output('ip -4 route show dev dummy98')
2158 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2159 output
= check_output('ip -6 route show dev dummy98')
2161 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2163 check_output('ip link del dummy98')
2165 print('## Enable ipv6')
2166 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2167 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
2170 self
.wait_online(['dummy98:routable'])
2172 output
= check_output('ip -4 address show dummy98')
2174 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2175 output
= check_output('ip -6 address show dummy98')
2177 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
2178 self
.assertRegex(output
, 'inet6 .* scope link')
2179 output
= check_output('ip -4 route show dev dummy98')
2181 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2182 output
= check_output('ip -6 route show dev dummy98')
2184 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2186 def test_bind_carrier(self
):
2187 check_output('ip link add dummy98 type dummy')
2188 check_output('ip link set dummy98 up')
2191 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2193 self
.wait_online(['test1:routable'])
2195 output
= check_output('ip address show test1')
2197 self
.assertRegex(output
, 'UP,LOWER_UP')
2198 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2199 self
.wait_operstate('test1', 'routable')
2201 check_output('ip link add dummy99 type dummy')
2202 check_output('ip link set dummy99 up')
2204 output
= check_output('ip address show test1')
2206 self
.assertRegex(output
, 'UP,LOWER_UP')
2207 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2208 self
.wait_operstate('test1', 'routable')
2210 check_output('ip link del dummy98')
2212 output
= check_output('ip address show test1')
2214 self
.assertRegex(output
, 'UP,LOWER_UP')
2215 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2216 self
.wait_operstate('test1', 'routable')
2218 check_output('ip link set dummy99 down')
2220 output
= check_output('ip address show test1')
2222 self
.assertNotRegex(output
, 'UP,LOWER_UP')
2223 self
.assertRegex(output
, 'DOWN')
2224 self
.assertNotRegex(output
, '192.168.10')
2225 self
.wait_operstate('test1', 'off')
2227 check_output('ip link set dummy99 up')
2229 output
= check_output('ip address show test1')
2231 self
.assertRegex(output
, 'UP,LOWER_UP')
2232 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2233 self
.wait_operstate('test1', 'routable')
2235 def test_domain(self
):
2236 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2238 self
.wait_online(['dummy98:routable'])
2240 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'dummy98', env
=env
)
2242 self
.assertRegex(output
, 'Address: 192.168.42.100')
2243 self
.assertRegex(output
, 'DNS: 192.168.42.1')
2244 self
.assertRegex(output
, 'Search Domains: one')
2246 def test_keep_configuration_static(self
):
2247 check_output('systemctl stop systemd-networkd')
2249 check_output('ip link add name dummy98 type dummy')
2250 check_output('ip address add 10.1.2.3/16 dev dummy98')
2251 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2252 output
= check_output('ip address show dummy98')
2254 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2255 self
.assertRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2256 output
= check_output('ip route show dev dummy98')
2259 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2261 self
.wait_online(['dummy98:routable'])
2263 output
= check_output('ip address show dummy98')
2265 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2266 self
.assertNotRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2268 @expectedFailureIfNexthopIsNotAvailable()
2269 def test_nexthop(self
):
2270 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2272 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2274 output
= check_output('ip nexthop list dev veth99')
2276 self
.assertRegex(output
, '192.168.5.1')
2278 def test_qdisc(self
):
2279 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
2280 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2281 check_output('modprobe sch_teql max_equalizers=2')
2284 self
.wait_online(['dummy98:routable', 'test1:routable'])
2286 output
= check_output('tc qdisc show dev test1')
2288 self
.assertRegex(output
, 'qdisc netem')
2289 self
.assertRegex(output
, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2290 self
.assertRegex(output
, 'qdisc ingress')
2292 output
= check_output('tc qdisc show dev dummy98')
2294 self
.assertRegex(output
, 'qdisc clsact')
2296 self
.assertRegex(output
, 'qdisc htb 2: root')
2297 self
.assertRegex(output
, r
'default (0x30|30)')
2299 self
.assertRegex(output
, 'qdisc netem 30: parent 2:30')
2300 self
.assertRegex(output
, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2301 self
.assertRegex(output
, 'qdisc fq_codel')
2302 self
.assertRegex(output
, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
2304 self
.assertRegex(output
, 'qdisc teql1 31: parent 2:31')
2306 self
.assertRegex(output
, 'qdisc fq 32: parent 2:32')
2307 self
.assertRegex(output
, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2308 self
.assertRegex(output
, 'quantum 1500')
2309 self
.assertRegex(output
, 'initial_quantum 13000')
2310 self
.assertRegex(output
, 'maxrate 1Mbit')
2312 self
.assertRegex(output
, 'qdisc codel 33: parent 2:33')
2313 self
.assertRegex(output
, 'limit 2000p target 10.0ms ce_threshold 100.0ms interval 50.0ms ecn')
2315 self
.assertRegex(output
, 'qdisc fq_codel 34: parent 2:34')
2316 self
.assertRegex(output
, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
2318 self
.assertRegex(output
, 'qdisc tbf 35: parent 2:35')
2319 self
.assertRegex(output
, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70.0ms')
2321 self
.assertRegex(output
, 'qdisc sfq 36: parent 2:36')
2322 self
.assertRegex(output
, 'perturb 5sec')
2324 self
.assertRegex(output
, 'qdisc pfifo 37: parent 2:37')
2325 self
.assertRegex(output
, 'limit 100000p')
2327 self
.assertRegex(output
, 'qdisc gred 38: parent 2:38')
2328 self
.assertRegex(output
, 'vqs 12 default 10 grio')
2330 self
.assertRegex(output
, 'qdisc sfb 39: parent 2:39')
2331 self
.assertRegex(output
, 'limit 200000')
2333 self
.assertRegex(output
, 'qdisc bfifo 3a: parent 2:3a')
2334 self
.assertRegex(output
, 'limit 1000000')
2336 self
.assertRegex(output
, 'qdisc pfifo_head_drop 3b: parent 2:3b')
2337 self
.assertRegex(output
, 'limit 1023p')
2339 output
= check_output('tc class show dev dummy98')
2341 self
.assertRegex(output
, 'class htb 2:30 root leaf 30:')
2342 self
.assertRegex(output
, 'class htb 2:31 root leaf 31:')
2343 self
.assertRegex(output
, 'class htb 2:32 root leaf 32:')
2344 self
.assertRegex(output
, 'class htb 2:33 root leaf 33:')
2345 self
.assertRegex(output
, 'class htb 2:34 root leaf 34:')
2346 self
.assertRegex(output
, 'class htb 2:35 root leaf 35:')
2347 self
.assertRegex(output
, 'class htb 2:36 root leaf 36:')
2348 self
.assertRegex(output
, 'class htb 2:37 root leaf 37:')
2349 self
.assertRegex(output
, 'class htb 2:38 root leaf 38:')
2350 self
.assertRegex(output
, 'class htb 2:39 root leaf 39:')
2351 self
.assertRegex(output
, 'class htb 2:3a root leaf 3a:')
2352 self
.assertRegex(output
, 'class htb 2:3b root leaf 3b:')
2353 self
.assertRegex(output
, 'prio 1 rate 1Mbit ceil 500Kbit')
2355 def test_qdisc2(self
):
2356 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev')
2359 self
.wait_online(['dummy98:routable'])
2361 output
= check_output('tc qdisc show dev dummy98')
2363 self
.assertRegex(output
, 'qdisc drr 2: root')
2364 output
= check_output('tc class show dev dummy98')
2366 self
.assertRegex(output
, 'class drr 2:30 root quantum 2000b')
2368 @expectedFailureIfCAKEIsNotAvailable()
2369 def test_qdisc_cake(self
):
2370 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
2372 self
.wait_online(['dummy98:routable'])
2374 output
= check_output('tc qdisc show dev dummy98')
2376 self
.assertRegex(output
, 'qdisc cake 3a: root')
2377 self
.assertRegex(output
, 'bandwidth 500Mbit')
2378 self
.assertRegex(output
, 'overhead 128')
2380 @expectedFailureIfPIEIsNotAvailable()
2381 def test_qdisc_pie(self
):
2382 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
2384 self
.wait_online(['dummy98:routable'])
2386 output
= check_output('tc qdisc show dev dummy98')
2388 self
.assertRegex(output
, 'qdisc pie 3a: root')
2389 self
.assertRegex(output
, 'limit 200000')
2391 class NetworkdStateFileTests(unittest
.TestCase
, Utilities
):
2398 'state-file-tests.network',
2402 remove_links(self
.links
)
2403 stop_networkd(show_logs
=False)
2406 remove_links(self
.links
)
2407 remove_unit_from_networkd_path(self
.units
)
2408 stop_networkd(show_logs
=True)
2410 def test_state_file(self
):
2411 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2413 self
.wait_online(['dummy98:routable'])
2415 output
= check_output(*networkctl_cmd
, '--no-legend', 'list', 'dummy98', env
=env
)
2417 ifindex
= output
.split()[0]
2419 path
= os
.path
.join('/run/systemd/netif/links/', ifindex
)
2420 self
.assertTrue(os
.path
.exists(path
))
2423 with
open(path
) as f
:
2425 self
.assertRegex(data
, r
'ADMIN_STATE=configured')
2426 self
.assertRegex(data
, r
'OPER_STATE=routable')
2427 self
.assertRegex(data
, r
'REQUIRED_FOR_ONLINE=yes')
2428 self
.assertRegex(data
, r
'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2429 self
.assertRegex(data
, r
'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2430 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2431 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2432 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2433 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2434 self
.assertRegex(data
, r
'LLMNR=no')
2435 self
.assertRegex(data
, r
'MDNS=yes')
2436 self
.assertRegex(data
, r
'DNSSEC=no')
2437 self
.assertRegex(data
, r
'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2439 check_output(*resolvectl_cmd
, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env
=env
)
2440 check_output(*resolvectl_cmd
, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env
=env
)
2441 check_output(*resolvectl_cmd
, 'llmnr', 'dummy98', 'yes', env
=env
)
2442 check_output(*resolvectl_cmd
, 'mdns', 'dummy98', 'no', env
=env
)
2443 check_output(*resolvectl_cmd
, 'dnssec', 'dummy98', 'yes', env
=env
)
2444 check_output(*timedatectl_cmd
, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env
=env
)
2447 with
open(path
) as f
:
2449 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2450 self
.assertRegex(data
, r
'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2451 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2452 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2453 self
.assertRegex(data
, r
'LLMNR=yes')
2454 self
.assertRegex(data
, r
'MDNS=no')
2455 self
.assertRegex(data
, r
'DNSSEC=yes')
2457 check_output(*timedatectl_cmd
, 'revert', 'dummy98', env
=env
)
2460 with
open(path
) as f
:
2462 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2463 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2464 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2465 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2466 self
.assertRegex(data
, r
'LLMNR=yes')
2467 self
.assertRegex(data
, r
'MDNS=no')
2468 self
.assertRegex(data
, r
'DNSSEC=yes')
2470 check_output(*resolvectl_cmd
, 'revert', 'dummy98', env
=env
)
2473 with
open(path
) as f
:
2475 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2476 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2477 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2478 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2479 self
.assertRegex(data
, r
'LLMNR=no')
2480 self
.assertRegex(data
, r
'MDNS=yes')
2481 self
.assertRegex(data
, r
'DNSSEC=no')
2483 class NetworkdBondTests(unittest
.TestCase
, Utilities
):
2493 '23-active-slave.network',
2494 '23-bond199.network',
2495 '23-primary-slave.network',
2496 '25-bond-active-backup-slave.netdev',
2499 'bond-slave.network']
2502 remove_links(self
.links
)
2503 stop_networkd(show_logs
=False)
2506 remove_links(self
.links
)
2507 remove_unit_from_networkd_path(self
.units
)
2508 stop_networkd(show_logs
=True)
2510 def test_bond_active_slave(self
):
2511 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2513 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2515 output
= check_output('ip -d link show bond199')
2517 self
.assertRegex(output
, 'active_slave dummy98')
2519 def test_bond_primary_slave(self
):
2520 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2522 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2524 output
= check_output('ip -d link show bond199')
2526 self
.assertRegex(output
, 'primary dummy98')
2528 def test_bond_operstate(self
):
2529 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2530 'bond99.network','bond-slave.network')
2532 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2534 output
= check_output('ip -d link show dummy98')
2536 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2538 output
= check_output('ip -d link show test1')
2540 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2542 output
= check_output('ip -d link show bond99')
2544 self
.assertRegex(output
, 'MASTER,UP,LOWER_UP')
2546 self
.wait_operstate('dummy98', 'enslaved')
2547 self
.wait_operstate('test1', 'enslaved')
2548 self
.wait_operstate('bond99', 'routable')
2550 check_output('ip link set dummy98 down')
2552 self
.wait_operstate('dummy98', 'off')
2553 self
.wait_operstate('test1', 'enslaved')
2554 self
.wait_operstate('bond99', 'degraded-carrier')
2556 check_output('ip link set dummy98 up')
2558 self
.wait_operstate('dummy98', 'enslaved')
2559 self
.wait_operstate('test1', 'enslaved')
2560 self
.wait_operstate('bond99', 'routable')
2562 check_output('ip link set dummy98 down')
2563 check_output('ip link set test1 down')
2565 self
.wait_operstate('dummy98', 'off')
2566 self
.wait_operstate('test1', 'off')
2568 if not self
.wait_operstate('bond99', 'no-carrier', setup_timeout
=30, fail_assert
=False):
2569 # Huh? Kernel does not recognize that all slave interfaces are down?
2570 # Let's confirm that networkd's operstate is consistent with ip's result.
2571 self
.assertNotRegex(output
, 'NO-CARRIER')
2573 class NetworkdBridgeTests(unittest
.TestCase
, Utilities
):
2583 '26-bridge-slave-interface-1.network',
2584 '26-bridge-slave-interface-2.network',
2585 '26-bridge-vlan-master.network',
2586 '26-bridge-vlan-slave.network',
2587 'bridge99-ignore-carrier-loss.network',
2590 routing_policy_rule_tables
= ['100']
2593 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2594 remove_links(self
.links
)
2595 stop_networkd(show_logs
=False)
2598 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2599 remove_links(self
.links
)
2600 remove_unit_from_networkd_path(self
.units
)
2601 stop_networkd(show_logs
=True)
2603 def test_bridge_vlan(self
):
2604 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2605 '26-bridge.netdev', '26-bridge-vlan-master.network')
2607 self
.wait_online(['test1:enslaved', 'bridge99:degraded'])
2609 output
= check_output('bridge vlan show dev test1')
2611 self
.assertNotRegex(output
, '4063')
2612 for i
in range(4064, 4095):
2613 self
.assertRegex(output
, f
'{i}')
2614 self
.assertNotRegex(output
, '4095')
2616 output
= check_output('bridge vlan show dev bridge99')
2618 self
.assertNotRegex(output
, '4059')
2619 for i
in range(4060, 4095):
2620 self
.assertRegex(output
, f
'{i}')
2621 self
.assertNotRegex(output
, '4095')
2623 def test_bridge_property(self
):
2624 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2625 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2628 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2630 output
= check_output('ip -d link show test1')
2632 self
.assertRegex(output
, 'master')
2633 self
.assertRegex(output
, 'bridge')
2635 output
= check_output('ip -d link show dummy98')
2637 self
.assertRegex(output
, 'master')
2638 self
.assertRegex(output
, 'bridge')
2640 output
= check_output('ip addr show bridge99')
2642 self
.assertRegex(output
, '192.168.0.15/24')
2644 output
= check_output('bridge -d link show dummy98')
2646 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2647 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2648 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2649 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2650 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2651 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2652 if (os
.path
.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2653 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2654 if (os
.path
.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2655 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2656 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2657 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2658 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2659 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2661 output
= check_output('bridge -d link show test1')
2663 self
.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2665 check_output('ip address add 192.168.0.16/24 dev bridge99')
2668 output
= check_output('ip addr show bridge99')
2670 self
.assertRegex(output
, '192.168.0.16/24')
2673 print('### ip -6 route list table all dev bridge99')
2674 output
= check_output('ip -6 route list table all dev bridge99')
2676 self
.assertRegex(output
, 'ff00::/8 table local metric 256 pref medium')
2678 self
.assertEqual(call('ip link del test1'), 0)
2680 self
.wait_operstate('bridge99', 'degraded-carrier')
2682 check_output('ip link del dummy98')
2684 self
.wait_operstate('bridge99', 'no-carrier')
2686 output
= check_output('ip address show bridge99')
2688 self
.assertRegex(output
, 'NO-CARRIER')
2689 self
.assertNotRegex(output
, '192.168.0.15/24')
2690 self
.assertNotRegex(output
, '192.168.0.16/24')
2692 print('### ip -6 route list table all dev bridge99')
2693 output
= check_output('ip -6 route list table all dev bridge99')
2695 self
.assertRegex(output
, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2697 def test_bridge_ignore_carrier_loss(self
):
2698 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2699 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2700 'bridge99-ignore-carrier-loss.network')
2702 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2704 check_output('ip address add 192.168.0.16/24 dev bridge99')
2707 check_output('ip link del test1')
2708 check_output('ip link del dummy98')
2711 output
= check_output('ip address show bridge99')
2713 self
.assertRegex(output
, 'NO-CARRIER')
2714 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2715 self
.assertRegex(output
, 'inet 192.168.0.16/24 scope global secondary bridge99')
2717 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self
):
2718 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2719 'bridge99-ignore-carrier-loss.network')
2721 self
.wait_online(['bridge99:no-carrier'])
2723 for trial
in range(4):
2724 check_output('ip link add dummy98 type dummy')
2725 check_output('ip link set dummy98 up')
2727 check_output('ip link del dummy98')
2729 self
.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2731 output
= check_output('ip address show bridge99')
2733 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2735 output
= check_output('ip rule list table 100')
2737 self
.assertEqual(output
, '0: from all to 8.8.8.8 lookup 100')
2739 class NetworkdLLDPTests(unittest
.TestCase
, Utilities
):
2743 '23-emit-lldp.network',
2748 remove_links(self
.links
)
2749 stop_networkd(show_logs
=False)
2752 remove_links(self
.links
)
2753 remove_unit_from_networkd_path(self
.units
)
2754 stop_networkd(show_logs
=True)
2756 def test_lldp(self
):
2757 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2759 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2761 output
= check_output(*networkctl_cmd
, 'lldp', env
=env
)
2763 self
.assertRegex(output
, 'veth-peer')
2764 self
.assertRegex(output
, 'veth99')
2766 class NetworkdRATests(unittest
.TestCase
, Utilities
):
2771 'ipv6-prefix.network',
2772 'ipv6-prefix-veth.network',
2773 'ipv6-prefix-veth-token-static.network',
2774 'ipv6-prefix-veth-token-static-explicit.network',
2775 'ipv6-prefix-veth-token-static-multiple.network',
2776 'ipv6-prefix-veth-token-prefixstable.network']
2779 remove_links(self
.links
)
2780 stop_networkd(show_logs
=False)
2783 remove_links(self
.links
)
2784 remove_unit_from_networkd_path(self
.units
)
2785 stop_networkd(show_logs
=True)
2787 def test_ipv6_prefix_delegation(self
):
2788 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2790 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2792 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
2794 self
.assertRegex(output
, 'fe80::')
2795 self
.assertRegex(output
, '2002:da8:1::1')
2797 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2799 self
.assertRegex(output
, '2002:da8:1:0')
2801 def test_ipv6_token_static(self
):
2802 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
2804 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2806 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2808 self
.assertRegex(output
, '2002:da8:1:0:1a:2b:3c:4d')
2810 def test_ipv6_token_static_explicit(self
):
2811 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2813 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2815 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2817 self
.assertRegex(output
, '2002:da8:1:0:1a:2b:3c:4d')
2819 def test_ipv6_token_static_multiple(self
):
2820 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2822 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2824 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2826 self
.assertRegex(output
, '2002:da8:1:0:1a:2b:3c:4d')
2827 self
.assertRegex(output
, '2002:da8:1:0:fa:de:ca:fe')
2829 def test_ipv6_token_prefixstable(self
):
2830 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2832 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2834 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2836 self
.assertRegex(output
, '2002:da8:1:0')
2838 class NetworkdDHCPServerTests(unittest
.TestCase
, Utilities
):
2843 'dhcp-client.network',
2844 'dhcp-client-timezone-router.network',
2845 'dhcp-server.network',
2846 'dhcp-server-timezone-router.network']
2849 remove_links(self
.links
)
2850 stop_networkd(show_logs
=False)
2853 remove_links(self
.links
)
2854 remove_unit_from_networkd_path(self
.units
)
2855 stop_networkd(show_logs
=True)
2857 def test_dhcp_server(self
):
2858 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2860 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2862 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2864 self
.assertRegex(output
, '192.168.5.*')
2865 self
.assertRegex(output
, 'Gateway: 192.168.5.1')
2866 self
.assertRegex(output
, 'DNS: 192.168.5.1')
2867 self
.assertRegex(output
, 'NTP: 192.168.5.1')
2869 def test_emit_router_timezone(self
):
2870 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2872 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2874 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2876 self
.assertRegex(output
, 'Gateway: 192.168.5.*')
2877 self
.assertRegex(output
, '192.168.5.*')
2878 self
.assertRegex(output
, 'Europe/Berlin')
2880 class NetworkdDHCPClientTests(unittest
.TestCase
, Utilities
):
2889 'dhcp-client-anonymize.network',
2890 'dhcp-client-decline.network',
2891 'dhcp-client-gateway-ipv4.network',
2892 'dhcp-client-gateway-ipv6.network',
2893 'dhcp-client-gateway-onlink-implicit.network',
2894 'dhcp-client-ipv4-dhcp-settings.network',
2895 'dhcp-client-ipv4-only-ipv6-disabled.network',
2896 'dhcp-client-ipv4-only.network',
2897 'dhcp-client-ipv4-use-routes-no.network',
2898 'dhcp-client-ipv6-only.network',
2899 'dhcp-client-ipv6-rapid-commit.network',
2900 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2901 'dhcp-client-keep-configuration-dhcp.network',
2902 'dhcp-client-listen-port.network',
2903 'dhcp-client-reassign-static-routes-ipv4.network',
2904 'dhcp-client-reassign-static-routes-ipv6.network',
2905 'dhcp-client-route-metric.network',
2906 'dhcp-client-route-table.network',
2907 'dhcp-client-use-dns-ipv4-and-ra.network',
2908 'dhcp-client-use-dns-ipv4.network',
2909 'dhcp-client-use-dns-no.network',
2910 'dhcp-client-use-dns-yes.network',
2911 'dhcp-client-use-domains.network',
2912 'dhcp-client-use-routes-no.network',
2913 'dhcp-client-vrf.network',
2914 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2915 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2916 'dhcp-client-with-static-address.network',
2917 'dhcp-client.network',
2918 'dhcp-server-decline.network',
2919 'dhcp-server-veth-peer.network',
2920 'dhcp-v4-server-veth-peer.network',
2921 'dhcp-client-use-domains.network',
2925 stop_dnsmasq(dnsmasq_pid_file
)
2926 remove_links(self
.links
)
2927 stop_networkd(show_logs
=False)
2930 stop_dnsmasq(dnsmasq_pid_file
)
2933 remove_links(self
.links
)
2934 remove_unit_from_networkd_path(self
.units
)
2935 stop_networkd(show_logs
=True)
2937 def test_dhcp_client_ipv6_only(self
):
2938 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2941 self
.wait_online(['veth-peer:carrier'])
2943 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2945 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2947 self
.assertRegex(output
, '2600::')
2948 self
.assertNotRegex(output
, '192.168.5')
2950 # Confirm that ipv6 token is not set in the kernel
2951 output
= check_output('ip token show dev veth99')
2953 self
.assertRegex(output
, 'token :: dev veth99')
2955 def test_dhcp_client_ipv4_only(self
):
2956 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2959 self
.wait_online(['veth-peer:carrier'])
2960 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
2961 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2963 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2965 self
.assertNotRegex(output
, '2600::')
2966 self
.assertRegex(output
, '192.168.5')
2967 self
.assertRegex(output
, '192.168.5.6')
2968 self
.assertRegex(output
, '192.168.5.7')
2970 # checking routes to DNS servers
2971 output
= check_output('ip route show dev veth99')
2973 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2974 self
.assertRegex(output
, r
'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2975 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2977 stop_dnsmasq(dnsmasq_pid_file
)
2978 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time
='2m')
2980 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2981 print('Wait for the dynamic address to be renewed')
2984 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2986 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
2988 self
.assertNotRegex(output
, '2600::')
2989 self
.assertRegex(output
, '192.168.5')
2990 self
.assertNotRegex(output
, '192.168.5.6')
2991 self
.assertRegex(output
, '192.168.5.7')
2992 self
.assertRegex(output
, '192.168.5.8')
2994 # checking routes to DNS servers
2995 output
= check_output('ip route show dev veth99')
2997 self
.assertNotRegex(output
, r
'192.168.5.6')
2998 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2999 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3000 self
.assertRegex(output
, r
'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
3002 def test_dhcp_client_ipv4_use_routes_no(self
):
3003 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
3006 self
.wait_online(['veth-peer:carrier'])
3007 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
3008 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3010 output
= check_output('ip route show dev veth99')
3012 self
.assertNotRegex(output
, r
'192.168.5.5')
3013 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3014 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3016 def test_dhcp_client_ipv4_ipv6(self
):
3017 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3018 'dhcp-client-ipv4-only.network')
3020 self
.wait_online(['veth-peer:carrier'])
3022 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3024 # link become 'routable' when at least one protocol provide an valid address.
3025 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3026 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3028 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3030 self
.assertRegex(output
, '2600::')
3031 self
.assertRegex(output
, '192.168.5')
3033 def test_dhcp_client_settings(self
):
3034 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
3037 self
.wait_online(['veth-peer:carrier'])
3039 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3041 print('## ip address show dev veth99')
3042 output
= check_output('ip address show dev veth99')
3044 self
.assertRegex(output
, '12:34:56:78:9a:bc')
3045 self
.assertRegex(output
, '192.168.5')
3046 self
.assertRegex(output
, '1492')
3048 print('## ip route show table main dev veth99')
3049 output
= check_output('ip route show table main dev veth99')
3052 main_table_is_empty
= output
== ''
3053 if not main_table_is_empty
:
3054 self
.assertNotRegex(output
, 'proto dhcp')
3056 print('## ip route show table 211 dev veth99')
3057 output
= check_output('ip route show table 211 dev veth99')
3059 self
.assertRegex(output
, 'default via 192.168.5.1 proto dhcp')
3060 if main_table_is_empty
:
3061 self
.assertRegex(output
, '192.168.5.0/24 proto dhcp')
3062 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3063 self
.assertRegex(output
, '192.168.5.1 proto dhcp scope link')
3065 print('## dnsmasq log')
3066 self
.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3067 self
.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3068 self
.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3069 self
.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
3071 def test_dhcp6_client_settings_rapidcommit_true(self
):
3072 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3074 self
.wait_online(['veth-peer:carrier'])
3076 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3078 output
= check_output('ip address show dev veth99')
3080 self
.assertRegex(output
, '12:34:56:78:9a:bc')
3081 self
.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
3083 def test_dhcp6_client_settings_rapidcommit_false(self
):
3084 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
3086 self
.wait_online(['veth-peer:carrier'])
3088 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3090 output
= check_output('ip address show dev veth99')
3092 self
.assertRegex(output
, '12:34:56:78:9a:bc')
3093 self
.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
3095 def test_dhcp_client_settings_anonymize(self
):
3096 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
3098 self
.wait_online(['veth-peer:carrier'])
3100 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3102 self
.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3103 self
.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3104 self
.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
3106 def test_dhcp_client_listen_port(self
):
3107 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
3109 self
.wait_online(['veth-peer:carrier'])
3110 start_dnsmasq('--dhcp-alternate-port=67,5555')
3111 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3113 output
= check_output('ip -4 address show dev veth99')
3115 self
.assertRegex(output
, '192.168.5.* dynamic')
3117 def test_dhcp_client_with_static_address(self
):
3118 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3119 'dhcp-client-with-static-address.network')
3121 self
.wait_online(['veth-peer:carrier'])
3123 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3125 output
= check_output('ip address show dev veth99 scope global')
3127 self
.assertRegex(output
, r
'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3128 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3130 output
= check_output('ip route show dev veth99')
3132 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3133 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3134 self
.assertRegex(output
, r
'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3135 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3137 def test_dhcp_route_table_id(self
):
3138 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
3140 self
.wait_online(['veth-peer:carrier'])
3142 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3144 output
= check_output('ip route show table 12')
3146 self
.assertRegex(output
, 'veth99 proto dhcp')
3147 self
.assertRegex(output
, '192.168.5.1')
3149 def test_dhcp_route_metric(self
):
3150 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
3152 self
.wait_online(['veth-peer:carrier'])
3154 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3156 output
= check_output('ip route show dev veth99')
3158 self
.assertRegex(output
, 'metric 24')
3160 def test_dhcp_client_reassign_static_routes_ipv4(self
):
3161 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3162 'dhcp-client-reassign-static-routes-ipv4.network')
3164 self
.wait_online(['veth-peer:carrier'])
3165 start_dnsmasq(lease_time
='2m')
3166 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3168 output
= check_output('ip address show dev veth99 scope global')
3170 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3172 output
= check_output('ip route show dev veth99')
3174 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3175 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
3176 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
3177 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
3179 stop_dnsmasq(dnsmasq_pid_file
)
3180 start_dnsmasq(ipv4_range
='192.168.5.210,192.168.5.220', lease_time
='2m')
3182 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3183 print('Wait for the dynamic address to be renewed')
3186 self
.wait_online(['veth99:routable'])
3188 output
= check_output('ip route show dev veth99')
3190 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3191 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
3192 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
3193 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
3195 def test_dhcp_client_reassign_static_routes_ipv6(self
):
3196 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3197 'dhcp-client-reassign-static-routes-ipv6.network')
3199 self
.wait_online(['veth-peer:carrier'])
3200 start_dnsmasq(lease_time
='2m')
3201 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3203 output
= check_output('ip address show dev veth99 scope global')
3205 self
.assertRegex(output
, r
'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
3207 output
= check_output('ip -6 route show dev veth99')
3209 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
3210 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
3212 stop_dnsmasq(dnsmasq_pid_file
)
3213 start_dnsmasq(ipv6_range
='2600::30,2600::40', lease_time
='2m')
3215 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3216 print('Wait for the dynamic address to be renewed')
3219 self
.wait_online(['veth99:routable'])
3221 output
= check_output('ip -6 route show dev veth99')
3223 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
3224 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
3226 def test_dhcp_keep_configuration_dhcp(self
):
3227 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
3229 self
.wait_online(['veth-peer:carrier'])
3230 start_dnsmasq(lease_time
='2m')
3231 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3233 output
= check_output('ip address show dev veth99 scope global')
3235 self
.assertRegex(output
, r
'192.168.5.*')
3237 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3239 self
.assertRegex(output
, r
'192.168.5.*')
3241 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
3242 stop_dnsmasq(dnsmasq_pid_file
)
3244 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3245 print('Wait for the dynamic address to be expired')
3248 print('The lease address should be kept after lease expired')
3249 output
= check_output('ip address show dev veth99 scope global')
3251 self
.assertRegex(output
, r
'192.168.5.*')
3253 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3255 self
.assertRegex(output
, r
'192.168.5.*')
3257 check_output('systemctl stop systemd-networkd')
3259 print('The lease address should be kept after networkd stopped')
3260 output
= check_output('ip address show dev veth99 scope global')
3262 self
.assertRegex(output
, r
'192.168.5.*')
3264 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3266 self
.assertRegex(output
, r
'192.168.5.*')
3269 self
.wait_online(['veth-peer:routable'])
3271 print('Still the lease address should be kept after networkd restarted')
3272 output
= check_output('ip address show dev veth99 scope global')
3274 self
.assertRegex(output
, r
'192.168.5.*')
3276 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3278 self
.assertRegex(output
, r
'192.168.5.*')
3280 def test_dhcp_keep_configuration_dhcp_on_stop(self
):
3281 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
3283 self
.wait_online(['veth-peer:carrier'])
3284 start_dnsmasq(lease_time
='2m')
3285 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3287 output
= check_output('ip address show dev veth99 scope global')
3289 self
.assertRegex(output
, r
'192.168.5.*')
3291 stop_dnsmasq(dnsmasq_pid_file
)
3292 check_output('systemctl stop systemd-networkd')
3294 output
= check_output('ip address show dev veth99 scope global')
3296 self
.assertRegex(output
, r
'192.168.5.*')
3299 self
.wait_online(['veth-peer:routable'])
3301 output
= check_output('ip address show dev veth99 scope global')
3303 self
.assertNotRegex(output
, r
'192.168.5.*')
3305 def test_dhcp_client_reuse_address_as_static(self
):
3306 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
3308 self
.wait_online(['veth-peer:carrier'])
3310 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3312 # link become 'routable' when at least one protocol provide an valid address.
3313 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3314 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3316 output
= check_output('ip address show dev veth99 scope global')
3318 self
.assertRegex(output
, '192.168.5')
3319 self
.assertRegex(output
, '2600::')
3321 ipv4_address
= re
.search(r
'192.168.5.[0-9]*/24', output
)
3322 ipv6_address
= re
.search(r
'2600::[0-9a-f:]*/128', output
)
3323 static_network
= '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address
.group(), 'Address=' + ipv6_address
.group()])
3324 print(static_network
)
3326 remove_unit_from_networkd_path(['dhcp-client.network'])
3328 with
open(os
.path
.join(network_unit_file_path
, 'static.network'), mode
='w') as f
:
3329 f
.write(static_network
)
3331 # When networkd started, the links are already configured, so let's wait for 5 seconds
3332 # the links to be re-configured.
3334 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3336 output
= check_output('ip -4 address show dev veth99 scope global')
3338 self
.assertRegex(output
, '192.168.5')
3339 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
3341 output
= check_output('ip -6 address show dev veth99 scope global')
3343 self
.assertRegex(output
, '2600::')
3344 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
3346 @expectedFailureIfModuleIsNotAvailable('vrf')
3347 def test_dhcp_client_vrf(self
):
3348 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3349 '25-vrf.netdev', '25-vrf.network')
3351 self
.wait_online(['veth-peer:carrier'])
3353 self
.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
3355 # link become 'routable' when at least one protocol provide an valid address.
3356 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3357 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3359 print('## ip -d link show dev vrf99')
3360 output
= check_output('ip -d link show dev vrf99')
3362 self
.assertRegex(output
, 'vrf table 42')
3364 print('## ip address show vrf vrf99')
3365 output
= check_output('ip address show vrf vrf99')
3367 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3368 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3369 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3370 self
.assertRegex(output
, 'inet6 .* scope link')
3372 print('## ip address show dev veth99')
3373 output
= check_output('ip address show dev veth99')
3375 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3376 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3377 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3378 self
.assertRegex(output
, 'inet6 .* scope link')
3380 print('## ip route show vrf vrf99')
3381 output
= check_output('ip route show vrf vrf99')
3383 self
.assertRegex(output
, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3384 self
.assertRegex(output
, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3385 self
.assertRegex(output
, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3386 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3387 self
.assertRegex(output
, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3389 print('## ip route show table main dev veth99')
3390 output
= check_output('ip route show table main dev veth99')
3392 self
.assertEqual(output
, '')
3394 def test_dhcp_client_gateway_ipv4(self
):
3395 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3396 'dhcp-client-gateway-ipv4.network')
3398 self
.wait_online(['veth-peer:carrier'])
3400 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3402 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3404 self
.assertRegex(output
, '10.0.0.0/8 via 192.168.5.1 proto static')
3406 def test_dhcp_client_gateway_ipv6(self
):
3407 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3408 'dhcp-client-gateway-ipv6.network')
3410 self
.wait_online(['veth-peer:carrier'])
3412 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3414 output
= check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3416 self
.assertRegex(output
, 'via fe80::1034:56ff:fe78:9abd')
3418 def test_dhcp_client_gateway_onlink_implicit(self
):
3419 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3420 'dhcp-client-gateway-onlink-implicit.network')
3422 self
.wait_online(['veth-peer:carrier'])
3424 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3426 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3428 self
.assertRegex(output
, '192.168.5')
3430 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3432 self
.assertRegex(output
, 'onlink')
3433 output
= check_output('ip route list dev veth99 192.168.100.0/24')
3435 self
.assertRegex(output
, 'onlink')
3437 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self
):
3438 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3439 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3441 self
.wait_online(['veth-peer:carrier'])
3442 start_dnsmasq(lease_time
='2m')
3443 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3445 output
= check_output('ip address show dev veth99')
3448 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3449 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3450 output
= check_output('ip -6 address show dev veth99 scope link')
3451 self
.assertRegex(output
, 'inet6 .* scope link')
3452 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3453 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3454 output
= check_output('ip -4 address show dev veth99 scope link')
3455 self
.assertNotRegex(output
, 'inet .* scope link')
3457 print('Wait for the dynamic address to be expired')
3460 output
= check_output('ip address show dev veth99')
3463 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3464 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3465 output
= check_output('ip -6 address show dev veth99 scope link')
3466 self
.assertRegex(output
, 'inet6 .* scope link')
3467 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3468 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3469 output
= check_output('ip -4 address show dev veth99 scope link')
3470 self
.assertNotRegex(output
, 'inet .* scope link')
3472 search_words_in_dnsmasq_log('DHCPOFFER', show_all
=True)
3474 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self
):
3475 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3476 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3478 self
.wait_online(['veth99:degraded', 'veth-peer:routable'])
3480 output
= check_output('ip address show dev veth99')
3483 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3484 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3485 output
= check_output('ip -6 address show dev veth99 scope link')
3486 self
.assertRegex(output
, 'inet6 .* scope link')
3487 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3488 self
.assertNotRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3489 output
= check_output('ip -4 address show dev veth99 scope link')
3490 self
.assertRegex(output
, 'inet .* scope link')
3492 def test_dhcp_client_route_remove_on_renew(self
):
3493 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3494 'dhcp-client-ipv4-only-ipv6-disabled.network')
3496 self
.wait_online(['veth-peer:carrier'])
3497 start_dnsmasq(ipv4_range
='192.168.5.100,192.168.5.199', lease_time
='2m')
3498 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3500 # test for issue #12490
3502 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3504 self
.assertRegex(output
, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3506 for line
in output
.splitlines():
3507 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3508 address1
= line
.split()[1].split('/')[0]
3511 output
= check_output('ip -4 route show dev veth99')
3513 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3514 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3516 stop_dnsmasq(dnsmasq_pid_file
)
3517 start_dnsmasq(ipv4_range
='192.168.5.200,192.168.5.250', lease_time
='2m')
3519 print('Wait for the dynamic address to be expired')
3522 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3524 self
.assertRegex(output
, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3526 for line
in output
.splitlines():
3527 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3528 address2
= line
.split()[1].split('/')[0]
3531 self
.assertNotEqual(address1
, address2
)
3533 output
= check_output('ip -4 route show dev veth99')
3535 self
.assertNotRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3536 self
.assertNotRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3537 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3538 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3540 def test_dhcp_client_use_dns_yes(self
):
3541 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3544 self
.wait_online(['veth-peer:carrier'])
3545 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3546 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3548 # link become 'routable' when at least one protocol provide an valid address.
3549 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3550 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3553 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3555 self
.assertRegex(output
, '192.168.5.1')
3556 self
.assertRegex(output
, '2600::1')
3558 def test_dhcp_client_use_dns_no(self
):
3559 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3562 self
.wait_online(['veth-peer:carrier'])
3563 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3564 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3566 # link become 'routable' when at least one protocol provide an valid address.
3567 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3568 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3571 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3573 self
.assertNotRegex(output
, '192.168.5.1')
3574 self
.assertNotRegex(output
, '2600::1')
3576 def test_dhcp_client_use_dns_ipv4(self
):
3577 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3580 self
.wait_online(['veth-peer:carrier'])
3581 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3582 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3584 # link become 'routable' when at least one protocol provide an valid address.
3585 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3586 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3589 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3591 self
.assertRegex(output
, '192.168.5.1')
3592 self
.assertNotRegex(output
, '2600::1')
3594 def test_dhcp_client_use_dns_ipv4_and_ra(self
):
3595 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3598 self
.wait_online(['veth-peer:carrier'])
3599 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3600 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3602 # link become 'routable' when at least one protocol provide an valid address.
3603 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3604 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3607 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3609 self
.assertRegex(output
, '192.168.5.1')
3610 self
.assertRegex(output
, '2600::1')
3612 def test_dhcp_client_use_domains(self
):
3613 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3616 self
.wait_online(['veth-peer:carrier'])
3617 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3618 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3620 output
= check_output(*networkctl_cmd
, '-n', '0', 'status', 'veth99', env
=env
)
3622 self
.assertRegex(output
, 'Search Domains: example.com')
3625 output
= check_output(*resolvectl_cmd
, 'domain', 'veth99', env
=env
)
3627 self
.assertRegex(output
, 'example.com')
3629 def test_dhcp_client_decline(self
):
3630 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3633 self
.wait_online(['veth-peer:carrier'])
3634 rc
= call(*wait_online_cmd
, '--timeout=10s', '--interface=veth99:routable', env
=env
)
3635 self
.assertTrue(rc
== 1)
3637 class NetworkdIPv6PrefixTests(unittest
.TestCase
, Utilities
):
3642 'ipv6ra-prefix-client.network',
3643 'ipv6ra-prefix.network'
3647 remove_links(self
.links
)
3648 stop_networkd(show_logs
=False)
3652 remove_links(self
.links
)
3653 remove_unit_from_networkd_path(self
.units
)
3654 stop_networkd(show_logs
=True)
3656 def test_ipv6_route_prefix(self
):
3657 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3660 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3662 output
= check_output('ip -6 route show dev veth-peer')
3664 self
.assertRegex(output
, '2001:db8:0:1::/64 proto ra')
3666 output
= check_output('ip addr show dev veth99')
3668 self
.assertNotRegex(output
, '2001:db8:0:1')
3669 self
.assertRegex(output
, '2001:db8:0:2')
3671 class NetworkdMTUTests(unittest
.TestCase
, Utilities
):
3676 '12-dummy-mtu.netdev',
3677 '12-dummy-mtu.link',
3682 remove_links(self
.links
)
3683 stop_networkd(show_logs
=False)
3687 remove_links(self
.links
)
3688 remove_unit_from_networkd_path(self
.units
)
3689 stop_networkd(show_logs
=True)
3691 def check_mtu(self
, mtu
, ipv6_mtu
=None, reset
=True):
3697 self
.wait_online(['dummy98:routable'])
3698 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu
)
3699 self
.assertEqual(read_link_attr('dummy98', 'mtu'), mtu
)
3701 # test normal restart
3703 self
.wait_online(['dummy98:routable'])
3704 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu
)
3705 self
.assertEqual(read_link_attr('dummy98', 'mtu'), mtu
)
3708 self
.reset_check_mtu(mtu
, ipv6_mtu
)
3710 def reset_check_mtu(self
, mtu
, ipv6_mtu
=None):
3711 ''' test setting mtu/ipv6_mtu with interface already up '''
3714 # note - changing the device mtu resets the ipv6 mtu
3715 run('ip link set up mtu 1501 dev dummy98')
3716 run('ip link set up mtu 1500 dev dummy98')
3717 self
.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3718 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3720 self
.check_mtu(mtu
, ipv6_mtu
, reset
=False)
3722 def test_mtu_network(self
):
3723 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3724 self
.check_mtu('1600')
3726 def test_mtu_netdev(self
):
3727 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins
=False)
3728 # note - MTU set by .netdev happens ONLY at device creation!
3729 self
.check_mtu('1600', reset
=False)
3731 def test_mtu_link(self
):
3732 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins
=False)
3733 # must reload udev because it only picks up new files after 3 second delay
3734 call('udevadm control --reload')
3735 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3736 self
.check_mtu('1600', reset
=False)
3738 def test_ipv6_mtu(self
):
3739 ''' set ipv6 mtu without setting device mtu '''
3740 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3741 self
.check_mtu('1500', '1400')
3743 def test_ipv6_mtu_toolarge(self
):
3744 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3745 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3746 self
.check_mtu('1500', '1500')
3748 def test_mtu_network_ipv6_mtu(self
):
3749 ''' set ipv6 mtu and set device mtu via network file '''
3750 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3751 self
.check_mtu('1600', '1550')
3753 def test_mtu_netdev_ipv6_mtu(self
):
3754 ''' set ipv6 mtu and set device mtu via netdev file '''
3755 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3756 self
.check_mtu('1600', '1550', reset
=False)
3758 def test_mtu_link_ipv6_mtu(self
):
3759 ''' set ipv6 mtu and set device mtu via link file '''
3760 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3761 # must reload udev because it only picks up new files after 3 second delay
3762 call('udevadm control --reload')
3763 self
.check_mtu('1600', '1550', reset
=False)
3766 if __name__
== '__main__':
3767 parser
= argparse
.ArgumentParser()
3768 parser
.add_argument('--build-dir', help='Path to build dir', dest
='build_dir')
3769 parser
.add_argument('--networkd', help='Path to systemd-networkd', dest
='networkd_bin')
3770 parser
.add_argument('--resolved', help='Path to systemd-resolved', dest
='resolved_bin')
3771 parser
.add_argument('--udevd', help='Path to systemd-udevd', dest
='udevd_bin')
3772 parser
.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest
='wait_online_bin')
3773 parser
.add_argument('--networkctl', help='Path to networkctl', dest
='networkctl_bin')
3774 parser
.add_argument('--resolvectl', help='Path to resolvectl', dest
='resolvectl_bin')
3775 parser
.add_argument('--timedatectl', help='Path to timedatectl', dest
='timedatectl_bin')
3776 parser
.add_argument('--valgrind', help='Enable valgrind', dest
='use_valgrind', type=bool, nargs
='?', const
=True, default
=use_valgrind
)
3777 parser
.add_argument('--debug', help='Generate debugging logs', dest
='enable_debug', type=bool, nargs
='?', const
=True, default
=enable_debug
)
3778 parser
.add_argument('--asan-options', help='ASAN options', dest
='asan_options')
3779 parser
.add_argument('--lsan-options', help='LSAN options', dest
='lsan_options')
3780 parser
.add_argument('--ubsan-options', help='UBSAN options', dest
='ubsan_options')
3781 ns
, args
= parser
.parse_known_args(namespace
=unittest
)
3784 if ns
.networkd_bin
or ns
.resolved_bin
or ns
.udevd_bin
or ns
.wait_online_bin
or ns
.networkctl_bin
or ns
.resolvectl_bin
or ns
.timedatectl_bin
:
3785 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3786 networkd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd')
3787 resolved_bin
= os
.path
.join(ns
.build_dir
, 'systemd-resolved')
3788 udevd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-udevd')
3789 wait_online_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd-wait-online')
3790 networkctl_bin
= os
.path
.join(ns
.build_dir
, 'networkctl')
3791 resolvectl_bin
= os
.path
.join(ns
.build_dir
, 'resolvectl')
3792 timedatectl_bin
= os
.path
.join(ns
.build_dir
, 'timedatectl')
3795 networkd_bin
= ns
.networkd_bin
3797 resolved_bin
= ns
.resolved_bin
3799 udevd_bin
= ns
.udevd_bin
3800 if ns
.wait_online_bin
:
3801 wait_online_bin
= ns
.wait_online_bin
3802 if ns
.networkctl_bin
:
3803 networkctl_bin
= ns
.networkctl_bin
3804 if ns
.resolvectl_bin
:
3805 resolvectl_bin
= ns
.resolvectl_bin
3806 if ns
.timedatectl_bin
:
3807 timedatectl_bin
= ns
.timedatectl_bin
3809 use_valgrind
= ns
.use_valgrind
3810 enable_debug
= ns
.enable_debug
3811 asan_options
= ns
.asan_options
3812 lsan_options
= ns
.lsan_options
3813 ubsan_options
= ns
.ubsan_options
3816 networkctl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin
]
3817 resolvectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin
]
3818 timedatectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin
]
3819 wait_online_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin
]
3821 networkctl_cmd
= [networkctl_bin
]
3822 resolvectl_cmd
= [resolvectl_bin
]
3823 timedatectl_cmd
= [timedatectl_bin
]
3824 wait_online_cmd
= [wait_online_bin
]
3827 env
.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3829 env
.update({ 'ASAN_OPTIONS' : asan_options
})
3831 env
.update({ 'LSAN_OPTIONS' : lsan_options
})
3833 env
.update({ 'UBSAN_OPTIONS' : ubsan_options
})
3836 unittest
.main(testRunner
=unittest
.TextTestRunner(stream
=sys
.stdout
,