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
= [
604 '10-dropin-test.netdev',
608 '13-not-match-udev-property.network',
609 '14-match-udev-property.network',
610 '15-name-conflict-test.netdev',
613 '21-vlan-test1.network',
616 '25-6rd-tunnel.netdev',
618 '25-bond-balanced-tlb.netdev',
620 '25-bridge-configure-without-carrier.network',
622 '25-erspan-tunnel-local-any.netdev',
623 '25-erspan-tunnel.netdev',
624 '25-fou-gretap.netdev',
626 '25-fou-ipip.netdev',
627 '25-fou-ipproto-gre.netdev',
628 '25-fou-ipproto-ipip.netdev',
631 '25-gretap-tunnel-local-any.netdev',
632 '25-gretap-tunnel.netdev',
633 '25-gre-tunnel-any-any.netdev',
634 '25-gre-tunnel-local-any.netdev',
635 '25-gre-tunnel-remote-any.netdev',
636 '25-gre-tunnel.netdev',
638 '25-ip6gretap-tunnel-local-any.netdev',
639 '25-ip6gretap-tunnel.netdev',
640 '25-ip6gre-tunnel-any-any.netdev',
641 '25-ip6gre-tunnel-local-any.netdev',
642 '25-ip6gre-tunnel-remote-any.netdev',
643 '25-ip6gre-tunnel.netdev',
644 '25-ip6tnl-tunnel-any-any.netdev',
645 '25-ip6tnl-tunnel-local-any.netdev',
646 '25-ip6tnl-tunnel-remote-any.netdev',
647 '25-ip6tnl-tunnel.netdev',
648 '25-ipip-tunnel-any-any.netdev',
649 '25-ipip-tunnel-independent.netdev',
650 '25-ipip-tunnel-independent-loopback.netdev',
651 '25-ipip-tunnel-local-any.netdev',
652 '25-ipip-tunnel-remote-any.netdev',
653 '25-ipip-tunnel.netdev',
656 '25-isatap-tunnel.netdev',
661 '25-sit-tunnel-any-any.netdev',
662 '25-sit-tunnel-local-any.netdev',
663 '25-sit-tunnel-remote-any.netdev',
664 '25-sit-tunnel.netdev',
667 '25-tunnel-local-any.network',
668 '25-tunnel-remote-any.network',
673 '25-vti6-tunnel-any-any.netdev',
674 '25-vti6-tunnel-local-any.netdev',
675 '25-vti6-tunnel-remote-any.netdev',
676 '25-vti6-tunnel.netdev',
677 '25-vti-tunnel-any-any.netdev',
678 '25-vti-tunnel-local-any.netdev',
679 '25-vti-tunnel-remote-any.netdev',
680 '25-vti-tunnel.netdev',
683 '25-wireguard-23-peers.netdev',
684 '25-wireguard-23-peers.network',
685 '25-wireguard-preshared-key.txt',
686 '25-wireguard-private-key.txt',
687 '25-wireguard.netdev',
688 '25-wireguard.network',
690 '25-xfrm-independent.netdev',
706 'netdev-link-local-addressing-yes.network',
710 'vxlan-test1.network',
720 remove_fou_ports(self
.fou_ports
)
721 remove_links(self
.links_remove_earlier
)
722 remove_links(self
.links
)
723 stop_networkd(show_logs
=False)
726 remove_fou_ports(self
.fou_ports
)
727 remove_links(self
.links_remove_earlier
)
728 remove_links(self
.links
)
729 remove_unit_from_networkd_path(self
.units
)
730 stop_networkd(show_logs
=True)
732 def test_dropin_and_name_conflict(self
):
733 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
736 self
.wait_online(['dropin-test:off'], setup_state
='unmanaged')
738 output
= check_output('ip link show dropin-test')
740 self
.assertRegex(output
, '00:50:56:c0:00:28')
742 def test_match_udev_property(self
):
743 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
745 self
.wait_online(['dummy98:routable'])
747 output
= check_output('networkctl status dummy98')
749 self
.assertRegex(output
, 'Network File: /run/systemd/network/14-match-udev-property')
751 def test_wait_online_any(self
):
752 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
755 self
.wait_online(['bridge99', 'test1:degraded'], bool_any
=True)
757 self
.check_operstate('bridge99', '(off|no-carrier)', setup_state
='configuring')
758 self
.check_operstate('test1', 'degraded')
760 def test_bridge(self
):
761 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
764 self
.wait_online(['bridge99:no-carrier'])
766 tick
= os
.sysconf('SC_CLK_TCK')
767 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick
))
768 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick
))
769 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick
))
770 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick
))
771 self
.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
772 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
773 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
774 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
775 self
.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
777 output
= check_output(*networkctl_cmd
, 'status', 'bridge99')
779 self
.assertRegex(output
, 'Priority: 9')
780 self
.assertRegex(output
, 'STP: yes')
781 self
.assertRegex(output
, 'Multicast IGMP Version: 3')
784 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
787 self
.wait_online(['bond99:off', 'bond98:off'], setup_state
='unmanaged')
789 self
.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
790 self
.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
791 self
.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
792 self
.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
793 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
794 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
795 self
.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
796 self
.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
797 self
.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
798 self
.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
799 self
.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
801 self
.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
802 self
.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
805 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
806 '21-vlan.network', '21-vlan-test1.network')
809 self
.wait_online(['test1:degraded', 'vlan99:routable'])
811 output
= check_output('ip -d link show test1')
813 self
.assertRegex(output
, ' mtu 2000 ')
815 output
= check_output('ip -d link show vlan99')
817 self
.assertRegex(output
, ' mtu 2000 ')
818 self
.assertRegex(output
, 'REORDER_HDR')
819 self
.assertRegex(output
, 'LOOSE_BINDING')
820 self
.assertRegex(output
, 'GVRP')
821 self
.assertRegex(output
, 'MVRP')
822 self
.assertRegex(output
, ' id 99 ')
824 output
= check_output('ip -4 address show dev test1')
826 self
.assertRegex(output
, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
827 self
.assertRegex(output
, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
829 output
= check_output('ip -4 address show dev vlan99')
831 self
.assertRegex(output
, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
833 def test_macvtap(self
):
834 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
835 with self
.subTest(mode
=mode
):
836 if mode
!= 'private':
838 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
839 '11-dummy.netdev', 'macvtap.network')
840 with
open(os
.path
.join(network_unit_file_path
, '21-macvtap.netdev'), mode
='a') as f
:
841 f
.write('[MACVTAP]\nMode=' + mode
)
844 self
.wait_online(['macvtap99:degraded', 'test1:degraded'])
846 output
= check_output('ip -d link show macvtap99')
848 self
.assertRegex(output
, 'macvtap mode ' + mode
+ ' ')
850 def test_macvlan(self
):
851 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
852 with self
.subTest(mode
=mode
):
853 if mode
!= 'private':
855 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
856 '11-dummy.netdev', 'macvlan.network')
857 with
open(os
.path
.join(network_unit_file_path
, '21-macvlan.netdev'), mode
='a') as f
:
858 f
.write('[MACVLAN]\nMode=' + mode
)
861 self
.wait_online(['macvlan99:degraded', 'test1:degraded'])
863 output
= check_output('ip -d link show test1')
865 self
.assertRegex(output
, ' mtu 2000 ')
867 output
= check_output('ip -d link show macvlan99')
869 self
.assertRegex(output
, ' mtu 2000 ')
870 self
.assertRegex(output
, 'macvlan mode ' + mode
+ ' ')
872 @expectedFailureIfModuleIsNotAvailable('ipvlan')
873 def test_ipvlan(self
):
874 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
875 with self
.subTest(mode
=mode
, flag
=flag
):
878 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
879 '11-dummy.netdev', 'ipvlan.network')
880 with
open(os
.path
.join(network_unit_file_path
, '25-ipvlan.netdev'), mode
='a') as f
:
881 f
.write('[IPVLAN]\nMode=' + mode
+ '\nFlags=' + flag
)
884 self
.wait_online(['ipvlan99:degraded', 'test1:degraded'])
886 output
= check_output('ip -d link show ipvlan99')
888 self
.assertRegex(output
, 'ipvlan *mode ' + mode
.lower() + ' ' + flag
)
890 @expectedFailureIfModuleIsNotAvailable('ipvtap')
891 def test_ipvtap(self
):
892 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
893 with self
.subTest(mode
=mode
, flag
=flag
):
896 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
897 '11-dummy.netdev', 'ipvtap.network')
898 with
open(os
.path
.join(network_unit_file_path
, '25-ipvtap.netdev'), mode
='a') as f
:
899 f
.write('[IPVTAP]\nMode=' + mode
+ '\nFlags=' + flag
)
902 self
.wait_online(['ipvtap99:degraded', 'test1:degraded'])
904 output
= check_output('ip -d link show ipvtap99')
906 self
.assertRegex(output
, 'ipvtap *mode ' + mode
.lower() + ' ' + flag
)
909 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
912 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
914 output
= check_output('ip -d link show veth99')
916 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bc')
917 output
= check_output('ip -d link show veth-peer')
919 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bd')
922 copy_unit_to_networkd_unit_path('25-tun.netdev')
925 self
.wait_online(['tun99:off'], setup_state
='unmanaged')
927 output
= check_output('ip -d link show tun99')
929 # Old ip command does not support IFF_ flags
930 self
.assertRegex(output
, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
933 copy_unit_to_networkd_unit_path('25-tap.netdev')
936 self
.wait_online(['tap99:off'], setup_state
='unmanaged')
938 output
= check_output('ip -d link show tap99')
940 # Old ip command does not support IFF_ flags
941 self
.assertRegex(output
, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
943 @expectedFailureIfModuleIsNotAvailable('vrf')
945 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
948 self
.wait_online(['vrf99:carrier'])
950 @expectedFailureIfModuleIsNotAvailable('vcan')
952 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
955 self
.wait_online(['vcan99:carrier'])
957 @expectedFailureIfModuleIsNotAvailable('vxcan')
958 def test_vxcan(self
):
959 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
962 self
.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
964 @expectedFailureIfModuleIsNotAvailable('wireguard')
965 def test_wireguard(self
):
966 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
967 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
968 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
970 self
.wait_online(['wg99:carrier', 'wg98:routable'])
972 if shutil
.which('wg'):
975 output
= check_output('wg show wg99 listen-port')
976 self
.assertRegex(output
, '51820')
977 output
= check_output('wg show wg99 fwmark')
978 self
.assertRegex(output
, '0x4d2')
979 output
= check_output('wg show wg99 allowed-ips')
980 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
981 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
982 output
= check_output('wg show wg99 persistent-keepalive')
983 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
984 output
= check_output('wg show wg99 endpoints')
985 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
986 output
= check_output('wg show wg99 private-key')
987 self
.assertRegex(output
, r
'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
988 output
= check_output('wg show wg99 preshared-keys')
989 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
990 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
992 output
= check_output('wg show wg98 private-key')
993 self
.assertRegex(output
, r
'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
995 def test_geneve(self
):
996 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
999 self
.wait_online(['geneve99:degraded'])
1001 output
= check_output('ip -d link show geneve99')
1003 self
.assertRegex(output
, '192.168.22.1')
1004 self
.assertRegex(output
, '6082')
1005 self
.assertRegex(output
, 'udpcsum')
1006 self
.assertRegex(output
, 'udp6zerocsumrx')
1008 def test_ipip_tunnel(self
):
1009 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1010 '25-ipip-tunnel.netdev', '25-tunnel.network',
1011 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1012 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1013 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1015 self
.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1017 output
= check_output('ip -d link show ipiptun99')
1019 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1020 output
= check_output('ip -d link show ipiptun98')
1022 self
.assertRegex(output
, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
1023 output
= check_output('ip -d link show ipiptun97')
1025 self
.assertRegex(output
, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
1026 output
= check_output('ip -d link show ipiptun96')
1028 self
.assertRegex(output
, 'ipip (ipip )?remote any local any dev dummy98')
1030 def test_gre_tunnel(self
):
1031 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1032 '25-gre-tunnel.netdev', '25-tunnel.network',
1033 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1034 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1035 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1037 self
.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1039 output
= check_output('ip -d link show gretun99')
1041 self
.assertRegex(output
, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1042 self
.assertRegex(output
, 'ikey 1.2.3.103')
1043 self
.assertRegex(output
, 'okey 1.2.4.103')
1044 self
.assertRegex(output
, 'iseq')
1045 self
.assertRegex(output
, 'oseq')
1046 output
= check_output('ip -d link show gretun98')
1048 self
.assertRegex(output
, 'gre remote 10.65.223.239 local any dev dummy98')
1049 self
.assertRegex(output
, 'ikey 0.0.0.104')
1050 self
.assertRegex(output
, 'okey 0.0.0.104')
1051 self
.assertNotRegex(output
, 'iseq')
1052 self
.assertNotRegex(output
, 'oseq')
1053 output
= check_output('ip -d link show gretun97')
1055 self
.assertRegex(output
, 'gre remote any local 10.65.223.238 dev dummy98')
1056 self
.assertRegex(output
, 'ikey 0.0.0.105')
1057 self
.assertRegex(output
, 'okey 0.0.0.105')
1058 self
.assertNotRegex(output
, 'iseq')
1059 self
.assertNotRegex(output
, 'oseq')
1060 output
= check_output('ip -d link show gretun96')
1062 self
.assertRegex(output
, 'gre remote any local any dev dummy98')
1063 self
.assertRegex(output
, 'ikey 0.0.0.106')
1064 self
.assertRegex(output
, 'okey 0.0.0.106')
1065 self
.assertNotRegex(output
, 'iseq')
1066 self
.assertNotRegex(output
, 'oseq')
1068 def test_ip6gre_tunnel(self
):
1069 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1070 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1071 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1072 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1073 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1076 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1078 self
.check_link_exists('dummy98')
1079 self
.check_link_exists('ip6gretun99')
1080 self
.check_link_exists('ip6gretun98')
1081 self
.check_link_exists('ip6gretun97')
1082 self
.check_link_exists('ip6gretun96')
1084 output
= check_output('ip -d link show ip6gretun99')
1086 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1087 output
= check_output('ip -d link show ip6gretun98')
1089 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1090 output
= check_output('ip -d link show ip6gretun97')
1092 self
.assertRegex(output
, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1093 output
= check_output('ip -d link show ip6gretun96')
1095 self
.assertRegex(output
, 'ip6gre remote any local any dev dummy98')
1097 def test_gretap_tunnel(self
):
1098 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1099 '25-gretap-tunnel.netdev', '25-tunnel.network',
1100 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1102 self
.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1104 output
= check_output('ip -d link show gretap99')
1106 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1107 self
.assertRegex(output
, 'ikey 0.0.0.106')
1108 self
.assertRegex(output
, 'okey 0.0.0.106')
1109 self
.assertRegex(output
, 'iseq')
1110 self
.assertRegex(output
, 'oseq')
1111 output
= check_output('ip -d link show gretap98')
1113 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local any dev dummy98')
1114 self
.assertRegex(output
, 'ikey 0.0.0.107')
1115 self
.assertRegex(output
, 'okey 0.0.0.107')
1116 self
.assertRegex(output
, 'iseq')
1117 self
.assertRegex(output
, 'oseq')
1119 def test_ip6gretap_tunnel(self
):
1120 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1121 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1122 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1124 self
.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1126 output
= check_output('ip -d link show ip6gretap99')
1128 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1129 output
= check_output('ip -d link show ip6gretap98')
1131 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1133 def test_vti_tunnel(self
):
1134 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1135 '25-vti-tunnel.netdev', '25-tunnel.network',
1136 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1137 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1138 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1140 self
.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1142 output
= check_output('ip -d link show vtitun99')
1144 self
.assertRegex(output
, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1145 output
= check_output('ip -d link show vtitun98')
1147 self
.assertRegex(output
, 'vti remote 10.65.223.239 local any dev dummy98')
1148 output
= check_output('ip -d link show vtitun97')
1150 self
.assertRegex(output
, 'vti remote any local 10.65.223.238 dev dummy98')
1151 output
= check_output('ip -d link show vtitun96')
1153 self
.assertRegex(output
, 'vti remote any local any dev dummy98')
1155 def test_vti6_tunnel(self
):
1156 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1157 '25-vti6-tunnel.netdev', '25-tunnel.network',
1158 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1159 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1161 self
.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1163 output
= check_output('ip -d link show vti6tun99')
1165 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1166 output
= check_output('ip -d link show vti6tun98')
1168 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1169 output
= check_output('ip -d link show vti6tun97')
1171 self
.assertRegex(output
, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1173 def test_ip6tnl_tunnel(self
):
1174 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1175 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1176 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1177 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1179 self
.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1181 output
= check_output('ip -d link show ip6tnl99')
1183 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1184 output
= check_output('ip -d link show ip6tnl98')
1186 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1187 output
= check_output('ip -d link show ip6tnl97')
1189 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1191 def test_sit_tunnel(self
):
1192 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1193 '25-sit-tunnel.netdev', '25-tunnel.network',
1194 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1195 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1196 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1198 self
.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1200 output
= check_output('ip -d link show sittun99')
1202 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1203 output
= check_output('ip -d link show sittun98')
1205 self
.assertRegex(output
, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
1206 output
= check_output('ip -d link show sittun97')
1208 self
.assertRegex(output
, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
1209 output
= check_output('ip -d link show sittun96')
1211 self
.assertRegex(output
, "sit (ip6ip )?remote any local any dev dummy98")
1213 def test_isatap_tunnel(self
):
1214 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1215 '25-isatap-tunnel.netdev', '25-tunnel.network')
1217 self
.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1219 output
= check_output('ip -d link show isataptun99')
1221 self
.assertRegex(output
, "isatap ")
1223 def test_6rd_tunnel(self
):
1224 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1225 '25-6rd-tunnel.netdev', '25-tunnel.network')
1227 self
.wait_online(['sittun99:routable', 'dummy98:degraded'])
1229 output
= check_output('ip -d link show sittun99')
1231 self
.assertRegex(output
, '6rd-prefix 2602::/24')
1233 @expectedFailureIfERSPANModuleIsNotAvailable()
1234 def test_erspan_tunnel(self
):
1235 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1236 '25-erspan-tunnel.netdev', '25-tunnel.network',
1237 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1239 self
.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1241 output
= check_output('ip -d link show erspan99')
1243 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local 172.16.1.200')
1244 self
.assertRegex(output
, 'ikey 0.0.0.101')
1245 self
.assertRegex(output
, 'okey 0.0.0.101')
1246 self
.assertRegex(output
, 'iseq')
1247 self
.assertRegex(output
, 'oseq')
1248 output
= check_output('ip -d link show erspan98')
1250 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local any')
1251 self
.assertRegex(output
, '102')
1252 self
.assertRegex(output
, 'ikey 0.0.0.102')
1253 self
.assertRegex(output
, 'okey 0.0.0.102')
1254 self
.assertRegex(output
, 'iseq')
1255 self
.assertRegex(output
, 'oseq')
1257 def test_tunnel_independent(self
):
1258 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1261 self
.wait_online(['ipiptun99:carrier'])
1263 def test_tunnel_independent_loopback(self
):
1264 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1267 self
.wait_online(['ipiptun99:carrier'])
1269 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1270 def test_xfrm(self
):
1271 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1272 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1275 self
.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1277 output
= check_output('ip link show dev xfrm99')
1280 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1281 def test_xfrm_independent(self
):
1282 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1285 self
.wait_online(['xfrm99:degraded'])
1287 @expectedFailureIfModuleIsNotAvailable('fou')
1289 # The following redundant check is necessary for CentOS CI.
1290 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1291 self
.assertTrue(is_module_available('fou'))
1293 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1294 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1295 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1298 self
.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state
='unmanaged')
1300 output
= check_output('ip fou show')
1302 self
.assertRegex(output
, 'port 55555 ipproto 4')
1303 self
.assertRegex(output
, 'port 55556 ipproto 47')
1305 output
= check_output('ip -d link show ipiptun96')
1307 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1308 output
= check_output('ip -d link show sittun96')
1310 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1311 output
= check_output('ip -d link show gretun96')
1313 self
.assertRegex(output
, 'encap fou encap-sport 1001 encap-dport 55556')
1314 output
= check_output('ip -d link show gretap96')
1316 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55556')
1318 def test_vxlan(self
):
1319 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1320 '11-dummy.netdev', 'vxlan-test1.network')
1323 self
.wait_online(['test1:degraded', 'vxlan99:degraded'])
1325 output
= check_output('ip -d link show vxlan99')
1327 self
.assertRegex(output
, '999')
1328 self
.assertRegex(output
, '5555')
1329 self
.assertRegex(output
, 'l2miss')
1330 self
.assertRegex(output
, 'l3miss')
1331 self
.assertRegex(output
, 'udpcsum')
1332 self
.assertRegex(output
, 'udp6zerocsumtx')
1333 self
.assertRegex(output
, 'udp6zerocsumrx')
1334 self
.assertRegex(output
, 'remcsumtx')
1335 self
.assertRegex(output
, 'remcsumrx')
1336 self
.assertRegex(output
, 'gbp')
1338 output
= check_output('bridge fdb show dev vxlan99')
1340 self
.assertRegex(output
, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1341 self
.assertRegex(output
, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1342 self
.assertRegex(output
, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1344 output
= check_output(*networkctl_cmd
, 'status', 'vxlan99')
1346 self
.assertRegex(output
, 'VNI: 999')
1347 self
.assertRegex(output
, 'Destination Port: 5555')
1348 self
.assertRegex(output
, 'Underlying Device: test1')
1350 def test_macsec(self
):
1351 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1352 'macsec.network', '12-dummy.netdev')
1355 self
.wait_online(['dummy98:degraded', 'macsec99:routable'])
1357 output
= check_output('ip -d link show macsec99')
1359 self
.assertRegex(output
, 'macsec99@dummy98')
1360 self
.assertRegex(output
, 'macsec sci [0-9a-f]*000b')
1361 self
.assertRegex(output
, 'encrypt on')
1363 output
= check_output('ip macsec show macsec99')
1365 self
.assertRegex(output
, 'encrypt on')
1366 self
.assertRegex(output
, 'TXSC: [0-9a-f]*000b on SA 1')
1367 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1368 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1369 self
.assertRegex(output
, 'RXSC: c619528fe6a00100, state on')
1370 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1371 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1372 self
.assertRegex(output
, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1373 self
.assertRegex(output
, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1374 self
.assertNotRegex(output
, 'key 02030405067080900000000000000000')
1375 self
.assertRegex(output
, 'RXSC: 8c16456c83a90002, state on')
1376 self
.assertRegex(output
, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1378 def test_nlmon(self
):
1379 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1382 self
.wait_online(['nlmon99:carrier'])
1384 @expectedFailureIfModuleIsNotAvailable('ifb')
1386 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1389 self
.wait_online(['ifb99:degraded'])
1391 class NetworkdL2TPTests(unittest
.TestCase
, Utilities
):
1402 '25-l2tp-dummy.network',
1404 '25-l2tp-ip.netdev',
1405 '25-l2tp-udp.netdev']
1407 l2tp_tunnel_ids
= [ '10' ]
1410 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1411 remove_links(self
.links
)
1412 stop_networkd(show_logs
=False)
1415 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1416 remove_links(self
.links
)
1417 remove_unit_from_networkd_path(self
.units
)
1418 stop_networkd(show_logs
=True)
1420 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1421 def test_l2tp_udp(self
):
1422 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1423 '25-l2tp-udp.netdev', '25-l2tp.network')
1426 self
.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1428 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1430 self
.assertRegex(output
, "Tunnel 10, encap UDP")
1431 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1432 self
.assertRegex(output
, "Peer tunnel 11")
1433 self
.assertRegex(output
, "UDP source / dest ports: 3000/4000")
1434 self
.assertRegex(output
, "UDP checksum: enabled")
1436 output
= check_output('ip l2tp show session tid 10 session_id 15')
1438 self
.assertRegex(output
, "Session 15 in tunnel 10")
1439 self
.assertRegex(output
, "Peer session 16, tunnel 11")
1440 self
.assertRegex(output
, "interface name: l2tp-ses1")
1442 output
= check_output('ip l2tp show session tid 10 session_id 17')
1444 self
.assertRegex(output
, "Session 17 in tunnel 10")
1445 self
.assertRegex(output
, "Peer session 18, tunnel 11")
1446 self
.assertRegex(output
, "interface name: l2tp-ses2")
1448 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1449 def test_l2tp_ip(self
):
1450 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1451 '25-l2tp-ip.netdev', '25-l2tp.network')
1454 self
.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1456 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1458 self
.assertRegex(output
, "Tunnel 10, encap IP")
1459 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1460 self
.assertRegex(output
, "Peer tunnel 12")
1462 output
= check_output('ip l2tp show session tid 10 session_id 25')
1464 self
.assertRegex(output
, "Session 25 in tunnel 10")
1465 self
.assertRegex(output
, "Peer session 26, tunnel 12")
1466 self
.assertRegex(output
, "interface name: l2tp-ses3")
1468 output
= check_output('ip l2tp show session tid 10 session_id 27')
1470 self
.assertRegex(output
, "Session 27 in tunnel 10")
1471 self
.assertRegex(output
, "Peer session 28, tunnel 12")
1472 self
.assertRegex(output
, "interface name: l2tp-ses4")
1474 class NetworkdNetworkTests(unittest
.TestCase
, Utilities
):
1488 '23-active-slave.network',
1489 '24-keep-configuration-static.network',
1490 '24-search-domain.network',
1491 '25-address-link-section.network',
1492 '25-address-preferred-lifetime-zero.network',
1493 '25-address-static.network',
1494 '25-bind-carrier.network',
1495 '25-bond-active-backup-slave.netdev',
1496 '25-fibrule-invert.network',
1497 '25-fibrule-port-range.network',
1498 '25-gre-tunnel-remote-any.netdev',
1499 '25-ip6gre-tunnel-remote-any.netdev',
1500 '25-ipv6-address-label-section.network',
1501 '25-link-local-addressing-no.network',
1502 '25-link-local-addressing-yes.network',
1503 '25-link-section-unmanaged.network',
1504 '25-neighbor-section.network',
1505 '25-neighbor-next.network',
1506 '25-neighbor-ipv6.network',
1507 '25-neighbor-ip-dummy.network',
1508 '25-neighbor-ip.network',
1509 '25-nexthop.network',
1510 '25-qdisc-netem.network',
1511 '25-qdisc-tbf-and-sfq.network',
1512 '25-route-ipv6-src.network',
1513 '25-route-static.network',
1514 '25-gateway-static.network',
1515 '25-gateway-next-static.network',
1516 '25-sysctl-disable-ipv6.network',
1517 '25-sysctl.network',
1518 '25-veth-peer.network',
1520 '26-link-local-addressing-ipv6.network',
1521 'configure-without-carrier.network',
1522 'routing-policy-rule-dummy98.network',
1523 'routing-policy-rule-test1.network']
1525 routing_policy_rule_tables
= ['7', '8', '9']
1526 routes
= [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1529 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1530 remove_routes(self
.routes
)
1531 remove_links(self
.links
)
1532 stop_networkd(show_logs
=False)
1535 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1536 remove_routes(self
.routes
)
1537 remove_links(self
.links
)
1538 remove_unit_from_networkd_path(self
.units
)
1539 stop_networkd(show_logs
=True)
1541 def test_address_static(self
):
1542 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1545 self
.wait_online(['dummy98:routable'])
1547 output
= check_output('ip -4 address show dev dummy98')
1549 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1550 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1551 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1554 self
.assertNotRegex(output
, '10.10.0.1/16')
1555 self
.assertNotRegex(output
, '10.10.0.2/16')
1557 output
= check_output('ip -4 address show dev dummy98 label 32')
1558 self
.assertRegex(output
, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1560 output
= check_output('ip -4 address show dev dummy98 label 33')
1561 self
.assertRegex(output
, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1563 output
= check_output('ip -4 address show dev dummy98 label 34')
1564 self
.assertRegex(output
, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1566 output
= check_output('ip -4 address show dev dummy98 label 35')
1567 self
.assertRegex(output
, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1569 output
= check_output('ip -6 address show dev dummy98')
1571 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::15/64 scope global')
1572 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::16/64 scope global')
1573 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::15/64 scope global')
1574 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::16/64 scope global')
1575 self
.assertRegex(output
, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1576 self
.assertRegex(output
, 'inet6 fd[0-9a-f:]*1/64 scope global')
1578 def test_address_preferred_lifetime_zero_ipv6(self
):
1579 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1582 self
.wait_online(['dummy98:routable'])
1584 output
= check_output('ip address show dummy98')
1586 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1587 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::1/64 scope global')
1589 output
= check_output('ip route show dev dummy98')
1591 self
.assertRegex(output
, 'default via 20.20.20.1 proto static')
1593 def test_configure_without_carrier(self
):
1594 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1596 self
.wait_online(['test1:routable'])
1598 output
= check_output(*networkctl_cmd
, 'status', 'test1')
1600 self
.assertRegex(output
, '192.168.0.15')
1601 self
.assertRegex(output
, '192.168.0.1')
1602 self
.assertRegex(output
, 'routable')
1604 def test_routing_policy_rule(self
):
1605 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1607 self
.wait_online(['test1:degraded'])
1609 output
= check_output('ip rule list iif test1 priority 111')
1611 self
.assertRegex(output
, '111:')
1612 self
.assertRegex(output
, 'from 192.168.100.18')
1613 self
.assertRegex(output
, r
'tos (0x08|throughput)\s')
1614 self
.assertRegex(output
, 'iif test1')
1615 self
.assertRegex(output
, 'oif test1')
1616 self
.assertRegex(output
, 'lookup 7')
1618 output
= check_output('ip rule list iif test1 priority 101')
1620 self
.assertRegex(output
, '101:')
1621 self
.assertRegex(output
, 'from all')
1622 self
.assertRegex(output
, 'iif test1')
1623 self
.assertRegex(output
, 'lookup 9')
1625 output
= check_output('ip -6 rule list iif test1 priority 100')
1627 self
.assertRegex(output
, '100:')
1628 self
.assertRegex(output
, 'from all')
1629 self
.assertRegex(output
, 'iif test1')
1630 self
.assertRegex(output
, 'lookup 8')
1632 output
= check_output('ip -6 rule list iif test1 priority 101')
1634 self
.assertRegex(output
, '101:')
1635 self
.assertRegex(output
, 'from all')
1636 self
.assertRegex(output
, 'iif test1')
1637 self
.assertRegex(output
, 'lookup 9')
1639 def test_routing_policy_rule_issue_11280(self
):
1640 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1641 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1643 for trial
in range(3):
1644 # Remove state files only first time
1646 self
.wait_online(['test1:degraded', 'dummy98:degraded'])
1649 output
= check_output('ip rule list table 7')
1651 self
.assertRegex(output
, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1653 output
= check_output('ip rule list table 8')
1655 self
.assertRegex(output
, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1657 stop_networkd(remove_state_files
=False)
1659 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1660 def test_routing_policy_rule_port_range(self
):
1661 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1663 self
.wait_online(['test1:degraded'])
1665 output
= check_output('ip rule')
1667 self
.assertRegex(output
, '111')
1668 self
.assertRegex(output
, 'from 192.168.100.18')
1669 self
.assertRegex(output
, '1123-1150')
1670 self
.assertRegex(output
, '3224-3290')
1671 self
.assertRegex(output
, 'tcp')
1672 self
.assertRegex(output
, 'lookup 7')
1674 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1675 def test_routing_policy_rule_invert(self
):
1676 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1678 self
.wait_online(['test1:degraded'])
1680 output
= check_output('ip rule')
1682 self
.assertRegex(output
, '111')
1683 self
.assertRegex(output
, 'not.*?from.*?192.168.100.18')
1684 self
.assertRegex(output
, 'tcp')
1685 self
.assertRegex(output
, 'lookup 7')
1687 def test_route_static(self
):
1688 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1690 self
.wait_online(['dummy98:routable'])
1692 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
1695 print('### ip -6 route show dev dummy98')
1696 output
= check_output('ip -6 route show dev dummy98')
1698 self
.assertRegex(output
, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1699 self
.assertRegex(output
, '2001:1234:5:8f63::1 proto kernel')
1701 print('### ip -6 route show dev dummy98 default')
1702 output
= check_output('ip -6 route show dev dummy98 default')
1704 self
.assertRegex(output
, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1706 print('### ip -4 route show dev dummy98')
1707 output
= check_output('ip -4 route show dev dummy98')
1709 self
.assertRegex(output
, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1710 self
.assertRegex(output
, '149.10.124.64 proto static scope link')
1711 self
.assertRegex(output
, '169.254.0.0/16 proto static scope link metric 2048')
1712 self
.assertRegex(output
, '192.168.1.1 proto static initcwnd 20')
1713 self
.assertRegex(output
, '192.168.1.2 proto static initrwnd 30')
1714 self
.assertRegex(output
, 'multicast 149.10.123.4 proto static')
1716 print('### ip -4 route show dev dummy98 default')
1717 output
= check_output('ip -4 route show dev dummy98 default')
1719 self
.assertRegex(output
, 'default via 149.10.125.65 proto static onlink')
1720 self
.assertRegex(output
, 'default via 149.10.124.64 proto static')
1721 self
.assertRegex(output
, 'default proto static')
1723 print('### ip -4 route show table local dev dummy98')
1724 output
= check_output('ip -4 route show table local dev dummy98')
1726 self
.assertRegex(output
, 'local 149.10.123.1 proto static scope host')
1727 self
.assertRegex(output
, 'anycast 149.10.123.2 proto static scope link')
1728 self
.assertRegex(output
, 'broadcast 149.10.123.3 proto static scope link')
1730 print('### ip route show type blackhole')
1731 output
= check_output('ip route show type blackhole')
1733 self
.assertRegex(output
, 'blackhole 202.54.1.2 proto static')
1735 print('### ip route show type unreachable')
1736 output
= check_output('ip route show type unreachable')
1738 self
.assertRegex(output
, 'unreachable 202.54.1.3 proto static')
1740 print('### ip route show type prohibit')
1741 output
= check_output('ip route show type prohibit')
1743 self
.assertRegex(output
, 'prohibit 202.54.1.4 proto static')
1745 def test_gateway_reconfigure(self
):
1746 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1748 self
.wait_online(['dummy98:routable'])
1749 print('### ip -4 route show dev dummy98 default')
1750 output
= check_output('ip -4 route show dev dummy98 default')
1752 self
.assertRegex(output
, 'default via 149.10.124.59 proto static')
1753 self
.assertNotRegex(output
, '149.10.124.60')
1755 remove_unit_from_networkd_path(['25-gateway-static.network'])
1756 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1758 self
.wait_online(['dummy98:routable'])
1759 print('### ip -4 route show dev dummy98 default')
1760 output
= check_output('ip -4 route show dev dummy98 default')
1762 self
.assertNotRegex(output
, '149.10.124.59')
1763 self
.assertRegex(output
, 'default via 149.10.124.60 proto static')
1765 def test_ip_route_ipv6_src_route(self
):
1766 # a dummy device does not make the addresses go through tentative state, so we
1767 # reuse a bond from an earlier test, which does make the addresses go through
1768 # tentative state, and do our test on that
1769 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1771 self
.wait_online(['dummy98:enslaved', 'bond199:routable'])
1773 output
= check_output('ip -6 route list dev bond199')
1775 self
.assertRegex(output
, 'abcd::/16')
1776 self
.assertRegex(output
, 'src')
1777 self
.assertRegex(output
, '2001:1234:56:8f63::2')
1779 def test_ip_link_mac_address(self
):
1780 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1782 self
.wait_online(['dummy98:degraded'])
1784 output
= check_output('ip link show dummy98')
1786 self
.assertRegex(output
, '00:01:02:aa:bb:cc')
1788 def test_ip_link_unmanaged(self
):
1789 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1792 self
.check_link_exists('dummy98')
1794 self
.check_operstate('dummy98', 'off', setup_state
='unmanaged')
1796 def test_ipv6_address_label(self
):
1797 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1799 self
.wait_online(['dummy98:degraded'])
1801 output
= check_output('ip addrlabel list')
1803 self
.assertRegex(output
, '2004:da8:1::/64')
1805 def test_neighbor_section(self
):
1806 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1808 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1810 print('### ip neigh list dev dummy98')
1811 output
= check_output('ip neigh list dev dummy98')
1813 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1814 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1816 def test_neighbor_reconfigure(self
):
1817 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1819 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1821 print('### ip neigh list dev dummy98')
1822 output
= check_output('ip neigh list dev dummy98')
1824 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1825 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1827 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1828 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1830 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1831 print('### ip neigh list dev dummy98')
1832 output
= check_output('ip neigh list dev dummy98')
1834 self
.assertNotRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1835 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1836 self
.assertNotRegex(output
, '2004:da8:1::1.*PERMANENT')
1838 def test_neighbor_gre(self
):
1839 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1840 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1842 self
.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout
='40s')
1844 output
= check_output('ip neigh list dev gretun97')
1846 self
.assertRegex(output
, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1848 output
= check_output('ip neigh list dev ip6gretun97')
1850 self
.assertRegex(output
, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1852 def test_link_local_addressing(self
):
1853 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1854 '25-link-local-addressing-no.network', '12-dummy.netdev')
1856 self
.wait_online(['test1:degraded', 'dummy98:carrier'])
1858 output
= check_output('ip address show dev test1')
1860 self
.assertRegex(output
, 'inet .* scope link')
1861 self
.assertRegex(output
, 'inet6 .* scope link')
1863 output
= check_output('ip address show dev dummy98')
1865 self
.assertNotRegex(output
, 'inet6* .* scope link')
1868 Documentation/networking/ip-sysctl.txt
1870 addr_gen_mode - INTEGER
1871 Defines how link-local and autoconf addresses are generated.
1873 0: generate address based on EUI64 (default)
1874 1: do no generate a link-local address, use EUI64 for addresses generated
1876 2: generate stable privacy addresses, using the secret from
1877 stable_secret (RFC7217)
1878 3: generate stable privacy addresses, using a random secret if unset
1881 test1_addr_gen_mode
= ''
1882 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')):
1883 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')) as f
:
1887 # if stable_secret is unset, then EIO is returned
1888 test1_addr_gen_mode
= '0'
1890 test1_addr_gen_mode
= '2'
1892 test1_addr_gen_mode
= '0'
1894 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'addr_gen_mode')):
1895 self
.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode
)
1897 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'dummy98'), 'addr_gen_mode')):
1898 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1900 def test_link_local_addressing_remove_ipv6ll(self
):
1901 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1903 self
.wait_online(['dummy98:degraded'])
1905 output
= check_output('ip address show dev dummy98')
1907 self
.assertRegex(output
, 'inet6 .* scope link')
1909 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
1911 self
.wait_online(['dummy98:carrier'])
1913 output
= check_output('ip address show dev dummy98')
1915 self
.assertNotRegex(output
, 'inet6* .* scope link')
1917 def test_sysctl(self
):
1918 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1920 self
.wait_online(['dummy98:degraded'])
1922 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1923 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1924 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1925 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1926 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1927 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1928 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1930 def test_sysctl_disable_ipv6(self
):
1931 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1933 print('## Disable ipv6')
1934 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1935 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1938 self
.wait_online(['dummy98:routable'])
1940 output
= check_output('ip -4 address show dummy98')
1942 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1943 output
= check_output('ip -6 address show dummy98')
1945 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1946 self
.assertRegex(output
, 'inet6 .* scope link')
1947 output
= check_output('ip -4 route show dev dummy98')
1949 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1950 output
= check_output('ip -6 route show dev dummy98')
1952 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1954 check_output('ip link del dummy98')
1956 print('## Enable ipv6')
1957 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1958 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1961 self
.wait_online(['dummy98:routable'])
1963 output
= check_output('ip -4 address show dummy98')
1965 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1966 output
= check_output('ip -6 address show dummy98')
1968 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1969 self
.assertRegex(output
, 'inet6 .* scope link')
1970 output
= check_output('ip -4 route show dev dummy98')
1972 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1973 output
= check_output('ip -6 route show dev dummy98')
1975 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1977 def test_bind_carrier(self
):
1978 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1980 self
.wait_online(['test1:routable'])
1982 check_output('ip link add dummy98 type dummy')
1983 check_output('ip link set dummy98 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 add dummy99 type dummy')
1992 check_output('ip link set dummy99 up')
1994 output
= check_output('ip address show test1')
1996 self
.assertRegex(output
, 'UP,LOWER_UP')
1997 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1998 self
.check_operstate('test1', 'routable')
2000 check_output('ip link del dummy98')
2002 output
= check_output('ip address show test1')
2004 self
.assertRegex(output
, 'UP,LOWER_UP')
2005 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2006 self
.check_operstate('test1', 'routable')
2008 check_output('ip link del dummy99')
2010 output
= check_output('ip address show test1')
2012 self
.assertNotRegex(output
, 'UP,LOWER_UP')
2013 self
.assertRegex(output
, 'DOWN')
2014 self
.assertNotRegex(output
, '192.168.10')
2015 self
.check_operstate('test1', 'off')
2017 check_output('ip link add dummy98 type dummy')
2018 check_output('ip link set dummy98 up')
2020 output
= check_output('ip address show test1')
2022 self
.assertRegex(output
, 'UP,LOWER_UP')
2023 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2024 self
.check_operstate('test1', 'routable')
2026 def test_domain(self
):
2027 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2029 self
.wait_online(['dummy98:routable'])
2031 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
2033 self
.assertRegex(output
, 'Address: 192.168.42.100')
2034 self
.assertRegex(output
, 'DNS: 192.168.42.1')
2035 self
.assertRegex(output
, 'Search Domains: one')
2037 def test_keep_configuration_static(self
):
2038 check_output('systemctl stop systemd-networkd')
2040 check_output('ip link add name dummy98 type dummy')
2041 check_output('ip address add 10.1.2.3/16 dev dummy98')
2042 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2043 output
= check_output('ip address show dummy98')
2045 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2046 self
.assertRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2047 output
= check_output('ip route show dev dummy98')
2050 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2052 self
.wait_online(['dummy98:routable'])
2054 output
= check_output('ip address show dummy98')
2056 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2057 self
.assertNotRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2059 @expectedFailureIfNexthopIsNotAvailable()
2060 def test_nexthop(self
):
2061 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2063 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2065 output
= check_output('ip nexthop list dev veth99')
2067 self
.assertRegex(output
, '192.168.5.1')
2069 def test_qdisc(self
):
2070 copy_unit_to_networkd_unit_path('25-qdisc-netem.network', '12-dummy.netdev',
2071 '25-qdisc-tbf-and-sfq.network', '11-dummy.netdev')
2074 self
.wait_online(['dummy98:routable', 'test1:routable'])
2076 output
= check_output('tc qdisc show dev dummy98')
2078 self
.assertRegex(output
, 'qdisc netem')
2079 self
.assertRegex(output
, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2080 self
.assertRegex(output
, 'limit 200 delay 100.0ms 13.0ms loss 20.5%')
2081 output
= check_output('tc qdisc show dev test1')
2083 self
.assertRegex(output
, 'qdisc tbf')
2084 self
.assertRegex(output
, 'rate 500Kbit burst 5000b lat 70.0ms')
2085 self
.assertRegex(output
, 'qdisc sfq')
2086 self
.assertRegex(output
, 'perturb 5sec')
2088 class NetworkdStateFileTests(unittest
.TestCase
, Utilities
):
2095 'state-file-tests.network',
2099 remove_links(self
.links
)
2100 stop_networkd(show_logs
=False)
2103 remove_links(self
.links
)
2104 remove_unit_from_networkd_path(self
.units
)
2105 stop_networkd(show_logs
=True)
2107 def test_state_file(self
):
2108 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2110 self
.wait_online(['dummy98:routable'])
2112 output
= check_output(*networkctl_cmd
, '--no-legend', 'list', 'dummy98', env
=env
)
2114 ifindex
= output
.split()[0]
2116 path
= os
.path
.join('/run/systemd/netif/links/', ifindex
)
2117 self
.assertTrue(os
.path
.exists(path
))
2120 with
open(path
) as f
:
2122 self
.assertRegex(data
, r
'ADMIN_STATE=configured')
2123 self
.assertRegex(data
, r
'OPER_STATE=routable')
2124 self
.assertRegex(data
, r
'REQUIRED_FOR_ONLINE=yes')
2125 self
.assertRegex(data
, r
'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2126 self
.assertRegex(data
, r
'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2127 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2128 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2129 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2130 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2131 self
.assertRegex(data
, r
'LLMNR=no')
2132 self
.assertRegex(data
, r
'MDNS=yes')
2133 self
.assertRegex(data
, r
'DNSSEC=no')
2134 self
.assertRegex(data
, r
'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2136 check_output(*resolvectl_cmd
, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env
=env
)
2137 check_output(*resolvectl_cmd
, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env
=env
)
2138 check_output(*resolvectl_cmd
, 'llmnr', 'dummy98', 'yes', env
=env
)
2139 check_output(*resolvectl_cmd
, 'mdns', 'dummy98', 'no', env
=env
)
2140 check_output(*resolvectl_cmd
, 'dnssec', 'dummy98', 'yes', env
=env
)
2141 check_output(*timedatectl_cmd
, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', 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=2.fedora.pool.ntp.org 3.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(*timedatectl_cmd
, 'revert', 'dummy98', env
=env
)
2157 with
open(path
) as f
:
2159 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2160 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2161 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2162 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2163 self
.assertRegex(data
, r
'LLMNR=yes')
2164 self
.assertRegex(data
, r
'MDNS=no')
2165 self
.assertRegex(data
, r
'DNSSEC=yes')
2167 check_output(*resolvectl_cmd
, 'revert', 'dummy98', env
=env
)
2170 with
open(path
) as f
:
2172 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2173 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2174 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2175 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2176 self
.assertRegex(data
, r
'LLMNR=no')
2177 self
.assertRegex(data
, r
'MDNS=yes')
2178 self
.assertRegex(data
, r
'DNSSEC=no')
2180 class NetworkdBondTests(unittest
.TestCase
, Utilities
):
2190 '23-active-slave.network',
2191 '23-bond199.network',
2192 '23-primary-slave.network',
2193 '25-bond-active-backup-slave.netdev',
2196 'bond-slave.network']
2199 remove_links(self
.links
)
2200 stop_networkd(show_logs
=False)
2203 remove_links(self
.links
)
2204 remove_unit_from_networkd_path(self
.units
)
2205 stop_networkd(show_logs
=True)
2207 def test_bond_active_slave(self
):
2208 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2210 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2212 output
= check_output('ip -d link show bond199')
2214 self
.assertRegex(output
, 'active_slave dummy98')
2216 def test_bond_primary_slave(self
):
2217 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2219 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2221 output
= check_output('ip -d link show bond199')
2223 self
.assertRegex(output
, 'primary dummy98')
2225 def test_bond_operstate(self
):
2226 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2227 'bond99.network','bond-slave.network')
2229 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2231 output
= check_output('ip -d link show dummy98')
2233 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2235 output
= check_output('ip -d link show test1')
2237 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2239 output
= check_output('ip -d link show bond99')
2241 self
.assertRegex(output
, 'MASTER,UP,LOWER_UP')
2243 self
.check_operstate('dummy98', 'enslaved')
2244 self
.check_operstate('test1', 'enslaved')
2245 self
.check_operstate('bond99', 'routable')
2247 check_output('ip link set dummy98 down')
2250 self
.check_operstate('dummy98', 'off')
2251 self
.check_operstate('test1', 'enslaved')
2252 self
.check_operstate('bond99', 'degraded-carrier')
2254 check_output('ip link set dummy98 up')
2257 self
.check_operstate('dummy98', 'enslaved')
2258 self
.check_operstate('test1', 'enslaved')
2259 self
.check_operstate('bond99', 'routable')
2261 check_output('ip link set dummy98 down')
2262 check_output('ip link set test1 down')
2265 self
.check_operstate('dummy98', 'off')
2266 self
.check_operstate('test1', 'off')
2268 for trial
in range(30):
2271 output
= check_output('ip address show bond99')
2273 if get_operstate('bond99') == 'no-carrier':
2276 # Huh? Kernel does not recognize that all slave interfaces are down?
2277 # Let's confirm that networkd's operstate is consistent with ip's result.
2278 self
.assertNotRegex(output
, 'NO-CARRIER')
2280 class NetworkdBridgeTests(unittest
.TestCase
, Utilities
):
2290 '26-bridge-slave-interface-1.network',
2291 '26-bridge-slave-interface-2.network',
2292 '26-bridge-vlan-master.network',
2293 '26-bridge-vlan-slave.network',
2294 'bridge99-ignore-carrier-loss.network',
2297 routing_policy_rule_tables
= ['100']
2300 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2301 remove_links(self
.links
)
2302 stop_networkd(show_logs
=False)
2305 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2306 remove_links(self
.links
)
2307 remove_unit_from_networkd_path(self
.units
)
2308 stop_networkd(show_logs
=True)
2310 def test_bridge_vlan(self
):
2311 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2312 '26-bridge.netdev', '26-bridge-vlan-master.network')
2314 self
.wait_online(['test1:enslaved', 'bridge99:degraded'])
2316 output
= check_output('bridge vlan show dev test1')
2318 self
.assertNotRegex(output
, '4063')
2319 for i
in range(4064, 4095):
2320 self
.assertRegex(output
, f
'{i}')
2321 self
.assertNotRegex(output
, '4095')
2323 output
= check_output('bridge vlan show dev bridge99')
2325 self
.assertNotRegex(output
, '4059')
2326 for i
in range(4060, 4095):
2327 self
.assertRegex(output
, f
'{i}')
2328 self
.assertNotRegex(output
, '4095')
2330 def test_bridge_property(self
):
2331 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2332 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2335 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2337 output
= check_output('ip -d link show test1')
2339 self
.assertRegex(output
, 'master')
2340 self
.assertRegex(output
, 'bridge')
2342 output
= check_output('ip -d link show dummy98')
2344 self
.assertRegex(output
, 'master')
2345 self
.assertRegex(output
, 'bridge')
2347 output
= check_output('ip addr show bridge99')
2349 self
.assertRegex(output
, '192.168.0.15/24')
2351 output
= check_output('bridge -d link show dummy98')
2353 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2354 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2355 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2356 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2357 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2358 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2359 if (os
.path
.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2360 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2361 if (os
.path
.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2362 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2363 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2364 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2365 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2366 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2368 output
= check_output('bridge -d link show test1')
2370 self
.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2372 check_output('ip address add 192.168.0.16/24 dev bridge99')
2375 output
= check_output('ip addr show bridge99')
2377 self
.assertRegex(output
, '192.168.0.16/24')
2380 print('### ip -6 route list table all dev bridge99')
2381 output
= check_output('ip -6 route list table all dev bridge99')
2383 self
.assertRegex(output
, 'ff00::/8 table local metric 256 pref medium')
2385 self
.assertEqual(call('ip link del test1'), 0)
2388 self
.check_operstate('bridge99', 'degraded-carrier')
2390 check_output('ip link del dummy98')
2393 self
.check_operstate('bridge99', 'no-carrier')
2395 output
= check_output('ip address show bridge99')
2397 self
.assertRegex(output
, 'NO-CARRIER')
2398 self
.assertNotRegex(output
, '192.168.0.15/24')
2399 self
.assertNotRegex(output
, '192.168.0.16/24')
2401 print('### ip -6 route list table all dev bridge99')
2402 output
= check_output('ip -6 route list table all dev bridge99')
2404 self
.assertRegex(output
, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2406 def test_bridge_ignore_carrier_loss(self
):
2407 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2408 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2409 'bridge99-ignore-carrier-loss.network')
2411 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2413 check_output('ip address add 192.168.0.16/24 dev bridge99')
2416 check_output('ip link del test1')
2417 check_output('ip link del dummy98')
2420 output
= check_output('ip address show bridge99')
2422 self
.assertRegex(output
, 'NO-CARRIER')
2423 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2424 self
.assertRegex(output
, 'inet 192.168.0.16/24 scope global secondary bridge99')
2426 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self
):
2427 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2428 'bridge99-ignore-carrier-loss.network')
2430 self
.wait_online(['bridge99:no-carrier'])
2432 for trial
in range(4):
2433 check_output('ip link add dummy98 type dummy')
2434 check_output('ip link set dummy98 up')
2436 check_output('ip link del dummy98')
2438 self
.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2440 output
= check_output('ip address show bridge99')
2442 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2444 output
= check_output('ip rule list table 100')
2446 self
.assertEqual(output
, '0: from all to 8.8.8.8 lookup 100')
2448 class NetworkdLLDPTests(unittest
.TestCase
, Utilities
):
2452 '23-emit-lldp.network',
2457 remove_links(self
.links
)
2458 stop_networkd(show_logs
=False)
2461 remove_links(self
.links
)
2462 remove_unit_from_networkd_path(self
.units
)
2463 stop_networkd(show_logs
=True)
2465 def test_lldp(self
):
2466 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2468 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2470 output
= check_output(*networkctl_cmd
, 'lldp', env
=env
)
2472 self
.assertRegex(output
, 'veth-peer')
2473 self
.assertRegex(output
, 'veth99')
2475 class NetworkdRATests(unittest
.TestCase
, Utilities
):
2480 'ipv6-prefix.network',
2481 'ipv6-prefix-veth.network']
2484 remove_links(self
.links
)
2485 stop_networkd(show_logs
=False)
2488 remove_links(self
.links
)
2489 remove_unit_from_networkd_path(self
.units
)
2490 stop_networkd(show_logs
=True)
2492 def test_ipv6_prefix_delegation(self
):
2493 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2495 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2497 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2499 self
.assertRegex(output
, '2002:da8:1:0')
2501 class NetworkdDHCPServerTests(unittest
.TestCase
, Utilities
):
2506 'dhcp-client.network',
2507 'dhcp-client-timezone-router.network',
2508 'dhcp-server.network',
2509 'dhcp-server-timezone-router.network']
2512 remove_links(self
.links
)
2513 stop_networkd(show_logs
=False)
2516 remove_links(self
.links
)
2517 remove_unit_from_networkd_path(self
.units
)
2518 stop_networkd(show_logs
=True)
2520 def test_dhcp_server(self
):
2521 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2523 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2525 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2527 self
.assertRegex(output
, '192.168.5.*')
2528 self
.assertRegex(output
, 'Gateway: 192.168.5.1')
2529 self
.assertRegex(output
, 'DNS: 192.168.5.1')
2530 self
.assertRegex(output
, 'NTP: 192.168.5.1')
2532 def test_emit_router_timezone(self
):
2533 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2535 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2537 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2539 self
.assertRegex(output
, 'Gateway: 192.168.5.*')
2540 self
.assertRegex(output
, '192.168.5.*')
2541 self
.assertRegex(output
, 'Europe/Berlin')
2543 class NetworkdDHCPClientTests(unittest
.TestCase
, Utilities
):
2552 'dhcp-client-anonymize.network',
2553 'dhcp-client-gateway-onlink-implicit.network',
2554 'dhcp-client-ipv4-dhcp-settings.network',
2555 'dhcp-client-ipv4-only-ipv6-disabled.network',
2556 'dhcp-client-ipv4-only.network',
2557 'dhcp-client-ipv6-only.network',
2558 'dhcp-client-ipv6-rapid-commit.network',
2559 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2560 'dhcp-client-keep-configuration-dhcp.network',
2561 'dhcp-client-listen-port.network',
2562 'dhcp-client-reassign-static-routes-ipv4.network',
2563 'dhcp-client-reassign-static-routes-ipv6.network',
2564 'dhcp-client-route-metric.network',
2565 'dhcp-client-route-table.network',
2566 'dhcp-client-use-dns-ipv4-and-ra.network',
2567 'dhcp-client-use-dns-ipv4.network',
2568 'dhcp-client-use-dns-no.network',
2569 'dhcp-client-use-dns-yes.network',
2570 'dhcp-client-use-domains.network',
2571 'dhcp-client-use-routes-no.network',
2572 'dhcp-client-vrf.network',
2573 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2574 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2575 'dhcp-client-with-static-address.network',
2576 'dhcp-client.network',
2577 'dhcp-server-veth-peer.network',
2578 'dhcp-v4-server-veth-peer.network',
2579 'dhcp-client-use-domains.network',
2583 stop_dnsmasq(dnsmasq_pid_file
)
2584 remove_links(self
.links
)
2585 stop_networkd(show_logs
=False)
2588 stop_dnsmasq(dnsmasq_pid_file
)
2591 remove_links(self
.links
)
2592 remove_unit_from_networkd_path(self
.units
)
2593 stop_networkd(show_logs
=True)
2595 def test_dhcp_client_ipv6_only(self
):
2596 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2599 self
.wait_online(['veth-peer:carrier'])
2601 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2603 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2605 self
.assertRegex(output
, '2600::')
2606 self
.assertNotRegex(output
, '192.168.5')
2608 # Confirm that ipv6 token is not set in the kernel
2609 output
= check_output('ip token show dev veth99')
2611 self
.assertRegex(output
, 'token :: dev veth99')
2613 def test_dhcp_client_ipv4_only(self
):
2614 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2617 self
.wait_online(['veth-peer:carrier'])
2618 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
2619 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2621 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2623 self
.assertNotRegex(output
, '2600::')
2624 self
.assertRegex(output
, '192.168.5')
2625 self
.assertRegex(output
, '192.168.5.6')
2626 self
.assertRegex(output
, '192.168.5.7')
2628 # checking routes to DNS servers
2629 output
= check_output('ip route show dev veth99')
2631 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2632 self
.assertRegex(output
, r
'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2633 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2635 stop_dnsmasq(dnsmasq_pid_file
)
2636 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time
='2m')
2638 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2639 print('Wait for the dynamic address to be renewed')
2642 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2644 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2646 self
.assertNotRegex(output
, '2600::')
2647 self
.assertRegex(output
, '192.168.5')
2648 self
.assertNotRegex(output
, '192.168.5.6')
2649 self
.assertRegex(output
, '192.168.5.7')
2650 self
.assertRegex(output
, '192.168.5.8')
2652 # checking routes to DNS servers
2653 output
= check_output('ip route show dev veth99')
2655 self
.assertNotRegex(output
, r
'192.168.5.6')
2656 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2657 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2658 self
.assertRegex(output
, r
'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2660 def test_dhcp_client_ipv4_ipv6(self
):
2661 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2662 'dhcp-client-ipv4-only.network')
2664 self
.wait_online(['veth-peer:carrier'])
2666 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2668 # link become 'routable' when at least one protocol provide an valid address.
2669 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2670 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2672 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2674 self
.assertRegex(output
, '2600::')
2675 self
.assertRegex(output
, '192.168.5')
2677 def test_dhcp_client_settings(self
):
2678 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2681 self
.wait_online(['veth-peer:carrier'])
2683 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2685 print('## ip address show dev veth99')
2686 output
= check_output('ip address show dev veth99')
2688 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2689 self
.assertRegex(output
, '192.168.5')
2690 self
.assertRegex(output
, '1492')
2692 print('## ip route show table main dev veth99')
2693 output
= check_output('ip route show table main dev veth99')
2696 main_table_is_empty
= output
== ''
2697 if not main_table_is_empty
:
2698 self
.assertNotRegex(output
, 'proto dhcp')
2700 print('## ip route show table 211 dev veth99')
2701 output
= check_output('ip route show table 211 dev veth99')
2703 self
.assertRegex(output
, 'default via 192.168.5.1 proto dhcp')
2704 if main_table_is_empty
:
2705 self
.assertRegex(output
, '192.168.5.0/24 proto dhcp')
2706 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2707 self
.assertRegex(output
, '192.168.5.1 proto dhcp scope link')
2709 print('## dnsmasq log')
2710 self
.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2711 self
.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2712 self
.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2713 self
.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2715 def test_dhcp6_client_settings_rapidcommit_true(self
):
2716 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2718 self
.wait_online(['veth-peer:carrier'])
2720 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2722 output
= check_output('ip address show dev veth99')
2724 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2725 self
.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2727 def test_dhcp6_client_settings_rapidcommit_false(self
):
2728 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2730 self
.wait_online(['veth-peer:carrier'])
2732 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2734 output
= check_output('ip address show dev veth99')
2736 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2737 self
.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2739 def test_dhcp_client_settings_anonymize(self
):
2740 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2742 self
.wait_online(['veth-peer:carrier'])
2744 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2746 self
.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2747 self
.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2748 self
.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2750 def test_dhcp_client_listen_port(self
):
2751 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2753 self
.wait_online(['veth-peer:carrier'])
2754 start_dnsmasq('--dhcp-alternate-port=67,5555')
2755 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2757 output
= check_output('ip -4 address show dev veth99')
2759 self
.assertRegex(output
, '192.168.5.* dynamic')
2761 def test_dhcp_client_with_static_address(self
):
2762 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2763 'dhcp-client-with-static-address.network')
2765 self
.wait_online(['veth-peer:carrier'])
2767 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2769 output
= check_output('ip address show dev veth99 scope global')
2771 self
.assertRegex(output
, r
'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2772 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2774 output
= check_output('ip route show dev veth99')
2776 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2777 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2778 self
.assertRegex(output
, r
'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2779 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2781 def test_dhcp_route_table_id(self
):
2782 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2784 self
.wait_online(['veth-peer:carrier'])
2786 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2788 output
= check_output('ip route show table 12')
2790 self
.assertRegex(output
, 'veth99 proto dhcp')
2791 self
.assertRegex(output
, '192.168.5.1')
2793 def test_dhcp_route_metric(self
):
2794 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2796 self
.wait_online(['veth-peer:carrier'])
2798 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2800 output
= check_output('ip route show dev veth99')
2802 self
.assertRegex(output
, 'metric 24')
2804 def test_dhcp_client_reassign_static_routes_ipv4(self
):
2805 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2806 'dhcp-client-reassign-static-routes-ipv4.network')
2808 self
.wait_online(['veth-peer:carrier'])
2809 start_dnsmasq(lease_time
='2m')
2810 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2812 output
= check_output('ip address show dev veth99 scope global')
2814 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2816 output
= check_output('ip route show dev veth99')
2818 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2819 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2820 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2821 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2823 stop_dnsmasq(dnsmasq_pid_file
)
2824 start_dnsmasq(ipv4_range
='192.168.5.210,192.168.5.220', lease_time
='2m')
2826 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2827 print('Wait for the dynamic address to be renewed')
2830 self
.wait_online(['veth99:routable'])
2832 output
= check_output('ip route show dev veth99')
2834 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2835 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2836 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2837 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2839 def test_dhcp_client_reassign_static_routes_ipv6(self
):
2840 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2841 'dhcp-client-reassign-static-routes-ipv6.network')
2843 self
.wait_online(['veth-peer:carrier'])
2844 start_dnsmasq(lease_time
='2m')
2845 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2847 output
= check_output('ip address show dev veth99 scope global')
2849 self
.assertRegex(output
, r
'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
2851 output
= check_output('ip -6 route show dev veth99')
2853 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2854 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2856 stop_dnsmasq(dnsmasq_pid_file
)
2857 start_dnsmasq(ipv6_range
='2600::30,2600::40', lease_time
='2m')
2859 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2860 print('Wait for the dynamic address to be renewed')
2863 self
.wait_online(['veth99:routable'])
2865 output
= check_output('ip -6 route show dev veth99')
2867 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2868 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2870 def test_dhcp_keep_configuration_dhcp(self
):
2871 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2873 self
.wait_online(['veth-peer:carrier'])
2874 start_dnsmasq(lease_time
='2m')
2875 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2877 output
= check_output('ip address show dev veth99 scope global')
2879 self
.assertRegex(output
, r
'192.168.5.*')
2881 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2883 self
.assertRegex(output
, r
'192.168.5.*')
2885 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2886 stop_dnsmasq(dnsmasq_pid_file
)
2888 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2889 print('Wait for the dynamic address to be expired')
2892 print('The lease address should be kept after lease expired')
2893 output
= check_output('ip address show dev veth99 scope global')
2895 self
.assertRegex(output
, r
'192.168.5.*')
2897 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2899 self
.assertRegex(output
, r
'192.168.5.*')
2901 check_output('systemctl stop systemd-networkd')
2903 print('The lease address should be kept after networkd stopped')
2904 output
= check_output('ip address show dev veth99 scope global')
2906 self
.assertRegex(output
, r
'192.168.5.*')
2908 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2910 self
.assertRegex(output
, r
'192.168.5.*')
2913 self
.wait_online(['veth-peer:routable'])
2915 print('Still the lease address should be kept after networkd restarted')
2916 output
= check_output('ip address show dev veth99 scope global')
2918 self
.assertRegex(output
, r
'192.168.5.*')
2920 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2922 self
.assertRegex(output
, r
'192.168.5.*')
2924 def test_dhcp_keep_configuration_dhcp_on_stop(self
):
2925 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2927 self
.wait_online(['veth-peer:carrier'])
2928 start_dnsmasq(lease_time
='2m')
2929 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2931 output
= check_output('ip address show dev veth99 scope global')
2933 self
.assertRegex(output
, r
'192.168.5.*')
2935 stop_dnsmasq(dnsmasq_pid_file
)
2936 check_output('systemctl stop systemd-networkd')
2938 output
= check_output('ip address show dev veth99 scope global')
2940 self
.assertRegex(output
, r
'192.168.5.*')
2943 self
.wait_online(['veth-peer:routable'])
2945 output
= check_output('ip address show dev veth99 scope global')
2947 self
.assertNotRegex(output
, r
'192.168.5.*')
2949 def test_dhcp_client_reuse_address_as_static(self
):
2950 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2952 self
.wait_online(['veth-peer:carrier'])
2954 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2956 # link become 'routable' when at least one protocol provide an valid address.
2957 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2958 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2960 output
= check_output('ip address show dev veth99 scope global')
2962 self
.assertRegex(output
, '192.168.5')
2963 self
.assertRegex(output
, '2600::')
2965 ipv4_address
= re
.search(r
'192.168.5.[0-9]*/24', output
)
2966 ipv6_address
= re
.search(r
'2600::[0-9a-f:]*/128', output
)
2967 static_network
= '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address
.group(), 'Address=' + ipv6_address
.group()])
2968 print(static_network
)
2970 remove_unit_from_networkd_path(['dhcp-client.network'])
2972 with
open(os
.path
.join(network_unit_file_path
, 'static.network'), mode
='w') as f
:
2973 f
.write(static_network
)
2975 # When networkd started, the links are already configured, so let's wait for 5 seconds
2976 # the links to be re-configured.
2978 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2980 output
= check_output('ip -4 address show dev veth99 scope global')
2982 self
.assertRegex(output
, '192.168.5')
2983 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2985 output
= check_output('ip -6 address show dev veth99 scope global')
2987 self
.assertRegex(output
, '2600::')
2988 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2990 @expectedFailureIfModuleIsNotAvailable('vrf')
2991 def test_dhcp_client_vrf(self
):
2992 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2993 '25-vrf.netdev', '25-vrf.network')
2995 self
.wait_online(['veth-peer:carrier'])
2997 self
.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2999 # link become 'routable' when at least one protocol provide an valid address.
3000 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3001 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3003 print('## ip -d link show dev vrf99')
3004 output
= check_output('ip -d link show dev vrf99')
3006 self
.assertRegex(output
, 'vrf table 42')
3008 print('## ip address show vrf vrf99')
3009 output
= check_output('ip address show vrf vrf99')
3011 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3012 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3013 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3014 self
.assertRegex(output
, 'inet6 .* scope link')
3016 print('## ip address show dev veth99')
3017 output
= check_output('ip address show dev veth99')
3019 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3020 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3021 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3022 self
.assertRegex(output
, 'inet6 .* scope link')
3024 print('## ip route show vrf vrf99')
3025 output
= check_output('ip route show vrf vrf99')
3027 self
.assertRegex(output
, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3028 self
.assertRegex(output
, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3029 self
.assertRegex(output
, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3030 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3031 self
.assertRegex(output
, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3033 print('## ip route show table main dev veth99')
3034 output
= check_output('ip route show table main dev veth99')
3036 self
.assertEqual(output
, '')
3038 def test_dhcp_client_gateway_onlink_implicit(self
):
3039 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3040 'dhcp-client-gateway-onlink-implicit.network')
3042 self
.wait_online(['veth-peer:carrier'])
3044 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3046 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3048 self
.assertRegex(output
, '192.168.5')
3050 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3052 self
.assertRegex(output
, 'onlink')
3053 output
= check_output('ip route list dev veth99 192.168.100.0/24')
3055 self
.assertRegex(output
, 'onlink')
3057 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self
):
3058 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3059 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3061 self
.wait_online(['veth-peer:carrier'])
3062 start_dnsmasq(lease_time
='2m')
3063 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3065 output
= check_output('ip address show dev veth99')
3068 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3069 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3070 output
= check_output('ip -6 address show dev veth99 scope link')
3071 self
.assertRegex(output
, 'inet6 .* scope link')
3072 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3073 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3074 output
= check_output('ip -4 address show dev veth99 scope link')
3075 self
.assertNotRegex(output
, 'inet .* scope link')
3077 print('Wait for the dynamic address to be expired')
3080 output
= check_output('ip address show dev veth99')
3083 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3084 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3085 output
= check_output('ip -6 address show dev veth99 scope link')
3086 self
.assertRegex(output
, 'inet6 .* scope link')
3087 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3088 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3089 output
= check_output('ip -4 address show dev veth99 scope link')
3090 self
.assertNotRegex(output
, 'inet .* scope link')
3092 search_words_in_dnsmasq_log('DHCPOFFER', show_all
=True)
3094 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self
):
3095 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3096 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3098 self
.wait_online(['veth99:degraded', 'veth-peer:routable'])
3100 output
= check_output('ip address show dev veth99')
3103 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3104 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3105 output
= check_output('ip -6 address show dev veth99 scope link')
3106 self
.assertRegex(output
, 'inet6 .* scope link')
3107 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3108 self
.assertNotRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3109 output
= check_output('ip -4 address show dev veth99 scope link')
3110 self
.assertRegex(output
, 'inet .* scope link')
3112 def test_dhcp_client_route_remove_on_renew(self
):
3113 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3114 'dhcp-client-ipv4-only-ipv6-disabled.network')
3116 self
.wait_online(['veth-peer:carrier'])
3117 start_dnsmasq(ipv4_range
='192.168.5.100,192.168.5.199', lease_time
='2m')
3118 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3120 # test for issue #12490
3122 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3124 self
.assertRegex(output
, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3126 for line
in output
.splitlines():
3127 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3128 address1
= line
.split()[1].split('/')[0]
3131 output
= check_output('ip -4 route show dev veth99')
3133 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3134 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3136 stop_dnsmasq(dnsmasq_pid_file
)
3137 start_dnsmasq(ipv4_range
='192.168.5.200,192.168.5.250', lease_time
='2m')
3139 print('Wait for the dynamic address to be expired')
3142 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3144 self
.assertRegex(output
, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3146 for line
in output
.splitlines():
3147 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3148 address2
= line
.split()[1].split('/')[0]
3151 self
.assertNotEqual(address1
, address2
)
3153 output
= check_output('ip -4 route show dev veth99')
3155 self
.assertNotRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3156 self
.assertNotRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3157 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3158 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3160 def test_dhcp_client_use_dns_yes(self
):
3161 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3164 self
.wait_online(['veth-peer:carrier'])
3165 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3166 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3168 # link become 'routable' when at least one protocol provide an valid address.
3169 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3170 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3173 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3175 self
.assertRegex(output
, '192.168.5.1')
3176 self
.assertRegex(output
, '2600::1')
3178 def test_dhcp_client_use_dns_no(self
):
3179 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3182 self
.wait_online(['veth-peer:carrier'])
3183 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3184 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3186 # link become 'routable' when at least one protocol provide an valid address.
3187 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3188 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3191 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3193 self
.assertNotRegex(output
, '192.168.5.1')
3194 self
.assertNotRegex(output
, '2600::1')
3196 def test_dhcp_client_use_dns_ipv4(self
):
3197 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3200 self
.wait_online(['veth-peer:carrier'])
3201 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3202 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3204 # link become 'routable' when at least one protocol provide an valid address.
3205 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3206 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3209 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3211 self
.assertRegex(output
, '192.168.5.1')
3212 self
.assertNotRegex(output
, '2600::1')
3214 def test_dhcp_client_use_dns_ipv4_and_ra(self
):
3215 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3218 self
.wait_online(['veth-peer:carrier'])
3219 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3220 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3222 # link become 'routable' when at least one protocol provide an valid address.
3223 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3224 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3227 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3229 self
.assertRegex(output
, '192.168.5.1')
3230 self
.assertRegex(output
, '2600::1')
3232 def test_dhcp_client_use_domains(self
):
3233 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3236 self
.wait_online(['veth-peer:carrier'])
3237 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3238 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3240 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3242 self
.assertRegex(output
, 'Search Domains: example.com')
3245 output
= check_output(*resolvectl_cmd
, 'domain', 'veth99', env
=env
)
3247 self
.assertRegex(output
, 'example.com')
3249 class NetworkdIPv6PrefixTests(unittest
.TestCase
, Utilities
):
3254 'ipv6ra-prefix-client.network',
3255 'ipv6ra-prefix.network'
3259 remove_links(self
.links
)
3260 stop_networkd(show_logs
=False)
3264 remove_links(self
.links
)
3265 remove_unit_from_networkd_path(self
.units
)
3266 stop_networkd(show_logs
=True)
3268 def test_ipv6_route_prefix(self
):
3269 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3272 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3274 output
= check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3276 self
.assertRegex(output
, '2001:db8:0:1::/64 proto ra')
3278 if __name__
== '__main__':
3279 parser
= argparse
.ArgumentParser()
3280 parser
.add_argument('--build-dir', help='Path to build dir', dest
='build_dir')
3281 parser
.add_argument('--networkd', help='Path to systemd-networkd', dest
='networkd_bin')
3282 parser
.add_argument('--resolved', help='Path to systemd-resolved', dest
='resolved_bin')
3283 parser
.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest
='wait_online_bin')
3284 parser
.add_argument('--networkctl', help='Path to networkctl', dest
='networkctl_bin')
3285 parser
.add_argument('--resolvectl', help='Path to resolvectl', dest
='resolvectl_bin')
3286 parser
.add_argument('--timedatectl', help='Path to timedatectl', dest
='timedatectl_bin')
3287 parser
.add_argument('--valgrind', help='Enable valgrind', dest
='use_valgrind', type=bool, nargs
='?', const
=True, default
=use_valgrind
)
3288 parser
.add_argument('--debug', help='Generate debugging logs', dest
='enable_debug', type=bool, nargs
='?', const
=True, default
=enable_debug
)
3289 parser
.add_argument('--asan-options', help='ASAN options', dest
='asan_options')
3290 parser
.add_argument('--lsan-options', help='LSAN options', dest
='lsan_options')
3291 parser
.add_argument('--ubsan-options', help='UBSAN options', dest
='ubsan_options')
3292 ns
, args
= parser
.parse_known_args(namespace
=unittest
)
3295 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
:
3296 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3297 networkd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd')
3298 resolved_bin
= os
.path
.join(ns
.build_dir
, 'systemd-resolved')
3299 wait_online_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd-wait-online')
3300 networkctl_bin
= os
.path
.join(ns
.build_dir
, 'networkctl')
3301 resolvectl_bin
= os
.path
.join(ns
.build_dir
, 'resolvectl')
3302 timedatectl_bin
= os
.path
.join(ns
.build_dir
, 'timedatectl')
3305 networkd_bin
= ns
.networkd_bin
3307 resolved_bin
= ns
.resolved_bin
3308 if ns
.wait_online_bin
:
3309 wait_online_bin
= ns
.wait_online_bin
3310 if ns
.networkctl_bin
:
3311 networkctl_bin
= ns
.networkctl_bin
3312 if ns
.resolvectl_bin
:
3313 resolvectl_bin
= ns
.resolvectl_bin
3314 if ns
.timedatectl_bin
:
3315 timedatectl_bin
= ns
.timedatectl_bin
3317 use_valgrind
= ns
.use_valgrind
3318 enable_debug
= ns
.enable_debug
3319 asan_options
= ns
.asan_options
3320 lsan_options
= ns
.lsan_options
3321 ubsan_options
= ns
.ubsan_options
3324 networkctl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin
]
3325 resolvectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin
]
3326 timedatectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin
]
3327 wait_online_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin
]
3329 networkctl_cmd
= [networkctl_bin
]
3330 resolvectl_cmd
= [resolvectl_bin
]
3331 timedatectl_cmd
= [timedatectl_bin
]
3332 wait_online_cmd
= [wait_online_bin
]
3335 env
.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3337 env
.update({ 'ASAN_OPTIONS' : asan_options
})
3339 env
.update({ 'LSAN_OPTIONS' : lsan_options
})
3341 env
.update({ 'UBSAN_OPTIONS' : ubsan_options
})
3344 unittest
.main(testRunner
=unittest
.TextTestRunner(stream
=sys
.stdout
,