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