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