]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #16047 from poettering/udev-ro-block
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
4
5 import argparse
6 import itertools
7 import os
8 import re
9 import shutil
10 import signal
11 import subprocess
12 import sys
13 import time
14 import unittest
15 from shutil import copytree
16
17 network_unit_file_path='/run/systemd/network'
18 networkd_runtime_directory='/run/systemd/netif'
19 networkd_ci_path='/run/networkd-ci'
20 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
21 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
22
23 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
24 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
25
26 systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
27 which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
28
29 networkd_bin=shutil.which('systemd-networkd', path=which_paths)
30 resolved_bin=shutil.which('systemd-resolved', path=which_paths)
31 udevd_bin=shutil.which('systemd-udevd', path=which_paths)
32 wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
33 networkctl_bin=shutil.which('networkctl', path=which_paths)
34 resolvectl_bin=shutil.which('resolvectl', path=which_paths)
35 timedatectl_bin=shutil.which('timedatectl', path=which_paths)
36
37 use_valgrind=False
38 enable_debug=True
39 env = {}
40 asan_options=None
41 lsan_options=None
42 ubsan_options=None
43
44 running_units = []
45
46 def check_output(*command, **kwargs):
47 # This replaces both check_output and check_call (output can be ignored)
48 command = command[0].split() + list(command[1:])
49 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
50
51 def call(*command, **kwargs):
52 command = command[0].split() + list(command[1:])
53 return subprocess.call(command, universal_newlines=True, **kwargs)
54
55 def run(*command, **kwargs):
56 command = command[0].split() + list(command[1:])
57 return subprocess.run(command, universal_newlines=True, **kwargs)
58
59 def is_module_available(module_name):
60 lsmod_output = check_output('lsmod')
61 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
62 return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
63
64 def expectedFailureIfModuleIsNotAvailable(module_name):
65 def f(func):
66 if not is_module_available(module_name):
67 return unittest.expectedFailure(func)
68 return func
69
70 return f
71
72 def expectedFailureIfERSPANModuleIsNotAvailable():
73 def f(func):
74 rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr=subprocess.DEVNULL)
75 if rc == 0:
76 call('ip link del erspan99')
77 return func
78 else:
79 return unittest.expectedFailure(func)
80
81 return f
82
83 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
84 def f(func):
85 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
86 if rc == 0:
87 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
88 return func
89 else:
90 return unittest.expectedFailure(func)
91
92 return f
93
94 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
95 def f(func):
96 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
97 if rc == 0:
98 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
99 return func
100 else:
101 return unittest.expectedFailure(func)
102
103 return f
104
105 def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
106 def f(func):
107 support = False
108 rc = call('ip rule add from 192.168.100.19 table 7 uidrange 200-300', stderr=subprocess.DEVNULL)
109 if rc == 0:
110 ret = run('ip rule list from 192.168.100.19 table 7', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
111 if ret.returncode == 0 and 'uidrange 200-300' in ret.stdout.rstrip():
112 support = True
113 call('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
114
115 if support:
116 return func
117 else:
118 return unittest.expectedFailure(func)
119
120 return f
121
122 def expectedFailureIfLinkFileFieldIsNotSet():
123 def f(func):
124 support = False
125 rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
126 if rc == 0:
127 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
128 if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
129 support = True
130 call('ip link del dummy99')
131
132 if support:
133 return func
134 else:
135 return unittest.expectedFailure(func)
136
137 return f
138
139 def expectedFailureIfNexthopIsNotAvailable():
140 def f(func):
141 rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
142 if rc == 0:
143 return func
144 else:
145 return unittest.expectedFailure(func)
146
147 return f
148
149 def expectedFailureIfAlternativeNameIsNotAvailable():
150 def f(func):
151 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
152 rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
153 call('ip link del dummy98', stderr=subprocess.DEVNULL)
154 if rc == 0:
155 return func
156 else:
157 return unittest.expectedFailure(func)
158
159 return f
160
161 def expectedFailureIfCAKEIsNotAvailable():
162 def f(func):
163 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
164 rc = call('tc qdisc add dev dummy98 parent root cake', stderr=subprocess.DEVNULL)
165 call('ip link del dummy98', stderr=subprocess.DEVNULL)
166 if rc == 0:
167 return func
168 else:
169 return unittest.expectedFailure(func)
170
171 return f
172
173 def expectedFailureIfPIEIsNotAvailable():
174 def f(func):
175 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
176 rc = call('tc qdisc add dev dummy98 parent root pie', stderr=subprocess.DEVNULL)
177 call('ip link del dummy98', stderr=subprocess.DEVNULL)
178 if rc == 0:
179 return func
180 else:
181 return unittest.expectedFailure(func)
182
183 return f
184
185 def expectedFailureIfHHFIsNotAvailable():
186 def f(func):
187 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
188 rc = call('tc qdisc add dev dummy98 parent root hhf', stderr=subprocess.DEVNULL)
189 call('ip link del dummy98', stderr=subprocess.DEVNULL)
190 if rc == 0:
191 return func
192 else:
193 return unittest.expectedFailure(func)
194
195 return f
196
197 def setUpModule():
198 global running_units
199
200 os.makedirs(network_unit_file_path, exist_ok=True)
201 os.makedirs(networkd_ci_path, exist_ok=True)
202
203 shutil.rmtree(networkd_ci_path)
204 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
205
206 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service',
207 'systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service',
208 'firewalld.service']:
209 if call(f'systemctl is-active --quiet {u}') == 0:
210 check_output(f'systemctl stop {u}')
211 running_units.append(u)
212
213 drop_in = [
214 '[Unit]',
215 'StartLimitIntervalSec=0',
216 '[Service]',
217 'Restart=no',
218 'ExecStart=',
219 ]
220 if use_valgrind:
221 drop_in += [
222 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
223 'PrivateTmp=yes'
224 ]
225 else:
226 drop_in += ['ExecStart=!!' + networkd_bin]
227 if enable_debug:
228 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
229 if asan_options:
230 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
231 if lsan_options:
232 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
233 if ubsan_options:
234 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
235 if asan_options or lsan_options or ubsan_options:
236 drop_in += ['SystemCallFilter=']
237 if use_valgrind or asan_options or lsan_options or ubsan_options:
238 drop_in += ['MemoryDenyWriteExecute=no']
239
240 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
241 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
242 f.write('\n'.join(drop_in))
243
244 drop_in = [
245 '[Service]',
246 'Restart=no',
247 'ExecStart=',
248 ]
249 if use_valgrind:
250 drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin]
251 else:
252 drop_in += ['ExecStart=!!' + resolved_bin]
253 if enable_debug:
254 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
255 if asan_options:
256 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
257 if lsan_options:
258 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
259 if ubsan_options:
260 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
261 if asan_options or lsan_options or ubsan_options:
262 drop_in += ['SystemCallFilter=']
263 if use_valgrind or asan_options or lsan_options or ubsan_options:
264 drop_in += ['MemoryDenyWriteExecute=no']
265
266 os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True)
267 with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f:
268 f.write('\n'.join(drop_in))
269
270 drop_in = [
271 '[Service]',
272 'ExecStart=',
273 'ExecStart=!!' + udevd_bin,
274 ]
275
276 os.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok=True)
277 with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w') as f:
278 f.write('\n'.join(drop_in))
279
280 check_output('systemctl daemon-reload')
281 print(check_output('systemctl cat systemd-networkd.service'))
282 print(check_output('systemctl cat systemd-resolved.service'))
283 print(check_output('systemctl cat systemd-udevd.service'))
284 check_output('systemctl restart systemd-resolved')
285 check_output('systemctl restart systemd-udevd')
286
287 def tearDownModule():
288 global running_units
289
290 shutil.rmtree(networkd_ci_path)
291
292 for u in ['systemd-networkd.service', 'systemd-resolved.service']:
293 check_output(f'systemctl stop {u}')
294
295 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
296 shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
297 shutil.rmtree('/run/systemd/system/systemd-udevd.service.d')
298 check_output('systemctl daemon-reload')
299 check_output('systemctl restart systemd-udevd.service')
300
301 for u in running_units:
302 check_output(f'systemctl start {u}')
303
304 def read_link_attr(*args):
305 with open(os.path.join('/sys/class/net/', *args)) as f:
306 return f.readline().strip()
307
308 def read_bridge_port_attr(bridge, link, attribute):
309 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
310 path_port = 'lower_' + link + '/brport'
311 path = os.path.join(path_bridge, path_port)
312
313 with open(os.path.join(path, attribute)) as f:
314 return f.readline().strip()
315
316 def link_exists(link):
317 return os.path.exists(os.path.join('/sys/class/net', link))
318
319 def remove_links(links):
320 for link in links:
321 if link_exists(link):
322 call('ip link del dev', link)
323 time.sleep(1)
324
325 def remove_fou_ports(ports):
326 for port in ports:
327 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
328
329 def remove_routing_policy_rule_tables(tables):
330 for table in tables:
331 rc = 0
332 while rc == 0:
333 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
334
335 def remove_routes(routes):
336 for route_type, addr in routes:
337 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
338
339 def remove_l2tp_tunnels(tunnel_ids):
340 output = check_output('ip l2tp show tunnel')
341 for tid in tunnel_ids:
342 words='Tunnel ' + tid + ', encap'
343 if words in output:
344 call('ip l2tp del tunnel tid', tid)
345 time.sleep(1)
346
347 def read_ipv6_sysctl_attr(link, attribute):
348 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
349 return f.readline().strip()
350
351 def read_ipv4_sysctl_attr(link, attribute):
352 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
353 return f.readline().strip()
354
355 def copy_unit_to_networkd_unit_path(*units, dropins=True):
356 """Copy networkd unit files into the testbed.
357
358 Any networkd unit file type can be specified, as well as drop-in files.
359
360 By default, all drop-ins for a specified unit file are copied in;
361 to avoid that specify dropins=False.
362
363 When a drop-in file is specified, its unit file is also copied in automatically.
364 """
365 print()
366 for unit in units:
367 if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')):
368 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
369 if unit.endswith('.conf'):
370 dropin = unit
371 dropindir = os.path.join(network_unit_file_path, os.path.dirname(dropin))
372 os.makedirs(dropindir, exist_ok=True)
373 shutil.copy(os.path.join(networkd_ci_path, dropin), dropindir)
374 unit = os.path.dirname(dropin).rstrip('.d')
375 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
376
377 def remove_unit_from_networkd_path(units):
378 """Remove previously copied unit files from the testbed.
379
380 Drop-ins will be removed automatically.
381 """
382 for unit in units:
383 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
384 os.remove(os.path.join(network_unit_file_path, unit))
385 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
386 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
387
388 def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
389 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
390 check_output(dnsmasq_command)
391
392 def stop_dnsmasq(pid_file):
393 if os.path.exists(pid_file):
394 with open(pid_file, 'r') as f:
395 pid = f.read().rstrip(' \t\r\n\0')
396 os.kill(int(pid), signal.SIGTERM)
397
398 os.remove(pid_file)
399
400 def search_words_in_dnsmasq_log(words, show_all=False):
401 if os.path.exists(dnsmasq_log_file):
402 with open (dnsmasq_log_file) as in_file:
403 contents = in_file.read()
404 if show_all:
405 print(contents)
406 for line in contents.splitlines():
407 if words in line:
408 in_file.close()
409 print("%s, %s" % (words, line))
410 return True
411 return False
412
413 def remove_lease_file():
414 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
415 os.remove(os.path.join(networkd_ci_path, 'lease'))
416
417 def remove_log_file():
418 if os.path.exists(dnsmasq_log_file):
419 os.remove(dnsmasq_log_file)
420
421 def remove_networkd_state_files():
422 if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
423 os.remove(os.path.join(networkd_runtime_directory, 'state'))
424
425 def stop_networkd(show_logs=True, remove_state_files=True):
426 if show_logs:
427 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
428 check_output('systemctl stop systemd-networkd')
429 if show_logs:
430 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
431 if remove_state_files:
432 remove_networkd_state_files()
433
434 def start_networkd(sleep_sec=0):
435 check_output('systemctl start systemd-networkd')
436 if sleep_sec > 0:
437 time.sleep(sleep_sec)
438
439 def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
440 stop_networkd(show_logs, remove_state_files)
441 start_networkd(sleep_sec)
442
443
444 class Utilities():
445 def check_link_exists(self, link):
446 self.assertTrue(link_exists(link))
447
448 def check_link_attr(self, *args):
449 self.assertEqual(read_link_attr(*args[:-1]), args[-1]);
450
451 def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
452 """Wait for the link to reach the specified operstate and/or setup state.
453
454 Specify None or '' for either operstate or setup_state to ignore that state.
455 This will recheck until the state conditions are met or the timeout expires.
456
457 If the link successfully matches the requested state, this returns True.
458 If this times out waiting for the link to match, the behavior depends on the
459 'fail_assert' parameter; if True, this causes a test assertion failure,
460 otherwise this returns False. The default is to cause assertion failure.
461
462 Note that this function matches on *exactly* the given operstate and setup_state.
463 To wait for a link to reach *or exceed* a given operstate, use wait_online().
464 """
465 if not operstate:
466 operstate = r'\S+'
467 if not setup_state:
468 setup_state = r'\S+'
469
470 for secs in range(setup_timeout + 1):
471 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env)
472 print(output)
473 if re.search(rf'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output):
474 return True
475 # don't bother sleeping if time is up
476 if secs < setup_timeout:
477 time.sleep(1)
478 if fail_assert:
479 self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
480 return False
481
482 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured', setup_timeout=5):
483 """Wait for the link(s) to reach the specified operstate and/or setup state.
484
485 This is similar to wait_operstate() but can be used for multiple links,
486 and it also calls systemd-networkd-wait-online to wait for the given operstate.
487 The operstate should be specified in the link name, like 'eth0:degraded'.
488 If just a link name is provided, wait-online's default operstate to wait for is degraded.
489
490 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the
491 'setup_timeout' controls the per-link timeout waiting for the setup_state.
492
493 Set 'bool_any' to True to wait for any (instead of all) of the given links.
494 If this is set, no setup_state checks are done.
495
496 Note that this function waits for the link(s) to reach *or exceed* the given operstate.
497 However, the setup_state, if specified, must be matched *exactly*.
498
499 This returns if the link(s) reached the requested operstate/setup_state; otherwise it
500 raises CalledProcessError or fails test assertion.
501 """
502 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
503 if bool_any:
504 args += ['--any']
505 try:
506 check_output(*args, env=env)
507 except subprocess.CalledProcessError:
508 for link in links_with_operstate:
509 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env)
510 print(output)
511 raise
512 if not bool_any and setup_state:
513 for link in links_with_operstate:
514 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout)
515
516 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
517 for i in range(timeout_sec):
518 if i > 0:
519 time.sleep(1)
520 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
521 if re.search(address_regex, output):
522 break
523 else:
524 self.assertRegex(output, address_regex)
525
526 class NetworkctlTests(unittest.TestCase, Utilities):
527
528 links = [
529 'dummy98',
530 'test1',
531 'veth99',
532 ]
533
534 units = [
535 '11-dummy.netdev',
536 '11-dummy-mtu.netdev',
537 '11-dummy.network',
538 '12-dummy.netdev',
539 '12-dummy.link',
540 '25-address-static.network',
541 '25-veth.netdev',
542 'netdev-link-local-addressing-yes.network',
543 ]
544
545 def setUp(self):
546 remove_links(self.links)
547 stop_networkd(show_logs=False)
548
549 def tearDown(self):
550 remove_links(self.links)
551 remove_unit_from_networkd_path(self.units)
552 stop_networkd(show_logs=True)
553
554 @expectedFailureIfAlternativeNameIsNotAvailable()
555 def test_altname(self):
556 copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
557 check_output('udevadm control --reload')
558 start_networkd()
559 self.wait_online(['dummy98:degraded'])
560
561 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
562 self.assertRegex(output, 'hogehogehogehogehogehoge')
563
564 def test_reconfigure(self):
565 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
566 start_networkd()
567 self.wait_online(['dummy98:routable'])
568
569 output = check_output('ip -4 address show dev dummy98')
570 print(output)
571 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
572 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
573 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
574
575 check_output('ip address del 10.1.2.3/16 dev dummy98')
576 check_output('ip address del 10.1.2.4/16 dev dummy98')
577 check_output('ip address del 10.2.2.4/16 dev dummy98')
578
579 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
580 self.wait_online(['dummy98:routable'])
581
582 output = check_output('ip -4 address show dev dummy98')
583 print(output)
584 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
585 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
586 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
587
588 def test_reload(self):
589 start_networkd(3)
590
591 copy_unit_to_networkd_unit_path('11-dummy.netdev')
592 check_output(*networkctl_cmd, 'reload', env=env)
593 self.wait_operstate('test1', 'off', setup_state='unmanaged')
594
595 copy_unit_to_networkd_unit_path('11-dummy.network')
596 check_output(*networkctl_cmd, 'reload', env=env)
597 self.wait_online(['test1:degraded'])
598
599 remove_unit_from_networkd_path(['11-dummy.network'])
600 check_output(*networkctl_cmd, 'reload', env=env)
601 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
602
603 remove_unit_from_networkd_path(['11-dummy.netdev'])
604 check_output(*networkctl_cmd, 'reload', env=env)
605 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
606
607 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
608 check_output(*networkctl_cmd, 'reload', env=env)
609 self.wait_operstate('test1', 'degraded')
610
611 def test_glob(self):
612 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
613 start_networkd()
614
615 self.wait_online(['test1:degraded'])
616
617 output = check_output(*networkctl_cmd, 'list', env=env)
618 self.assertRegex(output, '1 lo ')
619 self.assertRegex(output, 'test1')
620
621 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
622 self.assertNotRegex(output, '1 lo ')
623 self.assertRegex(output, 'test1')
624
625 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
626 self.assertNotRegex(output, '1 lo ')
627 self.assertRegex(output, 'test1')
628
629 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
630 self.assertNotRegex(output, '1: lo ')
631 self.assertRegex(output, 'test1')
632
633 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
634 self.assertNotRegex(output, '1: lo ')
635 self.assertRegex(output, 'test1')
636
637 def test_mtu(self):
638 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
639 start_networkd()
640
641 self.wait_online(['test1:degraded'])
642
643 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
644 self.assertRegex(output, 'MTU: 1600')
645
646 def test_type(self):
647 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
648 start_networkd()
649 self.wait_online(['test1:degraded'])
650
651 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
652 print(output)
653 self.assertRegex(output, 'Type: ether')
654
655 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
656 print(output)
657 self.assertRegex(output, 'Type: loopback')
658
659 @expectedFailureIfLinkFileFieldIsNotSet()
660 def test_udev_link_file(self):
661 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
662 start_networkd()
663 self.wait_online(['test1:degraded'])
664
665 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
666 print(output)
667 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
668 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
669
670 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
671 print(output)
672 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
673 self.assertRegex(output, r'Network File: n/a')
674
675 def test_delete_links(self):
676 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
677 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
678 start_networkd()
679
680 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
681
682 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
683 self.assertFalse(link_exists('test1'))
684 self.assertFalse(link_exists('veth99'))
685 self.assertFalse(link_exists('veth-peer'))
686
687 class NetworkdNetDevTests(unittest.TestCase, Utilities):
688
689 links_remove_earlier = [
690 'xfrm99',
691 ]
692
693 links = [
694 '6rdtun99',
695 'bond99',
696 'bridge99',
697 'dropin-test',
698 'dummy98',
699 'erspan98',
700 'erspan99',
701 'geneve99',
702 'gretap96',
703 'gretap98',
704 'gretap99',
705 'gretun96',
706 'gretun97',
707 'gretun98',
708 'gretun99',
709 'ifb99',
710 'ip6gretap98',
711 'ip6gretap99',
712 'ip6gretun96',
713 'ip6gretun97',
714 'ip6gretun98',
715 'ip6gretun99',
716 'ip6tnl97',
717 'ip6tnl98',
718 'ip6tnl99',
719 'ipiptun96',
720 'ipiptun97',
721 'ipiptun98',
722 'ipiptun99',
723 'ipvlan99',
724 'ipvtap99',
725 'isataptun99',
726 'macvlan99',
727 'macvtap99',
728 'nlmon99',
729 'sittun96',
730 'sittun97',
731 'sittun98',
732 'sittun99',
733 'tap99',
734 'test1',
735 'tun99',
736 'vcan99',
737 'veth99',
738 'vlan99',
739 'vrf99',
740 'vti6tun97',
741 'vti6tun98',
742 'vti6tun99',
743 'vtitun96',
744 'vtitun97',
745 'vtitun98',
746 'vtitun99',
747 'vxcan99',
748 'vxlan99',
749 'wg97',
750 'wg98',
751 'wg99',
752 ]
753
754 units = [
755 '10-dropin-test.netdev',
756 '11-dummy.netdev',
757 '11-dummy.network',
758 '12-dummy.netdev',
759 '13-not-match-udev-property.network',
760 '14-match-udev-property.network',
761 '15-name-conflict-test.netdev',
762 '21-macvlan.netdev',
763 '21-macvtap.netdev',
764 '21-vlan-test1.network',
765 '21-vlan.netdev',
766 '21-vlan.network',
767 '25-6rd-tunnel.netdev',
768 '25-bond.netdev',
769 '25-bond-balanced-tlb.netdev',
770 '25-bridge.netdev',
771 '25-bridge-configure-without-carrier.network',
772 '25-bridge.network',
773 '25-erspan-tunnel-local-any.netdev',
774 '25-erspan-tunnel.netdev',
775 '25-fou-gretap.netdev',
776 '25-fou-gre.netdev',
777 '25-fou-ipip.netdev',
778 '25-fou-ipproto-gre.netdev',
779 '25-fou-ipproto-ipip.netdev',
780 '25-fou-sit.netdev',
781 '25-geneve.netdev',
782 '25-gretap-tunnel-local-any.netdev',
783 '25-gretap-tunnel.netdev',
784 '25-gre-tunnel-any-any.netdev',
785 '25-gre-tunnel-local-any.netdev',
786 '25-gre-tunnel-remote-any.netdev',
787 '25-gre-tunnel.netdev',
788 '25-ifb.netdev',
789 '25-ip6gretap-tunnel-local-any.netdev',
790 '25-ip6gretap-tunnel.netdev',
791 '25-ip6gre-tunnel-any-any.netdev',
792 '25-ip6gre-tunnel-local-any.netdev',
793 '25-ip6gre-tunnel-remote-any.netdev',
794 '25-ip6gre-tunnel.netdev',
795 '25-ip6tnl-tunnel-any-any.netdev',
796 '25-ip6tnl-tunnel-local-any.netdev',
797 '25-ip6tnl-tunnel-remote-any.netdev',
798 '25-ip6tnl-tunnel.netdev',
799 '25-ipip-tunnel-any-any.netdev',
800 '25-ipip-tunnel-independent.netdev',
801 '25-ipip-tunnel-independent-loopback.netdev',
802 '25-ipip-tunnel-local-any.netdev',
803 '25-ipip-tunnel-remote-any.netdev',
804 '25-ipip-tunnel.netdev',
805 '25-ipvlan.netdev',
806 '25-ipvtap.netdev',
807 '25-isatap-tunnel.netdev',
808 '25-macsec.key',
809 '25-macsec.netdev',
810 '25-macsec.network',
811 '25-nlmon.netdev',
812 '25-sit-tunnel-any-any.netdev',
813 '25-sit-tunnel-local-any.netdev',
814 '25-sit-tunnel-remote-any.netdev',
815 '25-sit-tunnel.netdev',
816 '25-tap.netdev',
817 '25-tun.netdev',
818 '25-tunnel-local-any.network',
819 '25-tunnel-remote-any.network',
820 '25-tunnel.network',
821 '25-vcan.netdev',
822 '25-veth.netdev',
823 '25-vrf.netdev',
824 '25-vti6-tunnel-any-any.netdev',
825 '25-vti6-tunnel-local-any.netdev',
826 '25-vti6-tunnel-remote-any.netdev',
827 '25-vti6-tunnel.netdev',
828 '25-vti-tunnel-any-any.netdev',
829 '25-vti-tunnel-local-any.netdev',
830 '25-vti-tunnel-remote-any.netdev',
831 '25-vti-tunnel.netdev',
832 '25-vxcan.netdev',
833 '25-vxlan.netdev',
834 '25-wireguard-23-peers.netdev',
835 '25-wireguard-23-peers.network',
836 '25-wireguard-no-peer.netdev',
837 '25-wireguard-no-peer.network',
838 '25-wireguard-preshared-key.txt',
839 '25-wireguard-private-key.txt',
840 '25-wireguard.netdev',
841 '25-wireguard.network',
842 '25-xfrm.netdev',
843 '25-xfrm-independent.netdev',
844 '6rd.network',
845 'erspan.network',
846 'gre.network',
847 'gretap.network',
848 'gretun.network',
849 'ip6gretap.network',
850 'ip6gretun.network',
851 'ip6tnl.network',
852 'ipip.network',
853 'ipvlan.network',
854 'ipvtap.network',
855 'isatap.network',
856 'macsec.network',
857 'macvlan.network',
858 'macvtap.network',
859 'netdev-link-local-addressing-yes.network',
860 'sit.network',
861 'vti6.network',
862 'vti.network',
863 'vxlan-test1.network',
864 'vxlan.network',
865 'xfrm.network',
866 ]
867
868 fou_ports = [
869 '55555',
870 '55556']
871
872 def setUp(self):
873 remove_fou_ports(self.fou_ports)
874 remove_links(self.links_remove_earlier)
875 remove_links(self.links)
876 stop_networkd(show_logs=False)
877
878 def tearDown(self):
879 remove_fou_ports(self.fou_ports)
880 remove_links(self.links_remove_earlier)
881 remove_links(self.links)
882 remove_unit_from_networkd_path(self.units)
883 stop_networkd(show_logs=True)
884
885 def test_dropin_and_name_conflict(self):
886 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
887 start_networkd()
888
889 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
890
891 output = check_output('ip link show dropin-test')
892 print(output)
893 self.assertRegex(output, '00:50:56:c0:00:28')
894
895 def test_match_udev_property(self):
896 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
897 start_networkd()
898 self.wait_online(['dummy98:routable'])
899
900 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
901 print(output)
902 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
903
904 def test_wait_online_any(self):
905 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
906 start_networkd()
907
908 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
909
910 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
911 self.wait_operstate('test1', 'degraded')
912
913 def test_bridge(self):
914 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
915 start_networkd()
916
917 self.wait_online(['bridge99:no-carrier'])
918
919 tick = os.sysconf('SC_CLK_TCK')
920 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
921 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
922 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick))
923 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick))
924 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
925 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
926 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
927 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
928 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
929
930 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
931 print(output)
932 self.assertRegex(output, 'Priority: 9')
933 self.assertRegex(output, 'STP: yes')
934 self.assertRegex(output, 'Multicast IGMP Version: 3')
935
936 def test_bond(self):
937 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
938 start_networkd()
939
940 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
941
942 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
943 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
944 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
945 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
946 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
947 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
948 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
949 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
950 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
951 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
952 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
953
954 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
955 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
956
957 def test_vlan(self):
958 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
959 '21-vlan.network', '21-vlan-test1.network')
960 start_networkd()
961
962 self.wait_online(['test1:degraded', 'vlan99:routable'])
963
964 output = check_output('ip -d link show test1')
965 print(output)
966 self.assertRegex(output, ' mtu 2000 ')
967
968 output = check_output('ip -d link show vlan99')
969 print(output)
970 self.assertRegex(output, ' mtu 2000 ')
971 self.assertRegex(output, 'REORDER_HDR')
972 self.assertRegex(output, 'LOOSE_BINDING')
973 self.assertRegex(output, 'GVRP')
974 self.assertRegex(output, 'MVRP')
975 self.assertRegex(output, ' id 99 ')
976
977 output = check_output('ip -4 address show dev test1')
978 print(output)
979 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
980 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
981
982 output = check_output('ip -4 address show dev vlan99')
983 print(output)
984 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
985
986 def test_macvtap(self):
987 for mode in ['private', 'vepa', 'bridge', 'passthru']:
988 with self.subTest(mode=mode):
989 if mode != 'private':
990 self.tearDown()
991 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
992 '11-dummy.netdev', 'macvtap.network')
993 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
994 f.write('[MACVTAP]\nMode=' + mode)
995 start_networkd()
996
997 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
998
999 output = check_output('ip -d link show macvtap99')
1000 print(output)
1001 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1002
1003 def test_macvlan(self):
1004 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1005 with self.subTest(mode=mode):
1006 if mode != 'private':
1007 self.tearDown()
1008 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
1009 '11-dummy.netdev', 'macvlan.network')
1010 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
1011 f.write('[MACVLAN]\nMode=' + mode)
1012 start_networkd()
1013
1014 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
1015
1016 output = check_output('ip -d link show test1')
1017 print(output)
1018 self.assertRegex(output, ' mtu 2000 ')
1019
1020 output = check_output('ip -d link show macvlan99')
1021 print(output)
1022 self.assertRegex(output, ' mtu 2000 ')
1023 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
1024
1025 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1026 def test_ipvlan(self):
1027 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1028 with self.subTest(mode=mode, flag=flag):
1029 if mode != 'L2':
1030 self.tearDown()
1031 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1032 '11-dummy.netdev', 'ipvlan.network')
1033 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
1034 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1035
1036 start_networkd()
1037 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
1038
1039 output = check_output('ip -d link show ipvlan99')
1040 print(output)
1041 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1042
1043 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1044 def test_ipvtap(self):
1045 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1046 with self.subTest(mode=mode, flag=flag):
1047 if mode != 'L2':
1048 self.tearDown()
1049 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1050 '11-dummy.netdev', 'ipvtap.network')
1051 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
1052 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
1053
1054 start_networkd()
1055 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
1056
1057 output = check_output('ip -d link show ipvtap99')
1058 print(output)
1059 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
1060
1061 def test_veth(self):
1062 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
1063 start_networkd()
1064
1065 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1066
1067 output = check_output('ip -d link show veth99')
1068 print(output)
1069 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
1070 output = check_output('ip -d link show veth-peer')
1071 print(output)
1072 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1073
1074 def test_tun(self):
1075 copy_unit_to_networkd_unit_path('25-tun.netdev')
1076 start_networkd()
1077
1078 self.wait_online(['tun99:off'], setup_state='unmanaged')
1079
1080 output = check_output('ip -d link show tun99')
1081 print(output)
1082 # Old ip command does not support IFF_ flags
1083 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
1084
1085 def test_tap(self):
1086 copy_unit_to_networkd_unit_path('25-tap.netdev')
1087 start_networkd()
1088
1089 self.wait_online(['tap99:off'], setup_state='unmanaged')
1090
1091 output = check_output('ip -d link show tap99')
1092 print(output)
1093 # Old ip command does not support IFF_ flags
1094 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
1095
1096 @expectedFailureIfModuleIsNotAvailable('vrf')
1097 def test_vrf(self):
1098 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
1099 start_networkd()
1100
1101 self.wait_online(['vrf99:carrier'])
1102
1103 @expectedFailureIfModuleIsNotAvailable('vcan')
1104 def test_vcan(self):
1105 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
1106 start_networkd()
1107
1108 self.wait_online(['vcan99:carrier'])
1109
1110 @expectedFailureIfModuleIsNotAvailable('vxcan')
1111 def test_vxcan(self):
1112 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
1113 start_networkd()
1114
1115 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
1116
1117 @expectedFailureIfModuleIsNotAvailable('wireguard')
1118 def test_wireguard(self):
1119 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1120 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
1121 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
1122 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
1123 start_networkd()
1124 self.wait_online(['wg99:carrier', 'wg98:routable', 'wg97:carrier'])
1125
1126 if shutil.which('wg'):
1127 call('wg')
1128
1129 output = check_output('wg show wg99 listen-port')
1130 self.assertRegex(output, '51820')
1131 output = check_output('wg show wg99 fwmark')
1132 self.assertRegex(output, '0x4d2')
1133 output = check_output('wg show wg99 allowed-ips')
1134 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
1135 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
1136 output = check_output('wg show wg99 persistent-keepalive')
1137 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
1138 output = check_output('wg show wg99 endpoints')
1139 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
1140 output = check_output('wg show wg99 private-key')
1141 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
1142 output = check_output('wg show wg99 preshared-keys')
1143 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
1144 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
1145
1146 output = check_output('wg show wg98 private-key')
1147 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
1148
1149 output = check_output('wg show wg97 listen-port')
1150 self.assertRegex(output, '51821')
1151 output = check_output('wg show wg97 fwmark')
1152 self.assertRegex(output, '0x4d3')
1153
1154 def test_geneve(self):
1155 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
1156 start_networkd()
1157
1158 self.wait_online(['geneve99:degraded'])
1159
1160 output = check_output('ip -d link show geneve99')
1161 print(output)
1162 self.assertRegex(output, '192.168.22.1')
1163 self.assertRegex(output, '6082')
1164 self.assertRegex(output, 'udpcsum')
1165 self.assertRegex(output, 'udp6zerocsumrx')
1166
1167 def test_ipip_tunnel(self):
1168 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1169 '25-ipip-tunnel.netdev', '25-tunnel.network',
1170 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1171 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1172 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1173 start_networkd()
1174 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
1175
1176 output = check_output('ip -d link show ipiptun99')
1177 print(output)
1178 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
1179 output = check_output('ip -d link show ipiptun98')
1180 print(output)
1181 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
1182 output = check_output('ip -d link show ipiptun97')
1183 print(output)
1184 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
1185 output = check_output('ip -d link show ipiptun96')
1186 print(output)
1187 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1188
1189 def test_gre_tunnel(self):
1190 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1191 '25-gre-tunnel.netdev', '25-tunnel.network',
1192 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1193 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1194 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1195 start_networkd()
1196 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
1197
1198 output = check_output('ip -d link show gretun99')
1199 print(output)
1200 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1201 self.assertRegex(output, 'ikey 1.2.3.103')
1202 self.assertRegex(output, 'okey 1.2.4.103')
1203 self.assertRegex(output, 'iseq')
1204 self.assertRegex(output, 'oseq')
1205 output = check_output('ip -d link show gretun98')
1206 print(output)
1207 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
1208 self.assertRegex(output, 'ikey 0.0.0.104')
1209 self.assertRegex(output, 'okey 0.0.0.104')
1210 self.assertNotRegex(output, 'iseq')
1211 self.assertNotRegex(output, 'oseq')
1212 output = check_output('ip -d link show gretun97')
1213 print(output)
1214 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
1215 self.assertRegex(output, 'ikey 0.0.0.105')
1216 self.assertRegex(output, 'okey 0.0.0.105')
1217 self.assertNotRegex(output, 'iseq')
1218 self.assertNotRegex(output, 'oseq')
1219 output = check_output('ip -d link show gretun96')
1220 print(output)
1221 self.assertRegex(output, 'gre remote any local any dev dummy98')
1222 self.assertRegex(output, 'ikey 0.0.0.106')
1223 self.assertRegex(output, 'okey 0.0.0.106')
1224 self.assertNotRegex(output, 'iseq')
1225 self.assertNotRegex(output, 'oseq')
1226
1227 def test_ip6gre_tunnel(self):
1228 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1229 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1230 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1231 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1232 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1233 start_networkd(5)
1234
1235 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1236
1237 self.check_link_exists('dummy98')
1238 self.check_link_exists('ip6gretun99')
1239 self.check_link_exists('ip6gretun98')
1240 self.check_link_exists('ip6gretun97')
1241 self.check_link_exists('ip6gretun96')
1242
1243 output = check_output('ip -d link show ip6gretun99')
1244 print(output)
1245 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1246 output = check_output('ip -d link show ip6gretun98')
1247 print(output)
1248 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1249 output = check_output('ip -d link show ip6gretun97')
1250 print(output)
1251 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1252 output = check_output('ip -d link show ip6gretun96')
1253 print(output)
1254 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1255
1256 def test_gretap_tunnel(self):
1257 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1258 '25-gretap-tunnel.netdev', '25-tunnel.network',
1259 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1260 start_networkd()
1261 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1262
1263 output = check_output('ip -d link show gretap99')
1264 print(output)
1265 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1266 self.assertRegex(output, 'ikey 0.0.0.106')
1267 self.assertRegex(output, 'okey 0.0.0.106')
1268 self.assertRegex(output, 'iseq')
1269 self.assertRegex(output, 'oseq')
1270 output = check_output('ip -d link show gretap98')
1271 print(output)
1272 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
1273 self.assertRegex(output, 'ikey 0.0.0.107')
1274 self.assertRegex(output, 'okey 0.0.0.107')
1275 self.assertRegex(output, 'iseq')
1276 self.assertRegex(output, 'oseq')
1277
1278 def test_ip6gretap_tunnel(self):
1279 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1280 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1281 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1282 start_networkd()
1283 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1284
1285 output = check_output('ip -d link show ip6gretap99')
1286 print(output)
1287 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1288 output = check_output('ip -d link show ip6gretap98')
1289 print(output)
1290 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1291
1292 def test_vti_tunnel(self):
1293 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1294 '25-vti-tunnel.netdev', '25-tunnel.network',
1295 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1296 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1297 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1298 start_networkd()
1299 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1300
1301 output = check_output('ip -d link show vtitun99')
1302 print(output)
1303 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1304 output = check_output('ip -d link show vtitun98')
1305 print(output)
1306 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
1307 output = check_output('ip -d link show vtitun97')
1308 print(output)
1309 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
1310 output = check_output('ip -d link show vtitun96')
1311 print(output)
1312 self.assertRegex(output, 'vti remote any local any dev dummy98')
1313
1314 def test_vti6_tunnel(self):
1315 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1316 '25-vti6-tunnel.netdev', '25-tunnel.network',
1317 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1318 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1319 start_networkd()
1320 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1321
1322 output = check_output('ip -d link show vti6tun99')
1323 print(output)
1324 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1325 output = check_output('ip -d link show vti6tun98')
1326 print(output)
1327 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1328 output = check_output('ip -d link show vti6tun97')
1329 print(output)
1330 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1331
1332 def test_ip6tnl_tunnel(self):
1333 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1334 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1335 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1336 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1337 start_networkd()
1338 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1339
1340 output = check_output('ip -d link show ip6tnl99')
1341 print(output)
1342 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1343 output = check_output('ip -d link show ip6tnl98')
1344 print(output)
1345 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
1346 output = check_output('ip -d link show ip6tnl97')
1347 print(output)
1348 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1349
1350 def test_sit_tunnel(self):
1351 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1352 '25-sit-tunnel.netdev', '25-tunnel.network',
1353 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1354 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1355 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1356 start_networkd()
1357 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1358
1359 output = check_output('ip -d link show sittun99')
1360 print(output)
1361 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1362 output = check_output('ip -d link show sittun98')
1363 print(output)
1364 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
1365 output = check_output('ip -d link show sittun97')
1366 print(output)
1367 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
1368 output = check_output('ip -d link show sittun96')
1369 print(output)
1370 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1371
1372 def test_isatap_tunnel(self):
1373 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1374 '25-isatap-tunnel.netdev', '25-tunnel.network')
1375 start_networkd()
1376 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1377
1378 output = check_output('ip -d link show isataptun99')
1379 print(output)
1380 self.assertRegex(output, "isatap ")
1381
1382 def test_6rd_tunnel(self):
1383 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1384 '25-6rd-tunnel.netdev', '25-tunnel.network')
1385 start_networkd()
1386 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
1387
1388 output = check_output('ip -d link show sittun99')
1389 print(output)
1390 self.assertRegex(output, '6rd-prefix 2602::/24')
1391
1392 @expectedFailureIfERSPANModuleIsNotAvailable()
1393 def test_erspan_tunnel(self):
1394 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1395 '25-erspan-tunnel.netdev', '25-tunnel.network',
1396 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1397 start_networkd()
1398 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1399
1400 output = check_output('ip -d link show erspan99')
1401 print(output)
1402 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
1403 self.assertRegex(output, 'ikey 0.0.0.101')
1404 self.assertRegex(output, 'okey 0.0.0.101')
1405 self.assertRegex(output, 'iseq')
1406 self.assertRegex(output, 'oseq')
1407 output = check_output('ip -d link show erspan98')
1408 print(output)
1409 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1410 self.assertRegex(output, '102')
1411 self.assertRegex(output, 'ikey 0.0.0.102')
1412 self.assertRegex(output, 'okey 0.0.0.102')
1413 self.assertRegex(output, 'iseq')
1414 self.assertRegex(output, 'oseq')
1415
1416 def test_tunnel_independent(self):
1417 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1418 start_networkd()
1419
1420 self.wait_online(['ipiptun99:carrier'])
1421
1422 def test_tunnel_independent_loopback(self):
1423 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1424 start_networkd()
1425
1426 self.wait_online(['ipiptun99:carrier'])
1427
1428 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1429 def test_xfrm(self):
1430 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1431 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1432 start_networkd()
1433
1434 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1435
1436 output = check_output('ip link show dev xfrm99')
1437 print(output)
1438
1439 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1440 def test_xfrm_independent(self):
1441 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1442 start_networkd()
1443
1444 self.wait_online(['xfrm99:degraded'])
1445
1446 @expectedFailureIfModuleIsNotAvailable('fou')
1447 def test_fou(self):
1448 # The following redundant check is necessary for CentOS CI.
1449 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1450 self.assertTrue(is_module_available('fou'))
1451
1452 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1453 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1454 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1455 start_networkd()
1456
1457 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
1458
1459 output = check_output('ip fou show')
1460 print(output)
1461 self.assertRegex(output, 'port 55555 ipproto 4')
1462 self.assertRegex(output, 'port 55556 ipproto 47')
1463
1464 output = check_output('ip -d link show ipiptun96')
1465 print(output)
1466 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
1467 output = check_output('ip -d link show sittun96')
1468 print(output)
1469 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
1470 output = check_output('ip -d link show gretun96')
1471 print(output)
1472 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
1473 output = check_output('ip -d link show gretap96')
1474 print(output)
1475 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1476
1477 def test_vxlan(self):
1478 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1479 '11-dummy.netdev', 'vxlan-test1.network')
1480 start_networkd()
1481
1482 self.wait_online(['test1:degraded', 'vxlan99:degraded'])
1483
1484 output = check_output('ip -d link show vxlan99')
1485 print(output)
1486 self.assertRegex(output, '999')
1487 self.assertRegex(output, '5555')
1488 self.assertRegex(output, 'l2miss')
1489 self.assertRegex(output, 'l3miss')
1490 self.assertRegex(output, 'udpcsum')
1491 self.assertRegex(output, 'udp6zerocsumtx')
1492 self.assertRegex(output, 'udp6zerocsumrx')
1493 self.assertRegex(output, 'remcsumtx')
1494 self.assertRegex(output, 'remcsumrx')
1495 self.assertRegex(output, 'gbp')
1496
1497 output = check_output('bridge fdb show dev vxlan99')
1498 print(output)
1499 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1500 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1501 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1502
1503 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
1504 print(output)
1505 self.assertRegex(output, 'VNI: 999')
1506 self.assertRegex(output, 'Destination Port: 5555')
1507 self.assertRegex(output, 'Underlying Device: test1')
1508
1509 def test_macsec(self):
1510 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1511 'macsec.network', '12-dummy.netdev')
1512 start_networkd()
1513
1514 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
1515
1516 output = check_output('ip -d link show macsec99')
1517 print(output)
1518 self.assertRegex(output, 'macsec99@dummy98')
1519 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1520 self.assertRegex(output, 'encrypt on')
1521
1522 output = check_output('ip macsec show macsec99')
1523 print(output)
1524 self.assertRegex(output, 'encrypt on')
1525 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1526 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1527 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1528 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1529 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1530 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1531 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1532 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1533 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1534 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1535 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1536
1537 def test_nlmon(self):
1538 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1539 start_networkd()
1540
1541 self.wait_online(['nlmon99:carrier'])
1542
1543 @expectedFailureIfModuleIsNotAvailable('ifb')
1544 def test_ifb(self):
1545 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1546 start_networkd()
1547
1548 self.wait_online(['ifb99:degraded'])
1549
1550 class NetworkdL2TPTests(unittest.TestCase, Utilities):
1551
1552 links =[
1553 'l2tp-ses1',
1554 'l2tp-ses2',
1555 'l2tp-ses3',
1556 'l2tp-ses4',
1557 'test1']
1558
1559 units = [
1560 '11-dummy.netdev',
1561 '25-l2tp-dummy.network',
1562 '25-l2tp.network',
1563 '25-l2tp-ip.netdev',
1564 '25-l2tp-udp.netdev']
1565
1566 l2tp_tunnel_ids = [ '10' ]
1567
1568 def setUp(self):
1569 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
1570 remove_links(self.links)
1571 stop_networkd(show_logs=False)
1572
1573 def tearDown(self):
1574 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
1575 remove_links(self.links)
1576 remove_unit_from_networkd_path(self.units)
1577 stop_networkd(show_logs=True)
1578
1579 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1580 def test_l2tp_udp(self):
1581 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1582 '25-l2tp-udp.netdev', '25-l2tp.network')
1583 start_networkd()
1584
1585 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1586
1587 output = check_output('ip l2tp show tunnel tunnel_id 10')
1588 print(output)
1589 self.assertRegex(output, "Tunnel 10, encap UDP")
1590 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1591 self.assertRegex(output, "Peer tunnel 11")
1592 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1593 self.assertRegex(output, "UDP checksum: enabled")
1594
1595 output = check_output('ip l2tp show session tid 10 session_id 15')
1596 print(output)
1597 self.assertRegex(output, "Session 15 in tunnel 10")
1598 self.assertRegex(output, "Peer session 16, tunnel 11")
1599 self.assertRegex(output, "interface name: l2tp-ses1")
1600
1601 output = check_output('ip l2tp show session tid 10 session_id 17')
1602 print(output)
1603 self.assertRegex(output, "Session 17 in tunnel 10")
1604 self.assertRegex(output, "Peer session 18, tunnel 11")
1605 self.assertRegex(output, "interface name: l2tp-ses2")
1606
1607 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1608 def test_l2tp_ip(self):
1609 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1610 '25-l2tp-ip.netdev', '25-l2tp.network')
1611 start_networkd()
1612
1613 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1614
1615 output = check_output('ip l2tp show tunnel tunnel_id 10')
1616 print(output)
1617 self.assertRegex(output, "Tunnel 10, encap IP")
1618 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1619 self.assertRegex(output, "Peer tunnel 12")
1620
1621 output = check_output('ip l2tp show session tid 10 session_id 25')
1622 print(output)
1623 self.assertRegex(output, "Session 25 in tunnel 10")
1624 self.assertRegex(output, "Peer session 26, tunnel 12")
1625 self.assertRegex(output, "interface name: l2tp-ses3")
1626
1627 output = check_output('ip l2tp show session tid 10 session_id 27')
1628 print(output)
1629 self.assertRegex(output, "Session 27 in tunnel 10")
1630 self.assertRegex(output, "Peer session 28, tunnel 12")
1631 self.assertRegex(output, "interface name: l2tp-ses4")
1632
1633 class NetworkdNetworkTests(unittest.TestCase, Utilities):
1634 links = [
1635 'bond199',
1636 'dummy98',
1637 'dummy99',
1638 'gretun97',
1639 'ip6gretun97',
1640 'test1',
1641 'veth99',
1642 'vrf99',
1643 ]
1644
1645 units = [
1646 '11-dummy.netdev',
1647 '12-dummy.netdev',
1648 '23-active-slave.network',
1649 '24-keep-configuration-static.network',
1650 '24-search-domain.network',
1651 '25-address-dad-veth-peer.network',
1652 '25-address-dad-veth99.network',
1653 '25-address-link-section.network',
1654 '25-address-preferred-lifetime-zero.network',
1655 '25-address-static.network',
1656 '25-bind-carrier.network',
1657 '25-bond-active-backup-slave.netdev',
1658 '25-fibrule-invert.network',
1659 '25-fibrule-port-range.network',
1660 '25-fibrule-uidrange.network',
1661 '25-gre-tunnel-remote-any.netdev',
1662 '25-ip6gre-tunnel-remote-any.netdev',
1663 '25-ipv6-address-label-section.network',
1664 '25-link-local-addressing-no.network',
1665 '25-link-local-addressing-yes.network',
1666 '25-link-section-unmanaged.network',
1667 '25-neighbor-section.network',
1668 '25-neighbor-next.network',
1669 '25-neighbor-ipv6.network',
1670 '25-neighbor-ip-dummy.network',
1671 '25-neighbor-ip.network',
1672 '25-nexthop.network',
1673 '25-qdisc-cake.network',
1674 '25-qdisc-clsact-and-htb.network',
1675 '25-qdisc-drr.network',
1676 '25-qdisc-hhf.network',
1677 '25-qdisc-ingress-netem-compat.network',
1678 '25-qdisc-pie.network',
1679 '25-qdisc-qfq.network',
1680 '25-route-ipv6-src.network',
1681 '25-route-static.network',
1682 '25-route-vrf.network',
1683 '25-gateway-static.network',
1684 '25-gateway-next-static.network',
1685 '25-sysctl-disable-ipv6.network',
1686 '25-sysctl.network',
1687 '25-test1.network',
1688 '25-veth-peer.network',
1689 '25-veth.netdev',
1690 '25-vrf.netdev',
1691 '26-link-local-addressing-ipv6.network',
1692 'routing-policy-rule-dummy98.network',
1693 'routing-policy-rule-test1.network']
1694
1695 routing_policy_rule_tables = ['7', '8', '9']
1696 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1697
1698 def setUp(self):
1699 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1700 remove_routes(self.routes)
1701 remove_links(self.links)
1702 stop_networkd(show_logs=False)
1703
1704 def tearDown(self):
1705 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1706 remove_routes(self.routes)
1707 remove_links(self.links)
1708 remove_unit_from_networkd_path(self.units)
1709 stop_networkd(show_logs=True)
1710
1711 def test_address_static(self):
1712 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1713 start_networkd()
1714
1715 self.wait_online(['dummy98:routable'])
1716
1717 output = check_output('ip -4 address show dev dummy98')
1718 print(output)
1719 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1720 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1721 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1722
1723 # invalid sections
1724 self.assertNotRegex(output, '10.10.0.1/16')
1725 self.assertNotRegex(output, '10.10.0.2/16')
1726
1727 output = check_output('ip -4 address show dev dummy98 label 32')
1728 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1729
1730 output = check_output('ip -4 address show dev dummy98 label 33')
1731 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1732
1733 output = check_output('ip -4 address show dev dummy98 label 34')
1734 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1735
1736 output = check_output('ip -4 address show dev dummy98 label 35')
1737 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1738
1739 output = check_output('ip -6 address show dev dummy98')
1740 print(output)
1741 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1742 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1743 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1744 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1745 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1746 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1747
1748 def test_address_preferred_lifetime_zero_ipv6(self):
1749 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1750 start_networkd(5)
1751
1752 self.wait_online(['dummy98:routable'])
1753
1754 output = check_output('ip address show dummy98')
1755 print(output)
1756 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1757 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1758
1759 output = check_output('ip route show dev dummy98')
1760 print(output)
1761 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1762
1763 def test_address_dad(self):
1764 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1765 '25-veth.netdev')
1766 start_networkd()
1767 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1768
1769 output = check_output('ip -4 address show dev veth99')
1770 print(output)
1771 self.assertRegex(output, '192.168.100.10/24')
1772
1773 output = check_output('ip -4 address show dev veth-peer')
1774 print(output)
1775 self.assertNotRegex(output, '192.168.100.10/24')
1776
1777 def test_configure_without_carrier(self):
1778 copy_unit_to_networkd_unit_path('11-dummy.netdev')
1779 start_networkd()
1780 self.wait_operstate('test1', 'off', '')
1781 check_output('ip link set dev test1 up carrier off')
1782
1783 copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
1784 restart_networkd()
1785 self.wait_online(['test1:no-carrier'])
1786
1787 carrier_map = {'on': '1', 'off': '0'}
1788 routable_map = {'on': 'routable', 'off': 'no-carrier'}
1789 for carrier in ['off', 'on', 'off']:
1790 with self.subTest(carrier=carrier):
1791 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
1792 check_output(f'ip link set dev test1 carrier {carrier}')
1793 self.wait_online([f'test1:{routable_map[carrier]}'])
1794
1795 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1796 print(output)
1797 self.assertRegex(output, '192.168.0.15')
1798 self.assertRegex(output, '192.168.0.1')
1799 self.assertRegex(output, routable_map[carrier])
1800
1801 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
1802 copy_unit_to_networkd_unit_path('11-dummy.netdev')
1803 start_networkd()
1804 self.wait_operstate('test1', 'off', '')
1805 check_output('ip link set dev test1 up carrier off')
1806
1807 copy_unit_to_networkd_unit_path('25-test1.network')
1808 restart_networkd()
1809 self.wait_online(['test1:no-carrier'])
1810
1811 carrier_map = {'on': '1', 'off': '0'}
1812 routable_map = {'on': 'routable', 'off': 'no-carrier'}
1813 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
1814 with self.subTest(carrier=carrier, have_config=have_config):
1815 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
1816 check_output(f'ip link set dev test1 carrier {carrier}')
1817 self.wait_online([f'test1:{routable_map[carrier]}'])
1818
1819 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1820 print(output)
1821 if have_config:
1822 self.assertRegex(output, '192.168.0.15')
1823 self.assertRegex(output, '192.168.0.1')
1824 else:
1825 self.assertNotRegex(output, '192.168.0.15')
1826 self.assertNotRegex(output, '192.168.0.1')
1827 self.assertRegex(output, routable_map[carrier])
1828
1829 def test_routing_policy_rule(self):
1830 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1831 start_networkd()
1832 self.wait_online(['test1:degraded'])
1833
1834 output = check_output('ip rule list iif test1 priority 111')
1835 print(output)
1836 self.assertRegex(output, '111:')
1837 self.assertRegex(output, 'from 192.168.100.18')
1838 self.assertRegex(output, r'tos (0x08|throughput)\s')
1839 self.assertRegex(output, 'iif test1')
1840 self.assertRegex(output, 'oif test1')
1841 self.assertRegex(output, 'lookup 7')
1842
1843 output = check_output('ip rule list iif test1 priority 101')
1844 print(output)
1845 self.assertRegex(output, '101:')
1846 self.assertRegex(output, 'from all')
1847 self.assertRegex(output, 'iif test1')
1848 self.assertRegex(output, 'lookup 9')
1849
1850 output = check_output('ip -6 rule list iif test1 priority 100')
1851 print(output)
1852 self.assertRegex(output, '100:')
1853 self.assertRegex(output, 'from all')
1854 self.assertRegex(output, 'iif test1')
1855 self.assertRegex(output, 'lookup 8')
1856
1857 output = check_output('ip -6 rule list iif test1 priority 101')
1858 print(output)
1859 self.assertRegex(output, '101:')
1860 self.assertRegex(output, 'from all')
1861 self.assertRegex(output, 'iif test1')
1862 self.assertRegex(output, 'lookup 9')
1863
1864 def test_routing_policy_rule_issue_11280(self):
1865 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1866 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1867
1868 for trial in range(3):
1869 # Remove state files only first time
1870 start_networkd(3)
1871 self.wait_online(['test1:degraded', 'dummy98:degraded'])
1872 time.sleep(1)
1873
1874 output = check_output('ip rule list table 7')
1875 print(output)
1876 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1877
1878 output = check_output('ip rule list table 8')
1879 print(output)
1880 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1881
1882 stop_networkd(remove_state_files=False)
1883
1884 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1885 def test_routing_policy_rule_port_range(self):
1886 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1887 start_networkd()
1888 self.wait_online(['test1:degraded'])
1889
1890 output = check_output('ip rule')
1891 print(output)
1892 self.assertRegex(output, '111')
1893 self.assertRegex(output, 'from 192.168.100.18')
1894 self.assertRegex(output, '1123-1150')
1895 self.assertRegex(output, '3224-3290')
1896 self.assertRegex(output, 'tcp')
1897 self.assertRegex(output, 'lookup 7')
1898
1899 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1900 def test_routing_policy_rule_invert(self):
1901 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1902 start_networkd()
1903 self.wait_online(['test1:degraded'])
1904
1905 output = check_output('ip rule')
1906 print(output)
1907 self.assertRegex(output, '111')
1908 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1909 self.assertRegex(output, 'tcp')
1910 self.assertRegex(output, 'lookup 7')
1911
1912 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
1913 def test_routing_policy_rule_uidrange(self):
1914 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
1915 start_networkd()
1916 self.wait_online(['test1:degraded'])
1917
1918 output = check_output('ip rule')
1919 print(output)
1920 self.assertRegex(output, '111')
1921 self.assertRegex(output, 'from 192.168.100.18')
1922 self.assertRegex(output, 'lookup 7')
1923 self.assertRegex(output, 'uidrange 100-200')
1924
1925 def test_route_static(self):
1926 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1927 start_networkd()
1928 self.wait_online(['dummy98:routable'])
1929
1930 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
1931 print(output)
1932
1933 print('### ip -6 route show dev dummy98')
1934 output = check_output('ip -6 route show dev dummy98')
1935 print(output)
1936 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1937 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1938
1939 print('### ip -6 route show dev dummy98 default')
1940 output = check_output('ip -6 route show dev dummy98 default')
1941 print(output)
1942 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1943
1944 print('### ip -4 route show dev dummy98')
1945 output = check_output('ip -4 route show dev dummy98')
1946 print(output)
1947 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1948 self.assertRegex(output, '149.10.124.64 proto static scope link')
1949 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1950 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1951 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1952 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1953
1954 print('### ip -4 route show dev dummy98 default')
1955 output = check_output('ip -4 route show dev dummy98 default')
1956 print(output)
1957 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1958 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1959 self.assertRegex(output, 'default proto static')
1960
1961 print('### ip -4 route show table local dev dummy98')
1962 output = check_output('ip -4 route show table local dev dummy98')
1963 print(output)
1964 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1965 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1966 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1967
1968 print('### ip route show type blackhole')
1969 output = check_output('ip route show type blackhole')
1970 print(output)
1971 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1972
1973 print('### ip route show type unreachable')
1974 output = check_output('ip route show type unreachable')
1975 print(output)
1976 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1977
1978 print('### ip route show type prohibit')
1979 output = check_output('ip route show type prohibit')
1980 print(output)
1981 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1982
1983 print('### ip route show 192.168.10.1')
1984 output = check_output('ip route show 192.168.10.1')
1985 print(output)
1986 self.assertRegex(output, '192.168.10.1 proto static')
1987 self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1988 self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1989
1990 print('### ip route show 192.168.10.2')
1991 output = check_output('ip route show 192.168.10.2')
1992 print(output)
1993 # old ip command does not show IPv6 gateways...
1994 self.assertRegex(output, '192.168.10.2 proto static')
1995 self.assertRegex(output, 'nexthop')
1996 self.assertRegex(output, 'dev dummy98 weight 10')
1997 self.assertRegex(output, 'dev dummy98 weight 5')
1998
1999 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2000 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2001 print(output)
2002 # old ip command does not show 'nexthop' keyword and weight...
2003 self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
2004 self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
2005 self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
2006
2007 @expectedFailureIfModuleIsNotAvailable('vrf')
2008 def test_route_vrf(self):
2009 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
2010 '25-vrf.netdev', '25-vrf.network')
2011 start_networkd()
2012 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2013
2014 output = check_output('ip route show vrf vrf99')
2015 print(output)
2016 self.assertRegex(output, 'default via 192.168.100.1')
2017
2018 output = check_output('ip route show')
2019 print(output)
2020 self.assertNotRegex(output, 'default via 192.168.100.1')
2021
2022 def test_gateway_reconfigure(self):
2023 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
2024 start_networkd()
2025 self.wait_online(['dummy98:routable'])
2026 print('### ip -4 route show dev dummy98 default')
2027 output = check_output('ip -4 route show dev dummy98 default')
2028 print(output)
2029 self.assertRegex(output, 'default via 149.10.124.59 proto static')
2030 self.assertNotRegex(output, '149.10.124.60')
2031
2032 remove_unit_from_networkd_path(['25-gateway-static.network'])
2033 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
2034 restart_networkd(3)
2035 self.wait_online(['dummy98:routable'])
2036 print('### ip -4 route show dev dummy98 default')
2037 output = check_output('ip -4 route show dev dummy98 default')
2038 print(output)
2039 self.assertNotRegex(output, '149.10.124.59')
2040 self.assertRegex(output, 'default via 149.10.124.60 proto static')
2041
2042 def test_ip_route_ipv6_src_route(self):
2043 # a dummy device does not make the addresses go through tentative state, so we
2044 # reuse a bond from an earlier test, which does make the addresses go through
2045 # tentative state, and do our test on that
2046 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2047 start_networkd()
2048 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
2049
2050 output = check_output('ip -6 route list dev bond199')
2051 print(output)
2052 self.assertRegex(output, 'abcd::/16')
2053 self.assertRegex(output, 'src')
2054 self.assertRegex(output, '2001:1234:56:8f63::2')
2055
2056 def test_ip_link_mac_address(self):
2057 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2058 start_networkd()
2059 self.wait_online(['dummy98:degraded'])
2060
2061 output = check_output('ip link show dummy98')
2062 print(output)
2063 self.assertRegex(output, '00:01:02:aa:bb:cc')
2064
2065 def test_ip_link_unmanaged(self):
2066 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
2067 start_networkd(5)
2068
2069 self.check_link_exists('dummy98')
2070
2071 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
2072
2073 def test_ipv6_address_label(self):
2074 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2075 start_networkd()
2076 self.wait_online(['dummy98:degraded'])
2077
2078 output = check_output('ip addrlabel list')
2079 print(output)
2080 self.assertRegex(output, '2004:da8:1::/64')
2081
2082 def test_neighbor_section(self):
2083 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2084 start_networkd()
2085 self.wait_online(['dummy98:degraded'], timeout='40s')
2086
2087 print('### ip neigh list dev dummy98')
2088 output = check_output('ip neigh list dev dummy98')
2089 print(output)
2090 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2091 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2092
2093 def test_neighbor_reconfigure(self):
2094 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2095 start_networkd()
2096 self.wait_online(['dummy98:degraded'], timeout='40s')
2097
2098 print('### ip neigh list dev dummy98')
2099 output = check_output('ip neigh list dev dummy98')
2100 print(output)
2101 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2102 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2103
2104 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2105 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2106 restart_networkd(3)
2107 self.wait_online(['dummy98:degraded'], timeout='40s')
2108 print('### ip neigh list dev dummy98')
2109 output = check_output('ip neigh list dev dummy98')
2110 print(output)
2111 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2112 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2113 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2114
2115 def test_neighbor_gre(self):
2116 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2117 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
2118 start_networkd()
2119 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
2120
2121 output = check_output('ip neigh list dev gretun97')
2122 print(output)
2123 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
2124
2125 output = check_output('ip neigh list dev ip6gretun97')
2126 print(output)
2127 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
2128
2129 def test_link_local_addressing(self):
2130 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2131 '25-link-local-addressing-no.network', '12-dummy.netdev')
2132 start_networkd()
2133 self.wait_online(['test1:degraded', 'dummy98:carrier'])
2134
2135 output = check_output('ip address show dev test1')
2136 print(output)
2137 self.assertRegex(output, 'inet .* scope link')
2138 self.assertRegex(output, 'inet6 .* scope link')
2139
2140 output = check_output('ip address show dev dummy98')
2141 print(output)
2142 self.assertNotRegex(output, 'inet6* .* scope link')
2143
2144 '''
2145 Documentation/networking/ip-sysctl.txt
2146
2147 addr_gen_mode - INTEGER
2148 Defines how link-local and autoconf addresses are generated.
2149
2150 0: generate address based on EUI64 (default)
2151 1: do no generate a link-local address, use EUI64 for addresses generated
2152 from autoconf
2153 2: generate stable privacy addresses, using the secret from
2154 stable_secret (RFC7217)
2155 3: generate stable privacy addresses, using a random secret if unset
2156 '''
2157
2158 test1_addr_gen_mode = ''
2159 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2160 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2161 try:
2162 f.readline()
2163 except IOError:
2164 # if stable_secret is unset, then EIO is returned
2165 test1_addr_gen_mode = '0'
2166 else:
2167 test1_addr_gen_mode = '2'
2168 else:
2169 test1_addr_gen_mode = '0'
2170
2171 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
2172 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
2173
2174 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
2175 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
2176
2177 def test_link_local_addressing_remove_ipv6ll(self):
2178 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2179 start_networkd()
2180 self.wait_online(['dummy98:degraded'])
2181
2182 output = check_output('ip address show dev dummy98')
2183 print(output)
2184 self.assertRegex(output, 'inet6 .* scope link')
2185
2186 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2187 restart_networkd(1)
2188 self.wait_online(['dummy98:carrier'])
2189
2190 output = check_output('ip address show dev dummy98')
2191 print(output)
2192 self.assertNotRegex(output, 'inet6* .* scope link')
2193
2194 def test_sysctl(self):
2195 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2196 start_networkd()
2197 self.wait_online(['dummy98:degraded'])
2198
2199 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2200 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2201 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2202 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2203 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2204 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2205 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
2206 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
2207
2208 def test_sysctl_disable_ipv6(self):
2209 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
2210
2211 print('## Disable ipv6')
2212 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2213 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
2214
2215 start_networkd()
2216 self.wait_online(['dummy98:routable'])
2217
2218 output = check_output('ip -4 address show dummy98')
2219 print(output)
2220 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2221 output = check_output('ip -6 address show dummy98')
2222 print(output)
2223 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2224 self.assertRegex(output, 'inet6 .* scope link')
2225 output = check_output('ip -4 route show dev dummy98')
2226 print(output)
2227 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2228 output = check_output('ip -6 route show dev dummy98')
2229 print(output)
2230 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2231
2232 check_output('ip link del dummy98')
2233
2234 print('## Enable ipv6')
2235 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2236 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
2237
2238 restart_networkd(3)
2239 self.wait_online(['dummy98:routable'])
2240
2241 output = check_output('ip -4 address show dummy98')
2242 print(output)
2243 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2244 output = check_output('ip -6 address show dummy98')
2245 print(output)
2246 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2247 self.assertRegex(output, 'inet6 .* scope link')
2248 output = check_output('ip -4 route show dev dummy98')
2249 print(output)
2250 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2251 output = check_output('ip -6 route show dev dummy98')
2252 print(output)
2253 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2254
2255 def test_bind_carrier(self):
2256 check_output('ip link add dummy98 type dummy')
2257 check_output('ip link set dummy98 up')
2258 time.sleep(2)
2259
2260 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2261 start_networkd()
2262 self.wait_online(['test1:routable'])
2263
2264 output = check_output('ip address show test1')
2265 print(output)
2266 self.assertRegex(output, 'UP,LOWER_UP')
2267 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2268 self.wait_operstate('test1', 'routable')
2269
2270 check_output('ip link add dummy99 type dummy')
2271 check_output('ip link set dummy99 up')
2272 time.sleep(2)
2273 output = check_output('ip address show test1')
2274 print(output)
2275 self.assertRegex(output, 'UP,LOWER_UP')
2276 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2277 self.wait_operstate('test1', 'routable')
2278
2279 check_output('ip link del dummy98')
2280 time.sleep(2)
2281 output = check_output('ip address show test1')
2282 print(output)
2283 self.assertRegex(output, 'UP,LOWER_UP')
2284 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2285 self.wait_operstate('test1', 'routable')
2286
2287 check_output('ip link set dummy99 down')
2288 time.sleep(2)
2289 output = check_output('ip address show test1')
2290 print(output)
2291 self.assertNotRegex(output, 'UP,LOWER_UP')
2292 self.assertRegex(output, 'DOWN')
2293 self.assertNotRegex(output, '192.168.10')
2294 self.wait_operstate('test1', 'off')
2295
2296 check_output('ip link set dummy99 up')
2297 time.sleep(2)
2298 output = check_output('ip address show test1')
2299 print(output)
2300 self.assertRegex(output, 'UP,LOWER_UP')
2301 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2302 self.wait_operstate('test1', 'routable')
2303
2304 def test_domain(self):
2305 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2306 start_networkd()
2307 self.wait_online(['dummy98:routable'])
2308
2309 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2310 print(output)
2311 self.assertRegex(output, 'Address: 192.168.42.100')
2312 self.assertRegex(output, 'DNS: 192.168.42.1')
2313 self.assertRegex(output, 'Search Domains: one')
2314
2315 def test_keep_configuration_static(self):
2316 check_output('systemctl stop systemd-networkd')
2317
2318 check_output('ip link add name dummy98 type dummy')
2319 check_output('ip address add 10.1.2.3/16 dev dummy98')
2320 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2321 output = check_output('ip address show dummy98')
2322 print(output)
2323 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2324 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2325 output = check_output('ip route show dev dummy98')
2326 print(output)
2327
2328 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2329 start_networkd()
2330 self.wait_online(['dummy98:routable'])
2331
2332 output = check_output('ip address show dummy98')
2333 print(output)
2334 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2335 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2336
2337 @expectedFailureIfNexthopIsNotAvailable()
2338 def test_nexthop(self):
2339 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2340 start_networkd()
2341 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2342
2343 output = check_output('ip nexthop list dev veth99')
2344 print(output)
2345 self.assertRegex(output, '192.168.5.1')
2346
2347 def test_qdisc(self):
2348 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
2349 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2350 check_output('modprobe sch_teql max_equalizers=2')
2351 start_networkd()
2352
2353 self.wait_online(['dummy98:routable', 'test1:routable'])
2354
2355 output = check_output('tc qdisc show dev test1')
2356 print(output)
2357 self.assertRegex(output, 'qdisc netem')
2358 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
2359 self.assertRegex(output, 'qdisc ingress')
2360
2361 output = check_output('tc qdisc show dev dummy98')
2362 print(output)
2363 self.assertRegex(output, 'qdisc clsact')
2364
2365 self.assertRegex(output, 'qdisc htb 2: root')
2366 self.assertRegex(output, r'default (0x30|30)')
2367
2368 self.assertRegex(output, 'qdisc netem 30: parent 2:30')
2369 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
2370 self.assertRegex(output, 'qdisc fq_codel')
2371 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn')
2372
2373 self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
2374
2375 self.assertRegex(output, 'qdisc fq 32: parent 2:32')
2376 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2377 self.assertRegex(output, 'quantum 1500')
2378 self.assertRegex(output, 'initial_quantum 13000')
2379 self.assertRegex(output, 'maxrate 1Mbit')
2380
2381 self.assertRegex(output, 'qdisc codel 33: parent 2:33')
2382 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
2383
2384 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
2385 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn')
2386
2387 self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
2388 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
2389
2390 self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
2391 self.assertRegex(output, 'perturb 5sec')
2392
2393 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
2394 self.assertRegex(output, 'limit 100000p')
2395
2396 self.assertRegex(output, 'qdisc gred 38: parent 2:38')
2397 self.assertRegex(output, 'vqs 12 default 10 grio')
2398
2399 self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
2400 self.assertRegex(output, 'limit 200000')
2401
2402 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
2403 self.assertRegex(output, 'limit 1000000')
2404
2405 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b')
2406 self.assertRegex(output, 'limit 1023p')
2407
2408 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c')
2409
2410 output = check_output('tc class show dev dummy98')
2411 print(output)
2412 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
2413 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
2414 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
2415 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
2416 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
2417 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
2418 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
2419 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
2420 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
2421 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
2422 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
2423 self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
2424 self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
2425 self.assertRegex(output, 'prio 1 rate 1Mbit ceil 500Kbit')
2426
2427 def test_qdisc2(self):
2428 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
2429 '25-qdisc-qfq.network', '11-dummy.netdev')
2430 start_networkd()
2431
2432 self.wait_online(['dummy98:routable', 'test1:routable'])
2433
2434 output = check_output('tc qdisc show dev dummy98')
2435 print(output)
2436 self.assertRegex(output, 'qdisc drr 2: root')
2437 output = check_output('tc class show dev dummy98')
2438 print(output)
2439 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
2440
2441 output = check_output('tc qdisc show dev test1')
2442 print(output)
2443 self.assertRegex(output, 'qdisc qfq 2: root')
2444 output = check_output('tc class show dev test1')
2445 print(output)
2446 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
2447 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
2448
2449 @expectedFailureIfCAKEIsNotAvailable()
2450 def test_qdisc_cake(self):
2451 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
2452 start_networkd()
2453 self.wait_online(['dummy98:routable'])
2454
2455 output = check_output('tc qdisc show dev dummy98')
2456 print(output)
2457 self.assertRegex(output, 'qdisc cake 3a: root')
2458 self.assertRegex(output, 'bandwidth 500Mbit')
2459 self.assertRegex(output, 'overhead 128')
2460
2461 @expectedFailureIfPIEIsNotAvailable()
2462 def test_qdisc_pie(self):
2463 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
2464 start_networkd()
2465 self.wait_online(['dummy98:routable'])
2466
2467 output = check_output('tc qdisc show dev dummy98')
2468 print(output)
2469 self.assertRegex(output, 'qdisc pie 3a: root')
2470 self.assertRegex(output, 'limit 200000')
2471
2472 @expectedFailureIfHHFIsNotAvailable()
2473 def test_qdisc_hhf(self):
2474 copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev')
2475 start_networkd()
2476 self.wait_online(['dummy98:routable'])
2477
2478 output = check_output('tc qdisc show dev dummy98')
2479 print(output)
2480 self.assertRegex(output, 'qdisc hhf 3a: root')
2481 self.assertRegex(output, 'limit 1022p')
2482
2483 class NetworkdStateFileTests(unittest.TestCase, Utilities):
2484 links = [
2485 'dummy98',
2486 ]
2487
2488 units = [
2489 '12-dummy.netdev',
2490 'state-file-tests.network',
2491 ]
2492
2493 def setUp(self):
2494 remove_links(self.links)
2495 stop_networkd(show_logs=False)
2496
2497 def tearDown(self):
2498 remove_links(self.links)
2499 remove_unit_from_networkd_path(self.units)
2500 stop_networkd(show_logs=True)
2501
2502 def test_state_file(self):
2503 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2504 start_networkd()
2505 self.wait_online(['dummy98:routable'])
2506
2507 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2508 print(output)
2509 ifindex = output.split()[0]
2510
2511 path = os.path.join('/run/systemd/netif/links/', ifindex)
2512 self.assertTrue(os.path.exists(path))
2513 time.sleep(2)
2514
2515 with open(path) as f:
2516 data = f.read()
2517 self.assertRegex(data, r'ADMIN_STATE=configured')
2518 self.assertRegex(data, r'OPER_STATE=routable')
2519 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2520 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2521 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2522 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2523 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2524 self.assertRegex(data, r'DOMAINS=hogehoge')
2525 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2526 self.assertRegex(data, r'LLMNR=no')
2527 self.assertRegex(data, r'MDNS=yes')
2528 self.assertRegex(data, r'DNSSEC=no')
2529 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2530
2531 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2532 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2533 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2534 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2535 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2536 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2537 time.sleep(2)
2538
2539 with open(path) as f:
2540 data = f.read()
2541 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2542 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2543 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2544 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2545 self.assertRegex(data, r'LLMNR=yes')
2546 self.assertRegex(data, r'MDNS=no')
2547 self.assertRegex(data, r'DNSSEC=yes')
2548
2549 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2550 time.sleep(2)
2551
2552 with open(path) as f:
2553 data = f.read()
2554 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2555 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2556 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2557 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2558 self.assertRegex(data, r'LLMNR=yes')
2559 self.assertRegex(data, r'MDNS=no')
2560 self.assertRegex(data, r'DNSSEC=yes')
2561
2562 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2563 time.sleep(2)
2564
2565 with open(path) as f:
2566 data = f.read()
2567 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2568 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2569 self.assertRegex(data, r'DOMAINS=hogehoge')
2570 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2571 self.assertRegex(data, r'LLMNR=no')
2572 self.assertRegex(data, r'MDNS=yes')
2573 self.assertRegex(data, r'DNSSEC=no')
2574
2575 class NetworkdBondTests(unittest.TestCase, Utilities):
2576 links = [
2577 'bond199',
2578 'bond99',
2579 'dummy98',
2580 'test1']
2581
2582 units = [
2583 '11-dummy.netdev',
2584 '12-dummy.netdev',
2585 '23-active-slave.network',
2586 '23-bond199.network',
2587 '23-primary-slave.network',
2588 '25-bond-active-backup-slave.netdev',
2589 '25-bond.netdev',
2590 'bond99.network',
2591 'bond-slave.network']
2592
2593 def setUp(self):
2594 remove_links(self.links)
2595 stop_networkd(show_logs=False)
2596
2597 def tearDown(self):
2598 remove_links(self.links)
2599 remove_unit_from_networkd_path(self.units)
2600 stop_networkd(show_logs=True)
2601
2602 def test_bond_active_slave(self):
2603 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2604 start_networkd()
2605 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2606
2607 output = check_output('ip -d link show bond199')
2608 print(output)
2609 self.assertRegex(output, 'active_slave dummy98')
2610
2611 def test_bond_primary_slave(self):
2612 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2613 start_networkd()
2614 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2615
2616 output = check_output('ip -d link show bond199')
2617 print(output)
2618 self.assertRegex(output, 'primary dummy98')
2619
2620 def test_bond_operstate(self):
2621 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2622 'bond99.network','bond-slave.network')
2623 start_networkd()
2624 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2625
2626 output = check_output('ip -d link show dummy98')
2627 print(output)
2628 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2629
2630 output = check_output('ip -d link show test1')
2631 print(output)
2632 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2633
2634 output = check_output('ip -d link show bond99')
2635 print(output)
2636 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2637
2638 self.wait_operstate('dummy98', 'enslaved')
2639 self.wait_operstate('test1', 'enslaved')
2640 self.wait_operstate('bond99', 'routable')
2641
2642 check_output('ip link set dummy98 down')
2643
2644 self.wait_operstate('dummy98', 'off')
2645 self.wait_operstate('test1', 'enslaved')
2646 self.wait_operstate('bond99', 'degraded-carrier')
2647
2648 check_output('ip link set dummy98 up')
2649
2650 self.wait_operstate('dummy98', 'enslaved')
2651 self.wait_operstate('test1', 'enslaved')
2652 self.wait_operstate('bond99', 'routable')
2653
2654 check_output('ip link set dummy98 down')
2655 check_output('ip link set test1 down')
2656
2657 self.wait_operstate('dummy98', 'off')
2658 self.wait_operstate('test1', 'off')
2659
2660 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2661 # Huh? Kernel does not recognize that all slave interfaces are down?
2662 # Let's confirm that networkd's operstate is consistent with ip's result.
2663 self.assertNotRegex(output, 'NO-CARRIER')
2664
2665 class NetworkdBridgeTests(unittest.TestCase, Utilities):
2666 links = [
2667 'bridge99',
2668 'dummy98',
2669 'test1']
2670
2671 units = [
2672 '11-dummy.netdev',
2673 '12-dummy.netdev',
2674 '26-bridge.netdev',
2675 '26-bridge-configure-without-carrier.network',
2676 '26-bridge-slave-interface-1.network',
2677 '26-bridge-slave-interface-2.network',
2678 '26-bridge-vlan-master.network',
2679 '26-bridge-vlan-slave.network',
2680 'bridge99-ignore-carrier-loss.network',
2681 'bridge99.network']
2682
2683 routing_policy_rule_tables = ['100']
2684
2685 def setUp(self):
2686 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2687 remove_links(self.links)
2688 stop_networkd(show_logs=False)
2689
2690 def tearDown(self):
2691 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2692 remove_links(self.links)
2693 remove_unit_from_networkd_path(self.units)
2694 stop_networkd(show_logs=True)
2695
2696 def test_bridge_vlan(self):
2697 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2698 '26-bridge.netdev', '26-bridge-vlan-master.network')
2699 start_networkd()
2700 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
2701
2702 output = check_output('bridge vlan show dev test1')
2703 print(output)
2704 self.assertNotRegex(output, '4063')
2705 for i in range(4064, 4095):
2706 self.assertRegex(output, f'{i}')
2707 self.assertNotRegex(output, '4095')
2708
2709 output = check_output('bridge vlan show dev bridge99')
2710 print(output)
2711 self.assertNotRegex(output, '4059')
2712 for i in range(4060, 4095):
2713 self.assertRegex(output, f'{i}')
2714 self.assertNotRegex(output, '4095')
2715
2716 def test_bridge_property(self):
2717 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2718 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2719 'bridge99.network')
2720 start_networkd()
2721 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2722
2723 output = check_output('ip -d link show test1')
2724 print(output)
2725 self.assertRegex(output, 'master')
2726 self.assertRegex(output, 'bridge')
2727
2728 output = check_output('ip -d link show dummy98')
2729 print(output)
2730 self.assertRegex(output, 'master')
2731 self.assertRegex(output, 'bridge')
2732
2733 output = check_output('ip addr show bridge99')
2734 print(output)
2735 self.assertRegex(output, '192.168.0.15/24')
2736
2737 output = check_output('bridge -d link show dummy98')
2738 print(output)
2739 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2740 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2741 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2742 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2743 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2744 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2745 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2746 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2747 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2748 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2749 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2750 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2751 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2752 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2753
2754 output = check_output('bridge -d link show test1')
2755 print(output)
2756 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2757
2758 check_output('ip address add 192.168.0.16/24 dev bridge99')
2759 time.sleep(1)
2760
2761 output = check_output('ip addr show bridge99')
2762 print(output)
2763 self.assertRegex(output, '192.168.0.16/24')
2764
2765 # for issue #6088
2766 print('### ip -6 route list table all dev bridge99')
2767 output = check_output('ip -6 route list table all dev bridge99')
2768 print(output)
2769 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2770
2771 self.assertEqual(call('ip link del test1'), 0)
2772
2773 self.wait_operstate('bridge99', 'degraded-carrier')
2774
2775 check_output('ip link del dummy98')
2776
2777 self.wait_operstate('bridge99', 'no-carrier')
2778
2779 output = check_output('ip address show bridge99')
2780 print(output)
2781 self.assertRegex(output, 'NO-CARRIER')
2782 self.assertNotRegex(output, '192.168.0.15/24')
2783 self.assertNotRegex(output, '192.168.0.16/24')
2784
2785 print('### ip -6 route list table all dev bridge99')
2786 output = check_output('ip -6 route list table all dev bridge99')
2787 print(output)
2788 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2789
2790 def test_bridge_configure_without_carrier(self):
2791 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
2792 '11-dummy.netdev')
2793 start_networkd()
2794
2795 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
2796 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
2797 with self.subTest(test=test):
2798 if test == 'no-slave':
2799 # bridge has no slaves; it's up but *might* not have carrier
2800 self.wait_online(['bridge99:no-carrier'])
2801 # due to a bug in the kernel, newly-created bridges are brought up
2802 # *with* carrier, unless they have had any setting changed; e.g.
2803 # their mac set, priority set, etc. Then, they will lose carrier
2804 # as soon as a (down) slave interface is added, and regain carrier
2805 # again once the slave interface is brought up.
2806 #self.check_link_attr('bridge99', 'carrier', '0')
2807 elif test == 'add-slave':
2808 # add slave to bridge, but leave it down; bridge is definitely no-carrier
2809 self.check_link_attr('test1', 'operstate', 'down')
2810 check_output('ip link set dev test1 master bridge99')
2811 self.wait_online(['bridge99:no-carrier:no-carrier'])
2812 self.check_link_attr('bridge99', 'carrier', '0')
2813 elif test == 'slave-up':
2814 # bring up slave, which will have carrier; bridge gains carrier
2815 check_output('ip link set dev test1 up')
2816 self.wait_online(['bridge99:routable'])
2817 self.check_link_attr('bridge99', 'carrier', '1')
2818 elif test == 'slave-no-carrier':
2819 # drop slave carrier; bridge loses carrier
2820 check_output('ip link set dev test1 carrier off')
2821 self.wait_online(['bridge99:no-carrier:no-carrier'])
2822 self.check_link_attr('bridge99', 'carrier', '0')
2823 elif test == 'slave-carrier':
2824 # restore slave carrier; bridge gains carrier
2825 check_output('ip link set dev test1 carrier on')
2826 self.wait_online(['bridge99:routable'])
2827 self.check_link_attr('bridge99', 'carrier', '1')
2828 elif test == 'slave-down':
2829 # bring down slave; bridge loses carrier
2830 check_output('ip link set dev test1 down')
2831 self.wait_online(['bridge99:no-carrier:no-carrier'])
2832 self.check_link_attr('bridge99', 'carrier', '0')
2833
2834 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
2835 print(output)
2836 self.assertRegex(output, '10.1.2.3')
2837 self.assertRegex(output, '10.1.2.1')
2838
2839 def test_bridge_ignore_carrier_loss(self):
2840 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2841 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2842 'bridge99-ignore-carrier-loss.network')
2843 start_networkd()
2844 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2845
2846 check_output('ip address add 192.168.0.16/24 dev bridge99')
2847 time.sleep(1)
2848
2849 check_output('ip link del test1')
2850 check_output('ip link del dummy98')
2851 time.sleep(3)
2852
2853 output = check_output('ip address show bridge99')
2854 print(output)
2855 self.assertRegex(output, 'NO-CARRIER')
2856 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2857 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2858
2859 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2860 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2861 'bridge99-ignore-carrier-loss.network')
2862 start_networkd()
2863 self.wait_online(['bridge99:no-carrier'])
2864
2865 for trial in range(4):
2866 check_output('ip link add dummy98 type dummy')
2867 check_output('ip link set dummy98 up')
2868 if trial < 3:
2869 check_output('ip link del dummy98')
2870
2871 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2872
2873 output = check_output('ip address show bridge99')
2874 print(output)
2875 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2876
2877 output = check_output('ip rule list table 100')
2878 print(output)
2879 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2880
2881 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2882 links = ['veth99']
2883
2884 units = [
2885 '23-emit-lldp.network',
2886 '24-lldp.network',
2887 '25-veth.netdev']
2888
2889 def setUp(self):
2890 remove_links(self.links)
2891 stop_networkd(show_logs=False)
2892
2893 def tearDown(self):
2894 remove_links(self.links)
2895 remove_unit_from_networkd_path(self.units)
2896 stop_networkd(show_logs=True)
2897
2898 def test_lldp(self):
2899 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2900 start_networkd()
2901 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2902
2903 output = check_output(*networkctl_cmd, 'lldp', env=env)
2904 print(output)
2905 self.assertRegex(output, 'veth-peer')
2906 self.assertRegex(output, 'veth99')
2907
2908 class NetworkdRATests(unittest.TestCase, Utilities):
2909 links = ['veth99']
2910
2911 units = [
2912 '25-veth.netdev',
2913 'ipv6-prefix.network',
2914 'ipv6-prefix-veth.network',
2915 'ipv6-prefix-veth-token-static.network',
2916 'ipv6-prefix-veth-token-static-explicit.network',
2917 'ipv6-prefix-veth-token-static-multiple.network',
2918 'ipv6-prefix-veth-token-prefixstable.network']
2919
2920 def setUp(self):
2921 remove_links(self.links)
2922 stop_networkd(show_logs=False)
2923
2924 def tearDown(self):
2925 remove_links(self.links)
2926 remove_unit_from_networkd_path(self.units)
2927 stop_networkd(show_logs=True)
2928
2929 def test_ipv6_prefix_delegation(self):
2930 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2931 start_networkd()
2932 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2933
2934 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2935 print(output)
2936 self.assertRegex(output, 'fe80::')
2937 self.assertRegex(output, '2002:da8:1::1')
2938
2939 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2940 print(output)
2941 self.assertRegex(output, '2002:da8:1:0')
2942
2943 def test_ipv6_token_static(self):
2944 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
2945 start_networkd()
2946 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2947
2948 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2949 print(output)
2950 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2951
2952 def test_ipv6_token_static_explicit(self):
2953 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2954 start_networkd()
2955 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2956
2957 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2958 print(output)
2959 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2960
2961 def test_ipv6_token_static_multiple(self):
2962 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2963 start_networkd()
2964 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2965
2966 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2967 print(output)
2968 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2969 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
2970
2971 def test_ipv6_token_prefixstable(self):
2972 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2973 start_networkd()
2974 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2975
2976 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2977 print(output)
2978 self.assertRegex(output, '2002:da8:1:0')
2979
2980 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
2981 links = ['veth99']
2982
2983 units = [
2984 '25-veth.netdev',
2985 'dhcp-client.network',
2986 'dhcp-client-timezone-router.network',
2987 'dhcp-server.network',
2988 'dhcp-server-timezone-router.network']
2989
2990 def setUp(self):
2991 remove_links(self.links)
2992 stop_networkd(show_logs=False)
2993
2994 def tearDown(self):
2995 remove_links(self.links)
2996 remove_unit_from_networkd_path(self.units)
2997 stop_networkd(show_logs=True)
2998
2999 def test_dhcp_server(self):
3000 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
3001 start_networkd()
3002 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3003
3004 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3005 print(output)
3006 self.assertRegex(output, '192.168.5.*')
3007 self.assertRegex(output, 'Gateway: 192.168.5.1')
3008 self.assertRegex(output, 'DNS: 192.168.5.1')
3009 self.assertRegex(output, 'NTP: 192.168.5.1')
3010
3011 def test_emit_router_timezone(self):
3012 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
3013 start_networkd()
3014 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3015
3016 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3017 print(output)
3018 self.assertRegex(output, 'Gateway: 192.168.5.*')
3019 self.assertRegex(output, '192.168.5.*')
3020 self.assertRegex(output, 'Europe/Berlin')
3021
3022 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
3023 links = [
3024 'veth99',
3025 'vrf99']
3026
3027 units = [
3028 '25-veth.netdev',
3029 '25-vrf.netdev',
3030 '25-vrf.network',
3031 'dhcp-client-anonymize.network',
3032 'dhcp-client-decline.network',
3033 'dhcp-client-gateway-ipv4.network',
3034 'dhcp-client-gateway-ipv6.network',
3035 'dhcp-client-gateway-onlink-implicit.network',
3036 'dhcp-client-ipv4-dhcp-settings.network',
3037 'dhcp-client-ipv4-only-ipv6-disabled.network',
3038 'dhcp-client-ipv4-only.network',
3039 'dhcp-client-ipv4-use-routes-use-gateway.network',
3040 'dhcp-client-ipv6-only.network',
3041 'dhcp-client-ipv6-rapid-commit.network',
3042 'dhcp-client-keep-configuration-dhcp-on-stop.network',
3043 'dhcp-client-keep-configuration-dhcp.network',
3044 'dhcp-client-listen-port.network',
3045 'dhcp-client-reassign-static-routes-ipv4.network',
3046 'dhcp-client-reassign-static-routes-ipv6.network',
3047 'dhcp-client-route-metric.network',
3048 'dhcp-client-route-table.network',
3049 'dhcp-client-use-dns-ipv4-and-ra.network',
3050 'dhcp-client-use-dns-ipv4.network',
3051 'dhcp-client-use-dns-no.network',
3052 'dhcp-client-use-dns-yes.network',
3053 'dhcp-client-use-domains.network',
3054 'dhcp-client-vrf.network',
3055 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
3056 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
3057 'dhcp-client-with-static-address.network',
3058 'dhcp-client.network',
3059 'dhcp-server-decline.network',
3060 'dhcp-server-veth-peer.network',
3061 'dhcp-v4-server-veth-peer.network',
3062 'static.network']
3063
3064 def setUp(self):
3065 stop_dnsmasq(dnsmasq_pid_file)
3066 remove_links(self.links)
3067 stop_networkd(show_logs=False)
3068
3069 def tearDown(self):
3070 stop_dnsmasq(dnsmasq_pid_file)
3071 remove_lease_file()
3072 remove_log_file()
3073 remove_links(self.links)
3074 remove_unit_from_networkd_path(self.units)
3075 stop_networkd(show_logs=True)
3076
3077 def test_dhcp_client_ipv6_only(self):
3078 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3079
3080 start_networkd()
3081 self.wait_online(['veth-peer:carrier'])
3082 start_dnsmasq()
3083 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3084
3085 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3086 print(output)
3087 self.assertRegex(output, '2600::')
3088 self.assertNotRegex(output, '192.168.5')
3089
3090 # Confirm that ipv6 token is not set in the kernel
3091 output = check_output('ip token show dev veth99')
3092 print(output)
3093 self.assertRegex(output, 'token :: dev veth99')
3094
3095 def test_dhcp_client_ipv4_only(self):
3096 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
3097
3098 start_networkd()
3099 self.wait_online(['veth-peer:carrier'])
3100 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3101 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3102
3103 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3104 print(output)
3105 self.assertNotRegex(output, '2600::')
3106 self.assertRegex(output, '192.168.5')
3107 self.assertRegex(output, '192.168.5.6')
3108 self.assertRegex(output, '192.168.5.7')
3109
3110 # checking routes to DNS servers
3111 output = check_output('ip route show dev veth99')
3112 print(output)
3113 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3114 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3115 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3116
3117 stop_dnsmasq(dnsmasq_pid_file)
3118 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
3119
3120 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3121 print('Wait for the dynamic address to be renewed')
3122 time.sleep(125)
3123
3124 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3125
3126 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3127 print(output)
3128 self.assertNotRegex(output, '2600::')
3129 self.assertRegex(output, '192.168.5')
3130 self.assertNotRegex(output, '192.168.5.6')
3131 self.assertRegex(output, '192.168.5.7')
3132 self.assertRegex(output, '192.168.5.8')
3133
3134 # checking routes to DNS servers
3135 output = check_output('ip route show dev veth99')
3136 print(output)
3137 self.assertNotRegex(output, r'192.168.5.6')
3138 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3139 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3140 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
3141
3142 def test_dhcp_client_ipv4_use_routes_gateway(self):
3143 for (routes, gateway, dnsroutes) in itertools.product([True, False, None], repeat=3):
3144 self.setUp()
3145 with self.subTest(routes=routes, gateway=gateway, dnsroutes=dnsroutes):
3146 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dnsroutes)
3147 self.tearDown()
3148
3149 def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway, dnsroutes):
3150 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
3151 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
3152 if routes != None:
3153 testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
3154 if gateway != None:
3155 testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
3156 if dnsroutes != None:
3157 testunits.append(f'{testunit}.d/use-dns-routes-{dnsroutes}.conf');
3158 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
3159
3160 start_networkd()
3161 self.wait_online(['veth-peer:carrier'])
3162 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3163 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3164
3165 output = check_output('ip route show dev veth99')
3166 print(output)
3167
3168 # UseRoutes= defaults to true
3169 useroutes = routes in [True, None]
3170 # UseGateway= defaults to useroutes
3171 usegateway = useroutes if gateway == None else gateway
3172
3173 # Check UseRoutes=
3174 if useroutes:
3175 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
3176 else:
3177 self.assertNotRegex(output, r'192.168.5.5')
3178
3179 # Check UseGateway=
3180 if usegateway:
3181 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3182 else:
3183 self.assertNotRegex(output, r'default via 192.168.5.1')
3184
3185 # Check RoutesToDNS=, which defaults to false
3186 if dnsroutes:
3187 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3188 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3189 else:
3190 self.assertNotRegex(output, r'192.168.5.6')
3191 self.assertNotRegex(output, r'192.168.5.7')
3192
3193 def test_dhcp_client_ipv4_ipv6(self):
3194 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3195 'dhcp-client-ipv4-only.network')
3196 start_networkd()
3197 self.wait_online(['veth-peer:carrier'])
3198 start_dnsmasq()
3199 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3200
3201 # link become 'routable' when at least one protocol provide an valid address.
3202 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3203 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3204
3205 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3206 print(output)
3207 self.assertRegex(output, '2600::')
3208 self.assertRegex(output, '192.168.5')
3209
3210 def test_dhcp_client_settings(self):
3211 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
3212
3213 start_networkd()
3214 self.wait_online(['veth-peer:carrier'])
3215 start_dnsmasq()
3216 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3217
3218 print('## ip address show dev veth99')
3219 output = check_output('ip address show dev veth99')
3220 print(output)
3221 self.assertRegex(output, '12:34:56:78:9a:bc')
3222 self.assertRegex(output, '192.168.5')
3223 self.assertRegex(output, '1492')
3224
3225 print('## ip route show table main dev veth99')
3226 output = check_output('ip route show table main dev veth99')
3227 print(output)
3228 # See issue #8726
3229 main_table_is_empty = output == ''
3230 if not main_table_is_empty:
3231 self.assertNotRegex(output, 'proto dhcp')
3232
3233 print('## ip route show table 211 dev veth99')
3234 output = check_output('ip route show table 211 dev veth99')
3235 print(output)
3236 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
3237 if main_table_is_empty:
3238 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
3239 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3240 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
3241
3242 print('## dnsmasq log')
3243 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3244 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3245 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3246 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
3247
3248 def test_dhcp6_client_settings_rapidcommit_true(self):
3249 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3250 start_networkd()
3251 self.wait_online(['veth-peer:carrier'])
3252 start_dnsmasq()
3253 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3254
3255 output = check_output('ip address show dev veth99')
3256 print(output)
3257 self.assertRegex(output, '12:34:56:78:9a:bc')
3258 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
3259
3260 def test_dhcp6_client_settings_rapidcommit_false(self):
3261 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
3262 start_networkd()
3263 self.wait_online(['veth-peer:carrier'])
3264 start_dnsmasq()
3265 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3266
3267 output = check_output('ip address show dev veth99')
3268 print(output)
3269 self.assertRegex(output, '12:34:56:78:9a:bc')
3270 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
3271
3272 def test_dhcp_client_settings_anonymize(self):
3273 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
3274 start_networkd()
3275 self.wait_online(['veth-peer:carrier'])
3276 start_dnsmasq()
3277 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3278
3279 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3280 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3281 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
3282
3283 def test_dhcp_client_listen_port(self):
3284 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
3285 start_networkd()
3286 self.wait_online(['veth-peer:carrier'])
3287 start_dnsmasq('--dhcp-alternate-port=67,5555')
3288 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3289
3290 output = check_output('ip -4 address show dev veth99')
3291 print(output)
3292 self.assertRegex(output, '192.168.5.* dynamic')
3293
3294 def test_dhcp_client_with_static_address(self):
3295 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3296 'dhcp-client-with-static-address.network')
3297 start_networkd()
3298 self.wait_online(['veth-peer:carrier'])
3299 start_dnsmasq()
3300 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3301
3302 output = check_output('ip address show dev veth99 scope global')
3303 print(output)
3304 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3305 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3306
3307 output = check_output('ip route show dev veth99')
3308 print(output)
3309 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3310 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3311 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3312 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3313
3314 def test_dhcp_route_table_id(self):
3315 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
3316 start_networkd()
3317 self.wait_online(['veth-peer:carrier'])
3318 start_dnsmasq()
3319 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3320
3321 output = check_output('ip route show table 12')
3322 print(output)
3323 self.assertRegex(output, 'veth99 proto dhcp')
3324 self.assertRegex(output, '192.168.5.1')
3325
3326 def test_dhcp_route_metric(self):
3327 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
3328 start_networkd()
3329 self.wait_online(['veth-peer:carrier'])
3330 start_dnsmasq()
3331 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3332
3333 output = check_output('ip route show dev veth99')
3334 print(output)
3335 self.assertRegex(output, 'metric 24')
3336
3337 def test_dhcp_client_reassign_static_routes_ipv4(self):
3338 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3339 'dhcp-client-reassign-static-routes-ipv4.network')
3340 start_networkd()
3341 self.wait_online(['veth-peer:carrier'])
3342 start_dnsmasq(lease_time='2m')
3343 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3344
3345 output = check_output('ip address show dev veth99 scope global')
3346 print(output)
3347 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3348
3349 output = check_output('ip route show dev veth99')
3350 print(output)
3351 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3352 self.assertRegex(output, r'192.168.5.0/24 proto static')
3353 self.assertRegex(output, r'192.168.6.0/24 proto static')
3354 self.assertRegex(output, r'192.168.7.0/24 proto static')
3355
3356 stop_dnsmasq(dnsmasq_pid_file)
3357 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3358
3359 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3360 print('Wait for the dynamic address to be renewed')
3361 time.sleep(125)
3362
3363 self.wait_online(['veth99:routable'])
3364
3365 output = check_output('ip route show dev veth99')
3366 print(output)
3367 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3368 self.assertRegex(output, r'192.168.5.0/24 proto static')
3369 self.assertRegex(output, r'192.168.6.0/24 proto static')
3370 self.assertRegex(output, r'192.168.7.0/24 proto static')
3371
3372 def test_dhcp_client_reassign_static_routes_ipv6(self):
3373 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3374 'dhcp-client-reassign-static-routes-ipv6.network')
3375 start_networkd()
3376 self.wait_online(['veth-peer:carrier'])
3377 start_dnsmasq(lease_time='2m')
3378 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3379
3380 output = check_output('ip address show dev veth99 scope global')
3381 print(output)
3382 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
3383
3384 output = check_output('ip -6 route show dev veth99')
3385 print(output)
3386 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3387 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3388
3389 stop_dnsmasq(dnsmasq_pid_file)
3390 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3391
3392 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3393 print('Wait for the dynamic address to be renewed')
3394 time.sleep(125)
3395
3396 self.wait_online(['veth99:routable'])
3397
3398 output = check_output('ip -6 route show dev veth99')
3399 print(output)
3400 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3401 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3402
3403 def test_dhcp_keep_configuration_dhcp(self):
3404 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
3405 start_networkd()
3406 self.wait_online(['veth-peer:carrier'])
3407 start_dnsmasq(lease_time='2m')
3408 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3409
3410 output = check_output('ip address show dev veth99 scope global')
3411 print(output)
3412 self.assertRegex(output, r'192.168.5.*')
3413
3414 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3415 print(output)
3416 self.assertRegex(output, r'192.168.5.*')
3417
3418 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
3419 stop_dnsmasq(dnsmasq_pid_file)
3420
3421 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3422 print('Wait for the dynamic address to be expired')
3423 time.sleep(125)
3424
3425 print('The lease address should be kept after lease expired')
3426 output = check_output('ip address show dev veth99 scope global')
3427 print(output)
3428 self.assertRegex(output, r'192.168.5.*')
3429
3430 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3431 print(output)
3432 self.assertRegex(output, r'192.168.5.*')
3433
3434 check_output('systemctl stop systemd-networkd')
3435
3436 print('The lease address should be kept after networkd stopped')
3437 output = check_output('ip address show dev veth99 scope global')
3438 print(output)
3439 self.assertRegex(output, r'192.168.5.*')
3440
3441 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3442 print(output)
3443 self.assertRegex(output, r'192.168.5.*')
3444
3445 start_networkd(3)
3446 self.wait_online(['veth-peer:routable'])
3447
3448 print('Still the lease address should be kept after networkd restarted')
3449 output = check_output('ip address show dev veth99 scope global')
3450 print(output)
3451 self.assertRegex(output, r'192.168.5.*')
3452
3453 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3454 print(output)
3455 self.assertRegex(output, r'192.168.5.*')
3456
3457 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3458 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
3459 start_networkd()
3460 self.wait_online(['veth-peer:carrier'])
3461 start_dnsmasq(lease_time='2m')
3462 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3463
3464 output = check_output('ip address show dev veth99 scope global')
3465 print(output)
3466 self.assertRegex(output, r'192.168.5.*')
3467
3468 stop_dnsmasq(dnsmasq_pid_file)
3469 check_output('systemctl stop systemd-networkd')
3470
3471 output = check_output('ip address show dev veth99 scope global')
3472 print(output)
3473 self.assertRegex(output, r'192.168.5.*')
3474
3475 restart_networkd(3)
3476 self.wait_online(['veth-peer:routable'])
3477
3478 output = check_output('ip address show dev veth99 scope global')
3479 print(output)
3480 self.assertNotRegex(output, r'192.168.5.*')
3481
3482 def test_dhcp_client_reuse_address_as_static(self):
3483 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
3484 start_networkd()
3485 self.wait_online(['veth-peer:carrier'])
3486 start_dnsmasq()
3487 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3488
3489 # link become 'routable' when at least one protocol provide an valid address.
3490 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3491 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3492
3493 output = check_output('ip address show dev veth99 scope global')
3494 print(output)
3495 self.assertRegex(output, '192.168.5')
3496 self.assertRegex(output, '2600::')
3497
3498 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3499 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
3500 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3501 print(static_network)
3502
3503 remove_unit_from_networkd_path(['dhcp-client.network'])
3504
3505 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3506 f.write(static_network)
3507
3508 # When networkd started, the links are already configured, so let's wait for 5 seconds
3509 # the links to be re-configured.
3510 restart_networkd(5)
3511 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3512
3513 output = check_output('ip -4 address show dev veth99 scope global')
3514 print(output)
3515 self.assertRegex(output, '192.168.5')
3516 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3517
3518 output = check_output('ip -6 address show dev veth99 scope global')
3519 print(output)
3520 self.assertRegex(output, '2600::')
3521 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3522
3523 @expectedFailureIfModuleIsNotAvailable('vrf')
3524 def test_dhcp_client_vrf(self):
3525 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3526 '25-vrf.netdev', '25-vrf.network')
3527 start_networkd()
3528 self.wait_online(['veth-peer:carrier'])
3529 start_dnsmasq()
3530 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
3531
3532 # link become 'routable' when at least one protocol provide an valid address.
3533 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3534 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3535
3536 print('## ip -d link show dev vrf99')
3537 output = check_output('ip -d link show dev vrf99')
3538 print(output)
3539 self.assertRegex(output, 'vrf table 42')
3540
3541 print('## ip address show vrf vrf99')
3542 output = check_output('ip address show vrf vrf99')
3543 print(output)
3544 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3545 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3546 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3547 self.assertRegex(output, 'inet6 .* scope link')
3548
3549 print('## ip address show dev veth99')
3550 output = check_output('ip address show dev veth99')
3551 print(output)
3552 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3553 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3554 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3555 self.assertRegex(output, 'inet6 .* scope link')
3556
3557 print('## ip route show vrf vrf99')
3558 output = check_output('ip route show vrf vrf99')
3559 print(output)
3560 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3561 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3562 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3563 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3564 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3565
3566 print('## ip route show table main dev veth99')
3567 output = check_output('ip route show table main dev veth99')
3568 print(output)
3569 self.assertEqual(output, '')
3570
3571 def test_dhcp_client_gateway_ipv4(self):
3572 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3573 'dhcp-client-gateway-ipv4.network')
3574 start_networkd()
3575 self.wait_online(['veth-peer:carrier'])
3576 start_dnsmasq()
3577 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3578
3579 output = check_output('ip route list dev veth99 10.0.0.0/8')
3580 print(output)
3581 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3582
3583 def test_dhcp_client_gateway_ipv6(self):
3584 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3585 'dhcp-client-gateway-ipv6.network')
3586 start_networkd()
3587 self.wait_online(['veth-peer:carrier'])
3588 start_dnsmasq()
3589 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3590
3591 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3592 print(output)
3593 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3594
3595 def test_dhcp_client_gateway_onlink_implicit(self):
3596 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3597 'dhcp-client-gateway-onlink-implicit.network')
3598 start_networkd()
3599 self.wait_online(['veth-peer:carrier'])
3600 start_dnsmasq()
3601 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3602
3603 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3604 print(output)
3605 self.assertRegex(output, '192.168.5')
3606
3607 output = check_output('ip route list dev veth99 10.0.0.0/8')
3608 print(output)
3609 self.assertRegex(output, 'onlink')
3610 output = check_output('ip route list dev veth99 192.168.100.0/24')
3611 print(output)
3612 self.assertRegex(output, 'onlink')
3613
3614 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
3615 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3616 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3617 start_networkd()
3618 self.wait_online(['veth-peer:carrier'])
3619 start_dnsmasq(lease_time='2m')
3620 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3621
3622 output = check_output('ip address show dev veth99')
3623 print(output)
3624
3625 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3626 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3627 output = check_output('ip -6 address show dev veth99 scope link')
3628 self.assertRegex(output, 'inet6 .* scope link')
3629 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3630 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3631 output = check_output('ip -4 address show dev veth99 scope link')
3632 self.assertNotRegex(output, 'inet .* scope link')
3633
3634 print('Wait for the dynamic address to be expired')
3635 time.sleep(130)
3636
3637 output = check_output('ip address show dev veth99')
3638 print(output)
3639
3640 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3641 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3642 output = check_output('ip -6 address show dev veth99 scope link')
3643 self.assertRegex(output, 'inet6 .* scope link')
3644 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3645 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3646 output = check_output('ip -4 address show dev veth99 scope link')
3647 self.assertNotRegex(output, 'inet .* scope link')
3648
3649 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
3650
3651 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
3652 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3653 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3654 start_networkd()
3655 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
3656
3657 output = check_output('ip address show dev veth99')
3658 print(output)
3659
3660 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3661 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3662 output = check_output('ip -6 address show dev veth99 scope link')
3663 self.assertRegex(output, 'inet6 .* scope link')
3664 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3665 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3666 output = check_output('ip -4 address show dev veth99 scope link')
3667 self.assertRegex(output, 'inet .* scope link')
3668
3669 def test_dhcp_client_route_remove_on_renew(self):
3670 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3671 'dhcp-client-ipv4-only-ipv6-disabled.network')
3672 start_networkd()
3673 self.wait_online(['veth-peer:carrier'])
3674 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
3675 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3676
3677 # test for issue #12490
3678
3679 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3680 print(output)
3681 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3682 address1=None
3683 for line in output.splitlines():
3684 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3685 address1 = line.split()[1].split('/')[0]
3686 break
3687
3688 output = check_output('ip -4 route show dev veth99')
3689 print(output)
3690 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3691 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3692
3693 stop_dnsmasq(dnsmasq_pid_file)
3694 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
3695
3696 print('Wait for the dynamic address to be expired')
3697 time.sleep(130)
3698
3699 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3700 print(output)
3701 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3702 address2=None
3703 for line in output.splitlines():
3704 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3705 address2 = line.split()[1].split('/')[0]
3706 break
3707
3708 self.assertNotEqual(address1, address2)
3709
3710 output = check_output('ip -4 route show dev veth99')
3711 print(output)
3712 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3713 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3714 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3715 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3716
3717 def test_dhcp_client_use_dns_yes(self):
3718 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3719
3720 start_networkd()
3721 self.wait_online(['veth-peer:carrier'])
3722 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3723 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3724
3725 # link become 'routable' when at least one protocol provide an valid address.
3726 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3727 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3728
3729 time.sleep(3)
3730 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3731 print(output)
3732 self.assertRegex(output, '192.168.5.1')
3733 self.assertRegex(output, '2600::1')
3734
3735 def test_dhcp_client_use_dns_no(self):
3736 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3737
3738 start_networkd()
3739 self.wait_online(['veth-peer:carrier'])
3740 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3741 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3742
3743 # link become 'routable' when at least one protocol provide an valid address.
3744 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3745 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3746
3747 time.sleep(3)
3748 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3749 print(output)
3750 self.assertNotRegex(output, '192.168.5.1')
3751 self.assertNotRegex(output, '2600::1')
3752
3753 def test_dhcp_client_use_dns_ipv4(self):
3754 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3755
3756 start_networkd()
3757 self.wait_online(['veth-peer:carrier'])
3758 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3759 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3760
3761 # link become 'routable' when at least one protocol provide an valid address.
3762 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3763 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3764
3765 time.sleep(3)
3766 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3767 print(output)
3768 self.assertRegex(output, '192.168.5.1')
3769 self.assertNotRegex(output, '2600::1')
3770
3771 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3772 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3773
3774 start_networkd()
3775 self.wait_online(['veth-peer:carrier'])
3776 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3777 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3778
3779 # link become 'routable' when at least one protocol provide an valid address.
3780 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3781 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3782
3783 time.sleep(3)
3784 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3785 print(output)
3786 self.assertRegex(output, '192.168.5.1')
3787 self.assertRegex(output, '2600::1')
3788
3789 def test_dhcp_client_use_domains(self):
3790 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3791
3792 start_networkd()
3793 self.wait_online(['veth-peer:carrier'])
3794 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3795 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3796
3797 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3798 print(output)
3799 self.assertRegex(output, 'Search Domains: example.com')
3800
3801 time.sleep(3)
3802 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3803 print(output)
3804 self.assertRegex(output, 'example.com')
3805
3806 def test_dhcp_client_decline(self):
3807 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3808
3809 start_networkd()
3810 self.wait_online(['veth-peer:carrier'])
3811 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3812 self.assertTrue(rc == 1)
3813
3814 class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3815 links = ['veth99']
3816
3817 units = [
3818 '25-veth.netdev',
3819 'ipv6ra-prefix-client.network',
3820 'ipv6ra-prefix.network'
3821 ]
3822
3823 def setUp(self):
3824 remove_links(self.links)
3825 stop_networkd(show_logs=False)
3826
3827 def tearDown(self):
3828 remove_log_file()
3829 remove_links(self.links)
3830 remove_unit_from_networkd_path(self.units)
3831 stop_networkd(show_logs=True)
3832
3833 def test_ipv6_route_prefix(self):
3834 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3835
3836 start_networkd()
3837 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3838
3839 output = check_output('ip -6 route show dev veth-peer')
3840 print(output)
3841 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3842
3843 output = check_output('ip addr show dev veth99')
3844 print(output)
3845 self.assertNotRegex(output, '2001:db8:0:1')
3846 self.assertRegex(output, '2001:db8:0:2')
3847
3848 class NetworkdMTUTests(unittest.TestCase, Utilities):
3849 links = ['dummy98']
3850
3851 units = [
3852 '12-dummy.netdev',
3853 '12-dummy-mtu.netdev',
3854 '12-dummy-mtu.link',
3855 '12-dummy.network',
3856 ]
3857
3858 def setUp(self):
3859 remove_links(self.links)
3860 stop_networkd(show_logs=False)
3861
3862 def tearDown(self):
3863 remove_log_file()
3864 remove_links(self.links)
3865 remove_unit_from_networkd_path(self.units)
3866 stop_networkd(show_logs=True)
3867
3868 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3869 if not ipv6_mtu:
3870 ipv6_mtu = mtu
3871
3872 # test normal start
3873 start_networkd()
3874 self.wait_online(['dummy98:routable'])
3875 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3876 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3877
3878 # test normal restart
3879 restart_networkd()
3880 self.wait_online(['dummy98:routable'])
3881 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3882 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3883
3884 if reset:
3885 self.reset_check_mtu(mtu, ipv6_mtu)
3886
3887 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3888 ''' test setting mtu/ipv6_mtu with interface already up '''
3889 stop_networkd()
3890
3891 # note - changing the device mtu resets the ipv6 mtu
3892 run('ip link set up mtu 1501 dev dummy98')
3893 run('ip link set up mtu 1500 dev dummy98')
3894 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3895 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3896
3897 self.check_mtu(mtu, ipv6_mtu, reset=False)
3898
3899 def test_mtu_network(self):
3900 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3901 self.check_mtu('1600')
3902
3903 def test_mtu_netdev(self):
3904 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3905 # note - MTU set by .netdev happens ONLY at device creation!
3906 self.check_mtu('1600', reset=False)
3907
3908 def test_mtu_link(self):
3909 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3910 # must reload udev because it only picks up new files after 3 second delay
3911 call('udevadm control --reload')
3912 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3913 self.check_mtu('1600', reset=False)
3914
3915 def test_ipv6_mtu(self):
3916 ''' set ipv6 mtu without setting device mtu '''
3917 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3918 self.check_mtu('1500', '1400')
3919
3920 def test_ipv6_mtu_toolarge(self):
3921 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3922 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3923 self.check_mtu('1500', '1500')
3924
3925 def test_mtu_network_ipv6_mtu(self):
3926 ''' set ipv6 mtu and set device mtu via network file '''
3927 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3928 self.check_mtu('1600', '1550')
3929
3930 def test_mtu_netdev_ipv6_mtu(self):
3931 ''' set ipv6 mtu and set device mtu via netdev file '''
3932 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3933 self.check_mtu('1600', '1550', reset=False)
3934
3935 def test_mtu_link_ipv6_mtu(self):
3936 ''' set ipv6 mtu and set device mtu via link file '''
3937 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3938 # must reload udev because it only picks up new files after 3 second delay
3939 call('udevadm control --reload')
3940 self.check_mtu('1600', '1550', reset=False)
3941
3942
3943 if __name__ == '__main__':
3944 parser = argparse.ArgumentParser()
3945 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3946 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
3947 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
3948 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
3949 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3950 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
3951 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3952 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
3953 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3954 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
3955 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
3956 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
3957 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
3958 ns, args = parser.parse_known_args(namespace=unittest)
3959
3960 if ns.build_dir:
3961 if ns.networkd_bin or ns.resolved_bin or ns.udevd_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin:
3962 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3963 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
3964 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
3965 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
3966 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3967 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
3968 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3969 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
3970 else:
3971 if ns.networkd_bin:
3972 networkd_bin = ns.networkd_bin
3973 if ns.resolved_bin:
3974 resolved_bin = ns.resolved_bin
3975 if ns.udevd_bin:
3976 udevd_bin = ns.udevd_bin
3977 if ns.wait_online_bin:
3978 wait_online_bin = ns.wait_online_bin
3979 if ns.networkctl_bin:
3980 networkctl_bin = ns.networkctl_bin
3981 if ns.resolvectl_bin:
3982 resolvectl_bin = ns.resolvectl_bin
3983 if ns.timedatectl_bin:
3984 timedatectl_bin = ns.timedatectl_bin
3985
3986 use_valgrind = ns.use_valgrind
3987 enable_debug = ns.enable_debug
3988 asan_options = ns.asan_options
3989 lsan_options = ns.lsan_options
3990 ubsan_options = ns.ubsan_options
3991
3992 if use_valgrind:
3993 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
3994 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3995 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
3996 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3997 else:
3998 networkctl_cmd = [networkctl_bin]
3999 resolvectl_cmd = [resolvectl_bin]
4000 timedatectl_cmd = [timedatectl_bin]
4001 wait_online_cmd = [wait_online_bin]
4002
4003 if enable_debug:
4004 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
4005 if asan_options:
4006 env.update({ 'ASAN_OPTIONS' : asan_options })
4007 if lsan_options:
4008 env.update({ 'LSAN_OPTIONS' : lsan_options })
4009 if ubsan_options:
4010 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
4011
4012 sys.argv[1:] = args
4013 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
4014 verbosity=3))