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