2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
14 from shutil
import copytree
16 network_unit_file_path
='/run/systemd/network'
17 networkd_runtime_directory
='/run/systemd/netif'
18 networkd_ci_path
='/run/networkd-ci'
19 network_sysctl_ipv6_path
='/proc/sys/net/ipv6/conf'
20 network_sysctl_ipv4_path
='/proc/sys/net/ipv4/conf'
22 dnsmasq_pid_file
='/run/networkd-ci/test-test-dnsmasq.pid'
23 dnsmasq_log_file
='/run/networkd-ci/test-dnsmasq-log-file'
25 systemd_lib_paths
=['/usr/lib/systemd', '/lib/systemd']
26 which_paths
=':'.join(systemd_lib_paths
+ os
.getenv('PATH', os
.defpath
).lstrip(':').split(':'))
28 networkd_bin
=shutil
.which('systemd-networkd', path
=which_paths
)
29 resolved_bin
=shutil
.which('systemd-resolved', path
=which_paths
)
30 wait_online_bin
=shutil
.which('systemd-networkd-wait-online', path
=which_paths
)
31 networkctl_bin
=shutil
.which('networkctl', path
=which_paths
)
32 resolvectl_bin
=shutil
.which('resolvectl', path
=which_paths
)
33 timedatectl_bin
=shutil
.which('timedatectl', path
=which_paths
)
44 def check_output(*command
, **kwargs
):
45 # This replaces both check_output and check_call (output can be ignored)
46 command
= command
[0].split() + list(command
[1:])
47 return subprocess
.check_output(command
, universal_newlines
=True, **kwargs
).rstrip()
49 def call(*command
, **kwargs
):
50 command
= command
[0].split() + list(command
[1:])
51 return subprocess
.call(command
, universal_newlines
=True, **kwargs
)
53 def run(*command
, **kwargs
):
54 command
= command
[0].split() + list(command
[1:])
55 return subprocess
.run(command
, universal_newlines
=True, **kwargs
)
57 def is_module_available(module_name
):
58 lsmod_output
= check_output('lsmod')
59 module_re
= re
.compile(rf
'^{re.escape(module_name)}\b', re
.MULTILINE
)
60 return module_re
.search(lsmod_output
) or not call('modprobe', module_name
, stderr
=subprocess
.DEVNULL
)
62 def expectedFailureIfModuleIsNotAvailable(module_name
):
64 if not is_module_available(module_name
):
65 return unittest
.expectedFailure(func
)
70 def expectedFailureIfERSPANModuleIsNotAvailable():
72 rc
= call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr
=subprocess
.DEVNULL
)
74 call('ip link del erspan99')
77 return unittest
.expectedFailure(func
)
81 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
83 rc
= call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr
=subprocess
.DEVNULL
)
85 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
88 return unittest
.expectedFailure(func
)
92 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
94 rc
= call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr
=subprocess
.DEVNULL
)
96 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
99 return unittest
.expectedFailure(func
)
103 def expectedFailureIfLinkFileFieldIsNotSet():
106 rc
= call('ip link add name dummy99 type dummy', stderr
=subprocess
.DEVNULL
)
108 ret
= run('udevadm info -w10s /sys/class/net/dummy99', stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
109 if ret
.returncode
== 0 and 'E: ID_NET_LINK_FILE=' in ret
.stdout
.rstrip():
111 call('ip link del dummy99')
116 return unittest
.expectedFailure(func
)
120 def expectedFailureIfNexthopIsNotAvailable():
122 rc
= call('ip nexthop list', stderr
=subprocess
.DEVNULL
)
126 return unittest
.expectedFailure(func
)
133 os
.makedirs(network_unit_file_path
, exist_ok
=True)
134 os
.makedirs(networkd_ci_path
, exist_ok
=True)
136 shutil
.rmtree(networkd_ci_path
)
137 copytree(os
.path
.join(os
.path
.dirname(os
.path
.abspath(__file__
)), 'conf'), networkd_ci_path
)
139 for u
in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']:
140 if call(f
'systemctl is-active --quiet {u}') == 0:
141 check_output(f
'systemctl stop {u}')
142 running_units
.append(u
)
151 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin
,
155 drop_in
+= ['ExecStart=!!' + networkd_bin
]
157 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
159 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
161 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
163 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
164 if asan_options
or lsan_options
or ubsan_options
:
165 drop_in
+= ['SystemCallFilter=']
166 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
167 drop_in
+= ['MemoryDenyWriteExecute=no']
169 os
.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok
=True)
170 with
open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode
='w') as f
:
171 f
.write('\n'.join(drop_in
))
179 drop_in
+= ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin
]
181 drop_in
+= ['ExecStart=!!' + resolved_bin
]
183 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
185 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
187 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
189 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
190 if asan_options
or lsan_options
or ubsan_options
:
191 drop_in
+= ['SystemCallFilter=']
192 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
193 drop_in
+= ['MemoryDenyWriteExecute=no']
195 os
.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok
=True)
196 with
open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode
='w') as f
:
197 f
.write('\n'.join(drop_in
))
199 check_output('systemctl daemon-reload')
200 print(check_output('systemctl cat systemd-networkd.service'))
201 print(check_output('systemctl cat systemd-resolved.service'))
202 check_output('systemctl restart systemd-resolved')
204 def tearDownModule():
207 shutil
.rmtree(networkd_ci_path
)
209 for u
in ['systemd-networkd.service', 'systemd-resolved.service']:
210 check_output(f
'systemctl stop {u}')
212 shutil
.rmtree('/run/systemd/system/systemd-networkd.service.d')
213 shutil
.rmtree('/run/systemd/system/systemd-resolved.service.d')
214 check_output('systemctl daemon-reload')
216 for u
in running_units
:
217 check_output(f
'systemctl start {u}')
219 def read_link_attr(link
, dev
, attribute
):
220 with
open(os
.path
.join(os
.path
.join(os
.path
.join('/sys/class/net/', link
), dev
), attribute
)) as f
:
221 return f
.readline().strip()
223 def read_bridge_port_attr(bridge
, link
, attribute
):
224 path_bridge
= os
.path
.join('/sys/devices/virtual/net', bridge
)
225 path_port
= 'lower_' + link
+ '/brport'
226 path
= os
.path
.join(path_bridge
, path_port
)
228 with
open(os
.path
.join(path
, attribute
)) as f
:
229 return f
.readline().strip()
231 def link_exists(link
):
232 return os
.path
.exists(os
.path
.join('/sys/class/net', link
))
234 def remove_links(links
):
236 if link_exists(link
):
237 call('ip link del dev', link
)
240 def remove_fou_ports(ports
):
242 call('ip fou del port', port
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
244 def remove_routing_policy_rule_tables(tables
):
248 rc
= call('ip rule del table', table
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
250 def remove_routes(routes
):
251 for route_type
, addr
in routes
:
252 call('ip route del', route_type
, addr
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
254 def remove_l2tp_tunnels(tunnel_ids
):
255 output
= check_output('ip l2tp show tunnel')
256 for tid
in tunnel_ids
:
257 words
='Tunnel ' + tid
+ ', encap'
259 call('ip l2tp del tunnel tid', tid
)
262 def read_ipv6_sysctl_attr(link
, attribute
):
263 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, link
), attribute
)) as f
:
264 return f
.readline().strip()
266 def read_ipv4_sysctl_attr(link
, attribute
):
267 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv4_path
, link
), attribute
)) as f
:
268 return f
.readline().strip()
270 def copy_unit_to_networkd_unit_path(*units
):
273 shutil
.copy(os
.path
.join(networkd_ci_path
, unit
), network_unit_file_path
)
274 if (os
.path
.exists(os
.path
.join(networkd_ci_path
, unit
+ '.d'))):
275 copytree(os
.path
.join(networkd_ci_path
, unit
+ '.d'), os
.path
.join(network_unit_file_path
, unit
+ '.d'))
277 def remove_unit_from_networkd_path(units
):
279 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
))):
280 os
.remove(os
.path
.join(network_unit_file_path
, unit
))
281 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
+ '.d'))):
282 shutil
.rmtree(os
.path
.join(network_unit_file_path
, unit
+ '.d'))
284 def start_dnsmasq(additional_options
='', ipv4_range
='192.168.5.10,192.168.5.200', ipv6_range
='2600::10,2600::20', lease_time
='1h'):
285 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
286 check_output(dnsmasq_command
)
288 def stop_dnsmasq(pid_file
):
289 if os
.path
.exists(pid_file
):
290 with
open(pid_file
, 'r') as f
:
291 pid
= f
.read().rstrip(' \t\r\n\0')
292 os
.kill(int(pid
), signal
.SIGTERM
)
296 def search_words_in_dnsmasq_log(words
, show_all
=False):
297 if os
.path
.exists(dnsmasq_log_file
):
298 with
open (dnsmasq_log_file
) as in_file
:
299 contents
= in_file
.read()
302 for line
in contents
.splitlines():
305 print("%s, %s" % (words
, line
))
309 def remove_lease_file():
310 if os
.path
.exists(os
.path
.join(networkd_ci_path
, 'lease')):
311 os
.remove(os
.path
.join(networkd_ci_path
, 'lease'))
313 def remove_log_file():
314 if os
.path
.exists(dnsmasq_log_file
):
315 os
.remove(dnsmasq_log_file
)
317 def remove_networkd_state_files():
318 if os
.path
.exists(os
.path
.join(networkd_runtime_directory
, 'state')):
319 os
.remove(os
.path
.join(networkd_runtime_directory
, 'state'))
321 def stop_networkd(show_logs
=True, remove_state_files
=True):
323 invocation_id
= check_output('systemctl show systemd-networkd -p InvocationID --value')
324 check_output('systemctl stop systemd-networkd')
326 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id
))
327 if remove_state_files
:
328 remove_networkd_state_files()
330 def start_networkd(sleep_sec
=0):
331 check_output('systemctl start systemd-networkd')
333 time
.sleep(sleep_sec
)
335 def restart_networkd(sleep_sec
=0, show_logs
=True, remove_state_files
=True):
336 stop_networkd(show_logs
, remove_state_files
)
337 start_networkd(sleep_sec
)
339 def get_operstate(link
, show_status
=True, setup_state
='configured'):
340 output
= check_output(*networkctl_cmd
, 'status', link
, env
=env
)
343 for line
in output
.splitlines():
344 if 'State:' in line
and (not setup_state
or setup_state
in line
):
345 return line
.split()[1]
349 def check_link_exists(self
, link
):
350 self
.assertTrue(link_exists(link
))
352 def check_operstate(self
, link
, expected
, show_status
=True, setup_state
='configured'):
353 self
.assertRegex(get_operstate(link
, show_status
, setup_state
), expected
)
355 def wait_online(self
, links_with_operstate
, timeout
='20s', bool_any
=False, setup_state
='configured'):
356 args
= wait_online_cmd
+ [f
'--timeout={timeout}'] + [f
'--interface={link}' for link
in links_with_operstate
]
360 check_output(*args
, env
=env
)
361 except subprocess
.CalledProcessError
:
362 for link
in links_with_operstate
:
363 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0], env
=env
)
367 for link
in links_with_operstate
:
368 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0])
370 for line
in output
.splitlines():
372 self
.assertRegex(line
, setup_state
)
374 def wait_address(self
, link
, address_regex
, scope
='global', ipv
='', timeout_sec
=100):
375 for i
in range(timeout_sec
):
378 output
= check_output(f
'ip {ipv} address show dev {link} scope {scope}')
379 if re
.search(address_regex
, output
):
382 self
.assertRegex(output
, address_regex
)
384 class NetworkctlTests(unittest
.TestCase
, Utilities
):
394 '11-dummy-mtu.netdev',
397 '25-address-static.network',
399 'netdev-link-local-addressing-yes.network',
403 remove_links(self
.links
)
404 stop_networkd(show_logs
=False)
407 remove_links(self
.links
)
408 remove_unit_from_networkd_path(self
.units
)
409 stop_networkd(show_logs
=True)
411 def test_reconfigure(self
):
412 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
414 self
.wait_online(['dummy98:routable'])
416 output
= check_output('ip -4 address show dev dummy98')
418 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
419 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
420 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
422 check_output('ip address del 10.1.2.3/16 dev dummy98')
423 check_output('ip address del 10.1.2.4/16 dev dummy98')
424 check_output('ip address del 10.2.2.4/16 dev dummy98')
426 check_output(*networkctl_cmd
, 'reconfigure', 'dummy98', env
=env
)
427 self
.wait_online(['dummy98:routable'])
429 output
= check_output('ip -4 address show dev dummy98')
431 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
432 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
433 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
435 def test_reload(self
):
438 copy_unit_to_networkd_unit_path('11-dummy.netdev')
439 check_output(*networkctl_cmd
, 'reload', env
=env
)
441 self
.check_link_exists('test1')
442 self
.check_operstate('test1', 'off', setup_state
='unmanaged')
444 copy_unit_to_networkd_unit_path('11-dummy.network')
445 check_output(*networkctl_cmd
, 'reload', env
=env
)
446 self
.wait_online(['test1:degraded'])
448 remove_unit_from_networkd_path(['11-dummy.network'])
449 check_output(*networkctl_cmd
, 'reload', env
=env
)
451 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
453 remove_unit_from_networkd_path(['11-dummy.netdev'])
454 check_output(*networkctl_cmd
, 'reload', env
=env
)
455 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
457 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
458 check_output(*networkctl_cmd
, 'reload', env
=env
)
459 self
.check_operstate('test1', 'degraded')
462 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
465 self
.wait_online(['test1:degraded'])
467 output
= check_output(*networkctl_cmd
, 'list', env
=env
)
468 self
.assertRegex(output
, '1 lo ')
469 self
.assertRegex(output
, 'test1')
471 output
= check_output(*networkctl_cmd
, 'list', 'test1', env
=env
)
472 self
.assertNotRegex(output
, '1 lo ')
473 self
.assertRegex(output
, 'test1')
475 output
= check_output(*networkctl_cmd
, 'list', 'te*', env
=env
)
476 self
.assertNotRegex(output
, '1 lo ')
477 self
.assertRegex(output
, 'test1')
479 output
= check_output(*networkctl_cmd
, 'status', 'te*', env
=env
)
480 self
.assertNotRegex(output
, '1: lo ')
481 self
.assertRegex(output
, 'test1')
483 output
= check_output(*networkctl_cmd
, 'status', 'tes[a-z][0-9]', env
=env
)
484 self
.assertNotRegex(output
, '1: lo ')
485 self
.assertRegex(output
, 'test1')
488 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
491 self
.wait_online(['test1:degraded'])
493 output
= check_output(*networkctl_cmd
, 'status', 'test1', env
=env
)
494 self
.assertRegex(output
, 'MTU: 1600')
497 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
499 self
.wait_online(['test1:degraded'])
501 output
= check_output(*networkctl_cmd
, 'status', 'test1')
503 self
.assertRegex(output
, 'Type: ether')
505 output
= check_output(*networkctl_cmd
, 'status', 'lo')
507 self
.assertRegex(output
, 'Type: loopback')
509 @expectedFailureIfLinkFileFieldIsNotSet()
510 def test_udev_link_file(self
):
511 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
513 self
.wait_online(['test1:degraded'])
515 output
= check_output(*networkctl_cmd
, 'status', 'test1')
517 self
.assertRegex(output
, r
'Link File: (/usr)?/lib/systemd/network/99-default.link')
518 self
.assertRegex(output
, r
'Network File: /run/systemd/network/11-dummy.network')
520 output
= check_output(*networkctl_cmd
, 'status', 'lo')
522 self
.assertRegex(output
, r
'Link File: (/usr)?/lib/systemd/network/99-default.link')
523 self
.assertRegex(output
, r
'Network File: n/a')
525 def test_delete_links(self
):
526 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
527 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
530 self
.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
532 check_output(*networkctl_cmd
, 'delete', 'test1', 'veth99')
533 self
.assertFalse(link_exists('test1'))
534 self
.assertFalse(link_exists('veth99'))
535 self
.assertFalse(link_exists('veth-peer'))
537 class NetworkdNetDevTests(unittest
.TestCase
, Utilities
):
539 links_remove_earlier
= [
603 '10-dropin-test.netdev',
607 '13-not-match-udev-property.network',
608 '14-match-udev-property.network',
609 '15-name-conflict-test.netdev',
612 '21-vlan-test1.network',
615 '25-6rd-tunnel.netdev',
617 '25-bond-balanced-tlb.netdev',
619 '25-bridge-configure-without-carrier.network',
621 '25-erspan-tunnel-local-any.netdev',
622 '25-erspan-tunnel.netdev',
623 '25-fou-gretap.netdev',
625 '25-fou-ipip.netdev',
626 '25-fou-ipproto-gre.netdev',
627 '25-fou-ipproto-ipip.netdev',
630 '25-gretap-tunnel-local-any.netdev',
631 '25-gretap-tunnel.netdev',
632 '25-gre-tunnel-any-any.netdev',
633 '25-gre-tunnel-local-any.netdev',
634 '25-gre-tunnel-remote-any.netdev',
635 '25-gre-tunnel.netdev',
636 '25-ip6gretap-tunnel-local-any.netdev',
637 '25-ip6gretap-tunnel.netdev',
638 '25-ip6gre-tunnel-any-any.netdev',
639 '25-ip6gre-tunnel-local-any.netdev',
640 '25-ip6gre-tunnel-remote-any.netdev',
641 '25-ip6gre-tunnel.netdev',
642 '25-ip6tnl-tunnel-any-any.netdev',
643 '25-ip6tnl-tunnel-local-any.netdev',
644 '25-ip6tnl-tunnel-remote-any.netdev',
645 '25-ip6tnl-tunnel.netdev',
646 '25-ipip-tunnel-any-any.netdev',
647 '25-ipip-tunnel-independent.netdev',
648 '25-ipip-tunnel-independent-loopback.netdev',
649 '25-ipip-tunnel-local-any.netdev',
650 '25-ipip-tunnel-remote-any.netdev',
651 '25-ipip-tunnel.netdev',
654 '25-isatap-tunnel.netdev',
659 '25-sit-tunnel-any-any.netdev',
660 '25-sit-tunnel-local-any.netdev',
661 '25-sit-tunnel-remote-any.netdev',
662 '25-sit-tunnel.netdev',
665 '25-tunnel-local-any.network',
666 '25-tunnel-remote-any.network',
671 '25-vti6-tunnel-any-any.netdev',
672 '25-vti6-tunnel-local-any.netdev',
673 '25-vti6-tunnel-remote-any.netdev',
674 '25-vti6-tunnel.netdev',
675 '25-vti-tunnel-any-any.netdev',
676 '25-vti-tunnel-local-any.netdev',
677 '25-vti-tunnel-remote-any.netdev',
678 '25-vti-tunnel.netdev',
681 '25-wireguard-23-peers.netdev',
682 '25-wireguard-23-peers.network',
683 '25-wireguard-preshared-key.txt',
684 '25-wireguard-private-key.txt',
685 '25-wireguard.netdev',
686 '25-wireguard.network',
688 '25-xfrm-independent.netdev',
704 'netdev-link-local-addressing-yes.network',
708 'vxlan-test1.network',
718 remove_fou_ports(self
.fou_ports
)
719 remove_links(self
.links_remove_earlier
)
720 remove_links(self
.links
)
721 stop_networkd(show_logs
=False)
724 remove_fou_ports(self
.fou_ports
)
725 remove_links(self
.links_remove_earlier
)
726 remove_links(self
.links
)
727 remove_unit_from_networkd_path(self
.units
)
728 stop_networkd(show_logs
=True)
730 def test_dropin_and_name_conflict(self
):
731 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
734 self
.wait_online(['dropin-test:off'], setup_state
='unmanaged')
736 output
= check_output('ip link show dropin-test')
738 self
.assertRegex(output
, '00:50:56:c0:00:28')
740 def test_match_udev_property(self
):
741 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
743 self
.wait_online(['dummy98:routable'])
745 output
= check_output('networkctl status dummy98')
747 self
.assertRegex(output
, 'Network File: /run/systemd/network/14-match-udev-property')
749 def test_wait_online_any(self
):
750 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
753 self
.wait_online(['bridge99', 'test1:degraded'], bool_any
=True)
755 self
.check_operstate('bridge99', '(off|no-carrier)', setup_state
='configuring')
756 self
.check_operstate('test1', 'degraded')
758 def test_bridge(self
):
759 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
762 self
.wait_online(['bridge99:no-carrier'])
764 tick
= os
.sysconf('SC_CLK_TCK')
765 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick
))
766 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick
))
767 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick
))
768 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick
))
769 self
.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
770 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
771 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
772 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
773 self
.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
775 output
= check_output(*networkctl_cmd
, 'status', 'bridge99')
777 self
.assertRegex(output
, 'Priority: 9')
778 self
.assertRegex(output
, 'STP: yes')
779 self
.assertRegex(output
, 'Multicast IGMP Version: 3')
782 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
785 self
.wait_online(['bond99:off', 'bond98:off'], setup_state
='unmanaged')
787 self
.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
788 self
.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
789 self
.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
790 self
.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
791 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
792 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
793 self
.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
794 self
.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
795 self
.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
796 self
.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
797 self
.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
799 self
.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
800 self
.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
803 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
804 '21-vlan.network', '21-vlan-test1.network')
807 self
.wait_online(['test1:degraded', 'vlan99:routable'])
809 output
= check_output('ip -d link show test1')
811 self
.assertRegex(output
, ' mtu 2000 ')
813 output
= check_output('ip -d link show vlan99')
815 self
.assertRegex(output
, ' mtu 2000 ')
816 self
.assertRegex(output
, 'REORDER_HDR')
817 self
.assertRegex(output
, 'LOOSE_BINDING')
818 self
.assertRegex(output
, 'GVRP')
819 self
.assertRegex(output
, 'MVRP')
820 self
.assertRegex(output
, ' id 99 ')
822 output
= check_output('ip -4 address show dev test1')
824 self
.assertRegex(output
, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
825 self
.assertRegex(output
, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
827 output
= check_output('ip -4 address show dev vlan99')
829 self
.assertRegex(output
, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
831 def test_macvtap(self
):
832 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
833 with self
.subTest(mode
=mode
):
834 if mode
!= 'private':
836 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
837 '11-dummy.netdev', 'macvtap.network')
838 with
open(os
.path
.join(network_unit_file_path
, '21-macvtap.netdev'), mode
='a') as f
:
839 f
.write('[MACVTAP]\nMode=' + mode
)
842 self
.wait_online(['macvtap99:degraded', 'test1:degraded'])
844 output
= check_output('ip -d link show macvtap99')
846 self
.assertRegex(output
, 'macvtap mode ' + mode
+ ' ')
848 def test_macvlan(self
):
849 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
850 with self
.subTest(mode
=mode
):
851 if mode
!= 'private':
853 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
854 '11-dummy.netdev', 'macvlan.network')
855 with
open(os
.path
.join(network_unit_file_path
, '21-macvlan.netdev'), mode
='a') as f
:
856 f
.write('[MACVLAN]\nMode=' + mode
)
859 self
.wait_online(['macvlan99:degraded', 'test1:degraded'])
861 output
= check_output('ip -d link show test1')
863 self
.assertRegex(output
, ' mtu 2000 ')
865 output
= check_output('ip -d link show macvlan99')
867 self
.assertRegex(output
, ' mtu 2000 ')
868 self
.assertRegex(output
, 'macvlan mode ' + mode
+ ' ')
870 @expectedFailureIfModuleIsNotAvailable('ipvlan')
871 def test_ipvlan(self
):
872 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
873 with self
.subTest(mode
=mode
, flag
=flag
):
876 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
877 '11-dummy.netdev', 'ipvlan.network')
878 with
open(os
.path
.join(network_unit_file_path
, '25-ipvlan.netdev'), mode
='a') as f
:
879 f
.write('[IPVLAN]\nMode=' + mode
+ '\nFlags=' + flag
)
882 self
.wait_online(['ipvlan99:degraded', 'test1:degraded'])
884 output
= check_output('ip -d link show ipvlan99')
886 self
.assertRegex(output
, 'ipvlan *mode ' + mode
.lower() + ' ' + flag
)
888 @expectedFailureIfModuleIsNotAvailable('ipvtap')
889 def test_ipvtap(self
):
890 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
891 with self
.subTest(mode
=mode
, flag
=flag
):
894 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
895 '11-dummy.netdev', 'ipvtap.network')
896 with
open(os
.path
.join(network_unit_file_path
, '25-ipvtap.netdev'), mode
='a') as f
:
897 f
.write('[IPVTAP]\nMode=' + mode
+ '\nFlags=' + flag
)
900 self
.wait_online(['ipvtap99:degraded', 'test1:degraded'])
902 output
= check_output('ip -d link show ipvtap99')
904 self
.assertRegex(output
, 'ipvtap *mode ' + mode
.lower() + ' ' + flag
)
907 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
910 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
912 output
= check_output('ip -d link show veth99')
914 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bc')
915 output
= check_output('ip -d link show veth-peer')
917 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bd')
920 copy_unit_to_networkd_unit_path('25-tun.netdev')
923 self
.wait_online(['tun99:off'], setup_state
='unmanaged')
925 output
= check_output('ip -d link show tun99')
927 # Old ip command does not support IFF_ flags
928 self
.assertRegex(output
, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
931 copy_unit_to_networkd_unit_path('25-tap.netdev')
934 self
.wait_online(['tap99:off'], setup_state
='unmanaged')
936 output
= check_output('ip -d link show tap99')
938 # Old ip command does not support IFF_ flags
939 self
.assertRegex(output
, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
941 @expectedFailureIfModuleIsNotAvailable('vrf')
943 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
946 self
.wait_online(['vrf99:carrier'])
948 @expectedFailureIfModuleIsNotAvailable('vcan')
950 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
953 self
.wait_online(['vcan99:carrier'])
955 @expectedFailureIfModuleIsNotAvailable('vxcan')
956 def test_vxcan(self
):
957 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
960 self
.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
962 @expectedFailureIfModuleIsNotAvailable('wireguard')
963 def test_wireguard(self
):
964 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
965 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
966 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
968 self
.wait_online(['wg99:carrier', 'wg98:routable'])
970 if shutil
.which('wg'):
973 output
= check_output('wg show wg99 listen-port')
974 self
.assertRegex(output
, '51820')
975 output
= check_output('wg show wg99 fwmark')
976 self
.assertRegex(output
, '0x4d2')
977 output
= check_output('wg show wg99 allowed-ips')
978 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
979 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
980 output
= check_output('wg show wg99 persistent-keepalive')
981 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
982 output
= check_output('wg show wg99 endpoints')
983 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
984 output
= check_output('wg show wg99 private-key')
985 self
.assertRegex(output
, r
'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
986 output
= check_output('wg show wg99 preshared-keys')
987 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
988 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
990 output
= check_output('wg show wg98 private-key')
991 self
.assertRegex(output
, r
'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
993 def test_geneve(self
):
994 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
997 self
.wait_online(['geneve99:degraded'])
999 output
= check_output('ip -d link show geneve99')
1001 self
.assertRegex(output
, '192.168.22.1')
1002 self
.assertRegex(output
, '6082')
1003 self
.assertRegex(output
, 'udpcsum')
1004 self
.assertRegex(output
, 'udp6zerocsumrx')
1006 def test_ipip_tunnel(self
):
1007 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1008 '25-ipip-tunnel.netdev', '25-tunnel.network',
1009 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1010 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1011 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1013 self
.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1015 output
= check_output('ip -d link show ipiptun99')
1017 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1018 output
= check_output('ip -d link show ipiptun98')
1020 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
1021 output
= check_output('ip -d link show ipiptun97')
1023 self
.assertRegex(output
, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
1024 output
= check_output('ip -d link show ipiptun96')
1026 self
.assertRegex(output
, 'ipip (ipip )?remote any local any dev dummy98')
1028 def test_gre_tunnel(self
):
1029 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1030 '25-gre-tunnel.netdev', '25-tunnel.network',
1031 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1032 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1033 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1035 self
.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1037 output
= check_output('ip -d link show gretun99')
1039 self
.assertRegex(output
, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1040 self
.assertRegex(output
, 'ikey 1.2.3.103')
1041 self
.assertRegex(output
, 'okey 1.2.4.103')
1042 self
.assertRegex(output
, 'iseq')
1043 self
.assertRegex(output
, 'oseq')
1044 output
= check_output('ip -d link show gretun98')
1046 self
.assertRegex(output
, 'gre remote 10.65.223.239 local any dev dummy98')
1047 self
.assertRegex(output
, 'ikey 0.0.0.104')
1048 self
.assertRegex(output
, 'okey 0.0.0.104')
1049 self
.assertNotRegex(output
, 'iseq')
1050 self
.assertNotRegex(output
, 'oseq')
1051 output
= check_output('ip -d link show gretun97')
1053 self
.assertRegex(output
, 'gre remote any local 10.65.223.238 dev dummy98')
1054 self
.assertRegex(output
, 'ikey 0.0.0.105')
1055 self
.assertRegex(output
, 'okey 0.0.0.105')
1056 self
.assertNotRegex(output
, 'iseq')
1057 self
.assertNotRegex(output
, 'oseq')
1058 output
= check_output('ip -d link show gretun96')
1060 self
.assertRegex(output
, 'gre remote any local any dev dummy98')
1061 self
.assertRegex(output
, 'ikey 0.0.0.106')
1062 self
.assertRegex(output
, 'okey 0.0.0.106')
1063 self
.assertNotRegex(output
, 'iseq')
1064 self
.assertNotRegex(output
, 'oseq')
1066 def test_ip6gre_tunnel(self
):
1067 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1068 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1069 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1070 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1071 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1074 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1076 self
.check_link_exists('dummy98')
1077 self
.check_link_exists('ip6gretun99')
1078 self
.check_link_exists('ip6gretun98')
1079 self
.check_link_exists('ip6gretun97')
1080 self
.check_link_exists('ip6gretun96')
1082 output
= check_output('ip -d link show ip6gretun99')
1084 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1085 output
= check_output('ip -d link show ip6gretun98')
1087 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1088 output
= check_output('ip -d link show ip6gretun97')
1090 self
.assertRegex(output
, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1091 output
= check_output('ip -d link show ip6gretun96')
1093 self
.assertRegex(output
, 'ip6gre remote any local any dev dummy98')
1095 def test_gretap_tunnel(self
):
1096 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1097 '25-gretap-tunnel.netdev', '25-tunnel.network',
1098 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1100 self
.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1102 output
= check_output('ip -d link show gretap99')
1104 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1105 self
.assertRegex(output
, 'ikey 0.0.0.106')
1106 self
.assertRegex(output
, 'okey 0.0.0.106')
1107 self
.assertRegex(output
, 'iseq')
1108 self
.assertRegex(output
, 'oseq')
1109 output
= check_output('ip -d link show gretap98')
1111 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local any dev dummy98')
1112 self
.assertRegex(output
, 'ikey 0.0.0.107')
1113 self
.assertRegex(output
, 'okey 0.0.0.107')
1114 self
.assertRegex(output
, 'iseq')
1115 self
.assertRegex(output
, 'oseq')
1117 def test_ip6gretap_tunnel(self
):
1118 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1119 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1120 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1122 self
.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1124 output
= check_output('ip -d link show ip6gretap99')
1126 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1127 output
= check_output('ip -d link show ip6gretap98')
1129 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1131 def test_vti_tunnel(self
):
1132 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1133 '25-vti-tunnel.netdev', '25-tunnel.network',
1134 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1135 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1136 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1138 self
.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1140 output
= check_output('ip -d link show vtitun99')
1142 self
.assertRegex(output
, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1143 output
= check_output('ip -d link show vtitun98')
1145 self
.assertRegex(output
, 'vti remote 10.65.223.239 local any dev dummy98')
1146 output
= check_output('ip -d link show vtitun97')
1148 self
.assertRegex(output
, 'vti remote any local 10.65.223.238 dev dummy98')
1149 output
= check_output('ip -d link show vtitun96')
1151 self
.assertRegex(output
, 'vti remote any local any dev dummy98')
1153 def test_vti6_tunnel(self
):
1154 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1155 '25-vti6-tunnel.netdev', '25-tunnel.network',
1156 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1157 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1159 self
.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1161 output
= check_output('ip -d link show vti6tun99')
1163 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1164 output
= check_output('ip -d link show vti6tun98')
1166 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1167 output
= check_output('ip -d link show vti6tun97')
1169 self
.assertRegex(output
, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1171 def test_ip6tnl_tunnel(self
):
1172 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1173 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1174 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1175 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1177 self
.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1179 output
= check_output('ip -d link show ip6tnl99')
1181 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1182 output
= check_output('ip -d link show ip6tnl98')
1184 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1185 output
= check_output('ip -d link show ip6tnl97')
1187 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1189 def test_sit_tunnel(self
):
1190 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1191 '25-sit-tunnel.netdev', '25-tunnel.network',
1192 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1193 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1194 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1196 self
.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1198 output
= check_output('ip -d link show sittun99')
1200 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1201 output
= check_output('ip -d link show sittun98')
1203 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
1204 output
= check_output('ip -d link show sittun97')
1206 self
.assertRegex(output
, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
1207 output
= check_output('ip -d link show sittun96')
1209 self
.assertRegex(output
, "sit (ip6ip )?remote any local any dev dummy98")
1211 def test_isatap_tunnel(self
):
1212 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1213 '25-isatap-tunnel.netdev', '25-tunnel.network')
1215 self
.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1217 output
= check_output('ip -d link show isataptun99')
1219 self
.assertRegex(output
, "isatap ")
1221 def test_6rd_tunnel(self
):
1222 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1223 '25-6rd-tunnel.netdev', '25-tunnel.network')
1225 self
.wait_online(['sittun99:routable', 'dummy98:degraded'])
1227 output
= check_output('ip -d link show sittun99')
1229 self
.assertRegex(output
, '6rd-prefix 2602::/24')
1231 @expectedFailureIfERSPANModuleIsNotAvailable()
1232 def test_erspan_tunnel(self
):
1233 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1234 '25-erspan-tunnel.netdev', '25-tunnel.network',
1235 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1237 self
.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1239 output
= check_output('ip -d link show erspan99')
1241 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local 172.16.1.200')
1242 self
.assertRegex(output
, 'ikey 0.0.0.101')
1243 self
.assertRegex(output
, 'okey 0.0.0.101')
1244 self
.assertRegex(output
, 'iseq')
1245 self
.assertRegex(output
, 'oseq')
1246 output
= check_output('ip -d link show erspan98')
1248 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local any')
1249 self
.assertRegex(output
, '102')
1250 self
.assertRegex(output
, 'ikey 0.0.0.102')
1251 self
.assertRegex(output
, 'okey 0.0.0.102')
1252 self
.assertRegex(output
, 'iseq')
1253 self
.assertRegex(output
, 'oseq')
1255 def test_tunnel_independent(self
):
1256 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1259 self
.wait_online(['ipiptun99:carrier'])
1261 def test_tunnel_independent_loopback(self
):
1262 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1265 self
.wait_online(['ipiptun99:carrier'])
1267 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1268 def test_xfrm(self
):
1269 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1270 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1273 self
.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1275 output
= check_output('ip link show dev xfrm99')
1278 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1279 def test_xfrm_independent(self
):
1280 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1283 self
.wait_online(['xfrm99:degraded'])
1285 @expectedFailureIfModuleIsNotAvailable('fou')
1287 # The following redundant check is necessary for CentOS CI.
1288 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1289 self
.assertTrue(is_module_available('fou'))
1291 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1292 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1293 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1296 self
.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state
='unmanaged')
1298 output
= check_output('ip fou show')
1300 self
.assertRegex(output
, 'port 55555 ipproto 4')
1301 self
.assertRegex(output
, 'port 55556 ipproto 47')
1303 output
= check_output('ip -d link show ipiptun96')
1305 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1306 output
= check_output('ip -d link show sittun96')
1308 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1309 output
= check_output('ip -d link show gretun96')
1311 self
.assertRegex(output
, 'encap fou encap-sport 1001 encap-dport 55556')
1312 output
= check_output('ip -d link show gretap96')
1314 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55556')
1316 def test_vxlan(self
):
1317 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1318 '11-dummy.netdev', 'vxlan-test1.network')
1321 self
.wait_online(['test1:degraded', 'vxlan99:degraded'])
1323 output
= check_output('ip -d link show vxlan99')
1325 self
.assertRegex(output
, '999')
1326 self
.assertRegex(output
, '5555')
1327 self
.assertRegex(output
, 'l2miss')
1328 self
.assertRegex(output
, 'l3miss')
1329 self
.assertRegex(output
, 'udpcsum')
1330 self
.assertRegex(output
, 'udp6zerocsumtx')
1331 self
.assertRegex(output
, 'udp6zerocsumrx')
1332 self
.assertRegex(output
, 'remcsumtx')
1333 self
.assertRegex(output
, 'remcsumrx')
1334 self
.assertRegex(output
, 'gbp')
1336 output
= check_output('bridge fdb show dev vxlan99')
1338 self
.assertRegex(output
, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1339 self
.assertRegex(output
, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1340 self
.assertRegex(output
, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1342 output
= check_output(*networkctl_cmd
, 'status', 'vxlan99')
1344 self
.assertRegex(output
, 'VNI: 999')
1345 self
.assertRegex(output
, 'Destination Port: 5555')
1346 self
.assertRegex(output
, 'Underlying Device: test1')
1348 def test_macsec(self
):
1349 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1350 'macsec.network', '12-dummy.netdev')
1353 self
.wait_online(['dummy98:degraded', 'macsec99:routable'])
1355 output
= check_output('ip -d link show macsec99')
1357 self
.assertRegex(output
, 'macsec99@dummy98')
1358 self
.assertRegex(output
, 'macsec sci [0-9a-f]*000b')
1359 self
.assertRegex(output
, 'encrypt on')
1361 output
= check_output('ip macsec show macsec99')
1363 self
.assertRegex(output
, 'encrypt on')
1364 self
.assertRegex(output
, 'TXSC: [0-9a-f]*000b on SA 1')
1365 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1366 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1367 self
.assertRegex(output
, 'RXSC: c619528fe6a00100, state on')
1368 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1369 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1370 self
.assertRegex(output
, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1371 self
.assertRegex(output
, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1372 self
.assertNotRegex(output
, 'key 02030405067080900000000000000000')
1373 self
.assertRegex(output
, 'RXSC: 8c16456c83a90002, state on')
1374 self
.assertRegex(output
, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1376 def test_nlmon(self
):
1377 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1380 self
.wait_online(['nlmon99:carrier'])
1382 class NetworkdL2TPTests(unittest
.TestCase
, Utilities
):
1393 '25-l2tp-dummy.network',
1395 '25-l2tp-ip.netdev',
1396 '25-l2tp-udp.netdev']
1398 l2tp_tunnel_ids
= [ '10' ]
1401 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1402 remove_links(self
.links
)
1403 stop_networkd(show_logs
=False)
1406 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1407 remove_links(self
.links
)
1408 remove_unit_from_networkd_path(self
.units
)
1409 stop_networkd(show_logs
=True)
1411 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1412 def test_l2tp_udp(self
):
1413 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1414 '25-l2tp-udp.netdev', '25-l2tp.network')
1417 self
.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1419 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1421 self
.assertRegex(output
, "Tunnel 10, encap UDP")
1422 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1423 self
.assertRegex(output
, "Peer tunnel 11")
1424 self
.assertRegex(output
, "UDP source / dest ports: 3000/4000")
1425 self
.assertRegex(output
, "UDP checksum: enabled")
1427 output
= check_output('ip l2tp show session tid 10 session_id 15')
1429 self
.assertRegex(output
, "Session 15 in tunnel 10")
1430 self
.assertRegex(output
, "Peer session 16, tunnel 11")
1431 self
.assertRegex(output
, "interface name: l2tp-ses1")
1433 output
= check_output('ip l2tp show session tid 10 session_id 17')
1435 self
.assertRegex(output
, "Session 17 in tunnel 10")
1436 self
.assertRegex(output
, "Peer session 18, tunnel 11")
1437 self
.assertRegex(output
, "interface name: l2tp-ses2")
1439 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1440 def test_l2tp_ip(self
):
1441 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1442 '25-l2tp-ip.netdev', '25-l2tp.network')
1445 self
.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1447 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1449 self
.assertRegex(output
, "Tunnel 10, encap IP")
1450 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1451 self
.assertRegex(output
, "Peer tunnel 12")
1453 output
= check_output('ip l2tp show session tid 10 session_id 25')
1455 self
.assertRegex(output
, "Session 25 in tunnel 10")
1456 self
.assertRegex(output
, "Peer session 26, tunnel 12")
1457 self
.assertRegex(output
, "interface name: l2tp-ses3")
1459 output
= check_output('ip l2tp show session tid 10 session_id 27')
1461 self
.assertRegex(output
, "Session 27 in tunnel 10")
1462 self
.assertRegex(output
, "Peer session 28, tunnel 12")
1463 self
.assertRegex(output
, "interface name: l2tp-ses4")
1465 class NetworkdNetworkTests(unittest
.TestCase
, Utilities
):
1479 '23-active-slave.network',
1480 '24-keep-configuration-static.network',
1481 '24-search-domain.network',
1482 '25-address-link-section.network',
1483 '25-address-preferred-lifetime-zero.network',
1484 '25-address-static.network',
1485 '25-bind-carrier.network',
1486 '25-bond-active-backup-slave.netdev',
1487 '25-fibrule-invert.network',
1488 '25-fibrule-port-range.network',
1489 '25-gre-tunnel-remote-any.netdev',
1490 '25-ip6gre-tunnel-remote-any.netdev',
1491 '25-ipv6-address-label-section.network',
1492 '25-link-local-addressing-no.network',
1493 '25-link-local-addressing-yes.network',
1494 '25-link-section-unmanaged.network',
1495 '25-neighbor-section.network',
1496 '25-neighbor-next.network',
1497 '25-neighbor-ipv6.network',
1498 '25-neighbor-ip-dummy.network',
1499 '25-neighbor-ip.network',
1500 '25-nexthop.network',
1501 '25-qdisc-netem.network',
1502 '25-qdisc-tbf.network',
1503 '25-route-ipv6-src.network',
1504 '25-route-static.network',
1505 '25-gateway-static.network',
1506 '25-gateway-next-static.network',
1507 '25-sysctl-disable-ipv6.network',
1508 '25-sysctl.network',
1509 '25-veth-peer.network',
1511 '26-link-local-addressing-ipv6.network',
1512 'configure-without-carrier.network',
1513 'routing-policy-rule-dummy98.network',
1514 'routing-policy-rule-test1.network']
1516 routing_policy_rule_tables
= ['7', '8', '9']
1517 routes
= [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1520 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1521 remove_routes(self
.routes
)
1522 remove_links(self
.links
)
1523 stop_networkd(show_logs
=False)
1526 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1527 remove_routes(self
.routes
)
1528 remove_links(self
.links
)
1529 remove_unit_from_networkd_path(self
.units
)
1530 stop_networkd(show_logs
=True)
1532 def test_address_static(self
):
1533 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1536 self
.wait_online(['dummy98:routable'])
1538 output
= check_output('ip -4 address show dev dummy98')
1540 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1541 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1542 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1545 self
.assertNotRegex(output
, '10.10.0.1/16')
1546 self
.assertNotRegex(output
, '10.10.0.2/16')
1548 output
= check_output('ip -4 address show dev dummy98 label 32')
1549 self
.assertRegex(output
, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1551 output
= check_output('ip -4 address show dev dummy98 label 33')
1552 self
.assertRegex(output
, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1554 output
= check_output('ip -4 address show dev dummy98 label 34')
1555 self
.assertRegex(output
, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1557 output
= check_output('ip -4 address show dev dummy98 label 35')
1558 self
.assertRegex(output
, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1560 output
= check_output('ip -6 address show dev dummy98')
1562 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::15/64 scope global')
1563 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::16/64 scope global')
1564 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::15/64 scope global')
1565 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::16/64 scope global')
1566 self
.assertRegex(output
, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1567 self
.assertRegex(output
, 'inet6 fd[0-9a-f:]*1/64 scope global')
1569 def test_address_preferred_lifetime_zero_ipv6(self
):
1570 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1573 self
.wait_online(['dummy98:routable'])
1575 output
= check_output('ip address show dummy98')
1577 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1578 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::1/64 scope global')
1580 output
= check_output('ip route show dev dummy98')
1582 self
.assertRegex(output
, 'default via 20.20.20.1 proto static')
1584 def test_configure_without_carrier(self
):
1585 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1587 self
.wait_online(['test1:routable'])
1589 output
= check_output(*networkctl_cmd
, 'status', 'test1')
1591 self
.assertRegex(output
, '192.168.0.15')
1592 self
.assertRegex(output
, '192.168.0.1')
1593 self
.assertRegex(output
, 'routable')
1595 def test_routing_policy_rule(self
):
1596 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1598 self
.wait_online(['test1:degraded'])
1600 output
= check_output('ip rule list iif test1 priority 111')
1602 self
.assertRegex(output
, '111:')
1603 self
.assertRegex(output
, 'from 192.168.100.18')
1604 self
.assertRegex(output
, r
'tos (0x08|throughput)\s')
1605 self
.assertRegex(output
, 'iif test1')
1606 self
.assertRegex(output
, 'oif test1')
1607 self
.assertRegex(output
, 'lookup 7')
1609 output
= check_output('ip rule list iif test1 priority 101')
1611 self
.assertRegex(output
, '101:')
1612 self
.assertRegex(output
, 'from all')
1613 self
.assertRegex(output
, 'iif test1')
1614 self
.assertRegex(output
, 'lookup 9')
1616 output
= check_output('ip -6 rule list iif test1 priority 100')
1618 self
.assertRegex(output
, '100:')
1619 self
.assertRegex(output
, 'from all')
1620 self
.assertRegex(output
, 'iif test1')
1621 self
.assertRegex(output
, 'lookup 8')
1623 output
= check_output('ip -6 rule list iif test1 priority 101')
1625 self
.assertRegex(output
, '101:')
1626 self
.assertRegex(output
, 'from all')
1627 self
.assertRegex(output
, 'iif test1')
1628 self
.assertRegex(output
, 'lookup 9')
1630 def test_routing_policy_rule_issue_11280(self
):
1631 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1632 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1634 for trial
in range(3):
1635 # Remove state files only first time
1637 self
.wait_online(['test1:degraded', 'dummy98:degraded'])
1640 output
= check_output('ip rule list table 7')
1642 self
.assertRegex(output
, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1644 output
= check_output('ip rule list table 8')
1646 self
.assertRegex(output
, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1648 stop_networkd(remove_state_files
=False)
1650 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1651 def test_routing_policy_rule_port_range(self
):
1652 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1654 self
.wait_online(['test1:degraded'])
1656 output
= check_output('ip rule')
1658 self
.assertRegex(output
, '111')
1659 self
.assertRegex(output
, 'from 192.168.100.18')
1660 self
.assertRegex(output
, '1123-1150')
1661 self
.assertRegex(output
, '3224-3290')
1662 self
.assertRegex(output
, 'tcp')
1663 self
.assertRegex(output
, 'lookup 7')
1665 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1666 def test_routing_policy_rule_invert(self
):
1667 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1669 self
.wait_online(['test1:degraded'])
1671 output
= check_output('ip rule')
1673 self
.assertRegex(output
, '111')
1674 self
.assertRegex(output
, 'not.*?from.*?192.168.100.18')
1675 self
.assertRegex(output
, 'tcp')
1676 self
.assertRegex(output
, 'lookup 7')
1678 def test_route_static(self
):
1679 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1681 self
.wait_online(['dummy98:routable'])
1683 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
1686 print('### ip -6 route show dev dummy98')
1687 output
= check_output('ip -6 route show dev dummy98')
1689 self
.assertRegex(output
, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1690 self
.assertRegex(output
, '2001:1234:5:8f63::1 proto kernel')
1692 print('### ip -6 route show dev dummy98 default')
1693 output
= check_output('ip -6 route show dev dummy98 default')
1695 self
.assertRegex(output
, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1697 print('### ip -4 route show dev dummy98')
1698 output
= check_output('ip -4 route show dev dummy98')
1700 self
.assertRegex(output
, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1701 self
.assertRegex(output
, '149.10.124.64 proto static scope link')
1702 self
.assertRegex(output
, '169.254.0.0/16 proto static scope link metric 2048')
1703 self
.assertRegex(output
, '192.168.1.1 proto static initcwnd 20')
1704 self
.assertRegex(output
, '192.168.1.2 proto static initrwnd 30')
1705 self
.assertRegex(output
, 'multicast 149.10.123.4 proto static')
1707 print('### ip -4 route show dev dummy98 default')
1708 output
= check_output('ip -4 route show dev dummy98 default')
1710 self
.assertRegex(output
, 'default via 149.10.125.65 proto static onlink')
1711 self
.assertRegex(output
, 'default via 149.10.124.64 proto static')
1712 self
.assertRegex(output
, 'default proto static')
1714 print('### ip -4 route show table local dev dummy98')
1715 output
= check_output('ip -4 route show table local dev dummy98')
1717 self
.assertRegex(output
, 'local 149.10.123.1 proto static scope host')
1718 self
.assertRegex(output
, 'anycast 149.10.123.2 proto static scope link')
1719 self
.assertRegex(output
, 'broadcast 149.10.123.3 proto static scope link')
1721 print('### ip route show type blackhole')
1722 output
= check_output('ip route show type blackhole')
1724 self
.assertRegex(output
, 'blackhole 202.54.1.2 proto static')
1726 print('### ip route show type unreachable')
1727 output
= check_output('ip route show type unreachable')
1729 self
.assertRegex(output
, 'unreachable 202.54.1.3 proto static')
1731 print('### ip route show type prohibit')
1732 output
= check_output('ip route show type prohibit')
1734 self
.assertRegex(output
, 'prohibit 202.54.1.4 proto static')
1736 def test_gateway_reconfigure(self
):
1737 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1739 self
.wait_online(['dummy98:routable'])
1740 print('### ip -4 route show dev dummy98 default')
1741 output
= check_output('ip -4 route show dev dummy98 default')
1743 self
.assertRegex(output
, 'default via 149.10.124.59 proto static')
1744 self
.assertNotRegex(output
, '149.10.124.60')
1746 remove_unit_from_networkd_path(['25-gateway-static.network'])
1747 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1749 self
.wait_online(['dummy98:routable'])
1750 print('### ip -4 route show dev dummy98 default')
1751 output
= check_output('ip -4 route show dev dummy98 default')
1753 self
.assertNotRegex(output
, '149.10.124.59')
1754 self
.assertRegex(output
, 'default via 149.10.124.60 proto static')
1756 def test_ip_route_ipv6_src_route(self
):
1757 # a dummy device does not make the addresses go through tentative state, so we
1758 # reuse a bond from an earlier test, which does make the addresses go through
1759 # tentative state, and do our test on that
1760 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1762 self
.wait_online(['dummy98:enslaved', 'bond199:routable'])
1764 output
= check_output('ip -6 route list dev bond199')
1766 self
.assertRegex(output
, 'abcd::/16')
1767 self
.assertRegex(output
, 'src')
1768 self
.assertRegex(output
, '2001:1234:56:8f63::2')
1770 def test_ip_link_mac_address(self
):
1771 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1773 self
.wait_online(['dummy98:degraded'])
1775 output
= check_output('ip link show dummy98')
1777 self
.assertRegex(output
, '00:01:02:aa:bb:cc')
1779 def test_ip_link_unmanaged(self
):
1780 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1783 self
.check_link_exists('dummy98')
1785 self
.check_operstate('dummy98', 'off', setup_state
='unmanaged')
1787 def test_ipv6_address_label(self
):
1788 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1790 self
.wait_online(['dummy98:degraded'])
1792 output
= check_output('ip addrlabel list')
1794 self
.assertRegex(output
, '2004:da8:1::/64')
1796 def test_neighbor_section(self
):
1797 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1799 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1801 print('### ip neigh list dev dummy98')
1802 output
= check_output('ip neigh list dev dummy98')
1804 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1805 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1807 def test_neighbor_reconfigure(self
):
1808 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1810 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1812 print('### ip neigh list dev dummy98')
1813 output
= check_output('ip neigh list dev dummy98')
1815 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1816 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1818 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1819 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1821 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1822 print('### ip neigh list dev dummy98')
1823 output
= check_output('ip neigh list dev dummy98')
1825 self
.assertNotRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1826 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1827 self
.assertNotRegex(output
, '2004:da8:1::1.*PERMANENT')
1829 def test_neighbor_gre(self
):
1830 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1831 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1833 self
.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout
='40s')
1835 output
= check_output('ip neigh list dev gretun97')
1837 self
.assertRegex(output
, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1839 output
= check_output('ip neigh list dev ip6gretun97')
1841 self
.assertRegex(output
, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1843 def test_link_local_addressing(self
):
1844 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1845 '25-link-local-addressing-no.network', '12-dummy.netdev')
1847 self
.wait_online(['test1:degraded', 'dummy98:carrier'])
1849 output
= check_output('ip address show dev test1')
1851 self
.assertRegex(output
, 'inet .* scope link')
1852 self
.assertRegex(output
, 'inet6 .* scope link')
1854 output
= check_output('ip address show dev dummy98')
1856 self
.assertNotRegex(output
, 'inet6* .* scope link')
1859 Documentation/networking/ip-sysctl.txt
1861 addr_gen_mode - INTEGER
1862 Defines how link-local and autoconf addresses are generated.
1864 0: generate address based on EUI64 (default)
1865 1: do no generate a link-local address, use EUI64 for addresses generated
1867 2: generate stable privacy addresses, using the secret from
1868 stable_secret (RFC7217)
1869 3: generate stable privacy addresses, using a random secret if unset
1872 test1_addr_gen_mode
= ''
1873 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')):
1874 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')) as f
:
1878 # if stable_secret is unset, then EIO is returned
1879 test1_addr_gen_mode
= '0'
1881 test1_addr_gen_mode
= '2'
1883 test1_addr_gen_mode
= '0'
1885 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'addr_gen_mode')):
1886 self
.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode
)
1888 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'dummy98'), 'addr_gen_mode')):
1889 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1891 def test_link_local_addressing_remove_ipv6ll(self
):
1892 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1894 self
.wait_online(['dummy98:degraded'])
1896 output
= check_output('ip address show dev dummy98')
1898 self
.assertRegex(output
, 'inet6 .* scope link')
1900 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
1902 self
.wait_online(['dummy98:carrier'])
1904 output
= check_output('ip address show dev dummy98')
1906 self
.assertNotRegex(output
, 'inet6* .* scope link')
1908 def test_sysctl(self
):
1909 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1911 self
.wait_online(['dummy98:degraded'])
1913 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1914 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1915 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1916 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1917 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1918 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1919 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1921 def test_sysctl_disable_ipv6(self
):
1922 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1924 print('## Disable ipv6')
1925 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1926 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1929 self
.wait_online(['dummy98:routable'])
1931 output
= check_output('ip -4 address show dummy98')
1933 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1934 output
= check_output('ip -6 address show dummy98')
1936 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1937 self
.assertRegex(output
, 'inet6 .* scope link')
1938 output
= check_output('ip -4 route show dev dummy98')
1940 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1941 output
= check_output('ip -6 route show dev dummy98')
1943 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1945 check_output('ip link del dummy98')
1947 print('## Enable ipv6')
1948 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1949 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1952 self
.wait_online(['dummy98:routable'])
1954 output
= check_output('ip -4 address show dummy98')
1956 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1957 output
= check_output('ip -6 address show dummy98')
1959 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1960 self
.assertRegex(output
, 'inet6 .* scope link')
1961 output
= check_output('ip -4 route show dev dummy98')
1963 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1964 output
= check_output('ip -6 route show dev dummy98')
1966 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1968 def test_bind_carrier(self
):
1969 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1971 self
.wait_online(['test1:routable'])
1973 check_output('ip link add dummy98 type dummy')
1974 check_output('ip link set dummy98 up')
1976 output
= check_output('ip address show test1')
1978 self
.assertRegex(output
, 'UP,LOWER_UP')
1979 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1980 self
.check_operstate('test1', 'routable')
1982 check_output('ip link add dummy99 type dummy')
1983 check_output('ip link set dummy99 up')
1985 output
= check_output('ip address show test1')
1987 self
.assertRegex(output
, 'UP,LOWER_UP')
1988 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1989 self
.check_operstate('test1', 'routable')
1991 check_output('ip link del dummy98')
1993 output
= check_output('ip address show test1')
1995 self
.assertRegex(output
, 'UP,LOWER_UP')
1996 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1997 self
.check_operstate('test1', 'routable')
1999 check_output('ip link del dummy99')
2001 output
= check_output('ip address show test1')
2003 self
.assertNotRegex(output
, 'UP,LOWER_UP')
2004 self
.assertRegex(output
, 'DOWN')
2005 self
.assertNotRegex(output
, '192.168.10')
2006 self
.check_operstate('test1', 'off')
2008 check_output('ip link add dummy98 type dummy')
2009 check_output('ip link set dummy98 up')
2011 output
= check_output('ip address show test1')
2013 self
.assertRegex(output
, 'UP,LOWER_UP')
2014 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2015 self
.check_operstate('test1', 'routable')
2017 def test_domain(self
):
2018 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2020 self
.wait_online(['dummy98:routable'])
2022 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
2024 self
.assertRegex(output
, 'Address: 192.168.42.100')
2025 self
.assertRegex(output
, 'DNS: 192.168.42.1')
2026 self
.assertRegex(output
, 'Search Domains: one')
2028 def test_keep_configuration_static(self
):
2029 check_output('systemctl stop systemd-networkd')
2031 check_output('ip link add name dummy98 type dummy')
2032 check_output('ip address add 10.1.2.3/16 dev dummy98')
2033 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2034 output
= check_output('ip address show dummy98')
2036 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2037 self
.assertRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2038 output
= check_output('ip route show dev dummy98')
2041 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2043 self
.wait_online(['dummy98:routable'])
2045 output
= check_output('ip address show dummy98')
2047 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2048 self
.assertNotRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2050 @expectedFailureIfNexthopIsNotAvailable()
2051 def test_nexthop(self
):
2052 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2054 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2056 output
= check_output('ip nexthop list dev veth99')
2058 self
.assertRegex(output
, '192.168.5.1')
2060 def test_qdisc(self
):
2061 copy_unit_to_networkd_unit_path('25-qdisc-netem.network', '12-dummy.netdev',
2062 '25-qdisc-tbf.network', '11-dummy.netdev')
2065 self
.wait_online(['dummy98:routable', 'test1:routable'])
2067 output
= check_output('tc qdisc show dev dummy98')
2069 self
.assertRegex(output
, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2070 self
.assertRegex(output
, 'limit 200 delay 100.0ms 13.0ms loss 20.5%')
2071 output
= check_output('tc qdisc show dev test1')
2073 self
.assertRegex(output
, 'rate 500Kbit burst 5000b lat 70.0ms')
2075 class NetworkdStateFileTests(unittest
.TestCase
, Utilities
):
2082 'state-file-tests.network',
2086 remove_links(self
.links
)
2087 stop_networkd(show_logs
=False)
2090 remove_links(self
.links
)
2091 remove_unit_from_networkd_path(self
.units
)
2092 stop_networkd(show_logs
=True)
2094 def test_state_file(self
):
2095 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2097 self
.wait_online(['dummy98:routable'])
2099 output
= check_output(*networkctl_cmd
, '--no-legend', 'list', 'dummy98', env
=env
)
2101 ifindex
= output
.split()[0]
2103 path
= os
.path
.join('/run/systemd/netif/links/', ifindex
)
2104 self
.assertTrue(os
.path
.exists(path
))
2107 with
open(path
) as f
:
2109 self
.assertRegex(data
, r
'ADMIN_STATE=configured')
2110 self
.assertRegex(data
, r
'OPER_STATE=routable')
2111 self
.assertRegex(data
, r
'REQUIRED_FOR_ONLINE=yes')
2112 self
.assertRegex(data
, r
'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2113 self
.assertRegex(data
, r
'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2114 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2115 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2116 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2117 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2118 self
.assertRegex(data
, r
'LLMNR=no')
2119 self
.assertRegex(data
, r
'MDNS=yes')
2120 self
.assertRegex(data
, r
'DNSSEC=no')
2121 self
.assertRegex(data
, r
'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2123 check_output(*resolvectl_cmd
, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env
=env
)
2124 check_output(*resolvectl_cmd
, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env
=env
)
2125 check_output(*resolvectl_cmd
, 'llmnr', 'dummy98', 'yes', env
=env
)
2126 check_output(*resolvectl_cmd
, 'mdns', 'dummy98', 'no', env
=env
)
2127 check_output(*resolvectl_cmd
, 'dnssec', 'dummy98', 'yes', env
=env
)
2128 check_output(*timedatectl_cmd
, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env
=env
)
2131 with
open(path
) as f
:
2133 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2134 self
.assertRegex(data
, r
'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2135 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2136 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2137 self
.assertRegex(data
, r
'LLMNR=yes')
2138 self
.assertRegex(data
, r
'MDNS=no')
2139 self
.assertRegex(data
, r
'DNSSEC=yes')
2141 check_output(*timedatectl_cmd
, 'revert', 'dummy98', env
=env
)
2144 with
open(path
) as f
:
2146 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2147 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2148 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2149 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2150 self
.assertRegex(data
, r
'LLMNR=yes')
2151 self
.assertRegex(data
, r
'MDNS=no')
2152 self
.assertRegex(data
, r
'DNSSEC=yes')
2154 check_output(*resolvectl_cmd
, 'revert', 'dummy98', env
=env
)
2157 with
open(path
) as f
:
2159 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2160 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2161 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2162 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2163 self
.assertRegex(data
, r
'LLMNR=no')
2164 self
.assertRegex(data
, r
'MDNS=yes')
2165 self
.assertRegex(data
, r
'DNSSEC=no')
2167 class NetworkdBondTests(unittest
.TestCase
, Utilities
):
2177 '23-active-slave.network',
2178 '23-bond199.network',
2179 '23-primary-slave.network',
2180 '25-bond-active-backup-slave.netdev',
2183 'bond-slave.network']
2186 remove_links(self
.links
)
2187 stop_networkd(show_logs
=False)
2190 remove_links(self
.links
)
2191 remove_unit_from_networkd_path(self
.units
)
2192 stop_networkd(show_logs
=True)
2194 def test_bond_active_slave(self
):
2195 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2197 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2199 output
= check_output('ip -d link show bond199')
2201 self
.assertRegex(output
, 'active_slave dummy98')
2203 def test_bond_primary_slave(self
):
2204 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2206 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2208 output
= check_output('ip -d link show bond199')
2210 self
.assertRegex(output
, 'primary dummy98')
2212 def test_bond_operstate(self
):
2213 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2214 'bond99.network','bond-slave.network')
2216 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2218 output
= check_output('ip -d link show dummy98')
2220 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2222 output
= check_output('ip -d link show test1')
2224 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2226 output
= check_output('ip -d link show bond99')
2228 self
.assertRegex(output
, 'MASTER,UP,LOWER_UP')
2230 self
.check_operstate('dummy98', 'enslaved')
2231 self
.check_operstate('test1', 'enslaved')
2232 self
.check_operstate('bond99', 'routable')
2234 check_output('ip link set dummy98 down')
2237 self
.check_operstate('dummy98', 'off')
2238 self
.check_operstate('test1', 'enslaved')
2239 self
.check_operstate('bond99', 'degraded-carrier')
2241 check_output('ip link set dummy98 up')
2244 self
.check_operstate('dummy98', 'enslaved')
2245 self
.check_operstate('test1', 'enslaved')
2246 self
.check_operstate('bond99', 'routable')
2248 check_output('ip link set dummy98 down')
2249 check_output('ip link set test1 down')
2252 self
.check_operstate('dummy98', 'off')
2253 self
.check_operstate('test1', 'off')
2255 for trial
in range(30):
2258 output
= check_output('ip address show bond99')
2260 if get_operstate('bond99') == 'no-carrier':
2263 # Huh? Kernel does not recognize that all slave interfaces are down?
2264 # Let's confirm that networkd's operstate is consistent with ip's result.
2265 self
.assertNotRegex(output
, 'NO-CARRIER')
2267 class NetworkdBridgeTests(unittest
.TestCase
, Utilities
):
2277 '26-bridge-slave-interface-1.network',
2278 '26-bridge-slave-interface-2.network',
2279 '26-bridge-vlan-master.network',
2280 '26-bridge-vlan-slave.network',
2281 'bridge99-ignore-carrier-loss.network',
2284 routing_policy_rule_tables
= ['100']
2287 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2288 remove_links(self
.links
)
2289 stop_networkd(show_logs
=False)
2292 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2293 remove_links(self
.links
)
2294 remove_unit_from_networkd_path(self
.units
)
2295 stop_networkd(show_logs
=True)
2297 def test_bridge_vlan(self
):
2298 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2299 '26-bridge.netdev', '26-bridge-vlan-master.network')
2301 self
.wait_online(['test1:enslaved', 'bridge99:degraded'])
2303 output
= check_output('bridge vlan show dev test1')
2305 self
.assertNotRegex(output
, '4063')
2306 for i
in range(4064, 4095):
2307 self
.assertRegex(output
, f
'{i}')
2308 self
.assertNotRegex(output
, '4095')
2310 output
= check_output('bridge vlan show dev bridge99')
2312 self
.assertNotRegex(output
, '4059')
2313 for i
in range(4060, 4095):
2314 self
.assertRegex(output
, f
'{i}')
2315 self
.assertNotRegex(output
, '4095')
2317 def test_bridge_property(self
):
2318 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2319 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2322 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2324 output
= check_output('ip -d link show test1')
2326 self
.assertRegex(output
, 'master')
2327 self
.assertRegex(output
, 'bridge')
2329 output
= check_output('ip -d link show dummy98')
2331 self
.assertRegex(output
, 'master')
2332 self
.assertRegex(output
, 'bridge')
2334 output
= check_output('ip addr show bridge99')
2336 self
.assertRegex(output
, '192.168.0.15/24')
2338 output
= check_output('bridge -d link show dummy98')
2340 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2341 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2342 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2343 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2344 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2345 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2346 if (os
.path
.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2347 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2348 if (os
.path
.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2349 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2350 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2351 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2352 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2353 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2355 output
= check_output('bridge -d link show test1')
2357 self
.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2359 check_output('ip address add 192.168.0.16/24 dev bridge99')
2362 output
= check_output('ip addr show bridge99')
2364 self
.assertRegex(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 pref medium')
2372 self
.assertEqual(call('ip link del test1'), 0)
2375 self
.check_operstate('bridge99', 'degraded-carrier')
2377 check_output('ip link del dummy98')
2380 self
.check_operstate('bridge99', 'no-carrier')
2382 output
= check_output('ip address show bridge99')
2384 self
.assertRegex(output
, 'NO-CARRIER')
2385 self
.assertNotRegex(output
, '192.168.0.15/24')
2386 self
.assertNotRegex(output
, '192.168.0.16/24')
2388 print('### ip -6 route list table all dev bridge99')
2389 output
= check_output('ip -6 route list table all dev bridge99')
2391 self
.assertRegex(output
, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2393 def test_bridge_ignore_carrier_loss(self
):
2394 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2395 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2396 'bridge99-ignore-carrier-loss.network')
2398 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2400 check_output('ip address add 192.168.0.16/24 dev bridge99')
2403 check_output('ip link del test1')
2404 check_output('ip link del dummy98')
2407 output
= check_output('ip address show bridge99')
2409 self
.assertRegex(output
, 'NO-CARRIER')
2410 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2411 self
.assertRegex(output
, 'inet 192.168.0.16/24 scope global secondary bridge99')
2413 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self
):
2414 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2415 'bridge99-ignore-carrier-loss.network')
2417 self
.wait_online(['bridge99:no-carrier'])
2419 for trial
in range(4):
2420 check_output('ip link add dummy98 type dummy')
2421 check_output('ip link set dummy98 up')
2423 check_output('ip link del dummy98')
2425 self
.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2427 output
= check_output('ip address show bridge99')
2429 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2431 output
= check_output('ip rule list table 100')
2433 self
.assertEqual(output
, '0: from all to 8.8.8.8 lookup 100')
2435 class NetworkdLLDPTests(unittest
.TestCase
, Utilities
):
2439 '23-emit-lldp.network',
2444 remove_links(self
.links
)
2445 stop_networkd(show_logs
=False)
2448 remove_links(self
.links
)
2449 remove_unit_from_networkd_path(self
.units
)
2450 stop_networkd(show_logs
=True)
2452 def test_lldp(self
):
2453 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2455 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2457 output
= check_output(*networkctl_cmd
, 'lldp', env
=env
)
2459 self
.assertRegex(output
, 'veth-peer')
2460 self
.assertRegex(output
, 'veth99')
2462 class NetworkdRATests(unittest
.TestCase
, Utilities
):
2467 'ipv6-prefix.network',
2468 'ipv6-prefix-veth.network']
2471 remove_links(self
.links
)
2472 stop_networkd(show_logs
=False)
2475 remove_links(self
.links
)
2476 remove_unit_from_networkd_path(self
.units
)
2477 stop_networkd(show_logs
=True)
2479 def test_ipv6_prefix_delegation(self
):
2480 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2482 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2484 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2486 self
.assertRegex(output
, '2002:da8:1:0')
2488 class NetworkdDHCPServerTests(unittest
.TestCase
, Utilities
):
2493 'dhcp-client.network',
2494 'dhcp-client-timezone-router.network',
2495 'dhcp-server.network',
2496 'dhcp-server-timezone-router.network']
2499 remove_links(self
.links
)
2500 stop_networkd(show_logs
=False)
2503 remove_links(self
.links
)
2504 remove_unit_from_networkd_path(self
.units
)
2505 stop_networkd(show_logs
=True)
2507 def test_dhcp_server(self
):
2508 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2510 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2512 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2514 self
.assertRegex(output
, '192.168.5.*')
2515 self
.assertRegex(output
, 'Gateway: 192.168.5.1')
2516 self
.assertRegex(output
, 'DNS: 192.168.5.1')
2517 self
.assertRegex(output
, 'NTP: 192.168.5.1')
2519 def test_emit_router_timezone(self
):
2520 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2522 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2524 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2526 self
.assertRegex(output
, 'Gateway: 192.168.5.*')
2527 self
.assertRegex(output
, '192.168.5.*')
2528 self
.assertRegex(output
, 'Europe/Berlin')
2530 class NetworkdDHCPClientTests(unittest
.TestCase
, Utilities
):
2539 'dhcp-client-anonymize.network',
2540 'dhcp-client-gateway-onlink-implicit.network',
2541 'dhcp-client-ipv4-dhcp-settings.network',
2542 'dhcp-client-ipv4-only-ipv6-disabled.network',
2543 'dhcp-client-ipv4-only.network',
2544 'dhcp-client-ipv6-only.network',
2545 'dhcp-client-ipv6-rapid-commit.network',
2546 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2547 'dhcp-client-keep-configuration-dhcp.network',
2548 'dhcp-client-listen-port.network',
2549 'dhcp-client-reassign-static-routes-ipv4.network',
2550 'dhcp-client-reassign-static-routes-ipv6.network',
2551 'dhcp-client-route-metric.network',
2552 'dhcp-client-route-table.network',
2553 'dhcp-client-use-dns-ipv4-and-ra.network',
2554 'dhcp-client-use-dns-ipv4.network',
2555 'dhcp-client-use-dns-no.network',
2556 'dhcp-client-use-dns-yes.network',
2557 'dhcp-client-use-domains.network',
2558 'dhcp-client-use-routes-no.network',
2559 'dhcp-client-vrf.network',
2560 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2561 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2562 'dhcp-client-with-static-address.network',
2563 'dhcp-client.network',
2564 'dhcp-server-veth-peer.network',
2565 'dhcp-v4-server-veth-peer.network',
2566 'dhcp-client-use-domains.network',
2570 stop_dnsmasq(dnsmasq_pid_file
)
2571 remove_links(self
.links
)
2572 stop_networkd(show_logs
=False)
2575 stop_dnsmasq(dnsmasq_pid_file
)
2578 remove_links(self
.links
)
2579 remove_unit_from_networkd_path(self
.units
)
2580 stop_networkd(show_logs
=True)
2582 def test_dhcp_client_ipv6_only(self
):
2583 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2586 self
.wait_online(['veth-peer:carrier'])
2588 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2590 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2592 self
.assertRegex(output
, '2600::')
2593 self
.assertNotRegex(output
, '192.168.5')
2595 # Confirm that ipv6 token is not set in the kernel
2596 output
= check_output('ip token show dev veth99')
2598 self
.assertRegex(output
, 'token :: dev veth99')
2600 def test_dhcp_client_ipv4_only(self
):
2601 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2604 self
.wait_online(['veth-peer:carrier'])
2605 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
2606 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2608 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2610 self
.assertNotRegex(output
, '2600::')
2611 self
.assertRegex(output
, '192.168.5')
2612 self
.assertRegex(output
, '192.168.5.6')
2613 self
.assertRegex(output
, '192.168.5.7')
2615 # checking routes to DNS servers
2616 output
= check_output('ip route show dev veth99')
2618 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2619 self
.assertRegex(output
, r
'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2620 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2622 stop_dnsmasq(dnsmasq_pid_file
)
2623 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time
='2m')
2625 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2626 print('Wait for the dynamic address to be renewed')
2629 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2631 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2633 self
.assertNotRegex(output
, '2600::')
2634 self
.assertRegex(output
, '192.168.5')
2635 self
.assertNotRegex(output
, '192.168.5.6')
2636 self
.assertRegex(output
, '192.168.5.7')
2637 self
.assertRegex(output
, '192.168.5.8')
2639 # checking routes to DNS servers
2640 output
= check_output('ip route show dev veth99')
2642 self
.assertNotRegex(output
, r
'192.168.5.6')
2643 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2644 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2645 self
.assertRegex(output
, r
'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2647 def test_dhcp_client_ipv4_ipv6(self
):
2648 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2649 'dhcp-client-ipv4-only.network')
2651 self
.wait_online(['veth-peer:carrier'])
2653 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2655 # link become 'routable' when at least one protocol provide an valid address.
2656 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2657 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2659 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2661 self
.assertRegex(output
, '2600::')
2662 self
.assertRegex(output
, '192.168.5')
2664 def test_dhcp_client_settings(self
):
2665 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2668 self
.wait_online(['veth-peer:carrier'])
2670 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2672 print('## ip address show dev veth99')
2673 output
= check_output('ip address show dev veth99')
2675 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2676 self
.assertRegex(output
, '192.168.5')
2677 self
.assertRegex(output
, '1492')
2679 print('## ip route show table main dev veth99')
2680 output
= check_output('ip route show table main dev veth99')
2683 main_table_is_empty
= output
== ''
2684 if not main_table_is_empty
:
2685 self
.assertNotRegex(output
, 'proto dhcp')
2687 print('## ip route show table 211 dev veth99')
2688 output
= check_output('ip route show table 211 dev veth99')
2690 self
.assertRegex(output
, 'default via 192.168.5.1 proto dhcp')
2691 if main_table_is_empty
:
2692 self
.assertRegex(output
, '192.168.5.0/24 proto dhcp')
2693 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2694 self
.assertRegex(output
, '192.168.5.1 proto dhcp scope link')
2696 print('## dnsmasq log')
2697 self
.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2698 self
.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2699 self
.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2700 self
.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2702 def test_dhcp6_client_settings_rapidcommit_true(self
):
2703 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2705 self
.wait_online(['veth-peer:carrier'])
2707 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2709 output
= check_output('ip address show dev veth99')
2711 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2712 self
.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2714 def test_dhcp6_client_settings_rapidcommit_false(self
):
2715 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2717 self
.wait_online(['veth-peer:carrier'])
2719 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2721 output
= check_output('ip address show dev veth99')
2723 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2724 self
.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2726 def test_dhcp_client_settings_anonymize(self
):
2727 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2729 self
.wait_online(['veth-peer:carrier'])
2731 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2733 self
.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2734 self
.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2735 self
.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2737 def test_dhcp_client_listen_port(self
):
2738 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2740 self
.wait_online(['veth-peer:carrier'])
2741 start_dnsmasq('--dhcp-alternate-port=67,5555')
2742 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2744 output
= check_output('ip -4 address show dev veth99')
2746 self
.assertRegex(output
, '192.168.5.* dynamic')
2748 def test_dhcp_client_with_static_address(self
):
2749 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2750 'dhcp-client-with-static-address.network')
2752 self
.wait_online(['veth-peer:carrier'])
2754 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2756 output
= check_output('ip address show dev veth99 scope global')
2758 self
.assertRegex(output
, r
'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2759 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2761 output
= check_output('ip route show dev veth99')
2763 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2764 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2765 self
.assertRegex(output
, r
'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2766 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2768 def test_dhcp_route_table_id(self
):
2769 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2771 self
.wait_online(['veth-peer:carrier'])
2773 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2775 output
= check_output('ip route show table 12')
2777 self
.assertRegex(output
, 'veth99 proto dhcp')
2778 self
.assertRegex(output
, '192.168.5.1')
2780 def test_dhcp_route_metric(self
):
2781 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2783 self
.wait_online(['veth-peer:carrier'])
2785 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2787 output
= check_output('ip route show dev veth99')
2789 self
.assertRegex(output
, 'metric 24')
2791 def test_dhcp_client_reassign_static_routes_ipv4(self
):
2792 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2793 'dhcp-client-reassign-static-routes-ipv4.network')
2795 self
.wait_online(['veth-peer:carrier'])
2796 start_dnsmasq(lease_time
='2m')
2797 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2799 output
= check_output('ip address show dev veth99 scope global')
2801 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2803 output
= check_output('ip route show dev veth99')
2805 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2806 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2807 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2808 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2810 stop_dnsmasq(dnsmasq_pid_file
)
2811 start_dnsmasq(ipv4_range
='192.168.5.210,192.168.5.220', lease_time
='2m')
2813 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2814 print('Wait for the dynamic address to be renewed')
2817 self
.wait_online(['veth99:routable'])
2819 output
= check_output('ip route show dev veth99')
2821 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2822 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2823 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2824 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2826 def test_dhcp_client_reassign_static_routes_ipv6(self
):
2827 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2828 'dhcp-client-reassign-static-routes-ipv6.network')
2830 self
.wait_online(['veth-peer:carrier'])
2831 start_dnsmasq(lease_time
='2m')
2832 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2834 output
= check_output('ip address show dev veth99 scope global')
2836 self
.assertRegex(output
, r
'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
2838 output
= check_output('ip -6 route show dev veth99')
2840 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2841 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2843 stop_dnsmasq(dnsmasq_pid_file
)
2844 start_dnsmasq(ipv6_range
='2600::30,2600::40', lease_time
='2m')
2846 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2847 print('Wait for the dynamic address to be renewed')
2850 self
.wait_online(['veth99:routable'])
2852 output
= check_output('ip -6 route show dev veth99')
2854 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2855 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2857 def test_dhcp_keep_configuration_dhcp(self
):
2858 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2860 self
.wait_online(['veth-peer:carrier'])
2861 start_dnsmasq(lease_time
='2m')
2862 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2864 output
= check_output('ip address show dev veth99 scope global')
2866 self
.assertRegex(output
, r
'192.168.5.*')
2868 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2870 self
.assertRegex(output
, r
'192.168.5.*')
2872 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2873 stop_dnsmasq(dnsmasq_pid_file
)
2875 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2876 print('Wait for the dynamic address to be expired')
2879 print('The lease address should be kept after lease expired')
2880 output
= check_output('ip address show dev veth99 scope global')
2882 self
.assertRegex(output
, r
'192.168.5.*')
2884 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2886 self
.assertRegex(output
, r
'192.168.5.*')
2888 check_output('systemctl stop systemd-networkd')
2890 print('The lease address should be kept after networkd stopped')
2891 output
= check_output('ip address show dev veth99 scope global')
2893 self
.assertRegex(output
, r
'192.168.5.*')
2895 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2897 self
.assertRegex(output
, r
'192.168.5.*')
2900 self
.wait_online(['veth-peer:routable'])
2902 print('Still the lease address should be kept after networkd restarted')
2903 output
= check_output('ip address show dev veth99 scope global')
2905 self
.assertRegex(output
, r
'192.168.5.*')
2907 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2909 self
.assertRegex(output
, r
'192.168.5.*')
2911 def test_dhcp_keep_configuration_dhcp_on_stop(self
):
2912 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2914 self
.wait_online(['veth-peer:carrier'])
2915 start_dnsmasq(lease_time
='2m')
2916 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2918 output
= check_output('ip address show dev veth99 scope global')
2920 self
.assertRegex(output
, r
'192.168.5.*')
2922 stop_dnsmasq(dnsmasq_pid_file
)
2923 check_output('systemctl stop systemd-networkd')
2925 output
= check_output('ip address show dev veth99 scope global')
2927 self
.assertRegex(output
, r
'192.168.5.*')
2930 self
.wait_online(['veth-peer:routable'])
2932 output
= check_output('ip address show dev veth99 scope global')
2934 self
.assertNotRegex(output
, r
'192.168.5.*')
2936 def test_dhcp_client_reuse_address_as_static(self
):
2937 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2939 self
.wait_online(['veth-peer:carrier'])
2941 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2943 # link become 'routable' when at least one protocol provide an valid address.
2944 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2945 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2947 output
= check_output('ip address show dev veth99 scope global')
2949 self
.assertRegex(output
, '192.168.5')
2950 self
.assertRegex(output
, '2600::')
2952 ipv4_address
= re
.search(r
'192.168.5.[0-9]*/24', output
)
2953 ipv6_address
= re
.search(r
'2600::[0-9a-f:]*/128', output
)
2954 static_network
= '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address
.group(), 'Address=' + ipv6_address
.group()])
2955 print(static_network
)
2957 remove_unit_from_networkd_path(['dhcp-client.network'])
2959 with
open(os
.path
.join(network_unit_file_path
, 'static.network'), mode
='w') as f
:
2960 f
.write(static_network
)
2962 # When networkd started, the links are already configured, so let's wait for 5 seconds
2963 # the links to be re-configured.
2965 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2967 output
= check_output('ip -4 address show dev veth99 scope global')
2969 self
.assertRegex(output
, '192.168.5')
2970 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2972 output
= check_output('ip -6 address show dev veth99 scope global')
2974 self
.assertRegex(output
, '2600::')
2975 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2977 @expectedFailureIfModuleIsNotAvailable('vrf')
2978 def test_dhcp_client_vrf(self
):
2979 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2980 '25-vrf.netdev', '25-vrf.network')
2982 self
.wait_online(['veth-peer:carrier'])
2984 self
.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2986 # link become 'routable' when at least one protocol provide an valid address.
2987 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2988 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2990 print('## ip -d link show dev vrf99')
2991 output
= check_output('ip -d link show dev vrf99')
2993 self
.assertRegex(output
, 'vrf table 42')
2995 print('## ip address show vrf vrf99')
2996 output
= check_output('ip address show vrf vrf99')
2998 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2999 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3000 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3001 self
.assertRegex(output
, 'inet6 .* scope link')
3003 print('## ip address show dev veth99')
3004 output
= check_output('ip address show dev veth99')
3006 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3007 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3008 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3009 self
.assertRegex(output
, 'inet6 .* scope link')
3011 print('## ip route show vrf vrf99')
3012 output
= check_output('ip route show vrf vrf99')
3014 self
.assertRegex(output
, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3015 self
.assertRegex(output
, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3016 self
.assertRegex(output
, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3017 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3018 self
.assertRegex(output
, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3020 print('## ip route show table main dev veth99')
3021 output
= check_output('ip route show table main dev veth99')
3023 self
.assertEqual(output
, '')
3025 def test_dhcp_client_gateway_onlink_implicit(self
):
3026 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3027 'dhcp-client-gateway-onlink-implicit.network')
3029 self
.wait_online(['veth-peer:carrier'])
3031 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3033 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3035 self
.assertRegex(output
, '192.168.5')
3037 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3039 self
.assertRegex(output
, 'onlink')
3040 output
= check_output('ip route list dev veth99 192.168.100.0/24')
3042 self
.assertRegex(output
, 'onlink')
3044 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self
):
3045 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3046 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3048 self
.wait_online(['veth-peer:carrier'])
3049 start_dnsmasq(lease_time
='2m')
3050 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3052 output
= check_output('ip address show dev veth99')
3055 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3056 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3057 output
= check_output('ip -6 address show dev veth99 scope link')
3058 self
.assertRegex(output
, 'inet6 .* scope link')
3059 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3060 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3061 output
= check_output('ip -4 address show dev veth99 scope link')
3062 self
.assertNotRegex(output
, 'inet .* scope link')
3064 print('Wait for the dynamic address to be expired')
3067 output
= check_output('ip address show dev veth99')
3070 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3071 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3072 output
= check_output('ip -6 address show dev veth99 scope link')
3073 self
.assertRegex(output
, 'inet6 .* scope link')
3074 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3075 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3076 output
= check_output('ip -4 address show dev veth99 scope link')
3077 self
.assertNotRegex(output
, 'inet .* scope link')
3079 search_words_in_dnsmasq_log('DHCPOFFER', show_all
=True)
3081 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self
):
3082 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3083 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3085 self
.wait_online(['veth99:degraded', 'veth-peer:routable'])
3087 output
= check_output('ip address show dev veth99')
3090 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3091 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3092 output
= check_output('ip -6 address show dev veth99 scope link')
3093 self
.assertRegex(output
, 'inet6 .* scope link')
3094 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3095 self
.assertNotRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3096 output
= check_output('ip -4 address show dev veth99 scope link')
3097 self
.assertRegex(output
, 'inet .* scope link')
3099 def test_dhcp_client_route_remove_on_renew(self
):
3100 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3101 'dhcp-client-ipv4-only-ipv6-disabled.network')
3103 self
.wait_online(['veth-peer:carrier'])
3104 start_dnsmasq(ipv4_range
='192.168.5.100,192.168.5.199', lease_time
='2m')
3105 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3107 # test for issue #12490
3109 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3111 self
.assertRegex(output
, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3113 for line
in output
.splitlines():
3114 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3115 address1
= line
.split()[1].split('/')[0]
3118 output
= check_output('ip -4 route show dev veth99')
3120 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3121 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3123 stop_dnsmasq(dnsmasq_pid_file
)
3124 start_dnsmasq(ipv4_range
='192.168.5.200,192.168.5.250', lease_time
='2m')
3126 print('Wait for the dynamic address to be expired')
3129 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3131 self
.assertRegex(output
, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3133 for line
in output
.splitlines():
3134 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3135 address2
= line
.split()[1].split('/')[0]
3138 self
.assertNotEqual(address1
, address2
)
3140 output
= check_output('ip -4 route show dev veth99')
3142 self
.assertNotRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3143 self
.assertNotRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3144 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3145 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3147 def test_dhcp_client_use_dns_yes(self
):
3148 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3151 self
.wait_online(['veth-peer:carrier'])
3152 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3153 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3155 # link become 'routable' when at least one protocol provide an valid address.
3156 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3157 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3160 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3162 self
.assertRegex(output
, '192.168.5.1')
3163 self
.assertRegex(output
, '2600::1')
3165 def test_dhcp_client_use_dns_no(self
):
3166 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3169 self
.wait_online(['veth-peer:carrier'])
3170 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3171 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3173 # link become 'routable' when at least one protocol provide an valid address.
3174 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3175 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3178 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3180 self
.assertNotRegex(output
, '192.168.5.1')
3181 self
.assertNotRegex(output
, '2600::1')
3183 def test_dhcp_client_use_dns_ipv4(self
):
3184 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3187 self
.wait_online(['veth-peer:carrier'])
3188 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3189 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3191 # link become 'routable' when at least one protocol provide an valid address.
3192 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3193 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3196 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3198 self
.assertRegex(output
, '192.168.5.1')
3199 self
.assertNotRegex(output
, '2600::1')
3201 def test_dhcp_client_use_dns_ipv4_and_ra(self
):
3202 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3205 self
.wait_online(['veth-peer:carrier'])
3206 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3207 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3209 # link become 'routable' when at least one protocol provide an valid address.
3210 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3211 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3214 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3216 self
.assertRegex(output
, '192.168.5.1')
3217 self
.assertRegex(output
, '2600::1')
3219 def test_dhcp_client_use_domains(self
):
3220 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3223 self
.wait_online(['veth-peer:carrier'])
3224 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3225 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3227 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3229 self
.assertRegex(output
, 'Search Domains: example.com')
3232 output
= check_output(*resolvectl_cmd
, 'domain', 'veth99', env
=env
)
3234 self
.assertRegex(output
, 'example.com')
3236 class NetworkdIPv6PrefixTests(unittest
.TestCase
, Utilities
):
3241 'ipv6ra-prefix-client.network',
3242 'ipv6ra-prefix.network'
3246 remove_links(self
.links
)
3247 stop_networkd(show_logs
=False)
3251 remove_links(self
.links
)
3252 remove_unit_from_networkd_path(self
.units
)
3253 stop_networkd(show_logs
=True)
3255 def test_ipv6_route_prefix(self
):
3256 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3259 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3261 output
= check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3263 self
.assertRegex(output
, '2001:db8:0:1::/64 proto ra')
3265 if __name__
== '__main__':
3266 parser
= argparse
.ArgumentParser()
3267 parser
.add_argument('--build-dir', help='Path to build dir', dest
='build_dir')
3268 parser
.add_argument('--networkd', help='Path to systemd-networkd', dest
='networkd_bin')
3269 parser
.add_argument('--resolved', help='Path to systemd-resolved', dest
='resolved_bin')
3270 parser
.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest
='wait_online_bin')
3271 parser
.add_argument('--networkctl', help='Path to networkctl', dest
='networkctl_bin')
3272 parser
.add_argument('--resolvectl', help='Path to resolvectl', dest
='resolvectl_bin')
3273 parser
.add_argument('--timedatectl', help='Path to timedatectl', dest
='timedatectl_bin')
3274 parser
.add_argument('--valgrind', help='Enable valgrind', dest
='use_valgrind', type=bool, nargs
='?', const
=True, default
=use_valgrind
)
3275 parser
.add_argument('--debug', help='Generate debugging logs', dest
='enable_debug', type=bool, nargs
='?', const
=True, default
=enable_debug
)
3276 parser
.add_argument('--asan-options', help='ASAN options', dest
='asan_options')
3277 parser
.add_argument('--lsan-options', help='LSAN options', dest
='lsan_options')
3278 parser
.add_argument('--ubsan-options', help='UBSAN options', dest
='ubsan_options')
3279 ns
, args
= parser
.parse_known_args(namespace
=unittest
)
3282 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
:
3283 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3284 networkd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd')
3285 resolved_bin
= os
.path
.join(ns
.build_dir
, 'systemd-resolved')
3286 wait_online_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd-wait-online')
3287 networkctl_bin
= os
.path
.join(ns
.build_dir
, 'networkctl')
3288 resolvectl_bin
= os
.path
.join(ns
.build_dir
, 'resolvectl')
3289 timedatectl_bin
= os
.path
.join(ns
.build_dir
, 'timedatectl')
3292 networkd_bin
= ns
.networkd_bin
3294 resolved_bin
= ns
.resolved_bin
3295 if ns
.wait_online_bin
:
3296 wait_online_bin
= ns
.wait_online_bin
3297 if ns
.networkctl_bin
:
3298 networkctl_bin
= ns
.networkctl_bin
3299 if ns
.resolvectl_bin
:
3300 resolvectl_bin
= ns
.resolvectl_bin
3301 if ns
.timedatectl_bin
:
3302 timedatectl_bin
= ns
.timedatectl_bin
3304 use_valgrind
= ns
.use_valgrind
3305 enable_debug
= ns
.enable_debug
3306 asan_options
= ns
.asan_options
3307 lsan_options
= ns
.lsan_options
3308 ubsan_options
= ns
.ubsan_options
3311 networkctl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin
]
3312 resolvectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin
]
3313 timedatectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin
]
3314 wait_online_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin
]
3316 networkctl_cmd
= [networkctl_bin
]
3317 resolvectl_cmd
= [resolvectl_bin
]
3318 timedatectl_cmd
= [timedatectl_bin
]
3319 wait_online_cmd
= [wait_online_bin
]
3322 env
.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3324 env
.update({ 'ASAN_OPTIONS' : asan_options
})
3326 env
.update({ 'LSAN_OPTIONS' : lsan_options
})
3328 env
.update({ 'UBSAN_OPTIONS' : ubsan_options
})
3331 unittest
.main(testRunner
=unittest
.TextTestRunner(stream
=sys
.stdout
,