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