2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
14 from shutil
import copytree
16 network_unit_file_path
='/run/systemd/network'
17 networkd_runtime_directory
='/run/systemd/netif'
18 networkd_ci_path
='/run/networkd-ci'
19 network_sysctl_ipv6_path
='/proc/sys/net/ipv6/conf'
20 network_sysctl_ipv4_path
='/proc/sys/net/ipv4/conf'
22 dnsmasq_pid_file
='/run/networkd-ci/test-test-dnsmasq.pid'
23 dnsmasq_log_file
='/run/networkd-ci/test-dnsmasq-log-file'
25 networkd_bin
='/usr/lib/systemd/systemd-networkd'
26 resolved_bin
='/usr/lib/systemd/systemd-resolved'
27 wait_online_bin
='/usr/lib/systemd/systemd-networkd-wait-online'
28 networkctl_bin
='/usr/bin/networkctl'
29 resolvectl_bin
='/usr/bin/resolvectl'
30 timedatectl_bin
='/usr/bin/timedatectl'
40 def check_output(*command
, **kwargs
):
41 # This replaces both check_output and check_call (output can be ignored)
42 command
= command
[0].split() + list(command
[1:])
43 return subprocess
.check_output(command
, universal_newlines
=True, **kwargs
).rstrip()
45 def call(*command
, **kwargs
):
46 command
= command
[0].split() + list(command
[1:])
47 return subprocess
.call(command
, universal_newlines
=True, **kwargs
)
49 def run(*command
, **kwargs
):
50 command
= command
[0].split() + list(command
[1:])
51 return subprocess
.run(command
, universal_newlines
=True, **kwargs
)
53 def is_module_available(module_name
):
54 lsmod_output
= check_output('lsmod')
55 module_re
= re
.compile(rf
'^{re.escape(module_name)}\b', re
.MULTILINE
)
56 return module_re
.search(lsmod_output
) or not call('modprobe', module_name
, stderr
=subprocess
.DEVNULL
)
58 def expectedFailureIfModuleIsNotAvailable(module_name
):
60 if not is_module_available(module_name
):
61 return unittest
.expectedFailure(func
)
66 def expectedFailureIfERSPANModuleIsNotAvailable():
68 rc
= call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr
=subprocess
.DEVNULL
)
70 call('ip link del erspan99')
73 return unittest
.expectedFailure(func
)
77 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
79 rc
= call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr
=subprocess
.DEVNULL
)
81 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
84 return unittest
.expectedFailure(func
)
88 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
90 rc
= call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr
=subprocess
.DEVNULL
)
92 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
95 return unittest
.expectedFailure(func
)
99 def expectedFailureIfLinkFileFieldIsNotSet():
102 rc
= call('ip link add name dummy99 type dummy', stderr
=subprocess
.DEVNULL
)
104 ret
= run('udevadm info -w10s /sys/class/net/dummy99', stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
105 if ret
.returncode
== 0 and 'E: ID_NET_LINK_FILE=' in ret
.stdout
.rstrip():
107 call('ip link del dummy99')
112 return unittest
.expectedFailure(func
)
116 def expectedFailureIfNexthopIsNotAvailable():
118 rc
= call('ip nexthop list', stderr
=subprocess
.DEVNULL
)
122 return unittest
.expectedFailure(func
)
129 os
.makedirs(network_unit_file_path
, exist_ok
=True)
130 os
.makedirs(networkd_ci_path
, exist_ok
=True)
132 shutil
.rmtree(networkd_ci_path
)
133 copytree(os
.path
.join(os
.path
.dirname(os
.path
.abspath(__file__
)), 'conf'), networkd_ci_path
)
135 for u
in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']:
136 if call(f
'systemctl is-active --quiet {u}') == 0:
137 check_output(f
'systemctl stop {u}')
138 running_units
.append(u
)
147 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin
,
151 drop_in
+= ['ExecStart=!!' + networkd_bin
]
153 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
155 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
157 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
159 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
160 if asan_options
or lsan_options
or ubsan_options
:
161 drop_in
+= ['SystemCallFilter=']
162 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
163 drop_in
+= ['MemoryDenyWriteExecute=no']
165 os
.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok
=True)
166 with
open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode
='w') as f
:
167 f
.write('\n'.join(drop_in
))
175 drop_in
+= ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin
]
177 drop_in
+= ['ExecStart=!!' + resolved_bin
]
179 drop_in
+= ['Environment=SYSTEMD_LOG_LEVEL=debug']
181 drop_in
+= ['Environment=ASAN_OPTIONS="' + asan_options
+ '"']
183 drop_in
+= ['Environment=LSAN_OPTIONS="' + lsan_options
+ '"']
185 drop_in
+= ['Environment=UBSAN_OPTIONS="' + ubsan_options
+ '"']
186 if asan_options
or lsan_options
or ubsan_options
:
187 drop_in
+= ['SystemCallFilter=']
188 if use_valgrind
or asan_options
or lsan_options
or ubsan_options
:
189 drop_in
+= ['MemoryDenyWriteExecute=no']
191 os
.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok
=True)
192 with
open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode
='w') as f
:
193 f
.write('\n'.join(drop_in
))
195 check_output('systemctl daemon-reload')
196 print(check_output('systemctl cat systemd-networkd.service'))
197 print(check_output('systemctl cat systemd-resolved.service'))
198 check_output('systemctl restart systemd-resolved')
200 def tearDownModule():
203 shutil
.rmtree(networkd_ci_path
)
205 for u
in ['systemd-networkd.service', 'systemd-resolved.service']:
206 check_output(f
'systemctl stop {u}')
208 shutil
.rmtree('/run/systemd/system/systemd-networkd.service.d')
209 shutil
.rmtree('/run/systemd/system/systemd-resolved.service.d')
210 check_output('systemctl daemon-reload')
212 for u
in running_units
:
213 check_output(f
'systemctl start {u}')
215 def read_link_attr(link
, dev
, attribute
):
216 with
open(os
.path
.join(os
.path
.join(os
.path
.join('/sys/class/net/', link
), dev
), attribute
)) as f
:
217 return f
.readline().strip()
219 def read_bridge_port_attr(bridge
, link
, attribute
):
220 path_bridge
= os
.path
.join('/sys/devices/virtual/net', bridge
)
221 path_port
= 'lower_' + link
+ '/brport'
222 path
= os
.path
.join(path_bridge
, path_port
)
224 with
open(os
.path
.join(path
, attribute
)) as f
:
225 return f
.readline().strip()
227 def link_exists(link
):
228 return os
.path
.exists(os
.path
.join('/sys/class/net', link
))
230 def remove_links(links
):
232 if link_exists(link
):
233 call('ip link del dev', link
)
236 def remove_fou_ports(ports
):
238 call('ip fou del port', port
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
240 def remove_routing_policy_rule_tables(tables
):
244 rc
= call('ip rule del table', table
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
246 def remove_routes(routes
):
247 for route_type
, addr
in routes
:
248 call('ip route del', route_type
, addr
, stdout
=subprocess
.DEVNULL
, stderr
=subprocess
.DEVNULL
)
250 def remove_l2tp_tunnels(tunnel_ids
):
251 output
= check_output('ip l2tp show tunnel')
252 for tid
in tunnel_ids
:
253 words
='Tunnel ' + tid
+ ', encap'
255 call('ip l2tp del tunnel tid', tid
)
258 def read_ipv6_sysctl_attr(link
, attribute
):
259 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, link
), attribute
)) as f
:
260 return f
.readline().strip()
262 def read_ipv4_sysctl_attr(link
, attribute
):
263 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv4_path
, link
), attribute
)) as f
:
264 return f
.readline().strip()
266 def copy_unit_to_networkd_unit_path(*units
):
269 shutil
.copy(os
.path
.join(networkd_ci_path
, unit
), network_unit_file_path
)
270 if (os
.path
.exists(os
.path
.join(networkd_ci_path
, unit
+ '.d'))):
271 copytree(os
.path
.join(networkd_ci_path
, unit
+ '.d'), os
.path
.join(network_unit_file_path
, unit
+ '.d'))
273 def remove_unit_from_networkd_path(units
):
275 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
))):
276 os
.remove(os
.path
.join(network_unit_file_path
, unit
))
277 if (os
.path
.exists(os
.path
.join(network_unit_file_path
, unit
+ '.d'))):
278 shutil
.rmtree(os
.path
.join(network_unit_file_path
, unit
+ '.d'))
280 def start_dnsmasq(additional_options
='', ipv4_range
='192.168.5.10,192.168.5.200', ipv6_range
='2600::10,2600::20', lease_time
='1h'):
281 dnsmasq_command
= f
'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
282 check_output(dnsmasq_command
)
284 def stop_dnsmasq(pid_file
):
285 if os
.path
.exists(pid_file
):
286 with
open(pid_file
, 'r') as f
:
287 pid
= f
.read().rstrip(' \t\r\n\0')
288 os
.kill(int(pid
), signal
.SIGTERM
)
292 def search_words_in_dnsmasq_log(words
, show_all
=False):
293 if os
.path
.exists(dnsmasq_log_file
):
294 with
open (dnsmasq_log_file
) as in_file
:
295 contents
= in_file
.read()
298 for line
in contents
.splitlines():
301 print("%s, %s" % (words
, line
))
305 def remove_lease_file():
306 if os
.path
.exists(os
.path
.join(networkd_ci_path
, 'lease')):
307 os
.remove(os
.path
.join(networkd_ci_path
, 'lease'))
309 def remove_log_file():
310 if os
.path
.exists(dnsmasq_log_file
):
311 os
.remove(dnsmasq_log_file
)
313 def remove_networkd_state_files():
314 if os
.path
.exists(os
.path
.join(networkd_runtime_directory
, 'state')):
315 os
.remove(os
.path
.join(networkd_runtime_directory
, 'state'))
317 def stop_networkd(show_logs
=True, remove_state_files
=True):
319 invocation_id
= check_output('systemctl show systemd-networkd -p InvocationID --value')
320 check_output('systemctl stop systemd-networkd')
322 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id
))
323 if remove_state_files
:
324 remove_networkd_state_files()
326 def start_networkd(sleep_sec
=0):
327 check_output('systemctl start systemd-networkd')
329 time
.sleep(sleep_sec
)
331 def restart_networkd(sleep_sec
=0, show_logs
=True, remove_state_files
=True):
332 stop_networkd(show_logs
, remove_state_files
)
333 start_networkd(sleep_sec
)
335 def get_operstate(link
, show_status
=True, setup_state
='configured'):
336 output
= check_output(*networkctl_cmd
, 'status', link
, env
=env
)
339 for line
in output
.splitlines():
340 if 'State:' in line
and (not setup_state
or setup_state
in line
):
341 return line
.split()[1]
345 def check_link_exists(self
, link
):
346 self
.assertTrue(link_exists(link
))
348 def check_operstate(self
, link
, expected
, show_status
=True, setup_state
='configured'):
349 self
.assertRegex(get_operstate(link
, show_status
, setup_state
), expected
)
351 def wait_online(self
, links_with_operstate
, timeout
='20s', bool_any
=False, setup_state
='configured'):
352 args
= wait_online_cmd
+ [f
'--timeout={timeout}'] + [f
'--interface={link}' for link
in links_with_operstate
]
356 check_output(*args
, env
=env
)
357 except subprocess
.CalledProcessError
:
358 for link
in links_with_operstate
:
359 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0], env
=env
)
363 for link
in links_with_operstate
:
364 output
= check_output(*networkctl_cmd
, 'status', link
.split(':')[0])
366 for line
in output
.splitlines():
368 self
.assertRegex(line
, setup_state
)
370 def wait_address(self
, link
, address_regex
, scope
='global', ipv
='', timeout_sec
=100):
371 for i
in range(timeout_sec
):
374 output
= check_output(f
'ip {ipv} address show dev {link} scope {scope}')
375 if re
.search(address_regex
, output
):
378 self
.assertRegex(output
, address_regex
)
380 class NetworkctlTests(unittest
.TestCase
, Utilities
):
390 '11-dummy-mtu.netdev',
393 '25-address-static.network',
395 'netdev-link-local-addressing-yes.network',
399 remove_links(self
.links
)
400 stop_networkd(show_logs
=False)
403 remove_links(self
.links
)
404 remove_unit_from_networkd_path(self
.units
)
405 stop_networkd(show_logs
=True)
407 def test_reconfigure(self
):
408 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
410 self
.wait_online(['dummy98:routable'])
412 output
= check_output('ip -4 address show dev dummy98')
414 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
415 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
416 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
418 check_output('ip address del 10.1.2.3/16 dev dummy98')
419 check_output('ip address del 10.1.2.4/16 dev dummy98')
420 check_output('ip address del 10.2.2.4/16 dev dummy98')
422 check_output(*networkctl_cmd
, 'reconfigure', 'dummy98', env
=env
)
423 self
.wait_online(['dummy98:routable'])
425 output
= check_output('ip -4 address show dev dummy98')
427 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
428 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
429 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
431 def test_reload(self
):
434 copy_unit_to_networkd_unit_path('11-dummy.netdev')
435 check_output(*networkctl_cmd
, 'reload', env
=env
)
437 self
.check_link_exists('test1')
438 self
.check_operstate('test1', 'off', setup_state
='unmanaged')
440 copy_unit_to_networkd_unit_path('11-dummy.network')
441 check_output(*networkctl_cmd
, 'reload', env
=env
)
442 self
.wait_online(['test1:degraded'])
444 remove_unit_from_networkd_path(['11-dummy.network'])
445 check_output(*networkctl_cmd
, 'reload', env
=env
)
447 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
449 remove_unit_from_networkd_path(['11-dummy.netdev'])
450 check_output(*networkctl_cmd
, 'reload', env
=env
)
451 self
.check_operstate('test1', 'degraded', setup_state
='unmanaged')
453 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
454 check_output(*networkctl_cmd
, 'reload', env
=env
)
455 self
.check_operstate('test1', 'degraded')
458 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
461 self
.wait_online(['test1:degraded'])
463 output
= check_output(*networkctl_cmd
, 'list', env
=env
)
464 self
.assertRegex(output
, '1 lo ')
465 self
.assertRegex(output
, 'test1')
467 output
= check_output(*networkctl_cmd
, 'list', 'test1', env
=env
)
468 self
.assertNotRegex(output
, '1 lo ')
469 self
.assertRegex(output
, 'test1')
471 output
= check_output(*networkctl_cmd
, 'list', 'te*', env
=env
)
472 self
.assertNotRegex(output
, '1 lo ')
473 self
.assertRegex(output
, 'test1')
475 output
= check_output(*networkctl_cmd
, 'status', 'te*', env
=env
)
476 self
.assertNotRegex(output
, '1: lo ')
477 self
.assertRegex(output
, 'test1')
479 output
= check_output(*networkctl_cmd
, 'status', 'tes[a-z][0-9]', env
=env
)
480 self
.assertNotRegex(output
, '1: lo ')
481 self
.assertRegex(output
, 'test1')
484 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
487 self
.wait_online(['test1:degraded'])
489 output
= check_output(*networkctl_cmd
, 'status', 'test1', env
=env
)
490 self
.assertRegex(output
, 'MTU: 1600')
493 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
495 self
.wait_online(['test1:degraded'])
497 output
= check_output(*networkctl_cmd
, 'status', 'test1')
499 self
.assertRegex(output
, 'Type: ether')
501 output
= check_output(*networkctl_cmd
, 'status', 'lo')
503 self
.assertRegex(output
, 'Type: loopback')
505 @expectedFailureIfLinkFileFieldIsNotSet()
506 def test_udev_link_file(self
):
507 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
509 self
.wait_online(['test1:degraded'])
511 output
= check_output(*networkctl_cmd
, 'status', 'test1')
513 self
.assertRegex(output
, r
'Link File: (?:/usr)/lib/systemd/network/99-default.link')
514 self
.assertRegex(output
, r
'Network File: /run/systemd/network/11-dummy.network')
516 output
= check_output(*networkctl_cmd
, 'status', 'lo')
518 self
.assertRegex(output
, r
'Link File: (?:/usr)/lib/systemd/network/99-default.link')
519 self
.assertRegex(output
, r
'Network File: n/a')
521 def test_delete_links(self
):
522 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
523 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
526 self
.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
528 check_output(*networkctl_cmd
, 'delete', 'test1', 'veth99')
529 self
.assertFalse(link_exists('test1'))
530 self
.assertFalse(link_exists('veth99'))
531 self
.assertFalse(link_exists('veth-peer'))
533 class NetworkdNetDevTests(unittest
.TestCase
, Utilities
):
535 links_remove_earlier
= [
599 '10-dropin-test.netdev',
603 '13-not-match-udev-property.network',
604 '14-match-udev-property.network',
605 '15-name-conflict-test.netdev',
608 '21-vlan-test1.network',
611 '25-6rd-tunnel.netdev',
613 '25-bond-balanced-tlb.netdev',
615 '25-bridge-configure-without-carrier.network',
617 '25-erspan-tunnel-local-any.netdev',
618 '25-erspan-tunnel.netdev',
619 '25-fou-gretap.netdev',
621 '25-fou-ipip.netdev',
622 '25-fou-ipproto-gre.netdev',
623 '25-fou-ipproto-ipip.netdev',
626 '25-gretap-tunnel-local-any.netdev',
627 '25-gretap-tunnel.netdev',
628 '25-gre-tunnel-any-any.netdev',
629 '25-gre-tunnel-local-any.netdev',
630 '25-gre-tunnel-remote-any.netdev',
631 '25-gre-tunnel.netdev',
632 '25-ip6gretap-tunnel-local-any.netdev',
633 '25-ip6gretap-tunnel.netdev',
634 '25-ip6gre-tunnel-any-any.netdev',
635 '25-ip6gre-tunnel-local-any.netdev',
636 '25-ip6gre-tunnel-remote-any.netdev',
637 '25-ip6gre-tunnel.netdev',
638 '25-ip6tnl-tunnel-any-any.netdev',
639 '25-ip6tnl-tunnel-local-any.netdev',
640 '25-ip6tnl-tunnel-remote-any.netdev',
641 '25-ip6tnl-tunnel.netdev',
642 '25-ipip-tunnel-any-any.netdev',
643 '25-ipip-tunnel-independent.netdev',
644 '25-ipip-tunnel-independent-loopback.netdev',
645 '25-ipip-tunnel-local-any.netdev',
646 '25-ipip-tunnel-remote-any.netdev',
647 '25-ipip-tunnel.netdev',
650 '25-isatap-tunnel.netdev',
655 '25-sit-tunnel-any-any.netdev',
656 '25-sit-tunnel-local-any.netdev',
657 '25-sit-tunnel-remote-any.netdev',
658 '25-sit-tunnel.netdev',
661 '25-tunnel-local-any.network',
662 '25-tunnel-remote-any.network',
667 '25-vti6-tunnel-any-any.netdev',
668 '25-vti6-tunnel-local-any.netdev',
669 '25-vti6-tunnel-remote-any.netdev',
670 '25-vti6-tunnel.netdev',
671 '25-vti-tunnel-any-any.netdev',
672 '25-vti-tunnel-local-any.netdev',
673 '25-vti-tunnel-remote-any.netdev',
674 '25-vti-tunnel.netdev',
677 '25-wireguard-23-peers.netdev',
678 '25-wireguard-23-peers.network',
679 '25-wireguard-preshared-key.txt',
680 '25-wireguard-private-key.txt',
681 '25-wireguard.netdev',
682 '25-wireguard.network',
684 '25-xfrm-independent.netdev',
700 'netdev-link-local-addressing-yes.network',
704 'vxlan-test1.network',
714 remove_fou_ports(self
.fou_ports
)
715 remove_links(self
.links_remove_earlier
)
716 remove_links(self
.links
)
717 stop_networkd(show_logs
=False)
720 remove_fou_ports(self
.fou_ports
)
721 remove_links(self
.links_remove_earlier
)
722 remove_links(self
.links
)
723 remove_unit_from_networkd_path(self
.units
)
724 stop_networkd(show_logs
=True)
726 def test_dropin_and_name_conflict(self
):
727 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
730 self
.wait_online(['dropin-test:off'], setup_state
='unmanaged')
732 output
= check_output('ip link show dropin-test')
734 self
.assertRegex(output
, '00:50:56:c0:00:28')
736 def test_match_udev_property(self
):
737 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
739 self
.wait_online(['dummy98:routable'])
741 output
= check_output('networkctl status dummy98')
743 self
.assertRegex(output
, 'Network File: /run/systemd/network/14-match-udev-property')
745 def test_wait_online_any(self
):
746 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
749 self
.wait_online(['bridge99', 'test1:degraded'], bool_any
=True)
751 self
.check_operstate('bridge99', '(?:off|no-carrier)', setup_state
='configuring')
752 self
.check_operstate('test1', 'degraded')
754 def test_bridge(self
):
755 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
758 self
.wait_online(['bridge99:no-carrier'])
760 tick
= os
.sysconf('SC_CLK_TCK')
761 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick
))
762 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick
))
763 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick
))
764 self
.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick
))
765 self
.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
766 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
767 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
768 self
.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
769 self
.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
771 output
= check_output(*networkctl_cmd
, 'status', 'bridge99')
773 self
.assertRegex(output
, 'Priority: 9')
774 self
.assertRegex(output
, 'STP: yes')
775 self
.assertRegex(output
, 'Multicast IGMP Version: 3')
778 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
781 self
.wait_online(['bond99:off', 'bond98:off'], setup_state
='unmanaged')
783 self
.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
784 self
.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
785 self
.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
786 self
.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
787 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
788 self
.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
789 self
.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
790 self
.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
791 self
.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
792 self
.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
793 self
.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
795 self
.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
796 self
.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
799 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
800 '21-vlan.network', '21-vlan-test1.network')
803 self
.wait_online(['test1:degraded', 'vlan99:routable'])
805 output
= check_output('ip -d link show test1')
807 self
.assertRegex(output
, ' mtu 2000 ')
809 output
= check_output('ip -d link show vlan99')
811 self
.assertRegex(output
, ' mtu 2000 ')
812 self
.assertRegex(output
, 'REORDER_HDR')
813 self
.assertRegex(output
, 'LOOSE_BINDING')
814 self
.assertRegex(output
, 'GVRP')
815 self
.assertRegex(output
, 'MVRP')
816 self
.assertRegex(output
, ' id 99 ')
818 output
= check_output('ip -4 address show dev test1')
820 self
.assertRegex(output
, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
821 self
.assertRegex(output
, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
823 output
= check_output('ip -4 address show dev vlan99')
825 self
.assertRegex(output
, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
827 def test_macvtap(self
):
828 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
829 with self
.subTest(mode
=mode
):
830 if mode
!= 'private':
832 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
833 '11-dummy.netdev', 'macvtap.network')
834 with
open(os
.path
.join(network_unit_file_path
, '21-macvtap.netdev'), mode
='a') as f
:
835 f
.write('[MACVTAP]\nMode=' + mode
)
838 self
.wait_online(['macvtap99:degraded', 'test1:degraded'])
840 output
= check_output('ip -d link show macvtap99')
842 self
.assertRegex(output
, 'macvtap mode ' + mode
+ ' ')
844 def test_macvlan(self
):
845 for mode
in ['private', 'vepa', 'bridge', 'passthru']:
846 with self
.subTest(mode
=mode
):
847 if mode
!= 'private':
849 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
850 '11-dummy.netdev', 'macvlan.network')
851 with
open(os
.path
.join(network_unit_file_path
, '21-macvlan.netdev'), mode
='a') as f
:
852 f
.write('[MACVLAN]\nMode=' + mode
)
855 self
.wait_online(['macvlan99:degraded', 'test1:degraded'])
857 output
= check_output('ip -d link show test1')
859 self
.assertRegex(output
, ' mtu 2000 ')
861 output
= check_output('ip -d link show macvlan99')
863 self
.assertRegex(output
, ' mtu 2000 ')
864 self
.assertRegex(output
, 'macvlan mode ' + mode
+ ' ')
866 @expectedFailureIfModuleIsNotAvailable('ipvlan')
867 def test_ipvlan(self
):
868 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
869 with self
.subTest(mode
=mode
, flag
=flag
):
872 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
873 '11-dummy.netdev', 'ipvlan.network')
874 with
open(os
.path
.join(network_unit_file_path
, '25-ipvlan.netdev'), mode
='a') as f
:
875 f
.write('[IPVLAN]\nMode=' + mode
+ '\nFlags=' + flag
)
878 self
.wait_online(['ipvlan99:degraded', 'test1:degraded'])
880 output
= check_output('ip -d link show ipvlan99')
882 self
.assertRegex(output
, 'ipvlan *mode ' + mode
.lower() + ' ' + flag
)
884 @expectedFailureIfModuleIsNotAvailable('ipvtap')
885 def test_ipvtap(self
):
886 for mode
, flag
in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
887 with self
.subTest(mode
=mode
, flag
=flag
):
890 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
891 '11-dummy.netdev', 'ipvtap.network')
892 with
open(os
.path
.join(network_unit_file_path
, '25-ipvtap.netdev'), mode
='a') as f
:
893 f
.write('[IPVTAP]\nMode=' + mode
+ '\nFlags=' + flag
)
896 self
.wait_online(['ipvtap99:degraded', 'test1:degraded'])
898 output
= check_output('ip -d link show ipvtap99')
900 self
.assertRegex(output
, 'ipvtap *mode ' + mode
.lower() + ' ' + flag
)
903 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
906 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
908 output
= check_output('ip -d link show veth99')
910 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bc')
911 output
= check_output('ip -d link show veth-peer')
913 self
.assertRegex(output
, 'link/ether 12:34:56:78:9a:bd')
916 copy_unit_to_networkd_unit_path('25-tun.netdev')
919 self
.wait_online(['tun99:off'], setup_state
='unmanaged')
921 output
= check_output('ip -d link show tun99')
923 # Old ip command does not support IFF_ flags
924 self
.assertRegex(output
, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
927 copy_unit_to_networkd_unit_path('25-tap.netdev')
930 self
.wait_online(['tap99:off'], setup_state
='unmanaged')
932 output
= check_output('ip -d link show tap99')
934 # Old ip command does not support IFF_ flags
935 self
.assertRegex(output
, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
937 @expectedFailureIfModuleIsNotAvailable('vrf')
939 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
942 self
.wait_online(['vrf99:carrier'])
944 @expectedFailureIfModuleIsNotAvailable('vcan')
946 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
949 self
.wait_online(['vcan99:carrier'])
951 @expectedFailureIfModuleIsNotAvailable('vxcan')
952 def test_vxcan(self
):
953 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
956 self
.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
958 @expectedFailureIfModuleIsNotAvailable('wireguard')
959 def test_wireguard(self
):
960 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
961 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
962 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
964 self
.wait_online(['wg99:carrier', 'wg98:routable'])
966 if shutil
.which('wg'):
969 output
= check_output('wg show wg99 listen-port')
970 self
.assertRegex(output
, '51820')
971 output
= check_output('wg show wg99 fwmark')
972 self
.assertRegex(output
, '0x4d2')
973 output
= check_output('wg show wg99 allowed-ips')
974 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
975 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
976 output
= check_output('wg show wg99 persistent-keepalive')
977 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
978 output
= check_output('wg show wg99 endpoints')
979 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
980 output
= check_output('wg show wg99 private-key')
981 self
.assertRegex(output
, r
'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
982 output
= check_output('wg show wg99 preshared-keys')
983 self
.assertRegex(output
, r
'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
984 self
.assertRegex(output
, r
'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
986 output
= check_output('wg show wg98 private-key')
987 self
.assertRegex(output
, r
'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
989 def test_geneve(self
):
990 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
993 self
.wait_online(['geneve99:degraded'])
995 output
= check_output('ip -d link show geneve99')
997 self
.assertRegex(output
, '192.168.22.1')
998 self
.assertRegex(output
, '6082')
999 self
.assertRegex(output
, 'udpcsum')
1000 self
.assertRegex(output
, 'udp6zerocsumrx')
1002 def test_ipip_tunnel(self
):
1003 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1004 '25-ipip-tunnel.netdev', '25-tunnel.network',
1005 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1006 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1007 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1009 self
.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1011 output
= check_output('ip -d link show ipiptun99')
1013 self
.assertRegex(output
, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1014 output
= check_output('ip -d link show ipiptun98')
1016 self
.assertRegex(output
, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
1017 output
= check_output('ip -d link show ipiptun97')
1019 self
.assertRegex(output
, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
1020 output
= check_output('ip -d link show ipiptun96')
1022 self
.assertRegex(output
, 'ipip (?:ipip |)remote any local any dev dummy98')
1024 def test_gre_tunnel(self
):
1025 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1026 '25-gre-tunnel.netdev', '25-tunnel.network',
1027 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1028 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1029 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1031 self
.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1033 output
= check_output('ip -d link show gretun99')
1035 self
.assertRegex(output
, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1036 self
.assertRegex(output
, 'ikey 1.2.3.103')
1037 self
.assertRegex(output
, 'okey 1.2.4.103')
1038 self
.assertRegex(output
, 'iseq')
1039 self
.assertRegex(output
, 'oseq')
1040 output
= check_output('ip -d link show gretun98')
1042 self
.assertRegex(output
, 'gre remote 10.65.223.239 local any dev dummy98')
1043 self
.assertRegex(output
, 'ikey 0.0.0.104')
1044 self
.assertRegex(output
, 'okey 0.0.0.104')
1045 self
.assertNotRegex(output
, 'iseq')
1046 self
.assertNotRegex(output
, 'oseq')
1047 output
= check_output('ip -d link show gretun97')
1049 self
.assertRegex(output
, 'gre remote any local 10.65.223.238 dev dummy98')
1050 self
.assertRegex(output
, 'ikey 0.0.0.105')
1051 self
.assertRegex(output
, 'okey 0.0.0.105')
1052 self
.assertNotRegex(output
, 'iseq')
1053 self
.assertNotRegex(output
, 'oseq')
1054 output
= check_output('ip -d link show gretun96')
1056 self
.assertRegex(output
, 'gre remote any local any dev dummy98')
1057 self
.assertRegex(output
, 'ikey 0.0.0.106')
1058 self
.assertRegex(output
, 'okey 0.0.0.106')
1059 self
.assertNotRegex(output
, 'iseq')
1060 self
.assertNotRegex(output
, 'oseq')
1062 def test_ip6gre_tunnel(self
):
1063 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1064 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1065 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1066 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1067 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1070 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1072 self
.check_link_exists('dummy98')
1073 self
.check_link_exists('ip6gretun99')
1074 self
.check_link_exists('ip6gretun98')
1075 self
.check_link_exists('ip6gretun97')
1076 self
.check_link_exists('ip6gretun96')
1078 output
= check_output('ip -d link show ip6gretun99')
1080 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1081 output
= check_output('ip -d link show ip6gretun98')
1083 self
.assertRegex(output
, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1084 output
= check_output('ip -d link show ip6gretun97')
1086 self
.assertRegex(output
, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1087 output
= check_output('ip -d link show ip6gretun96')
1089 self
.assertRegex(output
, 'ip6gre remote any local any dev dummy98')
1091 def test_gretap_tunnel(self
):
1092 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1093 '25-gretap-tunnel.netdev', '25-tunnel.network',
1094 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1096 self
.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1098 output
= check_output('ip -d link show gretap99')
1100 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1101 self
.assertRegex(output
, 'ikey 0.0.0.106')
1102 self
.assertRegex(output
, 'okey 0.0.0.106')
1103 self
.assertRegex(output
, 'iseq')
1104 self
.assertRegex(output
, 'oseq')
1105 output
= check_output('ip -d link show gretap98')
1107 self
.assertRegex(output
, 'gretap remote 10.65.223.239 local any dev dummy98')
1108 self
.assertRegex(output
, 'ikey 0.0.0.107')
1109 self
.assertRegex(output
, 'okey 0.0.0.107')
1110 self
.assertRegex(output
, 'iseq')
1111 self
.assertRegex(output
, 'oseq')
1113 def test_ip6gretap_tunnel(self
):
1114 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1115 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1116 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1118 self
.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1120 output
= check_output('ip -d link show ip6gretap99')
1122 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1123 output
= check_output('ip -d link show ip6gretap98')
1125 self
.assertRegex(output
, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1127 def test_vti_tunnel(self
):
1128 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1129 '25-vti-tunnel.netdev', '25-tunnel.network',
1130 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1131 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1132 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1134 self
.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1136 output
= check_output('ip -d link show vtitun99')
1138 self
.assertRegex(output
, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1139 output
= check_output('ip -d link show vtitun98')
1141 self
.assertRegex(output
, 'vti remote 10.65.223.239 local any dev dummy98')
1142 output
= check_output('ip -d link show vtitun97')
1144 self
.assertRegex(output
, 'vti remote any local 10.65.223.238 dev dummy98')
1145 output
= check_output('ip -d link show vtitun96')
1147 self
.assertRegex(output
, 'vti remote any local any dev dummy98')
1149 def test_vti6_tunnel(self
):
1150 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1151 '25-vti6-tunnel.netdev', '25-tunnel.network',
1152 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1153 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1155 self
.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1157 output
= check_output('ip -d link show vti6tun99')
1159 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1160 output
= check_output('ip -d link show vti6tun98')
1162 self
.assertRegex(output
, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1163 output
= check_output('ip -d link show vti6tun97')
1165 self
.assertRegex(output
, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1167 def test_ip6tnl_tunnel(self
):
1168 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1169 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1170 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1171 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1173 self
.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1175 output
= check_output('ip -d link show ip6tnl99')
1177 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1178 output
= check_output('ip -d link show ip6tnl98')
1180 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1181 output
= check_output('ip -d link show ip6tnl97')
1183 self
.assertRegex(output
, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1185 def test_sit_tunnel(self
):
1186 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1187 '25-sit-tunnel.netdev', '25-tunnel.network',
1188 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1189 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1190 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1192 self
.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1194 output
= check_output('ip -d link show sittun99')
1196 self
.assertRegex(output
, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1197 output
= check_output('ip -d link show sittun98')
1199 self
.assertRegex(output
, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
1200 output
= check_output('ip -d link show sittun97')
1202 self
.assertRegex(output
, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1203 output
= check_output('ip -d link show sittun96')
1205 self
.assertRegex(output
, "sit (?:ip6ip |)remote any local any dev dummy98")
1207 def test_isatap_tunnel(self
):
1208 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1209 '25-isatap-tunnel.netdev', '25-tunnel.network')
1211 self
.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1213 output
= check_output('ip -d link show isataptun99')
1215 self
.assertRegex(output
, "isatap ")
1217 def test_6rd_tunnel(self
):
1218 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1219 '25-6rd-tunnel.netdev', '25-tunnel.network')
1221 self
.wait_online(['sittun99:routable', 'dummy98:degraded'])
1223 output
= check_output('ip -d link show sittun99')
1225 self
.assertRegex(output
, '6rd-prefix 2602::/24')
1227 @expectedFailureIfERSPANModuleIsNotAvailable()
1228 def test_erspan_tunnel(self
):
1229 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1230 '25-erspan-tunnel.netdev', '25-tunnel.network',
1231 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1233 self
.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1235 output
= check_output('ip -d link show erspan99')
1237 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local 172.16.1.200')
1238 self
.assertRegex(output
, 'ikey 0.0.0.101')
1239 self
.assertRegex(output
, 'okey 0.0.0.101')
1240 self
.assertRegex(output
, 'iseq')
1241 self
.assertRegex(output
, 'oseq')
1242 output
= check_output('ip -d link show erspan98')
1244 self
.assertRegex(output
, 'erspan remote 172.16.1.100 local any')
1245 self
.assertRegex(output
, '102')
1246 self
.assertRegex(output
, 'ikey 0.0.0.102')
1247 self
.assertRegex(output
, 'okey 0.0.0.102')
1248 self
.assertRegex(output
, 'iseq')
1249 self
.assertRegex(output
, 'oseq')
1251 def test_tunnel_independent(self
):
1252 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1255 self
.wait_online(['ipiptun99:carrier'])
1257 def test_tunnel_independent_loopback(self
):
1258 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1261 self
.wait_online(['ipiptun99:carrier'])
1263 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1264 def test_xfrm(self
):
1265 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1266 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1269 self
.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1271 output
= check_output('ip link show dev xfrm99')
1274 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1275 def test_xfrm_independent(self
):
1276 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1279 self
.wait_online(['xfrm99:degraded'])
1281 @expectedFailureIfModuleIsNotAvailable('fou')
1283 # The following redundant check is necessary for CentOS CI.
1284 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1285 self
.assertTrue(is_module_available('fou'))
1287 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1288 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1289 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1292 self
.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state
='unmanaged')
1294 output
= check_output('ip fou show')
1296 self
.assertRegex(output
, 'port 55555 ipproto 4')
1297 self
.assertRegex(output
, 'port 55556 ipproto 47')
1299 output
= check_output('ip -d link show ipiptun96')
1301 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1302 output
= check_output('ip -d link show sittun96')
1304 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55555')
1305 output
= check_output('ip -d link show gretun96')
1307 self
.assertRegex(output
, 'encap fou encap-sport 1001 encap-dport 55556')
1308 output
= check_output('ip -d link show gretap96')
1310 self
.assertRegex(output
, 'encap fou encap-sport auto encap-dport 55556')
1312 def test_vxlan(self
):
1313 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1314 '11-dummy.netdev', 'vxlan-test1.network')
1317 self
.wait_online(['test1:degraded', 'vxlan99:degraded'])
1319 output
= check_output('ip -d link show vxlan99')
1321 self
.assertRegex(output
, '999')
1322 self
.assertRegex(output
, '5555')
1323 self
.assertRegex(output
, 'l2miss')
1324 self
.assertRegex(output
, 'l3miss')
1325 self
.assertRegex(output
, 'udpcsum')
1326 self
.assertRegex(output
, 'udp6zerocsumtx')
1327 self
.assertRegex(output
, 'udp6zerocsumrx')
1328 self
.assertRegex(output
, 'remcsumtx')
1329 self
.assertRegex(output
, 'remcsumrx')
1330 self
.assertRegex(output
, 'gbp')
1332 output
= check_output('bridge fdb show dev vxlan99')
1334 self
.assertRegex(output
, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1335 self
.assertRegex(output
, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1336 self
.assertRegex(output
, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1338 output
= check_output(*networkctl_cmd
, 'status', 'vxlan99')
1340 self
.assertRegex(output
, 'VNI: 999')
1341 self
.assertRegex(output
, 'Destination Port: 5555')
1342 self
.assertRegex(output
, 'Underlying Device: test1')
1344 def test_macsec(self
):
1345 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1346 'macsec.network', '12-dummy.netdev')
1349 self
.wait_online(['dummy98:degraded', 'macsec99:routable'])
1351 output
= check_output('ip -d link show macsec99')
1353 self
.assertRegex(output
, 'macsec99@dummy98')
1354 self
.assertRegex(output
, 'macsec sci [0-9a-f]*000b')
1355 self
.assertRegex(output
, 'encrypt on')
1357 output
= check_output('ip macsec show macsec99')
1359 self
.assertRegex(output
, 'encrypt on')
1360 self
.assertRegex(output
, 'TXSC: [0-9a-f]*000b on SA 1')
1361 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1362 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1363 self
.assertRegex(output
, 'RXSC: c619528fe6a00100, state on')
1364 self
.assertRegex(output
, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1365 self
.assertRegex(output
, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1366 self
.assertRegex(output
, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1367 self
.assertRegex(output
, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1368 self
.assertNotRegex(output
, 'key 02030405067080900000000000000000')
1369 self
.assertRegex(output
, 'RXSC: 8c16456c83a90002, state on')
1370 self
.assertRegex(output
, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1372 def test_nlmon(self
):
1373 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1376 self
.wait_online(['nlmon99:carrier'])
1378 class NetworkdL2TPTests(unittest
.TestCase
, Utilities
):
1389 '25-l2tp-dummy.network',
1391 '25-l2tp-ip.netdev',
1392 '25-l2tp-udp.netdev']
1394 l2tp_tunnel_ids
= [ '10' ]
1397 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1398 remove_links(self
.links
)
1399 stop_networkd(show_logs
=False)
1402 remove_l2tp_tunnels(self
.l2tp_tunnel_ids
)
1403 remove_links(self
.links
)
1404 remove_unit_from_networkd_path(self
.units
)
1405 stop_networkd(show_logs
=True)
1407 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1408 def test_l2tp_udp(self
):
1409 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1410 '25-l2tp-udp.netdev', '25-l2tp.network')
1413 self
.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1415 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1417 self
.assertRegex(output
, "Tunnel 10, encap UDP")
1418 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1419 self
.assertRegex(output
, "Peer tunnel 11")
1420 self
.assertRegex(output
, "UDP source / dest ports: 3000/4000")
1421 self
.assertRegex(output
, "UDP checksum: enabled")
1423 output
= check_output('ip l2tp show session tid 10 session_id 15')
1425 self
.assertRegex(output
, "Session 15 in tunnel 10")
1426 self
.assertRegex(output
, "Peer session 16, tunnel 11")
1427 self
.assertRegex(output
, "interface name: l2tp-ses1")
1429 output
= check_output('ip l2tp show session tid 10 session_id 17')
1431 self
.assertRegex(output
, "Session 17 in tunnel 10")
1432 self
.assertRegex(output
, "Peer session 18, tunnel 11")
1433 self
.assertRegex(output
, "interface name: l2tp-ses2")
1435 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1436 def test_l2tp_ip(self
):
1437 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1438 '25-l2tp-ip.netdev', '25-l2tp.network')
1441 self
.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1443 output
= check_output('ip l2tp show tunnel tunnel_id 10')
1445 self
.assertRegex(output
, "Tunnel 10, encap IP")
1446 self
.assertRegex(output
, "From 192.168.30.100 to 192.168.30.101")
1447 self
.assertRegex(output
, "Peer tunnel 12")
1449 output
= check_output('ip l2tp show session tid 10 session_id 25')
1451 self
.assertRegex(output
, "Session 25 in tunnel 10")
1452 self
.assertRegex(output
, "Peer session 26, tunnel 12")
1453 self
.assertRegex(output
, "interface name: l2tp-ses3")
1455 output
= check_output('ip l2tp show session tid 10 session_id 27')
1457 self
.assertRegex(output
, "Session 27 in tunnel 10")
1458 self
.assertRegex(output
, "Peer session 28, tunnel 12")
1459 self
.assertRegex(output
, "interface name: l2tp-ses4")
1461 class NetworkdNetworkTests(unittest
.TestCase
, Utilities
):
1475 '23-active-slave.network',
1476 '24-keep-configuration-static.network',
1477 '24-search-domain.network',
1478 '25-address-link-section.network',
1479 '25-address-preferred-lifetime-zero.network',
1480 '25-address-static.network',
1481 '25-bind-carrier.network',
1482 '25-bond-active-backup-slave.netdev',
1483 '25-fibrule-invert.network',
1484 '25-fibrule-port-range.network',
1485 '25-gre-tunnel-remote-any.netdev',
1486 '25-ip6gre-tunnel-remote-any.netdev',
1487 '25-ipv6-address-label-section.network',
1488 '25-link-local-addressing-no.network',
1489 '25-link-local-addressing-yes.network',
1490 '25-link-section-unmanaged.network',
1491 '25-neighbor-section.network',
1492 '25-neighbor-next.network',
1493 '25-neighbor-ipv6.network',
1494 '25-neighbor-ip-dummy.network',
1495 '25-neighbor-ip.network',
1496 '25-nexthop.network',
1498 '25-route-ipv6-src.network',
1499 '25-route-static.network',
1500 '25-gateway-static.network',
1501 '25-gateway-next-static.network',
1502 '25-sysctl-disable-ipv6.network',
1503 '25-sysctl.network',
1504 '25-veth-peer.network',
1506 '26-link-local-addressing-ipv6.network',
1507 'configure-without-carrier.network',
1508 'routing-policy-rule-dummy98.network',
1509 'routing-policy-rule-test1.network']
1511 routing_policy_rule_tables
= ['7', '8', '9']
1512 routes
= [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1515 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1516 remove_routes(self
.routes
)
1517 remove_links(self
.links
)
1518 stop_networkd(show_logs
=False)
1521 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
1522 remove_routes(self
.routes
)
1523 remove_links(self
.links
)
1524 remove_unit_from_networkd_path(self
.units
)
1525 stop_networkd(show_logs
=True)
1527 def test_address_static(self
):
1528 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1531 self
.wait_online(['dummy98:routable'])
1533 output
= check_output('ip -4 address show dev dummy98')
1535 self
.assertRegex(output
, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1536 self
.assertRegex(output
, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1537 self
.assertRegex(output
, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1540 self
.assertNotRegex(output
, '10.10.0.1/16')
1541 self
.assertNotRegex(output
, '10.10.0.2/16')
1543 output
= check_output('ip -4 address show dev dummy98 label 32')
1544 self
.assertRegex(output
, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1546 output
= check_output('ip -4 address show dev dummy98 label 33')
1547 self
.assertRegex(output
, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1549 output
= check_output('ip -4 address show dev dummy98 label 34')
1550 self
.assertRegex(output
, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1552 output
= check_output('ip -4 address show dev dummy98 label 35')
1553 self
.assertRegex(output
, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1555 output
= check_output('ip -6 address show dev dummy98')
1557 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::15/64 scope global')
1558 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::16/64 scope global')
1559 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::15/64 scope global')
1560 self
.assertRegex(output
, 'inet6 2001:db8:0:f102::16/64 scope global')
1561 self
.assertRegex(output
, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1562 self
.assertRegex(output
, 'inet6 fd[0-9a-f:]*1/64 scope global')
1564 def test_address_preferred_lifetime_zero_ipv6(self
):
1565 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1568 self
.wait_online(['dummy98:routable'])
1570 output
= check_output('ip address show dummy98')
1572 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1573 self
.assertRegex(output
, 'inet6 2001:db8:0:f101::1/64 scope global')
1575 output
= check_output('ip route show dev dummy98')
1577 self
.assertRegex(output
, 'default via 20.20.20.1 proto static')
1579 def test_configure_without_carrier(self
):
1580 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1582 self
.wait_online(['test1:routable'])
1584 output
= check_output(*networkctl_cmd
, 'status', 'test1')
1586 self
.assertRegex(output
, '192.168.0.15')
1587 self
.assertRegex(output
, '192.168.0.1')
1588 self
.assertRegex(output
, 'routable')
1590 def test_routing_policy_rule(self
):
1591 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1593 self
.wait_online(['test1:degraded'])
1595 output
= check_output('ip rule list iif test1 priority 111')
1597 self
.assertRegex(output
, '111:')
1598 self
.assertRegex(output
, 'from 192.168.100.18')
1599 self
.assertRegex(output
, r
'tos (?:0x08|throughput)\s')
1600 self
.assertRegex(output
, 'iif test1')
1601 self
.assertRegex(output
, 'oif test1')
1602 self
.assertRegex(output
, 'lookup 7')
1604 output
= check_output('ip rule list iif test1 priority 101')
1606 self
.assertRegex(output
, '101:')
1607 self
.assertRegex(output
, 'from all')
1608 self
.assertRegex(output
, 'iif test1')
1609 self
.assertRegex(output
, 'lookup 9')
1611 output
= check_output('ip -6 rule list iif test1 priority 100')
1613 self
.assertRegex(output
, '100:')
1614 self
.assertRegex(output
, 'from all')
1615 self
.assertRegex(output
, 'iif test1')
1616 self
.assertRegex(output
, 'lookup 8')
1618 output
= check_output('ip -6 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 def test_routing_policy_rule_issue_11280(self
):
1626 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1627 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1629 for trial
in range(3):
1630 # Remove state files only first time
1632 self
.wait_online(['test1:degraded', 'dummy98:degraded'])
1635 output
= check_output('ip rule list table 7')
1637 self
.assertRegex(output
, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1639 output
= check_output('ip rule list table 8')
1641 self
.assertRegex(output
, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1643 stop_networkd(remove_state_files
=False)
1645 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1646 def test_routing_policy_rule_port_range(self
):
1647 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1649 self
.wait_online(['test1:degraded'])
1651 output
= check_output('ip rule')
1653 self
.assertRegex(output
, '111')
1654 self
.assertRegex(output
, 'from 192.168.100.18')
1655 self
.assertRegex(output
, '1123-1150')
1656 self
.assertRegex(output
, '3224-3290')
1657 self
.assertRegex(output
, 'tcp')
1658 self
.assertRegex(output
, 'lookup 7')
1660 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1661 def test_routing_policy_rule_invert(self
):
1662 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1664 self
.wait_online(['test1:degraded'])
1666 output
= check_output('ip rule')
1668 self
.assertRegex(output
, '111')
1669 self
.assertRegex(output
, 'not.*?from.*?192.168.100.18')
1670 self
.assertRegex(output
, 'tcp')
1671 self
.assertRegex(output
, 'lookup 7')
1673 def test_route_static(self
):
1674 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1676 self
.wait_online(['dummy98:routable'])
1678 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
1681 print('### ip -6 route show dev dummy98')
1682 output
= check_output('ip -6 route show dev dummy98')
1684 self
.assertRegex(output
, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1685 self
.assertRegex(output
, '2001:1234:5:8f63::1 proto kernel')
1687 print('### ip -6 route show dev dummy98 default')
1688 output
= check_output('ip -6 route show dev dummy98 default')
1690 self
.assertRegex(output
, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1692 print('### ip -4 route show dev dummy98')
1693 output
= check_output('ip -4 route show dev dummy98')
1695 self
.assertRegex(output
, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1696 self
.assertRegex(output
, '149.10.124.64 proto static scope link')
1697 self
.assertRegex(output
, '169.254.0.0/16 proto static scope link metric 2048')
1698 self
.assertRegex(output
, '192.168.1.1 proto static initcwnd 20')
1699 self
.assertRegex(output
, '192.168.1.2 proto static initrwnd 30')
1700 self
.assertRegex(output
, 'multicast 149.10.123.4 proto static')
1702 print('### ip -4 route show dev dummy98 default')
1703 output
= check_output('ip -4 route show dev dummy98 default')
1705 self
.assertRegex(output
, 'default via 149.10.125.65 proto static onlink')
1706 self
.assertRegex(output
, 'default via 149.10.124.64 proto static')
1707 self
.assertRegex(output
, 'default proto static')
1709 print('### ip -4 route show table local dev dummy98')
1710 output
= check_output('ip -4 route show table local dev dummy98')
1712 self
.assertRegex(output
, 'local 149.10.123.1 proto static scope host')
1713 self
.assertRegex(output
, 'anycast 149.10.123.2 proto static scope link')
1714 self
.assertRegex(output
, 'broadcast 149.10.123.3 proto static scope link')
1716 print('### ip route show type blackhole')
1717 output
= check_output('ip route show type blackhole')
1719 self
.assertRegex(output
, 'blackhole 202.54.1.2 proto static')
1721 print('### ip route show type unreachable')
1722 output
= check_output('ip route show type unreachable')
1724 self
.assertRegex(output
, 'unreachable 202.54.1.3 proto static')
1726 print('### ip route show type prohibit')
1727 output
= check_output('ip route show type prohibit')
1729 self
.assertRegex(output
, 'prohibit 202.54.1.4 proto static')
1731 def test_gateway_reconfigure(self
):
1732 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1734 self
.wait_online(['dummy98:routable'])
1735 print('### ip -4 route show dev dummy98 default')
1736 output
= check_output('ip -4 route show dev dummy98 default')
1738 self
.assertRegex(output
, 'default via 149.10.124.59 proto static')
1739 self
.assertNotRegex(output
, '149.10.124.60')
1741 remove_unit_from_networkd_path(['25-gateway-static.network'])
1742 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1744 self
.wait_online(['dummy98:routable'])
1745 print('### ip -4 route show dev dummy98 default')
1746 output
= check_output('ip -4 route show dev dummy98 default')
1748 self
.assertNotRegex(output
, '149.10.124.59')
1749 self
.assertRegex(output
, 'default via 149.10.124.60 proto static')
1751 def test_ip_route_ipv6_src_route(self
):
1752 # a dummy device does not make the addresses go through tentative state, so we
1753 # reuse a bond from an earlier test, which does make the addresses go through
1754 # tentative state, and do our test on that
1755 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1757 self
.wait_online(['dummy98:enslaved', 'bond199:routable'])
1759 output
= check_output('ip -6 route list dev bond199')
1761 self
.assertRegex(output
, 'abcd::/16')
1762 self
.assertRegex(output
, 'src')
1763 self
.assertRegex(output
, '2001:1234:56:8f63::2')
1765 def test_ip_link_mac_address(self
):
1766 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1768 self
.wait_online(['dummy98:degraded'])
1770 output
= check_output('ip link show dummy98')
1772 self
.assertRegex(output
, '00:01:02:aa:bb:cc')
1774 def test_ip_link_unmanaged(self
):
1775 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1778 self
.check_link_exists('dummy98')
1780 self
.check_operstate('dummy98', 'off', setup_state
='unmanaged')
1782 def test_ipv6_address_label(self
):
1783 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1785 self
.wait_online(['dummy98:degraded'])
1787 output
= check_output('ip addrlabel list')
1789 self
.assertRegex(output
, '2004:da8:1::/64')
1791 def test_neighbor_section(self
):
1792 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1794 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1796 print('### ip neigh list dev dummy98')
1797 output
= check_output('ip neigh list dev dummy98')
1799 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1800 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1802 def test_neighbor_reconfigure(self
):
1803 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1805 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1807 print('### ip neigh list dev dummy98')
1808 output
= check_output('ip neigh list dev dummy98')
1810 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1811 self
.assertRegex(output
, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1813 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1814 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1816 self
.wait_online(['dummy98:degraded'], timeout
='40s')
1817 print('### ip neigh list dev dummy98')
1818 output
= check_output('ip neigh list dev dummy98')
1820 self
.assertNotRegex(output
, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1821 self
.assertRegex(output
, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1822 self
.assertNotRegex(output
, '2004:da8:1::1.*PERMANENT')
1824 def test_neighbor_gre(self
):
1825 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1826 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1828 self
.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout
='40s')
1830 output
= check_output('ip neigh list dev gretun97')
1832 self
.assertRegex(output
, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1834 output
= check_output('ip neigh list dev ip6gretun97')
1836 self
.assertRegex(output
, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1838 def test_link_local_addressing(self
):
1839 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1840 '25-link-local-addressing-no.network', '12-dummy.netdev')
1842 self
.wait_online(['test1:degraded', 'dummy98:carrier'])
1844 output
= check_output('ip address show dev test1')
1846 self
.assertRegex(output
, 'inet .* scope link')
1847 self
.assertRegex(output
, 'inet6 .* scope link')
1849 output
= check_output('ip address show dev dummy98')
1851 self
.assertNotRegex(output
, 'inet6* .* scope link')
1854 Documentation/networking/ip-sysctl.txt
1856 addr_gen_mode - INTEGER
1857 Defines how link-local and autoconf addresses are generated.
1859 0: generate address based on EUI64 (default)
1860 1: do no generate a link-local address, use EUI64 for addresses generated
1862 2: generate stable privacy addresses, using the secret from
1863 stable_secret (RFC7217)
1864 3: generate stable privacy addresses, using a random secret if unset
1867 test1_addr_gen_mode
= ''
1868 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')):
1869 with
open(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'stable_secret')) as f
:
1873 # if stable_secret is unset, then EIO is returned
1874 test1_addr_gen_mode
= '0'
1876 test1_addr_gen_mode
= '2'
1878 test1_addr_gen_mode
= '0'
1880 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'test1'), 'addr_gen_mode')):
1881 self
.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode
)
1883 if os
.path
.exists(os
.path
.join(os
.path
.join(network_sysctl_ipv6_path
, 'dummy98'), 'addr_gen_mode')):
1884 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1886 def test_link_local_addressing_remove_ipv6ll(self
):
1887 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1889 self
.wait_online(['dummy98:degraded'])
1891 output
= check_output('ip address show dev dummy98')
1893 self
.assertRegex(output
, 'inet6 .* scope link')
1895 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
1897 self
.wait_online(['dummy98:carrier'])
1899 output
= check_output('ip address show dev dummy98')
1901 self
.assertNotRegex(output
, 'inet6* .* scope link')
1903 def test_sysctl(self
):
1904 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1906 self
.wait_online(['dummy98:degraded'])
1908 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1909 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1910 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1911 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1912 self
.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1913 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1914 self
.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1916 def test_sysctl_disable_ipv6(self
):
1917 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1919 print('## Disable ipv6')
1920 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1921 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1924 self
.wait_online(['dummy98:routable'])
1926 output
= check_output('ip -4 address show dummy98')
1928 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1929 output
= check_output('ip -6 address show dummy98')
1931 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1932 self
.assertRegex(output
, 'inet6 .* scope link')
1933 output
= check_output('ip -4 route show dev dummy98')
1935 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1936 output
= check_output('ip -6 route show dev dummy98')
1938 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1940 check_output('ip link del dummy98')
1942 print('## Enable ipv6')
1943 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1944 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1947 self
.wait_online(['dummy98:routable'])
1949 output
= check_output('ip -4 address show dummy98')
1951 self
.assertRegex(output
, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1952 output
= check_output('ip -6 address show dummy98')
1954 self
.assertRegex(output
, 'inet6 2607:5300:203:3906::/64 scope global')
1955 self
.assertRegex(output
, 'inet6 .* scope link')
1956 output
= check_output('ip -4 route show dev dummy98')
1958 self
.assertEqual(output
, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1959 output
= check_output('ip -6 route show dev dummy98')
1961 self
.assertRegex(output
, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1963 def test_bind_carrier(self
):
1964 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1966 self
.wait_online(['test1:routable'])
1968 check_output('ip link add dummy98 type dummy')
1969 check_output('ip link set dummy98 up')
1971 output
= check_output('ip address show test1')
1973 self
.assertRegex(output
, 'UP,LOWER_UP')
1974 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1975 self
.check_operstate('test1', 'routable')
1977 check_output('ip link add dummy99 type dummy')
1978 check_output('ip link set dummy99 up')
1980 output
= check_output('ip address show test1')
1982 self
.assertRegex(output
, 'UP,LOWER_UP')
1983 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1984 self
.check_operstate('test1', 'routable')
1986 check_output('ip link del dummy98')
1988 output
= check_output('ip address show test1')
1990 self
.assertRegex(output
, 'UP,LOWER_UP')
1991 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1992 self
.check_operstate('test1', 'routable')
1994 check_output('ip link del dummy99')
1996 output
= check_output('ip address show test1')
1998 self
.assertNotRegex(output
, 'UP,LOWER_UP')
1999 self
.assertRegex(output
, 'DOWN')
2000 self
.assertNotRegex(output
, '192.168.10')
2001 self
.check_operstate('test1', 'off')
2003 check_output('ip link add dummy98 type dummy')
2004 check_output('ip link set dummy98 up')
2006 output
= check_output('ip address show test1')
2008 self
.assertRegex(output
, 'UP,LOWER_UP')
2009 self
.assertRegex(output
, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2010 self
.check_operstate('test1', 'routable')
2012 def test_domain(self
):
2013 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2015 self
.wait_online(['dummy98:routable'])
2017 output
= check_output(*networkctl_cmd
, 'status', 'dummy98', env
=env
)
2019 self
.assertRegex(output
, 'Address: 192.168.42.100')
2020 self
.assertRegex(output
, 'DNS: 192.168.42.1')
2021 self
.assertRegex(output
, 'Search Domains: one')
2023 def test_keep_configuration_static(self
):
2024 check_output('systemctl stop systemd-networkd')
2026 check_output('ip link add name dummy98 type dummy')
2027 check_output('ip address add 10.1.2.3/16 dev dummy98')
2028 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2029 output
= check_output('ip address show dummy98')
2031 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2032 self
.assertRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2033 output
= check_output('ip route show dev dummy98')
2036 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2038 self
.wait_online(['dummy98:routable'])
2040 output
= check_output('ip address show dummy98')
2042 self
.assertRegex(output
, 'inet 10.1.2.3/16 scope global dummy98')
2043 self
.assertNotRegex(output
, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2045 @expectedFailureIfNexthopIsNotAvailable()
2046 def test_nexthop(self
):
2047 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2049 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2051 output
= check_output('ip nexthop list dev veth99')
2053 self
.assertRegex(output
, '192.168.5.1')
2055 def test_qdisc(self
):
2056 copy_unit_to_networkd_unit_path('25-qdisc.network', '12-dummy.netdev')
2059 self
.wait_online(['dummy98:routable'])
2061 output
= check_output('tc qdisc show dev dummy98')
2063 self
.assertRegex(output
, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2064 self
.assertRegex(output
, 'limit 200 delay 100.0ms 13.0ms loss 20.5%')
2066 class NetworkdStateFileTests(unittest
.TestCase
, Utilities
):
2073 'state-file-tests.network',
2077 remove_links(self
.links
)
2078 stop_networkd(show_logs
=False)
2081 remove_links(self
.links
)
2082 remove_unit_from_networkd_path(self
.units
)
2083 stop_networkd(show_logs
=True)
2085 def test_state_file(self
):
2086 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2088 self
.wait_online(['dummy98:routable'])
2090 output
= check_output(*networkctl_cmd
, '--no-legend', 'list', 'dummy98', env
=env
)
2092 ifindex
= output
.split()[0]
2094 path
= os
.path
.join('/run/systemd/netif/links/', ifindex
)
2095 self
.assertTrue(os
.path
.exists(path
))
2098 with
open(path
) as f
:
2100 self
.assertRegex(data
, r
'ADMIN_STATE=configured')
2101 self
.assertRegex(data
, r
'OPER_STATE=routable')
2102 self
.assertRegex(data
, r
'REQUIRED_FOR_ONLINE=yes')
2103 self
.assertRegex(data
, r
'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2104 self
.assertRegex(data
, r
'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2105 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2106 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2107 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2108 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2109 self
.assertRegex(data
, r
'LLMNR=no')
2110 self
.assertRegex(data
, r
'MDNS=yes')
2111 self
.assertRegex(data
, r
'DNSSEC=no')
2112 self
.assertRegex(data
, r
'ADDRESSES=192.168.(?:10.10|12.12)/24 192.168.(?:12.12|10.10)/24')
2114 check_output(*resolvectl_cmd
, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env
=env
)
2115 check_output(*resolvectl_cmd
, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env
=env
)
2116 check_output(*resolvectl_cmd
, 'llmnr', 'dummy98', 'yes', env
=env
)
2117 check_output(*resolvectl_cmd
, 'mdns', 'dummy98', 'no', env
=env
)
2118 check_output(*resolvectl_cmd
, 'dnssec', 'dummy98', 'yes', env
=env
)
2119 check_output(*timedatectl_cmd
, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env
=env
)
2122 with
open(path
) as f
:
2124 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2125 self
.assertRegex(data
, r
'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2126 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2127 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2128 self
.assertRegex(data
, r
'LLMNR=yes')
2129 self
.assertRegex(data
, r
'MDNS=no')
2130 self
.assertRegex(data
, r
'DNSSEC=yes')
2132 check_output(*timedatectl_cmd
, 'revert', 'dummy98', env
=env
)
2135 with
open(path
) as f
:
2137 self
.assertRegex(data
, r
'DNS=10.10.10.12 10.10.10.13')
2138 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2139 self
.assertRegex(data
, r
'DOMAINS=hogehogehoge')
2140 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoofoo')
2141 self
.assertRegex(data
, r
'LLMNR=yes')
2142 self
.assertRegex(data
, r
'MDNS=no')
2143 self
.assertRegex(data
, r
'DNSSEC=yes')
2145 check_output(*resolvectl_cmd
, 'revert', 'dummy98', env
=env
)
2148 with
open(path
) as f
:
2150 self
.assertRegex(data
, r
'DNS=10.10.10.10 10.10.10.11')
2151 self
.assertRegex(data
, r
'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2152 self
.assertRegex(data
, r
'DOMAINS=hogehoge')
2153 self
.assertRegex(data
, r
'ROUTE_DOMAINS=foofoo')
2154 self
.assertRegex(data
, r
'LLMNR=no')
2155 self
.assertRegex(data
, r
'MDNS=yes')
2156 self
.assertRegex(data
, r
'DNSSEC=no')
2158 class NetworkdBondTests(unittest
.TestCase
, Utilities
):
2168 '23-active-slave.network',
2169 '23-bond199.network',
2170 '23-primary-slave.network',
2171 '25-bond-active-backup-slave.netdev',
2174 'bond-slave.network']
2177 remove_links(self
.links
)
2178 stop_networkd(show_logs
=False)
2181 remove_links(self
.links
)
2182 remove_unit_from_networkd_path(self
.units
)
2183 stop_networkd(show_logs
=True)
2185 def test_bond_active_slave(self
):
2186 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2188 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2190 output
= check_output('ip -d link show bond199')
2192 self
.assertRegex(output
, 'active_slave dummy98')
2194 def test_bond_primary_slave(self
):
2195 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2197 self
.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2199 output
= check_output('ip -d link show bond199')
2201 self
.assertRegex(output
, 'primary dummy98')
2203 def test_bond_operstate(self
):
2204 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2205 'bond99.network','bond-slave.network')
2207 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2209 output
= check_output('ip -d link show dummy98')
2211 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2213 output
= check_output('ip -d link show test1')
2215 self
.assertRegex(output
, 'SLAVE,UP,LOWER_UP')
2217 output
= check_output('ip -d link show bond99')
2219 self
.assertRegex(output
, 'MASTER,UP,LOWER_UP')
2221 self
.check_operstate('dummy98', 'enslaved')
2222 self
.check_operstate('test1', 'enslaved')
2223 self
.check_operstate('bond99', 'routable')
2225 check_output('ip link set dummy98 down')
2228 self
.check_operstate('dummy98', 'off')
2229 self
.check_operstate('test1', 'enslaved')
2230 self
.check_operstate('bond99', 'degraded-carrier')
2232 check_output('ip link set dummy98 up')
2235 self
.check_operstate('dummy98', 'enslaved')
2236 self
.check_operstate('test1', 'enslaved')
2237 self
.check_operstate('bond99', 'routable')
2239 check_output('ip link set dummy98 down')
2240 check_output('ip link set test1 down')
2243 self
.check_operstate('dummy98', 'off')
2244 self
.check_operstate('test1', 'off')
2246 for trial
in range(30):
2249 output
= check_output('ip address show bond99')
2251 if get_operstate('bond99') == 'no-carrier':
2254 # Huh? Kernel does not recognize that all slave interfaces are down?
2255 # Let's confirm that networkd's operstate is consistent with ip's result.
2256 self
.assertNotRegex(output
, 'NO-CARRIER')
2258 class NetworkdBridgeTests(unittest
.TestCase
, Utilities
):
2268 '26-bridge-slave-interface-1.network',
2269 '26-bridge-slave-interface-2.network',
2270 '26-bridge-vlan-master.network',
2271 '26-bridge-vlan-slave.network',
2272 'bridge99-ignore-carrier-loss.network',
2275 routing_policy_rule_tables
= ['100']
2278 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2279 remove_links(self
.links
)
2280 stop_networkd(show_logs
=False)
2283 remove_routing_policy_rule_tables(self
.routing_policy_rule_tables
)
2284 remove_links(self
.links
)
2285 remove_unit_from_networkd_path(self
.units
)
2286 stop_networkd(show_logs
=True)
2288 def test_bridge_vlan(self
):
2289 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2290 '26-bridge.netdev', '26-bridge-vlan-master.network')
2292 self
.wait_online(['test1:enslaved', 'bridge99:degraded'])
2294 output
= check_output('bridge vlan show dev test1')
2296 self
.assertNotRegex(output
, '4063')
2297 for i
in range(4064, 4095):
2298 self
.assertRegex(output
, f
'{i}')
2299 self
.assertNotRegex(output
, '4095')
2301 output
= check_output('bridge vlan show dev bridge99')
2303 self
.assertNotRegex(output
, '4059')
2304 for i
in range(4060, 4095):
2305 self
.assertRegex(output
, f
'{i}')
2306 self
.assertNotRegex(output
, '4095')
2308 def test_bridge_property(self
):
2309 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2310 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2313 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2315 output
= check_output('ip -d link show test1')
2317 self
.assertRegex(output
, 'master')
2318 self
.assertRegex(output
, 'bridge')
2320 output
= check_output('ip -d link show dummy98')
2322 self
.assertRegex(output
, 'master')
2323 self
.assertRegex(output
, 'bridge')
2325 output
= check_output('ip addr show bridge99')
2327 self
.assertRegex(output
, '192.168.0.15/24')
2329 output
= check_output('bridge -d link show dummy98')
2331 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2332 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2333 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2334 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2335 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2336 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2337 if (os
.path
.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2338 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2339 if (os
.path
.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2340 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2341 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2342 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2343 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2344 self
.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2346 output
= check_output('bridge -d link show test1')
2348 self
.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2350 check_output('ip address add 192.168.0.16/24 dev bridge99')
2353 output
= check_output('ip addr show bridge99')
2355 self
.assertRegex(output
, '192.168.0.16/24')
2358 print('### ip -6 route list table all dev bridge99')
2359 output
= check_output('ip -6 route list table all dev bridge99')
2361 self
.assertRegex(output
, 'ff00::/8 table local metric 256 pref medium')
2363 self
.assertEqual(call('ip link del test1'), 0)
2366 self
.check_operstate('bridge99', 'degraded-carrier')
2368 check_output('ip link del dummy98')
2371 self
.check_operstate('bridge99', 'no-carrier')
2373 output
= check_output('ip address show bridge99')
2375 self
.assertRegex(output
, 'NO-CARRIER')
2376 self
.assertNotRegex(output
, '192.168.0.15/24')
2377 self
.assertNotRegex(output
, '192.168.0.16/24')
2379 print('### ip -6 route list table all dev bridge99')
2380 output
= check_output('ip -6 route list table all dev bridge99')
2382 self
.assertRegex(output
, 'ff00::/8 table local metric 256 (?:linkdown |)pref medium')
2384 def test_bridge_ignore_carrier_loss(self
):
2385 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2386 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2387 'bridge99-ignore-carrier-loss.network')
2389 self
.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2391 check_output('ip address add 192.168.0.16/24 dev bridge99')
2394 check_output('ip link del test1')
2395 check_output('ip link del dummy98')
2398 output
= check_output('ip address show bridge99')
2400 self
.assertRegex(output
, 'NO-CARRIER')
2401 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2402 self
.assertRegex(output
, 'inet 192.168.0.16/24 scope global secondary bridge99')
2404 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self
):
2405 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2406 'bridge99-ignore-carrier-loss.network')
2408 self
.wait_online(['bridge99:no-carrier'])
2410 for trial
in range(4):
2411 check_output('ip link add dummy98 type dummy')
2412 check_output('ip link set dummy98 up')
2414 check_output('ip link del dummy98')
2416 self
.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2418 output
= check_output('ip address show bridge99')
2420 self
.assertRegex(output
, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2422 output
= check_output('ip rule list table 100')
2424 self
.assertEqual(output
, '0: from all to 8.8.8.8 lookup 100')
2426 class NetworkdLLDPTests(unittest
.TestCase
, Utilities
):
2430 '23-emit-lldp.network',
2435 remove_links(self
.links
)
2436 stop_networkd(show_logs
=False)
2439 remove_links(self
.links
)
2440 remove_unit_from_networkd_path(self
.units
)
2441 stop_networkd(show_logs
=True)
2443 def test_lldp(self
):
2444 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2446 self
.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2448 output
= check_output(*networkctl_cmd
, 'lldp', env
=env
)
2450 self
.assertRegex(output
, 'veth-peer')
2451 self
.assertRegex(output
, 'veth99')
2453 class NetworkdRATests(unittest
.TestCase
, Utilities
):
2458 'ipv6-prefix.network',
2459 'ipv6-prefix-veth.network']
2462 remove_links(self
.links
)
2463 stop_networkd(show_logs
=False)
2466 remove_links(self
.links
)
2467 remove_unit_from_networkd_path(self
.units
)
2468 stop_networkd(show_logs
=True)
2470 def test_ipv6_prefix_delegation(self
):
2471 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2473 self
.wait_online(['veth99:routable', 'veth-peer:degraded'])
2475 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2477 self
.assertRegex(output
, '2002:da8:1:0')
2479 class NetworkdDHCPServerTests(unittest
.TestCase
, Utilities
):
2484 'dhcp-client.network',
2485 'dhcp-client-timezone-router.network',
2486 'dhcp-server.network',
2487 'dhcp-server-timezone-router.network']
2490 remove_links(self
.links
)
2491 stop_networkd(show_logs
=False)
2494 remove_links(self
.links
)
2495 remove_unit_from_networkd_path(self
.units
)
2496 stop_networkd(show_logs
=True)
2498 def test_dhcp_server(self
):
2499 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2501 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2503 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2505 self
.assertRegex(output
, '192.168.5.*')
2506 self
.assertRegex(output
, 'Gateway: 192.168.5.1')
2507 self
.assertRegex(output
, 'DNS: 192.168.5.1')
2508 self
.assertRegex(output
, 'NTP: 192.168.5.1')
2510 def test_emit_router_timezone(self
):
2511 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2513 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2515 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2517 self
.assertRegex(output
, 'Gateway: 192.168.5.*')
2518 self
.assertRegex(output
, '192.168.5.*')
2519 self
.assertRegex(output
, 'Europe/Berlin')
2521 class NetworkdDHCPClientTests(unittest
.TestCase
, Utilities
):
2530 'dhcp-client-anonymize.network',
2531 'dhcp-client-gateway-onlink-implicit.network',
2532 'dhcp-client-ipv4-dhcp-settings.network',
2533 'dhcp-client-ipv4-only-ipv6-disabled.network',
2534 'dhcp-client-ipv4-only.network',
2535 'dhcp-client-ipv6-only.network',
2536 'dhcp-client-ipv6-rapid-commit.network',
2537 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2538 'dhcp-client-keep-configuration-dhcp.network',
2539 'dhcp-client-listen-port.network',
2540 'dhcp-client-reassign-static-routes-ipv4.network',
2541 'dhcp-client-reassign-static-routes-ipv6.network',
2542 'dhcp-client-route-metric.network',
2543 'dhcp-client-route-table.network',
2544 'dhcp-client-use-dns-ipv4-and-ra.network',
2545 'dhcp-client-use-dns-ipv4.network',
2546 'dhcp-client-use-dns-no.network',
2547 'dhcp-client-use-dns-yes.network',
2548 'dhcp-client-use-domains.network',
2549 'dhcp-client-use-routes-no.network',
2550 'dhcp-client-vrf.network',
2551 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2552 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2553 'dhcp-client-with-static-address.network',
2554 'dhcp-client.network',
2555 'dhcp-server-veth-peer.network',
2556 'dhcp-v4-server-veth-peer.network',
2557 'dhcp-client-use-domains.network',
2561 stop_dnsmasq(dnsmasq_pid_file
)
2562 remove_links(self
.links
)
2563 stop_networkd(show_logs
=False)
2566 stop_dnsmasq(dnsmasq_pid_file
)
2569 remove_links(self
.links
)
2570 remove_unit_from_networkd_path(self
.units
)
2571 stop_networkd(show_logs
=True)
2573 def test_dhcp_client_ipv6_only(self
):
2574 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2577 self
.wait_online(['veth-peer:carrier'])
2579 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2581 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2583 self
.assertRegex(output
, '2600::')
2584 self
.assertNotRegex(output
, '192.168.5')
2586 # Confirm that ipv6 token is not set in the kernel
2587 output
= check_output('ip token show dev veth99')
2589 self
.assertRegex(output
, 'token :: dev veth99')
2591 def test_dhcp_client_ipv4_only(self
):
2592 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2595 self
.wait_online(['veth-peer:carrier'])
2596 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time
='2m')
2597 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2599 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2601 self
.assertNotRegex(output
, '2600::')
2602 self
.assertRegex(output
, '192.168.5')
2603 self
.assertRegex(output
, '192.168.5.6')
2604 self
.assertRegex(output
, '192.168.5.7')
2606 # checking routes to DNS servers
2607 output
= check_output('ip route show dev veth99')
2609 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2610 self
.assertRegex(output
, r
'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2611 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2613 stop_dnsmasq(dnsmasq_pid_file
)
2614 start_dnsmasq(additional_options
='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time
='2m')
2616 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2617 print('Wait for the dynamic address to be renewed')
2620 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2622 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2624 self
.assertNotRegex(output
, '2600::')
2625 self
.assertRegex(output
, '192.168.5')
2626 self
.assertNotRegex(output
, '192.168.5.6')
2627 self
.assertRegex(output
, '192.168.5.7')
2628 self
.assertRegex(output
, '192.168.5.8')
2630 # checking routes to DNS servers
2631 output
= check_output('ip route show dev veth99')
2633 self
.assertNotRegex(output
, r
'192.168.5.6')
2634 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2635 self
.assertRegex(output
, r
'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2636 self
.assertRegex(output
, r
'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2638 def test_dhcp_client_ipv4_ipv6(self
):
2639 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2640 'dhcp-client-ipv4-only.network')
2642 self
.wait_online(['veth-peer:carrier'])
2644 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2646 # link become 'routable' when at least one protocol provide an valid address.
2647 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2648 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2650 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2652 self
.assertRegex(output
, '2600::')
2653 self
.assertRegex(output
, '192.168.5')
2655 def test_dhcp_client_settings(self
):
2656 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2659 self
.wait_online(['veth-peer:carrier'])
2661 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2663 print('## ip address show dev veth99')
2664 output
= check_output('ip address show dev veth99')
2666 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2667 self
.assertRegex(output
, '192.168.5')
2668 self
.assertRegex(output
, '1492')
2670 print('## ip route show table main dev veth99')
2671 output
= check_output('ip route show table main dev veth99')
2674 main_table_is_empty
= output
== ''
2675 if not main_table_is_empty
:
2676 self
.assertNotRegex(output
, 'proto dhcp')
2678 print('## ip route show table 211 dev veth99')
2679 output
= check_output('ip route show table 211 dev veth99')
2681 self
.assertRegex(output
, 'default via 192.168.5.1 proto dhcp')
2682 if main_table_is_empty
:
2683 self
.assertRegex(output
, '192.168.5.0/24 proto dhcp')
2684 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2685 self
.assertRegex(output
, '192.168.5.1 proto dhcp scope link')
2687 print('## dnsmasq log')
2688 self
.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2689 self
.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2690 self
.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2691 self
.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2693 def test_dhcp6_client_settings_rapidcommit_true(self
):
2694 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2696 self
.wait_online(['veth-peer:carrier'])
2698 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2700 output
= check_output('ip address show dev veth99')
2702 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2703 self
.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2705 def test_dhcp6_client_settings_rapidcommit_false(self
):
2706 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2708 self
.wait_online(['veth-peer:carrier'])
2710 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2712 output
= check_output('ip address show dev veth99')
2714 self
.assertRegex(output
, '12:34:56:78:9a:bc')
2715 self
.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2717 def test_dhcp_client_settings_anonymize(self
):
2718 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2720 self
.wait_online(['veth-peer:carrier'])
2722 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2724 self
.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2725 self
.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2726 self
.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2728 def test_dhcp_client_listen_port(self
):
2729 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2731 self
.wait_online(['veth-peer:carrier'])
2732 start_dnsmasq('--dhcp-alternate-port=67,5555')
2733 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2735 output
= check_output('ip -4 address show dev veth99')
2737 self
.assertRegex(output
, '192.168.5.* dynamic')
2739 def test_dhcp_client_with_static_address(self
):
2740 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2741 'dhcp-client-with-static-address.network')
2743 self
.wait_online(['veth-peer:carrier'])
2745 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2747 output
= check_output('ip address show dev veth99 scope global')
2749 self
.assertRegex(output
, r
'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2750 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2752 output
= check_output('ip route show dev veth99')
2754 self
.assertRegex(output
, r
'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2755 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2756 self
.assertRegex(output
, r
'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2757 self
.assertRegex(output
, r
'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2759 def test_dhcp_route_table_id(self
):
2760 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2762 self
.wait_online(['veth-peer:carrier'])
2764 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2766 output
= check_output('ip route show table 12')
2768 self
.assertRegex(output
, 'veth99 proto dhcp')
2769 self
.assertRegex(output
, '192.168.5.1')
2771 def test_dhcp_route_metric(self
):
2772 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2774 self
.wait_online(['veth-peer:carrier'])
2776 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2778 output
= check_output('ip route show dev veth99')
2780 self
.assertRegex(output
, 'metric 24')
2782 def test_dhcp_client_reassign_static_routes_ipv4(self
):
2783 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2784 'dhcp-client-reassign-static-routes-ipv4.network')
2786 self
.wait_online(['veth-peer:carrier'])
2787 start_dnsmasq(lease_time
='2m')
2788 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2790 output
= check_output('ip address show dev veth99 scope global')
2792 self
.assertRegex(output
, r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2794 output
= check_output('ip route show dev veth99')
2796 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2797 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2798 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2799 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2801 stop_dnsmasq(dnsmasq_pid_file
)
2802 start_dnsmasq(ipv4_range
='192.168.5.210,192.168.5.220', lease_time
='2m')
2804 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2805 print('Wait for the dynamic address to be renewed')
2808 self
.wait_online(['veth99:routable'])
2810 output
= check_output('ip route show dev veth99')
2812 self
.assertRegex(output
, r
'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2813 self
.assertRegex(output
, r
'192.168.5.0/24 proto static')
2814 self
.assertRegex(output
, r
'192.168.6.0/24 proto static')
2815 self
.assertRegex(output
, r
'192.168.7.0/24 proto static')
2817 def test_dhcp_client_reassign_static_routes_ipv6(self
):
2818 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2819 'dhcp-client-reassign-static-routes-ipv6.network')
2821 self
.wait_online(['veth-peer:carrier'])
2822 start_dnsmasq(lease_time
='2m')
2823 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2825 output
= check_output('ip address show dev veth99 scope global')
2827 self
.assertRegex(output
, r
'inet6 2600::[0-9a-f]*/128 scope global (?:noprefixroute dynamic|dynamic noprefixroute)')
2829 output
= check_output('ip -6 route show dev veth99')
2831 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2832 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2834 stop_dnsmasq(dnsmasq_pid_file
)
2835 start_dnsmasq(ipv6_range
='2600::30,2600::40', lease_time
='2m')
2837 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2838 print('Wait for the dynamic address to be renewed')
2841 self
.wait_online(['veth99:routable'])
2843 output
= check_output('ip -6 route show dev veth99')
2845 self
.assertRegex(output
, r
'2600::/64 proto ra metric 1024')
2846 self
.assertRegex(output
, r
'2600:0:0:1::/64 proto static metric 1024 pref medium')
2848 def test_dhcp_keep_configuration_dhcp(self
):
2849 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2851 self
.wait_online(['veth-peer:carrier'])
2852 start_dnsmasq(lease_time
='2m')
2853 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2855 output
= check_output('ip address show dev veth99 scope global')
2857 self
.assertRegex(output
, r
'192.168.5.*')
2859 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2861 self
.assertRegex(output
, r
'192.168.5.*')
2863 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2864 stop_dnsmasq(dnsmasq_pid_file
)
2866 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2867 print('Wait for the dynamic address to be expired')
2870 print('The lease address should be kept after lease expired')
2871 output
= check_output('ip address show dev veth99 scope global')
2873 self
.assertRegex(output
, r
'192.168.5.*')
2875 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2877 self
.assertRegex(output
, r
'192.168.5.*')
2879 check_output('systemctl stop systemd-networkd')
2881 print('The lease address should be kept after networkd stopped')
2882 output
= check_output('ip address show dev veth99 scope global')
2884 self
.assertRegex(output
, r
'192.168.5.*')
2886 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2888 self
.assertRegex(output
, r
'192.168.5.*')
2891 self
.wait_online(['veth-peer:routable'])
2893 print('Still the lease address should be kept after networkd restarted')
2894 output
= check_output('ip address show dev veth99 scope global')
2896 self
.assertRegex(output
, r
'192.168.5.*')
2898 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
2900 self
.assertRegex(output
, r
'192.168.5.*')
2902 def test_dhcp_keep_configuration_dhcp_on_stop(self
):
2903 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2905 self
.wait_online(['veth-peer:carrier'])
2906 start_dnsmasq(lease_time
='2m')
2907 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2909 output
= check_output('ip address show dev veth99 scope global')
2911 self
.assertRegex(output
, r
'192.168.5.*')
2913 stop_dnsmasq(dnsmasq_pid_file
)
2914 check_output('systemctl stop systemd-networkd')
2916 output
= check_output('ip address show dev veth99 scope global')
2918 self
.assertRegex(output
, r
'192.168.5.*')
2921 self
.wait_online(['veth-peer:routable'])
2923 output
= check_output('ip address show dev veth99 scope global')
2925 self
.assertNotRegex(output
, r
'192.168.5.*')
2927 def test_dhcp_client_reuse_address_as_static(self
):
2928 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2930 self
.wait_online(['veth-peer:carrier'])
2932 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2934 # link become 'routable' when at least one protocol provide an valid address.
2935 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2936 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2938 output
= check_output('ip address show dev veth99 scope global')
2940 self
.assertRegex(output
, '192.168.5')
2941 self
.assertRegex(output
, '2600::')
2943 ipv4_address
= re
.search(r
'192.168.5.[0-9]*/24', output
)
2944 ipv6_address
= re
.search(r
'2600::[0-9a-f:]*/128', output
)
2945 static_network
= '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address
.group(), 'Address=' + ipv6_address
.group()])
2946 print(static_network
)
2948 remove_unit_from_networkd_path(['dhcp-client.network'])
2950 with
open(os
.path
.join(network_unit_file_path
, 'static.network'), mode
='w') as f
:
2951 f
.write(static_network
)
2953 # When networkd started, the links are already configured, so let's wait for 5 seconds
2954 # the links to be re-configured.
2956 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
2958 output
= check_output('ip -4 address show dev veth99 scope global')
2960 self
.assertRegex(output
, '192.168.5')
2961 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2963 output
= check_output('ip -6 address show dev veth99 scope global')
2965 self
.assertRegex(output
, '2600::')
2966 self
.assertRegex(output
, 'valid_lft forever preferred_lft forever')
2968 @expectedFailureIfModuleIsNotAvailable('vrf')
2969 def test_dhcp_client_vrf(self
):
2970 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2971 '25-vrf.netdev', '25-vrf.network')
2973 self
.wait_online(['veth-peer:carrier'])
2975 self
.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2977 # link become 'routable' when at least one protocol provide an valid address.
2978 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
2979 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
2981 print('## ip -d link show dev vrf99')
2982 output
= check_output('ip -d link show dev vrf99')
2984 self
.assertRegex(output
, 'vrf table 42')
2986 print('## ip address show vrf vrf99')
2987 output
= check_output('ip address show vrf vrf99')
2989 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2990 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2991 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2992 self
.assertRegex(output
, 'inet6 .* scope link')
2994 print('## ip address show dev veth99')
2995 output
= check_output('ip address show dev veth99')
2997 self
.assertRegex(output
, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2998 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2999 self
.assertRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
3000 self
.assertRegex(output
, 'inet6 .* scope link')
3002 print('## ip route show vrf vrf99')
3003 output
= check_output('ip route show vrf vrf99')
3005 self
.assertRegex(output
, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3006 self
.assertRegex(output
, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3007 self
.assertRegex(output
, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3008 self
.assertRegex(output
, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3009 self
.assertRegex(output
, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3011 print('## ip route show table main dev veth99')
3012 output
= check_output('ip route show table main dev veth99')
3014 self
.assertEqual(output
, '')
3016 def test_dhcp_client_gateway_onlink_implicit(self
):
3017 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3018 'dhcp-client-gateway-onlink-implicit.network')
3020 self
.wait_online(['veth-peer:carrier'])
3022 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3024 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3026 self
.assertRegex(output
, '192.168.5')
3028 output
= check_output('ip route list dev veth99 10.0.0.0/8')
3030 self
.assertRegex(output
, 'onlink')
3031 output
= check_output('ip route list dev veth99 192.168.100.0/24')
3033 self
.assertRegex(output
, 'onlink')
3035 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self
):
3036 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3037 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3039 self
.wait_online(['veth-peer:carrier'])
3040 start_dnsmasq(lease_time
='2m')
3041 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3043 output
= check_output('ip address show dev veth99')
3046 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3047 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3048 output
= check_output('ip -6 address show dev veth99 scope link')
3049 self
.assertRegex(output
, 'inet6 .* scope link')
3050 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3051 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3052 output
= check_output('ip -4 address show dev veth99 scope link')
3053 self
.assertNotRegex(output
, 'inet .* scope link')
3055 print('Wait for the dynamic address to be expired')
3058 output
= check_output('ip address show dev veth99')
3061 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3062 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3063 output
= check_output('ip -6 address show dev veth99 scope link')
3064 self
.assertRegex(output
, 'inet6 .* scope link')
3065 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3066 self
.assertRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3067 output
= check_output('ip -4 address show dev veth99 scope link')
3068 self
.assertNotRegex(output
, 'inet .* scope link')
3070 search_words_in_dnsmasq_log('DHCPOFFER', show_all
=True)
3072 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self
):
3073 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3074 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3076 self
.wait_online(['veth99:degraded', 'veth-peer:routable'])
3078 output
= check_output('ip address show dev veth99')
3081 output
= check_output('ip -6 address show dev veth99 scope global dynamic')
3082 self
.assertNotRegex(output
, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3083 output
= check_output('ip -6 address show dev veth99 scope link')
3084 self
.assertRegex(output
, 'inet6 .* scope link')
3085 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3086 self
.assertNotRegex(output
, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3087 output
= check_output('ip -4 address show dev veth99 scope link')
3088 self
.assertRegex(output
, 'inet .* scope link')
3090 def test_dhcp_client_route_remove_on_renew(self
):
3091 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3092 'dhcp-client-ipv4-only-ipv6-disabled.network')
3094 self
.wait_online(['veth-peer:carrier'])
3095 start_dnsmasq(ipv4_range
='192.168.5.100,192.168.5.199', lease_time
='2m')
3096 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3098 # test for issue #12490
3100 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3102 self
.assertRegex(output
, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3104 for line
in output
.splitlines():
3105 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3106 address1
= line
.split()[1].split('/')[0]
3109 output
= check_output('ip -4 route show dev veth99')
3111 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3112 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3114 stop_dnsmasq(dnsmasq_pid_file
)
3115 start_dnsmasq(ipv4_range
='192.168.5.200,192.168.5.250', lease_time
='2m')
3117 print('Wait for the dynamic address to be expired')
3120 output
= check_output('ip -4 address show dev veth99 scope global dynamic')
3122 self
.assertRegex(output
, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3124 for line
in output
.splitlines():
3125 if 'brd 192.168.5.255 scope global dynamic veth99' in line
:
3126 address2
= line
.split()[1].split('/')[0]
3129 self
.assertNotEqual(address1
, address2
)
3131 output
= check_output('ip -4 route show dev veth99')
3133 self
.assertNotRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3134 self
.assertNotRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3135 self
.assertRegex(output
, f
'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3136 self
.assertRegex(output
, f
'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3138 def test_dhcp_client_use_dns_yes(self
):
3139 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3142 self
.wait_online(['veth-peer:carrier'])
3143 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3144 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3146 # link become 'routable' when at least one protocol provide an valid address.
3147 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3148 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3151 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3153 self
.assertRegex(output
, '192.168.5.1')
3154 self
.assertRegex(output
, '2600::1')
3156 def test_dhcp_client_use_dns_no(self
):
3157 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3160 self
.wait_online(['veth-peer:carrier'])
3161 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3162 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3164 # link become 'routable' when at least one protocol provide an valid address.
3165 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3166 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3169 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3171 self
.assertNotRegex(output
, '192.168.5.1')
3172 self
.assertNotRegex(output
, '2600::1')
3174 def test_dhcp_client_use_dns_ipv4(self
):
3175 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3178 self
.wait_online(['veth-peer:carrier'])
3179 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3180 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3182 # link become 'routable' when at least one protocol provide an valid address.
3183 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3184 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3187 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3189 self
.assertRegex(output
, '192.168.5.1')
3190 self
.assertNotRegex(output
, '2600::1')
3192 def test_dhcp_client_use_dns_ipv4_and_ra(self
):
3193 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3196 self
.wait_online(['veth-peer:carrier'])
3197 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3198 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3200 # link become 'routable' when at least one protocol provide an valid address.
3201 self
.wait_address('veth99', r
'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv
='-4')
3202 self
.wait_address('veth99', r
'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv
='-6')
3205 output
= check_output(*resolvectl_cmd
, 'dns', 'veth99', env
=env
)
3207 self
.assertRegex(output
, '192.168.5.1')
3208 self
.assertRegex(output
, '2600::1')
3210 def test_dhcp_client_use_domains(self
):
3211 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3214 self
.wait_online(['veth-peer:carrier'])
3215 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3216 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3218 output
= check_output(*networkctl_cmd
, 'status', 'veth99', env
=env
)
3220 self
.assertRegex(output
, 'Search Domains: example.com')
3223 output
= check_output(*resolvectl_cmd
, 'domain', 'veth99', env
=env
)
3225 self
.assertRegex(output
, 'example.com')
3227 class NetworkdIPv6PrefixTests(unittest
.TestCase
, Utilities
):
3232 'ipv6ra-prefix-client.network',
3233 'ipv6ra-prefix.network'
3237 remove_links(self
.links
)
3238 stop_networkd(show_logs
=False)
3242 remove_links(self
.links
)
3243 remove_unit_from_networkd_path(self
.units
)
3244 stop_networkd(show_logs
=True)
3246 def test_ipv6_route_prefix(self
):
3247 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3250 self
.wait_online(['veth99:routable', 'veth-peer:routable'])
3252 output
= check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3254 self
.assertRegex(output
, '2001:db8:0:1::/64 proto ra')
3256 if __name__
== '__main__':
3257 parser
= argparse
.ArgumentParser()
3258 parser
.add_argument('--build-dir', help='Path to build dir', dest
='build_dir')
3259 parser
.add_argument('--networkd', help='Path to systemd-networkd', dest
='networkd_bin')
3260 parser
.add_argument('--resolved', help='Path to systemd-resolved', dest
='resolved_bin')
3261 parser
.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest
='wait_online_bin')
3262 parser
.add_argument('--networkctl', help='Path to networkctl', dest
='networkctl_bin')
3263 parser
.add_argument('--resolvectl', help='Path to resolvectl', dest
='resolvectl_bin')
3264 parser
.add_argument('--timedatectl', help='Path to timedatectl', dest
='timedatectl_bin')
3265 parser
.add_argument('--valgrind', help='Enable valgrind', dest
='use_valgrind', type=bool, nargs
='?', const
=True, default
=use_valgrind
)
3266 parser
.add_argument('--debug', help='Generate debugging logs', dest
='enable_debug', type=bool, nargs
='?', const
=True, default
=enable_debug
)
3267 parser
.add_argument('--asan-options', help='ASAN options', dest
='asan_options')
3268 parser
.add_argument('--lsan-options', help='LSAN options', dest
='lsan_options')
3269 parser
.add_argument('--ubsan-options', help='UBSAN options', dest
='ubsan_options')
3270 ns
, args
= parser
.parse_known_args(namespace
=unittest
)
3273 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
:
3274 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3275 networkd_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd')
3276 resolved_bin
= os
.path
.join(ns
.build_dir
, 'systemd-resolved')
3277 wait_online_bin
= os
.path
.join(ns
.build_dir
, 'systemd-networkd-wait-online')
3278 networkctl_bin
= os
.path
.join(ns
.build_dir
, 'networkctl')
3279 resolvectl_bin
= os
.path
.join(ns
.build_dir
, 'resolvectl')
3280 timedatectl_bin
= os
.path
.join(ns
.build_dir
, 'timedatectl')
3283 networkd_bin
= ns
.networkd_bin
3285 resolved_bin
= ns
.resolved_bin
3286 if ns
.wait_online_bin
:
3287 wait_online_bin
= ns
.wait_online_bin
3288 if ns
.networkctl_bin
:
3289 networkctl_bin
= ns
.networkctl_bin
3290 if ns
.resolvectl_bin
:
3291 resolvectl_bin
= ns
.resolvectl_bin
3292 if ns
.timedatectl_bin
:
3293 timedatectl_bin
= ns
.timedatectl_bin
3295 use_valgrind
= ns
.use_valgrind
3296 enable_debug
= ns
.enable_debug
3297 asan_options
= ns
.asan_options
3298 lsan_options
= ns
.lsan_options
3299 ubsan_options
= ns
.ubsan_options
3302 networkctl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin
]
3303 resolvectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin
]
3304 timedatectl_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin
]
3305 wait_online_cmd
= ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin
]
3307 networkctl_cmd
= [networkctl_bin
]
3308 resolvectl_cmd
= [resolvectl_bin
]
3309 timedatectl_cmd
= [timedatectl_bin
]
3310 wait_online_cmd
= [wait_online_bin
]
3313 env
.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3315 env
.update({ 'ASAN_OPTIONS' : asan_options
})
3317 env
.update({ 'LSAN_OPTIONS' : lsan_options
})
3319 env
.update({ 'UBSAN_OPTIONS' : ubsan_options
})
3322 unittest
.main(testRunner
=unittest
.TextTestRunner(stream
=sys
.stdout
,