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 networkd_bin
='/usr/lib/systemd/systemd-networkd'
26 resolved_bin
='/usr/lib/systemd/systemd-resolved'
27 wait_online_bin
='/usr/lib/systemd/systemd-networkd-wait-online'
28 networkctl_bin
='/usr/bin/networkctl'
29 resolvectl_bin
='/usr/bin/resolvectl'
30 timedatectl_bin
='/usr/bin/timedatectl'
40 def check_output(*command
, **kwargs
):
41 # This replaces both check_output and check_call (output can be ignored)
42 command
= command
[0].split() + list(command
[1:])
43 return subprocess
.check_output(command
, universal_newlines
=True, **kwargs
).rstrip()
45 def call(*command
, **kwargs
):
46 command
= command
[0].split() + list(command
[1:])
47 return subprocess
.call(command
, universal_newlines
=True, **kwargs
)
49 def run(*command
, **kwargs
):
50 command
= command
[0].split() + list(command
[1:])
51 return subprocess
.run(command
, universal_newlines
=True, **kwargs
)
53 def is_module_available(module_name
):
54 lsmod_output
= check_output('lsmod')
55 module_re
= re
.compile(rf
'^{re.escape(module_name)}\b', re
.MULTILINE
)
56 return module_re
.search(lsmod_output
) or not call('modprobe', module_name
)
58 def expectedFailureIfModuleIsNotAvailable(module_name
):
60 if not is_module_available(module_name
):
61 return unittest
.expectedFailure(func
)
66 def expectedFailureIfERSPANModuleIsNotAvailable():
68 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')
70 call('ip link del erspan99')
73 return unittest
.expectedFailure(func
)
77 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
79 rc
= call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
81 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
84 return unittest
.expectedFailure(func
)
88 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
90 rc
= call('ip rule add not from 192.168.100.19 ipproto tcp table 7')
92 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
95 return unittest
.expectedFailure(func
)
99 def expectedFailureIfLinkFileFieldIsNotSet():
102 rc
= call('ip link add name dummy99 type dummy')
104 ret
= run('udevadm info -w10s /sys/class/net/dummy99', stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
105 if ret
.returncode
== 0 and 'E: ID_NET_LINK_FILE=' in ret
.stdout
.rstrip():
107 call('ip link del dummy99')
112 return unittest
.expectedFailure(func
)
116 def expectedFailureIfNexthopIsNotAvailable():
118 rc
= call('ip nexthop list')
122 return unittest
.expectedFailure(func
)
129 os
.makedirs(network_unit_file_path
, exist_ok
=True)
130 os
.makedirs(networkd_ci_path
, exist_ok
=True)
132 shutil
.rmtree(networkd_ci_path
)
133 copytree(os
.path
.join(os
.path
.dirname(os
.path
.abspath(__file__
)), 'conf'), networkd_ci_path
)
135 for u
in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']:
136 if call(f
'systemctl is-active --quiet {u}') == 0:
137 check_output(f
'systemctl stop {u}')
138 running_units
.append(u
)
147 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin
,
151 drop_in
+= ['ExecStart=!!' + networkd_bin
]
153 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
155 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
157 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
159 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
160 if asan_options
or lsan_options
or ubsan_options
:
161 drop_in
+= ['SystemCallFilter=']
162 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
163 drop_in
+= ['MemoryDenyWriteExecute=no']
165 os
.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok
=True)
166 with
open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode
='w') as f
:
167 f
.write('\n'.join(drop_in
))
175 drop_in
+= ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin
]
177 drop_in
+= ['ExecStart=!!' + resolved_bin
]
179 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
181 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
183 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
185 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
186 if asan_options
or lsan_options
or ubsan_options
:
187 drop_in
+= ['SystemCallFilter=']
188 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
189 drop_in
+= ['MemoryDenyWriteExecute=no']
191 os
.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok
=True)
192 with
open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode
='w') as f
:
193 f
.write('\n'.join(drop_in
))
195 check_output('systemctl daemon-reload')
196 print(check_output('systemctl cat systemd-networkd.service'))
197 print(check_output('systemctl cat systemd-resolved.service'))
198 check_output('systemctl restart systemd-resolved')
200 def tearDownModule():
203 shutil
.rmtree(networkd_ci_path
)
205 for u
in ['systemd-networkd.service', 'systemd-resolved.service']:
206 check_output(f
'systemctl stop {u}')
208 shutil
.rmtree('/run/systemd/system/systemd-networkd.service.d')
209 shutil
.rmtree('/run/systemd/system/systemd-resolved.service.d')
210 check_output('systemctl daemon-reload')
212 for u
in running_units
:
213 check_output(f
'systemctl start {u}')
215 def read_link_attr(link
, dev
, attribute
):
216 with
open(os
.path
.join(os
.path
.join(os
.path
.join('/sys/class/net/', link
), dev
), attribute
)) as f
:
217 return f
.readline().strip()
219 def read_bridge_port_attr(bridge
, link
, attribute
):
220 path_bridge
= os
.path
.join('/sys/devices/virtual/net', bridge
)
221 path_port
= 'lower_' + link
+ '/brport'
222 path
= os
.path
.join(path_bridge
, path_port
)
224 with
open(os
.path
.join(path
, attribute
)) as f
:
225 return f
.readline().strip()
227 def link_exists(link
):
228 return os
.path
.exists(os
.path
.join('/sys/class/net', link
))
230 def remove_links(links
):
232 if link_exists(link
):
233 call('ip link del dev', link
)
236 def remove_fou_ports(ports
):
238 call('ip fou del port', port
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
240 def remove_routing_policy_rule_tables(tables
):
244 rc
= call('ip rule del table', table
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
246 def remove_routes(routes
):
247 for route_type
, addr
in routes
:
248 call('ip route del', route_type
, addr
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
250 def remove_l2tp_tunnels(tunnel_ids
):
251 output
= check_output('ip l2tp show tunnel')
252 for tid
in tunnel_ids
:
253 words
='Tunnel ' + tid
+ ', encap'
255 call('ip l2tp del tunnel tid', tid
)
258 def read_ipv6_sysctl_attr(link
, attribute
):
259 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, link
), attribute
)) as f
:
260 return f
.readline().strip()
262 def read_ipv4_sysctl_attr(link
, attribute
):
263 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv4_path
, link
), attribute
)) as f
:
264 return f
.readline().strip()
266 def copy_unit_to_networkd_unit_path(*units
):
269 shutil
.copy(os
.path
.join(networkd_ci_path
, unit
), network_unit_file_path
)
270 if (os
.path
.exists(os
.path
.join(networkd_ci_path
, unit
+ '.d'))):
271 copytree(os
.path
.join(networkd_ci_path
, unit
+ '.d'), os
.path
.join(network_unit_file_path
, unit
+ '.d'))
273 def remove_unit_from_networkd_path(units
):
275 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
))):
276 os
.remove(os
.path
.join(network_unit_file_path
, unit
))
277 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
+ '.d'))):
278 shutil
.rmtree(os
.path
.join(network_unit_file_path
, unit
+ '.d'))
280 def start_dnsmasq(additional_options
='', ipv4_range
='192.168.5.10,192.168.5.200', ipv6_range
='2600::10,2600::20', lease_time
='1h'):
281 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
282 check_output(dnsmasq_command
)
284 def stop_dnsmasq(pid_file
):
285 if os
.path
.exists(pid_file
):
286 with
open(pid_file
, 'r') as f
:
287 pid
= f
.read().rstrip(' \t\r\n\0')
288 os
.kill(int(pid
), signal
.SIGTERM
)
292 def search_words_in_dnsmasq_log(words
, show_all
=False):
293 if os
.path
.exists(dnsmasq_log_file
):
294 with
open (dnsmasq_log_file
) as in_file
:
295 contents
= in_file
.read()
298 for line
in contents
.splitlines():
301 print("%s, %s" % (words
, line
))
305 def remove_lease_file():
306 if os
.path
.exists(os
.path
.join(networkd_ci_path
, 'lease')):
307 os
.remove(os
.path
.join(networkd_ci_path
, 'lease'))
309 def remove_log_file():
310 if os
.path
.exists(dnsmasq_log_file
):
311 os
.remove(dnsmasq_log_file
)
313 def remove_networkd_state_files():
314 if os
.path
.exists(os
.path
.join(networkd_runtime_directory
, 'state')):
315 os
.remove(os
.path
.join(networkd_runtime_directory
, 'state'))
317 def stop_networkd(show_logs
=True, remove_state_files
=True):
319 invocation_id
= check_output('systemctl show systemd-networkd -p InvocationID --value')
320 check_output('systemctl stop systemd-networkd')
322 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id
))
323 if remove_state_files
:
324 remove_networkd_state_files()
326 def start_networkd(sleep_sec
=0):
327 check_output('systemctl start systemd-networkd')
329 time
.sleep(sleep_sec
)
331 def restart_networkd(sleep_sec
=0, show_logs
=True, remove_state_files
=True):
332 stop_networkd(show_logs
, remove_state_files
)
333 start_networkd(sleep_sec
)
335 def get_operstate(link
, show_status
=True, setup_state
='configured'):
336 output
= check_output(*networkctl_cmd
, 'status', link
, env
=env
)
339 for line
in output
.splitlines():
340 if 'State:' in line
and (not setup_state
or setup_state
in line
):
341 return line
.split()[1]
345 def check_link_exists(self
, link
):
346 self
.assertTrue(link_exists(link
))
348 def check_operstate(self
, link
, expected
, show_status
=True, setup_state
='configured'):
349 self
.assertRegex(get_operstate(link
, show_status
, setup_state
), expected
)
351 def wait_online(self
, links_with_operstate
, timeout
='20s', bool_any
=False, setup_state
='configured'):
352 args
= wait_online_cmd
+ [f
'--timeout={timeout}'] + [f
'--interface={link}' for link
in links_with_operstate
]
356 check_output(*args
, env
=env
)
357 except subprocess
.CalledProcessError
:
358 for link
in links_with_operstate
:
359 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0], env
=env
)
363 for link
in links_with_operstate
:
364 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0])
366 for line
in output
.splitlines():
368 self
.assertRegex(line
, setup_state
)
370 def wait_address(self
, link
, address_regex
, scope
='global', ipv
='', timeout_sec
=100):
371 for i
in range(timeout_sec
):
374 output
= check_output(f
'ip {ipv} address show dev {link} scope {scope}')
375 if re
.search(address_regex
, output
):
378 self
.assertRegex(output
, address_regex
)
380 class NetworkctlTests(unittest
.TestCase
, Utilities
):
390 '11-dummy-mtu.netdev',
393 '25-address-static.network',
395 'netdev-link-local-addressing-yes.network',
399 remove_links(self
.links
)
400 stop_networkd(show_logs
=False)
403 remove_links(self
.links
)
404 remove_unit_from_networkd_path(self
.units
)
405 stop_networkd(show_logs
=True)
407 def test_reconfigure(self
):
408 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
410 self
.wait_online(['dummy98:routable'])
412 output
= check_output('ip -4 address show dev dummy98')
414 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
415 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
416 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
418 check_output('ip address del 10.1.2.3/16 dev dummy98')
419 check_output('ip address del 10.1.2.4/16 dev dummy98')
420 check_output('ip address del 10.2.2.4/16 dev dummy98')
422 check_output(*networkctl_cmd
, 'reconfigure', 'dummy98', env
=env
)
423 self
.wait_online(['dummy98:routable'])
425 output
= check_output('ip -4 address show dev dummy98')
427 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
428 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
429 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
431 def test_reload(self
):
434 copy_unit_to_networkd_unit_path('11-dummy.netdev')
435 check_output(*networkctl_cmd
, 'reload', env
=env
)
437 self
.check_link_exists('test1')
438 self
.check_operstate('test1', 'off', setup_state
='unmanaged')
440 copy_unit_to_networkd_unit_path('11-dummy.network')
441 check_output(*networkctl_cmd
, 'reload', env
=env
)
442 self
.wait_online(['test1:degraded'])
444 remove_unit_from_networkd_path(['11-dummy.network'])
445 check_output(*networkctl_cmd
, 'reload', env
=env
)
447 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
449 remove_unit_from_networkd_path(['11-dummy.netdev'])
450 check_output(*networkctl_cmd
, 'reload', env
=env
)
451 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
453 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
454 check_output(*networkctl_cmd
, 'reload', env
=env
)
455 self
.check_operstate('test1', 'degraded')
458 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
461 self
.wait_online(['test1:degraded'])
463 output
= check_output(*networkctl_cmd
, 'list', env
=env
)
464 self
.assertRegex(output
, '1 lo ')
465 self
.assertRegex(output
, 'test1')
467 output
= check_output(*networkctl_cmd
, 'list', 'test1', env
=env
)
468 self
.assertNotRegex(output
, '1 lo ')
469 self
.assertRegex(output
, 'test1')
471 output
= check_output(*networkctl_cmd
, 'list', 'te*', env
=env
)
472 self
.assertNotRegex(output
, '1 lo ')
473 self
.assertRegex(output
, 'test1')
475 output
= check_output(*networkctl_cmd
, 'status', 'te*', env
=env
)
476 self
.assertNotRegex(output
, '1: lo ')
477 self
.assertRegex(output
, 'test1')
479 output
= check_output(*networkctl_cmd
, 'status', 'tes[a-z][0-9]', env
=env
)
480 self
.assertNotRegex(output
, '1: lo ')
481 self
.assertRegex(output
, 'test1')
484 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
487 self
.wait_online(['test1:degraded'])
489 output
= check_output(*networkctl_cmd
, 'status', 'test1', env
=env
)
490 self
.assertRegex(output
, 'MTU: 1600')
493 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
495 self
.wait_online(['test1:degraded'])
497 output
= check_output(*networkctl_cmd
, 'status', 'test1')
499 self
.assertRegex(output
, 'Type: ether')
501 output
= check_output(*networkctl_cmd
, 'status', 'lo')
503 self
.assertRegex(output
, 'Type: loopback')
505 @expectedFailureIfLinkFileFieldIsNotSet()
506 def test_udev_link_file(self
):
507 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
509 self
.wait_online(['test1:degraded'])
511 output
= check_output(*networkctl_cmd
, 'status', 'test1')
513 self
.assertRegex(output
, r
'Link File: (?:/usr)/lib/systemd/network/99-default.link')
514 self
.assertRegex(output
, r
'Network File: /run/systemd/network/11-dummy.network')
516 output
= check_output(*networkctl_cmd
, 'status', 'lo')
518 self
.assertRegex(output
, r
'Link File: (?:/usr)/lib/systemd/network/99-default.link')
519 self
.assertRegex(output
, r
'Network File: n/a')
521 def test_delete_links(self
):
522 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
523 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
526 self
.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
528 check_output(*networkctl_cmd
, 'delete', 'test1', 'veth99')
529 self
.assertFalse(link_exists('test1'))
530 self
.assertFalse(link_exists('veth99'))
531 self
.assertFalse(link_exists('veth-peer'))
533 class NetworkdNetDevTests(unittest
.TestCase
, Utilities
):
535 links_remove_earlier
= [
599 '10-dropin-test.netdev',
603 '13-not-match-udev-property.network',
604 '14-match-udev-property.network',
605 '15-name-conflict-test.netdev',
608 '21-vlan-test1.network',
611 '25-6rd-tunnel.netdev',
613 '25-bond-balanced-tlb.netdev',
615 '25-bridge-configure-without-carrier.network',
617 '25-erspan-tunnel-local-any.netdev',
618 '25-erspan-tunnel.netdev',
619 '25-fou-gretap.netdev',
621 '25-fou-ipip.netdev',
622 '25-fou-ipproto-gre.netdev',
623 '25-fou-ipproto-ipip.netdev',
626 '25-gretap-tunnel-local-any.netdev',
627 '25-gretap-tunnel.netdev',
628 '25-gre-tunnel-any-any.netdev',
629 '25-gre-tunnel-local-any.netdev',
630 '25-gre-tunnel-remote-any.netdev',
631 '25-gre-tunnel.netdev',
632 '25-ip6gretap-tunnel-local-any.netdev',
633 '25-ip6gretap-tunnel.netdev',
634 '25-ip6gre-tunnel-any-any.netdev',
635 '25-ip6gre-tunnel-local-any.netdev',
636 '25-ip6gre-tunnel-remote-any.netdev',
637 '25-ip6gre-tunnel.netdev',
638 '25-ip6tnl-tunnel-any-any.netdev',
639 '25-ip6tnl-tunnel-local-any.netdev',
640 '25-ip6tnl-tunnel-remote-any.netdev',
641 '25-ip6tnl-tunnel.netdev',
642 '25-ipip-tunnel-any-any.netdev',
643 '25-ipip-tunnel-independent.netdev',
644 '25-ipip-tunnel-independent-loopback.netdev',
645 '25-ipip-tunnel-local-any.netdev',
646 '25-ipip-tunnel-remote-any.netdev',
647 '25-ipip-tunnel.netdev',
650 '25-isatap-tunnel.netdev',
655 '25-sit-tunnel-any-any.netdev',
656 '25-sit-tunnel-local-any.netdev',
657 '25-sit-tunnel-remote-any.netdev',
658 '25-sit-tunnel.netdev',
661 '25-tunnel-local-any.network',
662 '25-tunnel-remote-any.network',
667 '25-vti6-tunnel-any-any.netdev',
668 '25-vti6-tunnel-local-any.netdev',
669 '25-vti6-tunnel-remote-any.netdev',
670 '25-vti6-tunnel.netdev',
671 '25-vti-tunnel-any-any.netdev',
672 '25-vti-tunnel-local-any.netdev',
673 '25-vti-tunnel-remote-any.netdev',
674 '25-vti-tunnel.netdev',
677 '25-wireguard-23-peers.netdev',
678 '25-wireguard-23-peers.network',
679 '25-wireguard-preshared-key.txt',
680 '25-wireguard-private-key.txt',
681 '25-wireguard.netdev',
682 '25-wireguard.network',
684 '25-xfrm-independent.netdev',
700 'netdev-link-local-addressing-yes.network',
704 'vxlan-test1.network',
714 remove_fou_ports(self
.fou_ports
)
715 remove_links(self
.links_remove_earlier
)
716 remove_links(self
.links
)
717 stop_networkd(show_logs
=False)
720 remove_fou_ports(self
.fou_ports
)
721 remove_links(self
.links_remove_earlier
)
722 remove_links(self
.links
)
723 remove_unit_from_networkd_path(self
.units
)
724 stop_networkd(show_logs
=True)
726 def test_dropin_and_name_conflict(self
):
727 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
730 self
.wait_online(['dropin-test:off'], setup_state
='unmanaged')
732 output
= check_output('ip link show dropin-test')
734 self
.assertRegex(output
, '00:50:56:c0:00:28')
736 def test_match_udev_property(self
):
737 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
739 self
.wait_online(['dummy98:routable'])
741 output
= check_output('networkctl status dummy98')
743 self
.assertRegex(output
, 'Network File: /run/systemd/network/14-match-udev-property')
745 def test_wait_online_any(self
):
746 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
749 self
.wait_online(['bridge99', 'test1:degraded'], bool_any
=True)
751 self
.check_operstate('bridge99', '(?:off|no-carrier)', setup_state
='configuring')
752 self
.check_operstate('test1', 'degraded')
754 def test_bridge(self
):
755 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
758 self
.wait_online(['bridge99:no-carrier'])
760 tick
= os
.sysconf('SC_CLK_TCK')
761 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick
))
762 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick
))
763 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick
))
764 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick
))
765 self
.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
766 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
767 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
768 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
769 self
.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
771 output
= check_output(*networkctl_cmd
, 'status', 'bridge99')
773 self
.assertRegex(output
, 'Priority: 9')
774 self
.assertRegex(output
, 'STP: yes')
775 self
.assertRegex(output
, 'Multicast IGMP Version: 3')
778 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
781 self
.wait_online(['bond99:off', 'bond98:off'], setup_state
='unmanaged')
783 self
.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
784 self
.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
785 self
.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
786 self
.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
787 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
788 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
789 self
.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
790 self
.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
791 self
.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
792 self
.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
793 self
.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
795 self
.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
796 self
.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
799 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
800 '21-vlan.network', '21-vlan-test1.network')
803 self
.wait_online(['test1:degraded', 'vlan99:routable'])
805 output
= check_output('ip -d link show test1')
807 self
.assertRegex(output
, ' mtu 2000 ')
809 output
= check_output('ip -d link show vlan99')
811 self
.assertRegex(output
, ' mtu 2000 ')
812 self
.assertRegex(output
, 'REORDER_HDR')
813 self
.assertRegex(output
, 'LOOSE_BINDING')
814 self
.assertRegex(output
, 'GVRP')
815 self
.assertRegex(output
, 'MVRP')
816 self
.assertRegex(output
, ' id 99 ')
818 output
= check_output('ip -4 address show dev test1')
820 self
.assertRegex(output
, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
821 self
.assertRegex(output
, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
823 output
= check_output('ip -4 address show dev vlan99')
825 self
.assertRegex(output
, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
827 def test_macvtap(self
):
828 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
829 with self
.subTest(mode
=mode
):
830 if mode
!= 'private':
832 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
833 '11-dummy.netdev', 'macvtap.network')
834 with
open(os
.path
.join(network_unit_file_path
, '21-macvtap.netdev'), mode
='a') as f
:
835 f
.write('[MACVTAP]\nMode=' + mode
)
838 self
.wait_online(['macvtap99:degraded', 'test1:degraded'])
840 output
= check_output('ip -d link show macvtap99')
842 self
.assertRegex(output
, 'macvtap mode ' + mode
+ ' ')
844 def test_macvlan(self
):
845 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
846 with self
.subTest(mode
=mode
):
847 if mode
!= 'private':
849 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
850 '11-dummy.netdev', 'macvlan.network')
851 with
open(os
.path
.join(network_unit_file_path
, '21-macvlan.netdev'), mode
='a') as f
:
852 f
.write('[MACVLAN]\nMode=' + mode
)
855 self
.wait_online(['macvlan99:degraded', 'test1:degraded'])
857 output
= check_output('ip -d link show test1')
859 self
.assertRegex(output
, ' mtu 2000 ')
861 output
= check_output('ip -d link show macvlan99')
863 self
.assertRegex(output
, ' mtu 2000 ')
864 self
.assertRegex(output
, 'macvlan mode ' + mode
+ ' ')
866 @expectedFailureIfModuleIsNotAvailable('ipvlan')
867 def test_ipvlan(self
):
868 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
869 with self
.subTest(mode
=mode
, flag
=flag
):
872 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
873 '11-dummy.netdev', 'ipvlan.network')
874 with
open(os
.path
.join(network_unit_file_path
, '25-ipvlan.netdev'), mode
='a') as f
:
875 f
.write('[IPVLAN]\nMode=' + mode
+ '\nFlags=' + flag
)
878 self
.wait_online(['ipvlan99:degraded', 'test1:degraded'])
880 output
= check_output('ip -d link show ipvlan99')
882 self
.assertRegex(output
, 'ipvlan *mode ' + mode
.lower() + ' ' + flag
)
884 @expectedFailureIfModuleIsNotAvailable('ipvtap')
885 def test_ipvtap(self
):
886 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
887 with self
.subTest(mode
=mode
, flag
=flag
):
890 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
891 '11-dummy.netdev', 'ipvtap.network')
892 with
open(os
.path
.join(network_unit_file_path
, '25-ipvtap.netdev'), mode
='a') as f
:
893 f
.write('[IPVTAP]\nMode=' + mode
+ '\nFlags=' + flag
)
896 self
.wait_online(['ipvtap99:degraded', 'test1:degraded'])
898 output
= check_output('ip -d link show ipvtap99')
900 self
.assertRegex(output
, 'ipvtap *mode ' + mode
.lower() + ' ' + flag
)
903 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
906 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
908 output
= check_output('ip -d link show veth99')
910 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bc')
911 output
= check_output('ip -d link show veth-peer')
913 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bd')
916 copy_unit_to_networkd_unit_path('25-tun.netdev')
919 self
.wait_online(['tun99:off'], setup_state
='unmanaged')
921 output
= check_output('ip -d link show tun99')
923 # Old ip command does not support IFF_ flags
924 self
.assertRegex(output
, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
927 copy_unit_to_networkd_unit_path('25-tap.netdev')
930 self
.wait_online(['tap99:off'], setup_state
='unmanaged')
932 output
= check_output('ip -d link show tap99')
934 # Old ip command does not support IFF_ flags
935 self
.assertRegex(output
, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
937 @expectedFailureIfModuleIsNotAvailable('vrf')
939 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
942 self
.wait_online(['vrf99:carrier'])
944 @expectedFailureIfModuleIsNotAvailable('vcan')
946 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
949 self
.wait_online(['vcan99:carrier'])
951 @expectedFailureIfModuleIsNotAvailable('vxcan')
952 def test_vxcan(self
):
953 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
956 self
.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
958 @expectedFailureIfModuleIsNotAvailable('wireguard')
959 def test_wireguard(self
):
960 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
961 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
962 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
964 self
.wait_online(['wg99:carrier', 'wg98:routable'])
966 if shutil
.which('wg'):
969 output
= check_output('wg show wg99 listen-port')
970 self
.assertRegex(output
, '51820')
971 output
= check_output('wg show wg99 fwmark')
972 self
.assertRegex(output
, '0x4d2')
973 output
= check_output('wg show wg99 allowed-ips')
974 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
975 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
976 output
= check_output('wg show wg99 persistent-keepalive')
977 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
978 output
= check_output('wg show wg99 endpoints')
979 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
980 output
= check_output('wg show wg99 private-key')
981 self
.assertRegex(output
, r
'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
982 output
= check_output('wg show wg99 preshared-keys')
983 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
984 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
986 output
= check_output('wg show wg98 private-key')
987 self
.assertRegex(output
, r
'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
989 def test_geneve(self
):
990 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
993 self
.wait_online(['geneve99:degraded'])
995 output
= check_output('ip -d link show geneve99')
997 self
.assertRegex(output
, '192.168.22.1')
998 self
.assertRegex(output
, '6082')
999 self
.assertRegex(output
, 'udpcsum')
1000 self
.assertRegex(output
, 'udp6zerocsumrx')
1002 def test_ipip_tunnel(self
):
1003 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1004 '25-ipip-tunnel.netdev', '25-tunnel.network',
1005 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1006 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1007 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1009 self
.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1011 output
= check_output('ip -d link show ipiptun99')
1013 self
.assertRegex(output
, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1014 output
= check_output('ip -d link show ipiptun98')
1016 self
.assertRegex(output
, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
1017 output
= check_output('ip -d link show ipiptun97')
1019 self
.assertRegex(output
, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
1020 output
= check_output('ip -d link show ipiptun96')
1022 self
.assertRegex(output
, 'ipip (?:ipip |)remote any local any dev dummy98')
1024 def test_gre_tunnel(self
):
1025 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1026 '25-gre-tunnel.netdev', '25-tunnel.network',
1027 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1028 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1029 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1031 self
.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1033 output
= check_output('ip -d link show gretun99')
1035 self
.assertRegex(output
, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1036 self
.assertRegex(output
, 'ikey 1.2.3.103')
1037 self
.assertRegex(output
, 'okey 1.2.4.103')
1038 self
.assertRegex(output
, 'iseq')
1039 self
.assertRegex(output
, 'oseq')
1040 output
= check_output('ip -d link show gretun98')
1042 self
.assertRegex(output
, 'gre remote 10.65.223.239 local any dev dummy98')
1043 self
.assertRegex(output
, 'ikey 0.0.0.104')
1044 self
.assertRegex(output
, 'okey 0.0.0.104')
1045 self
.assertNotRegex(output
, 'iseq')
1046 self
.assertNotRegex(output
, 'oseq')
1047 output
= check_output('ip -d link show gretun97')
1049 self
.assertRegex(output
, 'gre remote any local 10.65.223.238 dev dummy98')
1050 self
.assertRegex(output
, 'ikey 0.0.0.105')
1051 self
.assertRegex(output
, 'okey 0.0.0.105')
1052 self
.assertNotRegex(output
, 'iseq')
1053 self
.assertNotRegex(output
, 'oseq')
1054 output
= check_output('ip -d link show gretun96')
1056 self
.assertRegex(output
, 'gre remote any local any dev dummy98')
1057 self
.assertRegex(output
, 'ikey 0.0.0.106')
1058 self
.assertRegex(output
, 'okey 0.0.0.106')
1059 self
.assertNotRegex(output
, 'iseq')
1060 self
.assertNotRegex(output
, 'oseq')
1062 def test_ip6gre_tunnel(self
):
1063 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1064 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1065 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1066 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1067 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1070 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1072 self
.check_link_exists('dummy98')
1073 self
.check_link_exists('ip6gretun99')
1074 self
.check_link_exists('ip6gretun98')
1075 self
.check_link_exists('ip6gretun97')
1076 self
.check_link_exists('ip6gretun96')
1078 output
= check_output('ip -d link show ip6gretun99')
1080 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1081 output
= check_output('ip -d link show ip6gretun98')
1083 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1084 output
= check_output('ip -d link show ip6gretun97')
1086 self
.assertRegex(output
, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1087 output
= check_output('ip -d link show ip6gretun96')
1089 self
.assertRegex(output
, 'ip6gre remote any local any dev dummy98')
1091 def test_gretap_tunnel(self
):
1092 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1093 '25-gretap-tunnel.netdev', '25-tunnel.network',
1094 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1096 self
.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1098 output
= check_output('ip -d link show gretap99')
1100 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1101 self
.assertRegex(output
, 'ikey 0.0.0.106')
1102 self
.assertRegex(output
, 'okey 0.0.0.106')
1103 self
.assertRegex(output
, 'iseq')
1104 self
.assertRegex(output
, 'oseq')
1105 output
= check_output('ip -d link show gretap98')
1107 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local any dev dummy98')
1108 self
.assertRegex(output
, 'ikey 0.0.0.107')
1109 self
.assertRegex(output
, 'okey 0.0.0.107')
1110 self
.assertRegex(output
, 'iseq')
1111 self
.assertRegex(output
, 'oseq')
1113 def test_ip6gretap_tunnel(self
):
1114 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1115 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1116 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1118 self
.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1120 output
= check_output('ip -d link show ip6gretap99')
1122 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1123 output
= check_output('ip -d link show ip6gretap98')
1125 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1127 def test_vti_tunnel(self
):
1128 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1129 '25-vti-tunnel.netdev', '25-tunnel.network',
1130 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1131 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1132 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1134 self
.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1136 output
= check_output('ip -d link show vtitun99')
1138 self
.assertRegex(output
, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1139 output
= check_output('ip -d link show vtitun98')
1141 self
.assertRegex(output
, 'vti remote 10.65.223.239 local any dev dummy98')
1142 output
= check_output('ip -d link show vtitun97')
1144 self
.assertRegex(output
, 'vti remote any local 10.65.223.238 dev dummy98')
1145 output
= check_output('ip -d link show vtitun96')
1147 self
.assertRegex(output
, 'vti remote any local any dev dummy98')
1149 def test_vti6_tunnel(self
):
1150 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1151 '25-vti6-tunnel.netdev', '25-tunnel.network',
1152 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1153 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1155 self
.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1157 output
= check_output('ip -d link show vti6tun99')
1159 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1160 output
= check_output('ip -d link show vti6tun98')
1162 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1163 output
= check_output('ip -d link show vti6tun97')
1165 self
.assertRegex(output
, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1167 def test_ip6tnl_tunnel(self
):
1168 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1169 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1170 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1171 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1173 self
.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1175 output
= check_output('ip -d link show ip6tnl99')
1177 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1178 output
= check_output('ip -d link show ip6tnl98')
1180 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1181 output
= check_output('ip -d link show ip6tnl97')
1183 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1185 def test_sit_tunnel(self
):
1186 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1187 '25-sit-tunnel.netdev', '25-tunnel.network',
1188 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1189 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1190 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1192 self
.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1194 output
= check_output('ip -d link show sittun99')
1196 self
.assertRegex(output
, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1197 output
= check_output('ip -d link show sittun98')
1199 self
.assertRegex(output
, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
1200 output
= check_output('ip -d link show sittun97')
1202 self
.assertRegex(output
, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1203 output
= check_output('ip -d link show sittun96')
1205 self
.assertRegex(output
, "sit (?:ip6ip |)remote any local any dev dummy98")
1207 def test_isatap_tunnel(self
):
1208 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1209 '25-isatap-tunnel.netdev', '25-tunnel.network')
1211 self
.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1213 output
= check_output('ip -d link show isataptun99')
1215 self
.assertRegex(output
, "isatap ")
1217 def test_6rd_tunnel(self
):
1218 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1219 '25-6rd-tunnel.netdev', '25-tunnel.network')
1221 self
.wait_online(['sittun99:routable', 'dummy98:degraded'])
1223 output
= check_output('ip -d link show sittun99')
1225 self
.assertRegex(output
, '6rd-prefix 2602::/24')
1227 @expectedFailureIfERSPANModuleIsNotAvailable()
1228 def test_erspan_tunnel(self
):
1229 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1230 '25-erspan-tunnel.netdev', '25-tunnel.network',
1231 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1233 self
.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1235 output
= check_output('ip -d link show erspan99')
1237 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local 172.16.1.200')
1238 self
.assertRegex(output
, 'ikey 0.0.0.101')
1239 self
.assertRegex(output
, 'okey 0.0.0.101')
1240 self
.assertRegex(output
, 'iseq')
1241 self
.assertRegex(output
, 'oseq')
1242 output
= check_output('ip -d link show erspan98')
1244 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local any')
1245 self
.assertRegex(output
, '102')
1246 self
.assertRegex(output
, 'ikey 0.0.0.102')
1247 self
.assertRegex(output
, 'okey 0.0.0.102')
1248 self
.assertRegex(output
, 'iseq')
1249 self
.assertRegex(output
, 'oseq')
1251 def test_tunnel_independent(self
):
1252 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1255 self
.wait_online(['ipiptun99:carrier'])
1257 def test_tunnel_independent_loopback(self
):
1258 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1261 self
.wait_online(['ipiptun99:carrier'])
1263 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1264 def test_xfrm(self
):
1265 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1266 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1269 self
.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1271 output
= check_output('ip link show dev xfrm99')
1274 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1275 def test_xfrm_independent(self
):
1276 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1279 self
.wait_online(['xfrm99:degraded'])
1281 @expectedFailureIfModuleIsNotAvailable('fou')
1283 # The following redundant check is necessary for CentOS CI.
1284 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1285 self
.assertTrue(is_module_available('fou'))
1287 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1288 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1289 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1292 self
.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state
='unmanaged')
1294 output
= check_output('ip fou show')
1296 self
.assertRegex(output
, 'port 55555 ipproto 4')
1297 self
.assertRegex(output
, 'port 55556 ipproto 47')
1299 output
= check_output('ip -d link show ipiptun96')
1301 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1302 output
= check_output('ip -d link show sittun96')
1304 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1305 output
= check_output('ip -d link show gretun96')
1307 self
.assertRegex(output
, 'encap fou encap-sport 1001 encap-dport 55556')
1308 output
= check_output('ip -d link show gretap96')
1310 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55556')
1312 def test_vxlan(self
):
1313 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1314 '11-dummy.netdev', 'vxlan-test1.network')
1317 self
.wait_online(['test1:degraded', 'vxlan99:degraded'])
1319 output
= check_output('ip -d link show vxlan99')
1321 self
.assertRegex(output
, '999')
1322 self
.assertRegex(output
, '5555')
1323 self
.assertRegex(output
, 'l2miss')
1324 self
.assertRegex(output
, 'l3miss')
1325 self
.assertRegex(output
, 'udpcsum')
1326 self
.assertRegex(output
, 'udp6zerocsumtx')
1327 self
.assertRegex(output
, 'udp6zerocsumrx')
1328 self
.assertRegex(output
, 'remcsumtx')
1329 self
.assertRegex(output
, 'remcsumrx')
1330 self
.assertRegex(output
, 'gbp')
1332 output
= check_output('bridge fdb show dev vxlan99')
1334 self
.assertRegex(output
, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1335 self
.assertRegex(output
, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1336 self
.assertRegex(output
, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1338 output
= check_output(*networkctl_cmd
, 'status', 'vxlan99')
1340 self
.assertRegex(output
, 'VNI: 999')
1341 self
.assertRegex(output
, 'Destination Port: 5555')
1342 self
.assertRegex(output
, 'Underlying Device: test1')
1344 def test_macsec(self
):
1345 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1346 'macsec.network', '12-dummy.netdev')
1349 self
.wait_online(['dummy98:degraded', 'macsec99:routable'])
1351 output
= check_output('ip -d link show macsec99')
1353 self
.assertRegex(output
, 'macsec99@dummy98')
1354 self
.assertRegex(output
, 'macsec sci [0-9a-f]*000b')
1355 self
.assertRegex(output
, 'encrypt on')
1357 output
= check_output('ip macsec show macsec99')
1359 self
.assertRegex(output
, 'encrypt on')
1360 self
.assertRegex(output
, 'TXSC: [0-9a-f]*000b on SA 1')
1361 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1362 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1363 self
.assertRegex(output
, 'RXSC: c619528fe6a00100, state on')
1364 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1365 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1366 self
.assertRegex(output
, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1367 self
.assertRegex(output
, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1368 self
.assertNotRegex(output
, 'key 02030405067080900000000000000000')
1369 self
.assertRegex(output
, 'RXSC: 8c16456c83a90002, state on')
1370 self
.assertRegex(output
, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1372 def test_nlmon(self
):
1373 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1376 self
.wait_online(['nlmon99:carrier'])
1378 class NetworkdL2TPTests(unittest
.TestCase
, Utilities
):
1389 '25-l2tp-dummy.network',
1391 '25-l2tp-ip.netdev',
1392 '25-l2tp-udp.netdev']
1394 l2tp_tunnel_ids
= [ '10' ]
1397 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1398 remove_links(self
.links
)
1399 stop_networkd(show_logs
=False)
1402 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1403 remove_links(self
.links
)
1404 remove_unit_from_networkd_path(self
.units
)
1405 stop_networkd(show_logs
=True)
1407 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1408 def test_l2tp_udp(self
):
1409 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1410 '25-l2tp-udp.netdev', '25-l2tp.network')
1413 self
.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1415 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1417 self
.assertRegex(output
, "Tunnel 10, encap UDP")
1418 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1419 self
.assertRegex(output
, "Peer tunnel 11")
1420 self
.assertRegex(output
, "UDP source / dest ports: 3000/4000")
1421 self
.assertRegex(output
, "UDP checksum: enabled")
1423 output
= check_output('ip l2tp show session tid 10 session_id 15')
1425 self
.assertRegex(output
, "Session 15 in tunnel 10")
1426 self
.assertRegex(output
, "Peer session 16, tunnel 11")
1427 self
.assertRegex(output
, "interface name: l2tp-ses1")
1429 output
= check_output('ip l2tp show session tid 10 session_id 17')
1431 self
.assertRegex(output
, "Session 17 in tunnel 10")
1432 self
.assertRegex(output
, "Peer session 18, tunnel 11")
1433 self
.assertRegex(output
, "interface name: l2tp-ses2")
1435 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1436 def test_l2tp_ip(self
):
1437 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1438 '25-l2tp-ip.netdev', '25-l2tp.network')
1441 self
.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1443 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1445 self
.assertRegex(output
, "Tunnel 10, encap IP")
1446 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1447 self
.assertRegex(output
, "Peer tunnel 12")
1449 output
= check_output('ip l2tp show session tid 10 session_id 25')
1451 self
.assertRegex(output
, "Session 25 in tunnel 10")
1452 self
.assertRegex(output
, "Peer session 26, tunnel 12")
1453 self
.assertRegex(output
, "interface name: l2tp-ses3")
1455 output
= check_output('ip l2tp show session tid 10 session_id 27')
1457 self
.assertRegex(output
, "Session 27 in tunnel 10")
1458 self
.assertRegex(output
, "Peer session 28, tunnel 12")
1459 self
.assertRegex(output
, "interface name: l2tp-ses4")
1461 class NetworkdNetworkTests(unittest
.TestCase
, Utilities
):
1475 '23-active-slave.network',
1476 '24-keep-configuration-static.network',
1477 '24-search-domain.network',
1478 '25-address-link-section.network',
1479 '25-address-preferred-lifetime-zero.network',
1480 '25-address-static.network',
1481 '25-bind-carrier.network',
1482 '25-bond-active-backup-slave.netdev',
1483 '25-fibrule-invert.network',
1484 '25-fibrule-port-range.network',
1485 '25-gre-tunnel-remote-any.netdev',
1486 '25-ip6gre-tunnel-remote-any.netdev',
1487 '25-ipv6-address-label-section.network',
1488 '25-neighbor-section.network',
1489 '25-neighbor-next.network',
1490 '25-neighbor-ipv6.network',
1491 '25-neighbor-ip-dummy.network',
1492 '25-neighbor-ip.network',
1493 '25-nexthop.network',
1494 '25-link-local-addressing-no.network',
1495 '25-link-local-addressing-yes.network',
1496 '25-link-section-unmanaged.network',
1497 '25-route-ipv6-src.network',
1498 '25-route-static.network',
1499 '25-gateway-static.network',
1500 '25-gateway-next-static.network',
1501 '25-sysctl-disable-ipv6.network',
1502 '25-sysctl.network',
1503 '25-veth-peer.network',
1505 '26-link-local-addressing-ipv6.network',
1506 'configure-without-carrier.network',
1507 'routing-policy-rule-dummy98.network',
1508 'routing-policy-rule-test1.network']
1510 routing_policy_rule_tables
= ['7', '8', '9']
1511 routes
= [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1514 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1515 remove_routes(self
.routes
)
1516 remove_links(self
.links
)
1517 stop_networkd(show_logs
=False)
1520 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1521 remove_routes(self
.routes
)
1522 remove_links(self
.links
)
1523 remove_unit_from_networkd_path(self
.units
)
1524 stop_networkd(show_logs
=True)
1526 def test_address_static(self
):
1527 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1530 self
.wait_online(['dummy98:routable'])
1532 output
= check_output('ip -4 address show dev dummy98')
1534 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1535 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1536 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1539 self
.assertNotRegex(output
, '10.10.0.1/16')
1540 self
.assertNotRegex(output
, '10.10.0.2/16')
1542 output
= check_output('ip -4 address show dev dummy98 label 32')
1543 self
.assertRegex(output
, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1545 output
= check_output('ip -4 address show dev dummy98 label 33')
1546 self
.assertRegex(output
, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1548 output
= check_output('ip -4 address show dev dummy98 label 34')
1549 self
.assertRegex(output
, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1551 output
= check_output('ip -4 address show dev dummy98 label 35')
1552 self
.assertRegex(output
, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1554 output
= check_output('ip -6 address show dev dummy98')
1556 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::15/64 scope global')
1557 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::16/64 scope global')
1558 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::15/64 scope global')
1559 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::16/64 scope global')
1560 self
.assertRegex(output
, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1561 self
.assertRegex(output
, 'inet6 fd[0-9a-f:]*1/64 scope global')
1563 def test_address_preferred_lifetime_zero_ipv6(self
):
1564 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1567 self
.wait_online(['dummy98:routable'])
1569 output
= check_output('ip address show dummy98')
1571 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1572 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::1/64 scope global')
1574 output
= check_output('ip route show dev dummy98')
1576 self
.assertRegex(output
, 'default via 20.20.20.1 proto static')
1578 def test_configure_without_carrier(self
):
1579 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1581 self
.wait_online(['test1:routable'])
1583 output
= check_output(*networkctl_cmd
, 'status', 'test1')
1585 self
.assertRegex(output
, '192.168.0.15')
1586 self
.assertRegex(output
, '192.168.0.1')
1587 self
.assertRegex(output
, 'routable')
1589 def test_routing_policy_rule(self
):
1590 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1592 self
.wait_online(['test1:degraded'])
1594 output
= check_output('ip rule list iif test1 priority 111')
1596 self
.assertRegex(output
, '111:')
1597 self
.assertRegex(output
, 'from 192.168.100.18')
1598 self
.assertRegex(output
, r
'tos (?:0x08|throughput)\s')
1599 self
.assertRegex(output
, 'iif test1')
1600 self
.assertRegex(output
, 'oif test1')
1601 self
.assertRegex(output
, 'lookup 7')
1603 output
= check_output('ip rule list iif test1 priority 101')
1605 self
.assertRegex(output
, '101:')
1606 self
.assertRegex(output
, 'from all')
1607 self
.assertRegex(output
, 'iif test1')
1608 self
.assertRegex(output
, 'lookup 9')
1610 output
= check_output('ip -6 rule list iif test1 priority 100')
1612 self
.assertRegex(output
, '100:')
1613 self
.assertRegex(output
, 'from all')
1614 self
.assertRegex(output
, 'iif test1')
1615 self
.assertRegex(output
, 'lookup 8')
1617 output
= check_output('ip -6 rule list iif test1 priority 101')
1619 self
.assertRegex(output
, '101:')
1620 self
.assertRegex(output
, 'from all')
1621 self
.assertRegex(output
, 'iif test1')
1622 self
.assertRegex(output
, 'lookup 9')
1624 def test_routing_policy_rule_issue_11280(self
):
1625 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1626 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1628 for trial
in range(3):
1629 # Remove state files only first time
1631 self
.wait_online(['test1:degraded', 'dummy98:degraded'])
1634 output
= check_output('ip rule list table 7')
1636 self
.assertRegex(output
, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1638 output
= check_output('ip rule list table 8')
1640 self
.assertRegex(output
, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1642 stop_networkd(remove_state_files
=False)
1644 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1645 def test_routing_policy_rule_port_range(self
):
1646 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1648 self
.wait_online(['test1:degraded'])
1650 output
= check_output('ip rule')
1652 self
.assertRegex(output
, '111')
1653 self
.assertRegex(output
, 'from 192.168.100.18')
1654 self
.assertRegex(output
, '1123-1150')
1655 self
.assertRegex(output
, '3224-3290')
1656 self
.assertRegex(output
, 'tcp')
1657 self
.assertRegex(output
, 'lookup 7')
1659 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1660 def test_routing_policy_rule_invert(self
):
1661 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1663 self
.wait_online(['test1:degraded'])
1665 output
= check_output('ip rule')
1667 self
.assertRegex(output
, '111')
1668 self
.assertRegex(output
, 'not.*?from.*?192.168.100.18')
1669 self
.assertRegex(output
, 'tcp')
1670 self
.assertRegex(output
, 'lookup 7')
1672 def test_route_static(self
):
1673 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1675 self
.wait_online(['dummy98:routable'])
1677 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
1680 print('### ip -6 route show dev dummy98')
1681 output
= check_output('ip -6 route show dev dummy98')
1683 self
.assertRegex(output
, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1684 self
.assertRegex(output
, '2001:1234:5:8f63::1 proto kernel')
1686 print('### ip -6 route show dev dummy98 default')
1687 output
= check_output('ip -6 route show dev dummy98 default')
1689 self
.assertRegex(output
, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1691 print('### ip -4 route show dev dummy98')
1692 output
= check_output('ip -4 route show dev dummy98')
1694 self
.assertRegex(output
, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1695 self
.assertRegex(output
, '149.10.124.64 proto static scope link')
1696 self
.assertRegex(output
, '169.254.0.0/16 proto static scope link metric 2048')
1697 self
.assertRegex(output
, '192.168.1.1 proto static initcwnd 20')
1698 self
.assertRegex(output
, '192.168.1.2 proto static initrwnd 30')
1699 self
.assertRegex(output
, 'multicast 149.10.123.4 proto static')
1701 print('### ip -4 route show dev dummy98 default')
1702 output
= check_output('ip -4 route show dev dummy98 default')
1704 self
.assertRegex(output
, 'default via 149.10.125.65 proto static onlink')
1705 self
.assertRegex(output
, 'default via 149.10.124.64 proto static')
1706 self
.assertRegex(output
, 'default proto static')
1708 print('### ip -4 route show table local dev dummy98')
1709 output
= check_output('ip -4 route show table local dev dummy98')
1711 self
.assertRegex(output
, 'local 149.10.123.1 proto static scope host')
1712 self
.assertRegex(output
, 'anycast 149.10.123.2 proto static scope link')
1713 self
.assertRegex(output
, 'broadcast 149.10.123.3 proto static scope link')
1715 print('### ip route show type blackhole')
1716 output
= check_output('ip route show type blackhole')
1718 self
.assertRegex(output
, 'blackhole 202.54.1.2 proto static')
1720 print('### ip route show type unreachable')
1721 output
= check_output('ip route show type unreachable')
1723 self
.assertRegex(output
, 'unreachable 202.54.1.3 proto static')
1725 print('### ip route show type prohibit')
1726 output
= check_output('ip route show type prohibit')
1728 self
.assertRegex(output
, 'prohibit 202.54.1.4 proto static')
1730 def test_gateway_reconfigure(self
):
1731 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1733 self
.wait_online(['dummy98:routable'])
1734 print('### ip -4 route show dev dummy98 default')
1735 output
= check_output('ip -4 route show dev dummy98 default')
1737 self
.assertRegex(output
, 'default via 149.10.124.59 proto static')
1738 self
.assertNotRegex(output
, '149.10.124.60')
1740 remove_unit_from_networkd_path(['25-gateway-static.network'])
1741 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1743 self
.wait_online(['dummy98:routable'])
1744 print('### ip -4 route show dev dummy98 default')
1745 output
= check_output('ip -4 route show dev dummy98 default')
1747 self
.assertNotRegex(output
, '149.10.124.59')
1748 self
.assertRegex(output
, 'default via 149.10.124.60 proto static')
1750 def test_ip_route_ipv6_src_route(self
):
1751 # a dummy device does not make the addresses go through tentative state, so we
1752 # reuse a bond from an earlier test, which does make the addresses go through
1753 # tentative state, and do our test on that
1754 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1756 self
.wait_online(['dummy98:enslaved', 'bond199:routable'])
1758 output
= check_output('ip -6 route list dev bond199')
1760 self
.assertRegex(output
, 'abcd::/16')
1761 self
.assertRegex(output
, 'src')
1762 self
.assertRegex(output
, '2001:1234:56:8f63::2')
1764 def test_ip_link_mac_address(self
):
1765 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1767 self
.wait_online(['dummy98:degraded'])
1769 output
= check_output('ip link show dummy98')
1771 self
.assertRegex(output
, '00:01:02:aa:bb:cc')
1773 def test_ip_link_unmanaged(self
):
1774 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1777 self
.check_link_exists('dummy98')
1779 self
.check_operstate('dummy98', 'off', setup_state
='unmanaged')
1781 def test_ipv6_address_label(self
):
1782 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1784 self
.wait_online(['dummy98:degraded'])
1786 output
= check_output('ip addrlabel list')
1788 self
.assertRegex(output
, '2004:da8:1::/64')
1790 def test_neighbor_section(self
):
1791 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1793 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1795 print('### ip neigh list dev dummy98')
1796 output
= check_output('ip neigh list dev dummy98')
1798 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1799 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1801 def test_neighbor_reconfigure(self
):
1802 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1804 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1806 print('### ip neigh list dev dummy98')
1807 output
= check_output('ip neigh list dev dummy98')
1809 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1810 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1812 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1813 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1815 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1816 print('### ip neigh list dev dummy98')
1817 output
= check_output('ip neigh list dev dummy98')
1819 self
.assertNotRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1820 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1821 self
.assertNotRegex(output
, '2004:da8:1::1.*PERMANENT')
1823 def test_neighbor_gre(self
):
1824 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1825 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1827 self
.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout
='40s')
1829 output
= check_output('ip neigh list dev gretun97')
1831 self
.assertRegex(output
, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1833 output
= check_output('ip neigh list dev ip6gretun97')
1835 self
.assertRegex(output
, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1837 def test_link_local_addressing(self
):
1838 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1839 '25-link-local-addressing-no.network', '12-dummy.netdev')
1841 self
.wait_online(['test1:degraded', 'dummy98:carrier'])
1843 output
= check_output('ip address show dev test1')
1845 self
.assertRegex(output
, 'inet .* scope link')
1846 self
.assertRegex(output
, 'inet6 .* scope link')
1848 output
= check_output('ip address show dev dummy98')
1850 self
.assertNotRegex(output
, 'inet6* .* scope link')
1853 Documentation/networking/ip-sysctl.txt
1855 addr_gen_mode - INTEGER
1856 Defines how link-local and autoconf addresses are generated.
1858 0: generate address based on EUI64 (default)
1859 1: do no generate a link-local address, use EUI64 for addresses generated
1861 2: generate stable privacy addresses, using the secret from
1862 stable_secret (RFC7217)
1863 3: generate stable privacy addresses, using a random secret if unset
1866 test1_addr_gen_mode
= ''
1867 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')):
1868 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')) as f
:
1872 # if stable_secret is unset, then EIO is returned
1873 test1_addr_gen_mode
= '0'
1875 test1_addr_gen_mode
= '2'
1877 test1_addr_gen_mode
= '0'
1879 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'addr_gen_mode')):
1880 self
.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode
)
1882 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'dummy98'), 'addr_gen_mode')):
1883 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1885 def test_link_local_addressing_remove_ipv6ll(self
):
1886 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1888 self
.wait_online(['dummy98:degraded'])
1890 output
= check_output('ip address show dev dummy98')
1892 self
.assertRegex(output
, 'inet6 .* scope link')
1894 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
1896 self
.wait_online(['dummy98:carrier'])
1898 output
= check_output('ip address show dev dummy98')
1900 self
.assertNotRegex(output
, 'inet6* .* scope link')
1902 def test_sysctl(self
):
1903 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1905 self
.wait_online(['dummy98:degraded'])
1907 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1908 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1909 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1910 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1911 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1912 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1913 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1915 def test_sysctl_disable_ipv6(self
):
1916 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1918 print('## Disable ipv6')
1919 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1920 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1923 self
.wait_online(['dummy98:routable'])
1925 output
= check_output('ip -4 address show dummy98')
1927 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1928 output
= check_output('ip -6 address show dummy98')
1930 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1931 self
.assertRegex(output
, 'inet6 .* scope link')
1932 output
= check_output('ip -4 route show dev dummy98')
1934 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1935 output
= check_output('ip -6 route show dev dummy98')
1937 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1939 check_output('ip link del dummy98')
1941 print('## Enable ipv6')
1942 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1943 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1946 self
.wait_online(['dummy98:routable'])
1948 output
= check_output('ip -4 address show dummy98')
1950 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1951 output
= check_output('ip -6 address show dummy98')
1953 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1954 self
.assertRegex(output
, 'inet6 .* scope link')
1955 output
= check_output('ip -4 route show dev dummy98')
1957 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1958 output
= check_output('ip -6 route show dev dummy98')
1960 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1962 def test_bind_carrier(self
):
1963 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1965 self
.wait_online(['test1:routable'])
1967 check_output('ip link add dummy98 type dummy')
1968 check_output('ip link set dummy98 up')
1970 output
= check_output('ip address show test1')
1972 self
.assertRegex(output
, 'UP,LOWER_UP')
1973 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1974 self
.check_operstate('test1', 'routable')
1976 check_output('ip link add dummy99 type dummy')
1977 check_output('ip link set dummy99 up')
1979 output
= check_output('ip address show test1')
1981 self
.assertRegex(output
, 'UP,LOWER_UP')
1982 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1983 self
.check_operstate('test1', 'routable')
1985 check_output('ip link del dummy98')
1987 output
= check_output('ip address show test1')
1989 self
.assertRegex(output
, 'UP,LOWER_UP')
1990 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1991 self
.check_operstate('test1', 'routable')
1993 check_output('ip link del dummy99')
1995 output
= check_output('ip address show test1')
1997 self
.assertNotRegex(output
, 'UP,LOWER_UP')
1998 self
.assertRegex(output
, 'DOWN')
1999 self
.assertNotRegex(output
, '192.168.10')
2000 self
.check_operstate('test1', 'off')
2002 check_output('ip link add dummy98 type dummy')
2003 check_output('ip link set dummy98 up')
2005 output
= check_output('ip address show test1')
2007 self
.assertRegex(output
, 'UP,LOWER_UP')
2008 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2009 self
.check_operstate('test1', 'routable')
2011 def test_domain(self
):
2012 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2014 self
.wait_online(['dummy98:routable'])
2016 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
2018 self
.assertRegex(output
, 'Address: 192.168.42.100')
2019 self
.assertRegex(output
, 'DNS: 192.168.42.1')
2020 self
.assertRegex(output
, 'Search Domains: one')
2022 def test_keep_configuration_static(self
):
2023 check_output('systemctl stop systemd-networkd')
2025 check_output('ip link add name dummy98 type dummy')
2026 check_output('ip address add 10.1.2.3/16 dev dummy98')
2027 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2028 output
= check_output('ip address show dummy98')
2030 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2031 self
.assertRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2032 output
= check_output('ip route show dev dummy98')
2035 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2037 self
.wait_online(['dummy98:routable'])
2039 output
= check_output('ip address show dummy98')
2041 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2042 self
.assertNotRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2044 @expectedFailureIfNexthopIsNotAvailable()
2045 def test_nexthop(self
):
2046 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2048 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2050 output
= check_output('ip nexthop list dev veth99')
2052 self
.assertRegex(output
, '192.168.5.1')
2054 class NetworkdStateFileTests(unittest
.TestCase
, Utilities
):
2061 'state-file-tests.network',
2065 remove_links(self
.links
)
2066 stop_networkd(show_logs
=False)
2069 remove_links(self
.links
)
2070 remove_unit_from_networkd_path(self
.units
)
2071 stop_networkd(show_logs
=True)
2073 def test_state_file(self
):
2074 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2076 self
.wait_online(['dummy98:routable'])
2078 output
= check_output(*networkctl_cmd
, '--no-legend', 'list', 'dummy98', env
=env
)
2080 ifindex
= output
.split()[0]
2082 path
= os
.path
.join('/run/systemd/netif/links/', ifindex
)
2083 self
.assertTrue(os
.path
.exists(path
))
2086 with
open(path
) as f
:
2088 self
.assertRegex(data
, r
'ADMIN_STATE=configured')
2089 self
.assertRegex(data
, r
'OPER_STATE=routable')
2090 self
.assertRegex(data
, r
'REQUIRED_FOR_ONLINE=yes')
2091 self
.assertRegex(data
, r
'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2092 self
.assertRegex(data
, r
'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2093 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2094 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2095 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2096 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2097 self
.assertRegex(data
, r
'LLMNR=no')
2098 self
.assertRegex(data
, r
'MDNS=yes')
2099 self
.assertRegex(data
, r
'DNSSEC=no')
2100 self
.assertRegex(data
, r
'ADDRESSES=192.168.(?:10.10|12.12)/24 192.168.(?:12.12|10.10)/24')
2102 check_output(*resolvectl_cmd
, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env
=env
)
2103 check_output(*resolvectl_cmd
, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env
=env
)
2104 check_output(*resolvectl_cmd
, 'llmnr', 'dummy98', 'yes', env
=env
)
2105 check_output(*resolvectl_cmd
, 'mdns', 'dummy98', 'no', env
=env
)
2106 check_output(*resolvectl_cmd
, 'dnssec', 'dummy98', 'yes', env
=env
)
2107 check_output(*timedatectl_cmd
, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env
=env
)
2110 with
open(path
) as f
:
2112 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2113 self
.assertRegex(data
, r
'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2114 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2115 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2116 self
.assertRegex(data
, r
'LLMNR=yes')
2117 self
.assertRegex(data
, r
'MDNS=no')
2118 self
.assertRegex(data
, r
'DNSSEC=yes')
2120 check_output(*timedatectl_cmd
, 'revert', 'dummy98', env
=env
)
2123 with
open(path
) as f
:
2125 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2126 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2127 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2128 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2129 self
.assertRegex(data
, r
'LLMNR=yes')
2130 self
.assertRegex(data
, r
'MDNS=no')
2131 self
.assertRegex(data
, r
'DNSSEC=yes')
2133 check_output(*resolvectl_cmd
, 'revert', 'dummy98', env
=env
)
2136 with
open(path
) as f
:
2138 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2139 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2140 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2141 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2142 self
.assertRegex(data
, r
'LLMNR=no')
2143 self
.assertRegex(data
, r
'MDNS=yes')
2144 self
.assertRegex(data
, r
'DNSSEC=no')
2146 class NetworkdBondTests(unittest
.TestCase
, Utilities
):
2156 '23-active-slave.network',
2157 '23-bond199.network',
2158 '23-primary-slave.network',
2159 '25-bond-active-backup-slave.netdev',
2162 'bond-slave.network']
2165 remove_links(self
.links
)
2166 stop_networkd(show_logs
=False)
2169 remove_links(self
.links
)
2170 remove_unit_from_networkd_path(self
.units
)
2171 stop_networkd(show_logs
=True)
2173 def test_bond_active_slave(self
):
2174 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2176 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2178 output
= check_output('ip -d link show bond199')
2180 self
.assertRegex(output
, 'active_slave dummy98')
2182 def test_bond_primary_slave(self
):
2183 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2185 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2187 output
= check_output('ip -d link show bond199')
2189 self
.assertRegex(output
, 'primary dummy98')
2191 def test_bond_operstate(self
):
2192 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2193 'bond99.network','bond-slave.network')
2195 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2197 output
= check_output('ip -d link show dummy98')
2199 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2201 output
= check_output('ip -d link show test1')
2203 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2205 output
= check_output('ip -d link show bond99')
2207 self
.assertRegex(output
, 'MASTER,UP,LOWER_UP')
2209 self
.check_operstate('dummy98', 'enslaved')
2210 self
.check_operstate('test1', 'enslaved')
2211 self
.check_operstate('bond99', 'routable')
2213 check_output('ip link set dummy98 down')
2216 self
.check_operstate('dummy98', 'off')
2217 self
.check_operstate('test1', 'enslaved')
2218 self
.check_operstate('bond99', 'degraded-carrier')
2220 check_output('ip link set dummy98 up')
2223 self
.check_operstate('dummy98', 'enslaved')
2224 self
.check_operstate('test1', 'enslaved')
2225 self
.check_operstate('bond99', 'routable')
2227 check_output('ip link set dummy98 down')
2228 check_output('ip link set test1 down')
2231 self
.check_operstate('dummy98', 'off')
2232 self
.check_operstate('test1', 'off')
2234 for trial
in range(30):
2237 output
= check_output('ip address show bond99')
2239 if get_operstate('bond99') == 'no-carrier':
2242 # Huh? Kernel does not recognize that all slave interfaces are down?
2243 # Let's confirm that networkd's operstate is consistent with ip's result.
2244 self
.assertNotRegex(output
, 'NO-CARRIER')
2246 class NetworkdBridgeTests(unittest
.TestCase
, Utilities
):
2256 '26-bridge-slave-interface-1.network',
2257 '26-bridge-slave-interface-2.network',
2258 '26-bridge-vlan-master.network',
2259 '26-bridge-vlan-slave.network',
2260 'bridge99-ignore-carrier-loss.network',
2263 routing_policy_rule_tables
= ['100']
2266 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2267 remove_links(self
.links
)
2268 stop_networkd(show_logs
=False)
2271 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2272 remove_links(self
.links
)
2273 remove_unit_from_networkd_path(self
.units
)
2274 stop_networkd(show_logs
=True)
2276 def test_bridge_vlan(self
):
2277 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2278 '26-bridge.netdev', '26-bridge-vlan-master.network')
2280 self
.wait_online(['test1:enslaved', 'bridge99:degraded'])
2282 output
= check_output('bridge vlan show dev test1')
2284 self
.assertNotRegex(output
, '4063')
2285 for i
in range(4064, 4095):
2286 self
.assertRegex(output
, f
'{i}')
2287 self
.assertNotRegex(output
, '4095')
2289 output
= check_output('bridge vlan show dev bridge99')
2291 self
.assertNotRegex(output
, '4059')
2292 for i
in range(4060, 4095):
2293 self
.assertRegex(output
, f
'{i}')
2294 self
.assertNotRegex(output
, '4095')
2296 def test_bridge_property(self
):
2297 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2298 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2301 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2303 output
= check_output('ip -d link show test1')
2305 self
.assertRegex(output
, 'master')
2306 self
.assertRegex(output
, 'bridge')
2308 output
= check_output('ip -d link show dummy98')
2310 self
.assertRegex(output
, 'master')
2311 self
.assertRegex(output
, 'bridge')
2313 output
= check_output('ip addr show bridge99')
2315 self
.assertRegex(output
, '192.168.0.15/24')
2317 output
= check_output('bridge -d link show dummy98')
2319 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2320 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2321 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2322 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2323 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2324 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2325 if (os
.path
.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2326 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2327 if (os
.path
.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2328 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2329 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2330 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2331 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2332 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2334 output
= check_output('bridge -d link show test1')
2336 self
.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2338 check_output('ip address add 192.168.0.16/24 dev bridge99')
2341 output
= check_output('ip addr show bridge99')
2343 self
.assertRegex(output
, '192.168.0.16/24')
2346 print('### ip -6 route list table all dev bridge99')
2347 output
= check_output('ip -6 route list table all dev bridge99')
2349 self
.assertRegex(output
, 'ff00::/8 table local metric 256 pref medium')
2351 self
.assertEqual(call('ip link del test1'), 0)
2354 self
.check_operstate('bridge99', 'degraded-carrier')
2356 check_output('ip link del dummy98')
2359 self
.check_operstate('bridge99', 'no-carrier')
2361 output
= check_output('ip address show bridge99')
2363 self
.assertRegex(output
, 'NO-CARRIER')
2364 self
.assertNotRegex(output
, '192.168.0.15/24')
2365 self
.assertNotRegex(output
, '192.168.0.16/24')
2367 print('### ip -6 route list table all dev bridge99')
2368 output
= check_output('ip -6 route list table all dev bridge99')
2370 self
.assertRegex(output
, 'ff00::/8 table local metric 256 (?:linkdown |)pref medium')
2372 def test_bridge_ignore_carrier_loss(self
):
2373 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2374 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2375 'bridge99-ignore-carrier-loss.network')
2377 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2379 check_output('ip address add 192.168.0.16/24 dev bridge99')
2382 check_output('ip link del test1')
2383 check_output('ip link del dummy98')
2386 output
= check_output('ip address show bridge99')
2388 self
.assertRegex(output
, 'NO-CARRIER')
2389 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2390 self
.assertRegex(output
, 'inet 192.168.0.16/24 scope global secondary bridge99')
2392 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self
):
2393 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2394 'bridge99-ignore-carrier-loss.network')
2396 self
.wait_online(['bridge99:no-carrier'])
2398 for trial
in range(4):
2399 check_output('ip link add dummy98 type dummy')
2400 check_output('ip link set dummy98 up')
2402 check_output('ip link del dummy98')
2404 self
.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2406 output
= check_output('ip address show bridge99')
2408 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2410 output
= check_output('ip rule list table 100')
2412 self
.assertEqual(output
, '0: from all to 8.8.8.8 lookup 100')
2414 class NetworkdLLDPTests(unittest
.TestCase
, Utilities
):
2418 '23-emit-lldp.network',
2423 remove_links(self
.links
)
2424 stop_networkd(show_logs
=False)
2427 remove_links(self
.links
)
2428 remove_unit_from_networkd_path(self
.units
)
2429 stop_networkd(show_logs
=True)
2431 def test_lldp(self
):
2432 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2434 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2436 output
= check_output(*networkctl_cmd
, 'lldp', env
=env
)
2438 self
.assertRegex(output
, 'veth-peer')
2439 self
.assertRegex(output
, 'veth99')
2441 class NetworkdRATests(unittest
.TestCase
, Utilities
):
2446 'ipv6-prefix.network',
2447 'ipv6-prefix-veth.network']
2450 remove_links(self
.links
)
2451 stop_networkd(show_logs
=False)
2454 remove_links(self
.links
)
2455 remove_unit_from_networkd_path(self
.units
)
2456 stop_networkd(show_logs
=True)
2458 def test_ipv6_prefix_delegation(self
):
2459 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2461 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2463 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2465 self
.assertRegex(output
, '2002:da8:1:0')
2467 class NetworkdDHCPServerTests(unittest
.TestCase
, Utilities
):
2472 'dhcp-client.network',
2473 'dhcp-client-timezone-router.network',
2474 'dhcp-server.network',
2475 'dhcp-server-timezone-router.network']
2478 remove_links(self
.links
)
2479 stop_networkd(show_logs
=False)
2482 remove_links(self
.links
)
2483 remove_unit_from_networkd_path(self
.units
)
2484 stop_networkd(show_logs
=True)
2486 def test_dhcp_server(self
):
2487 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2489 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2491 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2493 self
.assertRegex(output
, '192.168.5.*')
2494 self
.assertRegex(output
, 'Gateway: 192.168.5.1')
2495 self
.assertRegex(output
, 'DNS: 192.168.5.1')
2496 self
.assertRegex(output
, 'NTP: 192.168.5.1')
2498 def test_emit_router_timezone(self
):
2499 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2501 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2503 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2505 self
.assertRegex(output
, 'Gateway: 192.168.5.*')
2506 self
.assertRegex(output
, '192.168.5.*')
2507 self
.assertRegex(output
, 'Europe/Berlin')
2509 class NetworkdDHCPClientTests(unittest
.TestCase
, Utilities
):
2518 'dhcp-client-anonymize.network',
2519 'dhcp-client-gateway-onlink-implicit.network',
2520 'dhcp-client-ipv4-dhcp-settings.network',
2521 'dhcp-client-ipv4-only-ipv6-disabled.network',
2522 'dhcp-client-ipv4-only.network',
2523 'dhcp-client-ipv6-only.network',
2524 'dhcp-client-ipv6-rapid-commit.network',
2525 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2526 'dhcp-client-keep-configuration-dhcp.network',
2527 'dhcp-client-listen-port.network',
2528 'dhcp-client-reassign-static-routes-ipv4.network',
2529 'dhcp-client-reassign-static-routes-ipv6.network',
2530 'dhcp-client-route-metric.network',
2531 'dhcp-client-route-table.network',
2532 'dhcp-client-use-dns-ipv4-and-ra.network',
2533 'dhcp-client-use-dns-ipv4.network',
2534 'dhcp-client-use-dns-no.network',
2535 'dhcp-client-use-dns-yes.network',
2536 'dhcp-client-use-domains.network',
2537 'dhcp-client-use-routes-no.network',
2538 'dhcp-client-vrf.network',
2539 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2540 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2541 'dhcp-client-with-static-address.network',
2542 'dhcp-client.network',
2543 'dhcp-server-veth-peer.network',
2544 'dhcp-v4-server-veth-peer.network',
2545 'dhcp-client-use-domains.network',
2549 stop_dnsmasq(dnsmasq_pid_file
)
2550 remove_links(self
.links
)
2551 stop_networkd(show_logs
=False)
2554 stop_dnsmasq(dnsmasq_pid_file
)
2557 remove_links(self
.links
)
2558 remove_unit_from_networkd_path(self
.units
)
2559 stop_networkd(show_logs
=True)
2561 def test_dhcp_client_ipv6_only(self
):
2562 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2565 self
.wait_online(['veth-peer:carrier'])
2567 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2569 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2571 self
.assertRegex(output
, '2600::')
2572 self
.assertNotRegex(output
, '192.168.5')
2574 # Confirm that ipv6 token is not set in the kernel
2575 output
= check_output('ip token show dev veth99')
2577 self
.assertRegex(output
, 'token :: dev veth99')
2579 def test_dhcp_client_ipv4_only(self
):
2580 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2583 self
.wait_online(['veth-peer:carrier'])
2584 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
2585 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2587 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2589 self
.assertNotRegex(output
, '2600::')
2590 self
.assertRegex(output
, '192.168.5')
2591 self
.assertRegex(output
, '192.168.5.6')
2592 self
.assertRegex(output
, '192.168.5.7')
2594 # checking routes to DNS servers
2595 output
= check_output('ip route show dev veth99')
2597 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2598 self
.assertRegex(output
, r
'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2599 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2601 stop_dnsmasq(dnsmasq_pid_file
)
2602 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time
='2m')
2604 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2605 print('Wait for the dynamic address to be renewed')
2608 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2610 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2612 self
.assertNotRegex(output
, '2600::')
2613 self
.assertRegex(output
, '192.168.5')
2614 self
.assertNotRegex(output
, '192.168.5.6')
2615 self
.assertRegex(output
, '192.168.5.7')
2616 self
.assertRegex(output
, '192.168.5.8')
2618 # checking routes to DNS servers
2619 output
= check_output('ip route show dev veth99')
2621 self
.assertNotRegex(output
, r
'192.168.5.6')
2622 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2623 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2624 self
.assertRegex(output
, r
'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2626 def test_dhcp_client_ipv4_ipv6(self
):
2627 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2628 'dhcp-client-ipv4-only.network')
2630 self
.wait_online(['veth-peer:carrier'])
2632 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2634 # link become 'routable' when at least one protocol provide an valid address.
2635 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2636 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2638 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2640 self
.assertRegex(output
, '2600::')
2641 self
.assertRegex(output
, '192.168.5')
2643 def test_dhcp_client_settings(self
):
2644 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2647 self
.wait_online(['veth-peer:carrier'])
2649 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2651 print('## ip address show dev veth99')
2652 output
= check_output('ip address show dev veth99')
2654 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2655 self
.assertRegex(output
, '192.168.5')
2656 self
.assertRegex(output
, '1492')
2658 print('## ip route show table main dev veth99')
2659 output
= check_output('ip route show table main dev veth99')
2662 main_table_is_empty
= output
== ''
2663 if not main_table_is_empty
:
2664 self
.assertNotRegex(output
, 'proto dhcp')
2666 print('## ip route show table 211 dev veth99')
2667 output
= check_output('ip route show table 211 dev veth99')
2669 self
.assertRegex(output
, 'default via 192.168.5.1 proto dhcp')
2670 if main_table_is_empty
:
2671 self
.assertRegex(output
, '192.168.5.0/24 proto dhcp')
2672 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2673 self
.assertRegex(output
, '192.168.5.1 proto dhcp scope link')
2675 print('## dnsmasq log')
2676 self
.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2677 self
.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2678 self
.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2679 self
.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2681 def test_dhcp6_client_settings_rapidcommit_true(self
):
2682 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2684 self
.wait_online(['veth-peer:carrier'])
2686 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2688 output
= check_output('ip address show dev veth99')
2690 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2691 self
.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2693 def test_dhcp6_client_settings_rapidcommit_false(self
):
2694 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2696 self
.wait_online(['veth-peer:carrier'])
2698 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2700 output
= check_output('ip address show dev veth99')
2702 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2703 self
.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2705 def test_dhcp_client_settings_anonymize(self
):
2706 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2708 self
.wait_online(['veth-peer:carrier'])
2710 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2712 self
.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2713 self
.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2714 self
.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2716 def test_dhcp_client_listen_port(self
):
2717 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2719 self
.wait_online(['veth-peer:carrier'])
2720 start_dnsmasq('--dhcp-alternate-port=67,5555')
2721 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2723 output
= check_output('ip -4 address show dev veth99')
2725 self
.assertRegex(output
, '192.168.5.* dynamic')
2727 def test_dhcp_client_with_static_address(self
):
2728 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2729 'dhcp-client-with-static-address.network')
2731 self
.wait_online(['veth-peer:carrier'])
2733 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2735 output
= check_output('ip address show dev veth99 scope global')
2737 self
.assertRegex(output
, r
'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2738 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2740 output
= check_output('ip route show dev veth99')
2742 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2743 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2744 self
.assertRegex(output
, r
'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2745 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2747 def test_dhcp_route_table_id(self
):
2748 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2750 self
.wait_online(['veth-peer:carrier'])
2752 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2754 output
= check_output('ip route show table 12')
2756 self
.assertRegex(output
, 'veth99 proto dhcp')
2757 self
.assertRegex(output
, '192.168.5.1')
2759 def test_dhcp_route_metric(self
):
2760 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2762 self
.wait_online(['veth-peer:carrier'])
2764 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2766 output
= check_output('ip route show dev veth99')
2768 self
.assertRegex(output
, 'metric 24')
2770 def test_dhcp_client_reassign_static_routes_ipv4(self
):
2771 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2772 'dhcp-client-reassign-static-routes-ipv4.network')
2774 self
.wait_online(['veth-peer:carrier'])
2775 start_dnsmasq(lease_time
='2m')
2776 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2778 output
= check_output('ip address show dev veth99 scope global')
2780 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2782 output
= check_output('ip route show dev veth99')
2784 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2785 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2786 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2787 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2789 stop_dnsmasq(dnsmasq_pid_file
)
2790 start_dnsmasq(ipv4_range
='192.168.5.210,192.168.5.220', lease_time
='2m')
2792 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2793 print('Wait for the dynamic address to be renewed')
2796 self
.wait_online(['veth99:routable'])
2798 output
= check_output('ip route show dev veth99')
2800 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2801 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2802 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2803 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2805 def test_dhcp_client_reassign_static_routes_ipv6(self
):
2806 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2807 'dhcp-client-reassign-static-routes-ipv6.network')
2809 self
.wait_online(['veth-peer:carrier'])
2810 start_dnsmasq(lease_time
='2m')
2811 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2813 output
= check_output('ip address show dev veth99 scope global')
2815 self
.assertRegex(output
, r
'inet6 2600::[0-9a-f]*/128 scope global (?:noprefixroute dynamic|dynamic noprefixroute)')
2817 output
= check_output('ip -6 route show dev veth99')
2819 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2820 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2822 stop_dnsmasq(dnsmasq_pid_file
)
2823 start_dnsmasq(ipv6_range
='2600::30,2600::40', lease_time
='2m')
2825 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2826 print('Wait for the dynamic address to be renewed')
2829 self
.wait_online(['veth99:routable'])
2831 output
= check_output('ip -6 route show dev veth99')
2833 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2834 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2836 def test_dhcp_keep_configuration_dhcp(self
):
2837 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2839 self
.wait_online(['veth-peer:carrier'])
2840 start_dnsmasq(lease_time
='2m')
2841 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2843 output
= check_output('ip address show dev veth99 scope global')
2845 self
.assertRegex(output
, r
'192.168.5.*')
2847 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2849 self
.assertRegex(output
, r
'192.168.5.*')
2851 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2852 stop_dnsmasq(dnsmasq_pid_file
)
2854 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2855 print('Wait for the dynamic address to be expired')
2858 print('The lease address should be kept after lease expired')
2859 output
= check_output('ip address show dev veth99 scope global')
2861 self
.assertRegex(output
, r
'192.168.5.*')
2863 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2865 self
.assertRegex(output
, r
'192.168.5.*')
2867 check_output('systemctl stop systemd-networkd')
2869 print('The lease address should be kept after networkd stopped')
2870 output
= check_output('ip address show dev veth99 scope global')
2872 self
.assertRegex(output
, r
'192.168.5.*')
2874 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2876 self
.assertRegex(output
, r
'192.168.5.*')
2879 self
.wait_online(['veth-peer:routable'])
2881 print('Still the lease address should be kept after networkd restarted')
2882 output
= check_output('ip address show dev veth99 scope global')
2884 self
.assertRegex(output
, r
'192.168.5.*')
2886 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2888 self
.assertRegex(output
, r
'192.168.5.*')
2890 def test_dhcp_keep_configuration_dhcp_on_stop(self
):
2891 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2893 self
.wait_online(['veth-peer:carrier'])
2894 start_dnsmasq(lease_time
='2m')
2895 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2897 output
= check_output('ip address show dev veth99 scope global')
2899 self
.assertRegex(output
, r
'192.168.5.*')
2901 stop_dnsmasq(dnsmasq_pid_file
)
2902 check_output('systemctl stop systemd-networkd')
2904 output
= check_output('ip address show dev veth99 scope global')
2906 self
.assertRegex(output
, r
'192.168.5.*')
2909 self
.wait_online(['veth-peer:routable'])
2911 output
= check_output('ip address show dev veth99 scope global')
2913 self
.assertNotRegex(output
, r
'192.168.5.*')
2915 def test_dhcp_client_reuse_address_as_static(self
):
2916 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2918 self
.wait_online(['veth-peer:carrier'])
2920 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2922 # link become 'routable' when at least one protocol provide an valid address.
2923 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2924 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2926 output
= check_output('ip address show dev veth99 scope global')
2928 self
.assertRegex(output
, '192.168.5')
2929 self
.assertRegex(output
, '2600::')
2931 ipv4_address
= re
.search(r
'192.168.5.[0-9]*/24', output
)
2932 ipv6_address
= re
.search(r
'2600::[0-9a-f:]*/128', output
)
2933 static_network
= '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address
.group(), 'Address=' + ipv6_address
.group()])
2934 print(static_network
)
2936 remove_unit_from_networkd_path(['dhcp-client.network'])
2938 with
open(os
.path
.join(network_unit_file_path
, 'static.network'), mode
='w') as f
:
2939 f
.write(static_network
)
2941 # When networkd started, the links are already configured, so let's wait for 5 seconds
2942 # the links to be re-configured.
2944 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2946 output
= check_output('ip -4 address show dev veth99 scope global')
2948 self
.assertRegex(output
, '192.168.5')
2949 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2951 output
= check_output('ip -6 address show dev veth99 scope global')
2953 self
.assertRegex(output
, '2600::')
2954 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2956 @expectedFailureIfModuleIsNotAvailable('vrf')
2957 def test_dhcp_client_vrf(self
):
2958 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2959 '25-vrf.netdev', '25-vrf.network')
2961 self
.wait_online(['veth-peer:carrier'])
2963 self
.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2965 # link become 'routable' when at least one protocol provide an valid address.
2966 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2967 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2969 print('## ip -d link show dev vrf99')
2970 output
= check_output('ip -d link show dev vrf99')
2972 self
.assertRegex(output
, 'vrf table 42')
2974 print('## ip address show vrf vrf99')
2975 output
= check_output('ip address show vrf vrf99')
2977 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2978 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2979 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2980 self
.assertRegex(output
, 'inet6 .* scope link')
2982 print('## ip address show dev veth99')
2983 output
= check_output('ip address show dev veth99')
2985 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2986 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2987 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2988 self
.assertRegex(output
, 'inet6 .* scope link')
2990 print('## ip route show vrf vrf99')
2991 output
= check_output('ip route show vrf vrf99')
2993 self
.assertRegex(output
, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2994 self
.assertRegex(output
, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2995 self
.assertRegex(output
, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2996 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2997 self
.assertRegex(output
, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2999 print('## ip route show table main dev veth99')
3000 output
= check_output('ip route show table main dev veth99')
3002 self
.assertEqual(output
, '')
3004 def test_dhcp_client_gateway_onlink_implicit(self
):
3005 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3006 'dhcp-client-gateway-onlink-implicit.network')
3008 self
.wait_online(['veth-peer:carrier'])
3010 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3012 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3014 self
.assertRegex(output
, '192.168.5')
3016 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3018 self
.assertRegex(output
, 'onlink')
3019 output
= check_output('ip route list dev veth99 192.168.100.0/24')
3021 self
.assertRegex(output
, 'onlink')
3023 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self
):
3024 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3025 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3027 self
.wait_online(['veth-peer:carrier'])
3028 start_dnsmasq(lease_time
='2m')
3029 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3031 output
= check_output('ip address show dev veth99')
3034 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3035 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3036 output
= check_output('ip -6 address show dev veth99 scope link')
3037 self
.assertRegex(output
, 'inet6 .* scope link')
3038 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3039 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3040 output
= check_output('ip -4 address show dev veth99 scope link')
3041 self
.assertNotRegex(output
, 'inet .* scope link')
3043 print('Wait for the dynamic address to be expired')
3046 output
= check_output('ip address show dev veth99')
3049 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3050 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3051 output
= check_output('ip -6 address show dev veth99 scope link')
3052 self
.assertRegex(output
, 'inet6 .* scope link')
3053 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3054 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3055 output
= check_output('ip -4 address show dev veth99 scope link')
3056 self
.assertNotRegex(output
, 'inet .* scope link')
3058 search_words_in_dnsmasq_log('DHCPOFFER', show_all
=True)
3060 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self
):
3061 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3062 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3064 self
.wait_online(['veth99:degraded', 'veth-peer:routable'])
3066 output
= check_output('ip address show dev veth99')
3069 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3070 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3071 output
= check_output('ip -6 address show dev veth99 scope link')
3072 self
.assertRegex(output
, 'inet6 .* scope link')
3073 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3074 self
.assertNotRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3075 output
= check_output('ip -4 address show dev veth99 scope link')
3076 self
.assertRegex(output
, 'inet .* scope link')
3078 def test_dhcp_client_route_remove_on_renew(self
):
3079 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3080 'dhcp-client-ipv4-only-ipv6-disabled.network')
3082 self
.wait_online(['veth-peer:carrier'])
3083 start_dnsmasq(ipv4_range
='192.168.5.100,192.168.5.199', lease_time
='2m')
3084 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3086 # test for issue #12490
3088 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3090 self
.assertRegex(output
, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3092 for line
in output
.splitlines():
3093 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3094 address1
= line
.split()[1].split('/')[0]
3097 output
= check_output('ip -4 route show dev veth99')
3099 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3100 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3102 stop_dnsmasq(dnsmasq_pid_file
)
3103 start_dnsmasq(ipv4_range
='192.168.5.200,192.168.5.250', lease_time
='2m')
3105 print('Wait for the dynamic address to be expired')
3108 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3110 self
.assertRegex(output
, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3112 for line
in output
.splitlines():
3113 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3114 address2
= line
.split()[1].split('/')[0]
3117 self
.assertNotEqual(address1
, address2
)
3119 output
= check_output('ip -4 route show dev veth99')
3121 self
.assertNotRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3122 self
.assertNotRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3123 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3124 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3126 def test_dhcp_client_use_dns_yes(self
):
3127 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3130 self
.wait_online(['veth-peer:carrier'])
3131 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3132 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3134 # link become 'routable' when at least one protocol provide an valid address.
3135 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3136 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3139 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3141 self
.assertRegex(output
, '192.168.5.1')
3142 self
.assertRegex(output
, '2600::1')
3144 def test_dhcp_client_use_dns_no(self
):
3145 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3148 self
.wait_online(['veth-peer:carrier'])
3149 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3150 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3152 # link become 'routable' when at least one protocol provide an valid address.
3153 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3154 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3157 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3159 self
.assertNotRegex(output
, '192.168.5.1')
3160 self
.assertNotRegex(output
, '2600::1')
3162 def test_dhcp_client_use_dns_ipv4(self
):
3163 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3166 self
.wait_online(['veth-peer:carrier'])
3167 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3168 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3170 # link become 'routable' when at least one protocol provide an valid address.
3171 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3172 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3175 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3177 self
.assertRegex(output
, '192.168.5.1')
3178 self
.assertNotRegex(output
, '2600::1')
3180 def test_dhcp_client_use_dns_ipv4_and_ra(self
):
3181 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3184 self
.wait_online(['veth-peer:carrier'])
3185 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3186 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3188 # link become 'routable' when at least one protocol provide an valid address.
3189 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3190 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3193 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3195 self
.assertRegex(output
, '192.168.5.1')
3196 self
.assertRegex(output
, '2600::1')
3198 def test_dhcp_client_use_domains(self
):
3199 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3202 self
.wait_online(['veth-peer:carrier'])
3203 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3204 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3206 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3208 self
.assertRegex(output
, 'Search Domains: example.com')
3211 output
= check_output(*resolvectl_cmd
, 'domain', 'veth99', env
=env
)
3213 self
.assertRegex(output
, 'example.com')
3215 class NetworkdIPv6PrefixTests(unittest
.TestCase
, Utilities
):
3220 'ipv6ra-prefix-client.network',
3221 'ipv6ra-prefix.network'
3225 remove_links(self
.links
)
3226 stop_networkd(show_logs
=False)
3230 remove_links(self
.links
)
3231 remove_unit_from_networkd_path(self
.units
)
3232 stop_networkd(show_logs
=True)
3234 def test_ipv6_route_prefix(self
):
3235 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3238 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3240 output
= check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3242 self
.assertRegex(output
, '2001:db8:0:1::/64 proto ra')
3244 if __name__
== '__main__':
3245 parser
= argparse
.ArgumentParser()
3246 parser
.add_argument('--build-dir', help='Path to build dir', dest
='build_dir')
3247 parser
.add_argument('--networkd', help='Path to systemd-networkd', dest
='networkd_bin')
3248 parser
.add_argument('--resolved', help='Path to systemd-resolved', dest
='resolved_bin')
3249 parser
.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest
='wait_online_bin')
3250 parser
.add_argument('--networkctl', help='Path to networkctl', dest
='networkctl_bin')
3251 parser
.add_argument('--resolvectl', help='Path to resolvectl', dest
='resolvectl_bin')
3252 parser
.add_argument('--timedatectl', help='Path to timedatectl', dest
='timedatectl_bin')
3253 parser
.add_argument('--valgrind', help='Enable valgrind', dest
='use_valgrind', type=bool, nargs
='?', const
=True, default
=use_valgrind
)
3254 parser
.add_argument('--debug', help='Generate debugging logs', dest
='enable_debug', type=bool, nargs
='?', const
=True, default
=enable_debug
)
3255 parser
.add_argument('--asan-options', help='ASAN options', dest
='asan_options')
3256 parser
.add_argument('--lsan-options', help='LSAN options', dest
='lsan_options')
3257 parser
.add_argument('--ubsan-options', help='UBSAN options', dest
='ubsan_options')
3258 ns
, args
= parser
.parse_known_args(namespace
=unittest
)
3261 if ns
.networkd_bin
or ns
.resolved_bin
or ns
.wait_online_bin
or ns
.networkctl_bin
or ns
.resolvectl_bin
or ns
.timedatectl_bin
:
3262 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3263 networkd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd')
3264 resolved_bin
= os
.path
.join(ns
.build_dir
, 'systemd-resolved')
3265 wait_online_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd-wait-online')
3266 networkctl_bin
= os
.path
.join(ns
.build_dir
, 'networkctl')
3267 resolvectl_bin
= os
.path
.join(ns
.build_dir
, 'resolvectl')
3268 timedatectl_bin
= os
.path
.join(ns
.build_dir
, 'timedatectl')
3271 networkd_bin
= ns
.networkd_bin
3273 resolved_bin
= ns
.resolved_bin
3274 if ns
.wait_online_bin
:
3275 wait_online_bin
= ns
.wait_online_bin
3276 if ns
.networkctl_bin
:
3277 networkctl_bin
= ns
.networkctl_bin
3278 if ns
.resolvectl_bin
:
3279 resolvectl_bin
= ns
.resolvectl_bin
3280 if ns
.timedatectl_bin
:
3281 timedatectl_bin
= ns
.timedatectl_bin
3283 use_valgrind
= ns
.use_valgrind
3284 enable_debug
= ns
.enable_debug
3285 asan_options
= ns
.asan_options
3286 lsan_options
= ns
.lsan_options
3287 ubsan_options
= ns
.ubsan_options
3290 networkctl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin
]
3291 resolvectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin
]
3292 timedatectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin
]
3293 wait_online_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin
]
3295 networkctl_cmd
= [networkctl_bin
]
3296 resolvectl_cmd
= [resolvectl_bin
]
3297 timedatectl_cmd
= [timedatectl_bin
]
3298 wait_online_cmd
= [wait_online_bin
]
3301 env
.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3303 env
.update({ 'ASAN_OPTIONS' : asan_options
})
3305 env
.update({ 'LSAN_OPTIONS' : lsan_options
})
3307 env
.update({ 'UBSAN_OPTIONS' : ubsan_options
})
3310 unittest
.main(testRunner
=unittest
.TextTestRunner(stream
=sys
.stdout
,