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