]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: dhcp4,ndisc: make addresses in Allow/DenyList= optionally take prefix length
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109 1#!/usr/bin/env python3
db9ecf05 2# SPDX-License-Identifier: LGPL-2.1-or-later
1f0e3109
SS
3# systemd-networkd tests
4
9c1ae484 5import argparse
7c0d36ff 6import itertools
1f0e3109 7import os
201bf07f 8import re
1f0e3109
SS
9import shutil
10import signal
a9bc5e37
YW
11import subprocess
12import sys
a9bc5e37
YW
13import time
14import unittest
1f0e3109
SS
15from shutil import copytree
16
d486a2d0 17network_unit_file_path='/run/systemd/network'
bad4969b 18networkd_runtime_directory='/run/systemd/netif'
1d26d4cd 19networkd_conf_dropin_path='/run/systemd/networkd.conf.d'
d486a2d0 20networkd_ci_path='/run/networkd-ci'
1f0e3109
SS
21network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
22network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
23
d486a2d0
YW
24dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
25dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
1f0e3109 26
7471bcb0
DS
27systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
28which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
29
30networkd_bin=shutil.which('systemd-networkd', path=which_paths)
31resolved_bin=shutil.which('systemd-resolved', path=which_paths)
641aa412 32udevd_bin=shutil.which('systemd-udevd', path=which_paths)
7471bcb0
DS
33wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
34networkctl_bin=shutil.which('networkctl', path=which_paths)
35resolvectl_bin=shutil.which('resolvectl', path=which_paths)
36timedatectl_bin=shutil.which('timedatectl', path=which_paths)
37
9c1ae484 38use_valgrind=False
aaae5713 39enable_debug=True
9c1ae484 40env = {}
94c03122 41asan_options=None
fa4c6095 42lsan_options=None
94c03122 43ubsan_options=None
5aa58329 44
2225e7fd
YW
45running_units = []
46
371810d1
ZJS
47def 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
52def call(*command, **kwargs):
53 command = command[0].split() + list(command[1:])
54 return subprocess.call(command, universal_newlines=True, **kwargs)
55
56def run(*command, **kwargs):
57 command = command[0].split() + list(command[1:])
58 return subprocess.run(command, universal_newlines=True, **kwargs)
59
7a0a37b2 60def is_module_available(module_name):
371810d1
ZJS
61 lsmod_output = check_output('lsmod')
62 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
856423f1 63 return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
7a0a37b2
EV
64
65def 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
7bea7f9b
SS
73def expectedFailureIfERSPANModuleIsNotAvailable():
74 def f(func):
856423f1 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)
7bea7f9b 76 if rc == 0:
371810d1 77 call('ip link del erspan99')
7bea7f9b
SS
78 return func
79 else:
80 return unittest.expectedFailure(func)
81
82 return f
83
d586a2c3
YW
84def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
85 def f(func):
856423f1 86 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
d586a2c3 87 if rc == 0:
371810d1 88 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3
YW
89 return func
90 else:
91 return unittest.expectedFailure(func)
92
93 return f
94
95def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
96 def f(func):
856423f1 97 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
d586a2c3 98 if rc == 0:
371810d1 99 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
d586a2c3
YW
100 return func
101 else:
102 return unittest.expectedFailure(func)
103
104 return f
105
6be8e78e
YW
106def 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
e28fd95f
YW
123def expectedFailureIfLinkFileFieldIsNotSet():
124 def f(func):
125 support = False
856423f1 126 rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
e28fd95f
YW
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
086bcf5d
YW
140def expectedFailureIfNexthopIsNotAvailable():
141 def f(func):
856423f1 142 rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
086bcf5d
YW
143 if rc == 0:
144 return func
145 else:
146 return unittest.expectedFailure(func)
147
148 return f
149
297f9d86
YW
150def 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
6934ace0
YW
164def 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)
834ea1a4 168 call('ip link del dummy98', stderr=subprocess.DEVNULL)
6934ace0
YW
169 if rc == 0:
170 return func
171 else:
172 return unittest.expectedFailure(func)
173
174 return f
175
3d2c2692
YW
176def 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
f6c6af38
YW
203def 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
be94e591
YW
215def 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
970ab1fc
YW
227def 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
b753e835
YW
239def 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
1578266b
YW
251def 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
1f0e3109 263def setUpModule():
2225e7fd
YW
264 global running_units
265
1f0e3109 266 os.makedirs(network_unit_file_path, exist_ok=True)
1d26d4cd 267 os.makedirs(networkd_conf_dropin_path, exist_ok=True)
1f0e3109
SS
268 os.makedirs(networkd_ci_path, exist_ok=True)
269
270 shutil.rmtree(networkd_ci_path)
6aea9276 271 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 272
f7ada4b8
YW
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']:
2225e7fd
YW
276 if call(f'systemctl is-active --quiet {u}') == 0:
277 check_output(f'systemctl stop {u}')
278 running_units.append(u)
c0bf6733 279
9c1ae484 280 drop_in = [
3e821525
DS
281 '[Unit]',
282 'StartLimitIntervalSec=0',
9c1ae484
YW
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,
94c03122 290 'PrivateTmp=yes'
9c1ae484
YW
291 ]
292 else:
293 drop_in += ['ExecStart=!!' + networkd_bin]
294 if enable_debug:
295 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
94c03122
YW
296 if asan_options:
297 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
fa4c6095
YW
298 if lsan_options:
299 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
94c03122
YW
300 if ubsan_options:
301 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
78690bb5
YW
302 if asan_options or lsan_options or ubsan_options:
303 drop_in += ['SystemCallFilter=']
fa4c6095 304 if use_valgrind or asan_options or lsan_options or ubsan_options:
94c03122 305 drop_in += ['MemoryDenyWriteExecute=no']
9c1ae484 306
9c1ae484
YW
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:
72917fcc 309 f.write('\n'.join(drop_in))
9c1ae484 310
b6d587d1
YW
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
641aa412
YW
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
371810d1
ZJS
347 check_output('systemctl daemon-reload')
348 print(check_output('systemctl cat systemd-networkd.service'))
b6d587d1 349 print(check_output('systemctl cat systemd-resolved.service'))
641aa412 350 print(check_output('systemctl cat systemd-udevd.service'))
b6d587d1 351 check_output('systemctl restart systemd-resolved')
641aa412 352 check_output('systemctl restart systemd-udevd')
9c1ae484 353
1f0e3109 354def tearDownModule():
2225e7fd
YW
355 global running_units
356
1f0e3109 357 shutil.rmtree(networkd_ci_path)
d4fda2a5 358
3aa645f0 359 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service']:
2225e7fd 360 check_output(f'systemctl stop {u}')
d4fda2a5 361
9c1ae484 362 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
b6d587d1 363 shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
641aa412 364 shutil.rmtree('/run/systemd/system/systemd-udevd.service.d')
371810d1 365 check_output('systemctl daemon-reload')
f7ada4b8 366 check_output('systemctl restart systemd-udevd.service')
1f0e3109 367
2225e7fd
YW
368 for u in running_units:
369 check_output(f'systemctl start {u}')
c0bf6733 370
befd4b8b
DS
371def read_link_attr(*args):
372 with open(os.path.join('/sys/class/net/', *args)) as f:
ec38833c
ZJS
373 return f.readline().strip()
374
375def 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
383def link_exists(link):
384 return os.path.exists(os.path.join('/sys/class/net', link))
385
386def 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
392def remove_fou_ports(ports):
393 for port in ports:
5239d7b3 394 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
395
396def remove_routing_policy_rule_tables(tables):
397 for table in tables:
4ef39b49
YW
398 rc = 0
399 while rc == 0:
400 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
66493453
YW
401 rc = 0
402 while rc == 0:
403 rc = call('ip -6 rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
404
405def remove_routes(routes):
406 for route_type, addr in routes:
5239d7b3 407 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c 408
69a91c70
YW
409def 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
ad78d7b0 416def remove_l2tp_tunnels(tunnel_ids):
ec38833c
ZJS
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
424def 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
428def 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
9dfc1a93
DS
432def 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 """
ec38833c
ZJS
442 print()
443 for unit in units:
9dfc1a93 444 if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')):
ec38833c 445 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
9dfc1a93
DS
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)
ec38833c
ZJS
453
454def remove_unit_from_networkd_path(units):
9dfc1a93
DS
455 """Remove previously copied unit files from the testbed.
456
457 Drop-ins will be removed automatically.
458 """
ec38833c
ZJS
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
1d26d4cd
YW
465def 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
470def 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
ec38833c 476def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
625772c9 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
ec38833c
ZJS
478 check_output(dnsmasq_command)
479
480def 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
488def 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
501def 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
505def remove_log_file():
506 if os.path.exists(dnsmasq_log_file):
507 os.remove(dnsmasq_log_file)
508
aaae5713
YW
509def remove_networkd_state_files():
510 if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
ec38833c 511 os.remove(os.path.join(networkd_runtime_directory, 'state'))
aaae5713
YW
512
513def 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')
3aa645f0
MB
516 check_output('systemctl stop systemd-networkd.socket')
517 check_output('systemctl stop systemd-networkd.service')
aaae5713
YW
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
523def start_networkd(sleep_sec=0):
524 check_output('systemctl start systemd-networkd')
ec38833c
ZJS
525 if sleep_sec > 0:
526 time.sleep(sleep_sec)
527
aaae5713
YW
528def 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
1f0e3109 532
ec38833c 533class Utilities():
e39cc445 534 def check_link_exists(self, link):
ec38833c 535 self.assertTrue(link_exists(link))
2be0b6fc 536
0fc0d85f
DS
537 def check_link_attr(self, *args):
538 self.assertEqual(read_link_attr(*args[:-1]), args[-1]);
539
a4632dc7
DS
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
2be0b6fc 570
70448bb1 571 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5):
0c020321
DS
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
70448bb1
L
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
0c020321
DS
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 """
e2aea43f
YW
594 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
595 if bool_any:
596 args += ['--any']
70448bb1
L
597 if ipv4:
598 args += ['--ipv4']
599 if ipv6:
600 args += ['--ipv6']
e2aea43f
YW
601 try:
602 check_output(*args, env=env)
603 except subprocess.CalledProcessError:
604 for link in links_with_operstate:
fc79e6ff 605 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env)
e2aea43f
YW
606 print(output)
607 raise
fd372b1a 608 if not bool_any and setup_state:
0c020321
DS
609 for link in links_with_operstate:
610 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout)
e2aea43f 611
53c32c2b 612 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
613 for i in range(timeout_sec):
614 if i > 0:
615 time.sleep(1)
371810d1 616 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
571f9539 617 if re.search(address_regex, output) and 'tentative' not in output:
2629df47 618 break
240e4137
YW
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)
2629df47 631
1ca44d7d
YW
632class NetworkctlTests(unittest.TestCase, Utilities):
633
634 links = [
dcd9f07c 635 'dummy98',
1ca44d7d
YW
636 'test1',
637 'veth99',
638 ]
639
640 units = [
641 '11-dummy.netdev',
6d5b4efe 642 '11-dummy-mtu.netdev',
1ca44d7d 643 '11-dummy.network',
dcd9f07c 644 '12-dummy.netdev',
6934ace0 645 '12-dummy.link',
dcd9f07c 646 '25-address-static.network',
1ca44d7d
YW
647 '25-veth.netdev',
648 'netdev-link-local-addressing-yes.network',
649 ]
650
651 def setUp(self):
ec38833c 652 remove_links(self.links)
aaae5713 653 stop_networkd(show_logs=False)
1ca44d7d
YW
654
655 def tearDown(self):
ec38833c
ZJS
656 remove_links(self.links)
657 remove_unit_from_networkd_path(self.units)
aaae5713 658 stop_networkd(show_logs=True)
1ca44d7d 659
6934ace0
YW
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
fc79e6ff 667 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6934ace0
YW
668 self.assertRegex(output, 'hogehogehogehogehogehoge')
669
dcd9f07c
YW
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)
3bad5487
YW
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)
dcd9f07c
YW
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)
3bad5487
YW
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)
dcd9f07c 714
66de8671
YW
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)
19cf3143 720 self.wait_operstate('test1', 'off', setup_state='unmanaged')
66de8671
YW
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)
19cf3143 728 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
729
730 remove_unit_from_networkd_path(['11-dummy.netdev'])
731 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 732 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
733
734 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
735 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 736 self.wait_operstate('test1', 'degraded')
66de8671 737
1ca44d7d 738 def test_glob(self):
ec38833c 739 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
2cf6fdff 740 start_networkd()
1ca44d7d 741
e2aea43f 742 self.wait_online(['test1:degraded'])
1ca44d7d 743
371810d1 744 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
745 self.assertRegex(output, '1 lo ')
746 self.assertRegex(output, 'test1')
747
371810d1 748 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
749 self.assertNotRegex(output, '1 lo ')
750 self.assertRegex(output, 'test1')
751
371810d1 752 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
753 self.assertNotRegex(output, '1 lo ')
754 self.assertRegex(output, 'test1')
755
fc79e6ff 756 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
1ca44d7d
YW
757 self.assertNotRegex(output, '1: lo ')
758 self.assertRegex(output, 'test1')
759
fc79e6ff 760 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
761 self.assertNotRegex(output, '1: lo ')
762 self.assertRegex(output, 'test1')
763
6d5b4efe 764 def test_mtu(self):
ec38833c 765 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
2cf6fdff 766 start_networkd()
6d5b4efe 767
e2aea43f 768 self.wait_online(['test1:degraded'])
6d5b4efe 769
fc79e6ff 770 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
6d5b4efe
YW
771 self.assertRegex(output, 'MTU: 1600')
772
e28fd95f
YW
773 def test_type(self):
774 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
775 start_networkd()
e2aea43f 776 self.wait_online(['test1:degraded'])
e28fd95f 777
fc79e6ff 778 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f
YW
779 print(output)
780 self.assertRegex(output, 'Type: ether')
781
fc79e6ff 782 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f
YW
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()
e2aea43f 790 self.wait_online(['test1:degraded'])
e28fd95f 791
fc79e6ff 792 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f 793 print(output)
426654d7 794 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
795 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
796
fc79e6ff 797 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f 798 print(output)
70f32a26 799 self.assertRegex(output, r'Link File: n/a')
e28fd95f
YW
800 self.assertRegex(output, r'Network File: n/a')
801
bee692fd 802 def test_delete_links(self):
ec38833c
ZJS
803 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
804 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 805 start_networkd()
bee692fd 806
e2aea43f 807 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 808
7a2f6fb6 809 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
ec38833c
ZJS
810 self.assertFalse(link_exists('test1'))
811 self.assertFalse(link_exists('veth99'))
812 self.assertFalse(link_exists('veth-peer'))
bee692fd 813
1f0e3109
SS
814class NetworkdNetDevTests(unittest.TestCase, Utilities):
815
e64dc406
YW
816 links_remove_earlier = [
817 'xfrm99',
818 ]
819
820 links = [
09ea6724 821 '6rdtun99',
13060471 822 'bareudp99',
c0267a59 823 'batadv99',
713bfdaa 824 'bond98',
09ea6724
YW
825 'bond99',
826 'bridge99',
827 'dropin-test',
828 'dummy98',
6a97a864
YW
829 'erspan98',
830 'erspan99',
09ea6724 831 'geneve99',
4b6a6d1e 832 'gretap96',
6a97a864 833 'gretap98',
09ea6724 834 'gretap99',
4b6a6d1e 835 'gretun96',
6a97a864
YW
836 'gretun97',
837 'gretun98',
09ea6724 838 'gretun99',
b076d5d7 839 'ifb99',
6a97a864 840 'ip6gretap98',
09ea6724 841 'ip6gretap99',
42a29fcb 842 'ip6gretun96',
6a97a864
YW
843 'ip6gretun97',
844 'ip6gretun98',
845 'ip6gretun99',
846 'ip6tnl97',
847 'ip6tnl98',
09ea6724 848 'ip6tnl99',
4b6a6d1e 849 'ipiptun96',
6a97a864
YW
850 'ipiptun97',
851 'ipiptun98',
09ea6724
YW
852 'ipiptun99',
853 'ipvlan99',
956c8fec 854 'ipvtap99',
09ea6724
YW
855 'isataptun99',
856 'macvlan99',
857 'macvtap99',
811f33d0 858 'nlmon99',
4b6a6d1e 859 'sittun96',
6a97a864
YW
860 'sittun97',
861 'sittun98',
09ea6724
YW
862 'sittun99',
863 'tap99',
864 'test1',
865 'tun99',
866 'vcan99',
867 'veth99',
868 'vlan99',
869 'vrf99',
6a97a864
YW
870 'vti6tun97',
871 'vti6tun98',
09ea6724 872 'vti6tun99',
42a29fcb 873 'vtitun96',
6a97a864
YW
874 'vtitun97',
875 'vtitun98',
09ea6724 876 'vtitun99',
f63b14d3 877 'vxcan99',
cca07d91 878 'vxlan97',
039971ea 879 'vxlan98',
09ea6724 880 'vxlan99',
da3509f0 881 'wg97',
da44fb8a 882 'wg98',
e64dc406
YW
883 'wg99',
884 ]
09ea6724
YW
885
886 units = [
887 '10-dropin-test.netdev',
888 '11-dummy.netdev',
03db80b2 889 '11-dummy.network',
09ea6724 890 '12-dummy.netdev',
6b9518a0
YW
891 '13-not-match-udev-property.network',
892 '14-match-udev-property.network',
753e0a24 893 '15-name-conflict-test.netdev',
09ea6724
YW
894 '21-macvlan.netdev',
895 '21-macvtap.netdev',
7f45d738 896 '21-vlan-test1.network',
09ea6724
YW
897 '21-vlan.netdev',
898 '21-vlan.network',
899 '25-6rd-tunnel.netdev',
13060471 900 '25-bareudp.netdev',
c0267a59 901 '25-batadv.netdev',
09ea6724 902 '25-bond.netdev',
fde60a42 903 '25-bond-balanced-tlb.netdev',
09ea6724 904 '25-bridge.netdev',
1285edf3 905 '25-bridge-configure-without-carrier.network',
03db80b2 906 '25-bridge.network',
6a97a864 907 '25-erspan-tunnel-local-any.netdev',
09ea6724 908 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
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',
09ea6724 915 '25-geneve.netdev',
6a97a864 916 '25-gretap-tunnel-local-any.netdev',
09ea6724 917 '25-gretap-tunnel.netdev',
42a29fcb 918 '25-gre-tunnel-any-any.netdev',
6a97a864
YW
919 '25-gre-tunnel-local-any.netdev',
920 '25-gre-tunnel-remote-any.netdev',
09ea6724 921 '25-gre-tunnel.netdev',
b076d5d7 922 '25-ifb.netdev',
6a97a864
YW
923 '25-ip6gretap-tunnel-local-any.netdev',
924 '25-ip6gretap-tunnel.netdev',
42a29fcb 925 '25-ip6gre-tunnel-any-any.netdev',
6a97a864
YW
926 '25-ip6gre-tunnel-local-any.netdev',
927 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 928 '25-ip6gre-tunnel.netdev',
42a29fcb 929 '25-ip6tnl-tunnel-any-any.netdev',
6a97a864 930 '25-ip6tnl-tunnel-local-any.netdev',
42a29fcb 931 '25-ip6tnl-tunnel-remote-any.netdev',
09ea6724 932 '25-ip6tnl-tunnel.netdev',
42a29fcb 933 '25-ipip-tunnel-any-any.netdev',
09ea6724 934 '25-ipip-tunnel-independent.netdev',
95082dbe 935 '25-ipip-tunnel-independent-loopback.netdev',
6a97a864
YW
936 '25-ipip-tunnel-local-any.netdev',
937 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
938 '25-ipip-tunnel.netdev',
939 '25-ipvlan.netdev',
956c8fec 940 '25-ipvtap.netdev',
09ea6724 941 '25-isatap-tunnel.netdev',
02849d8b
YW
942 '25-macsec.key',
943 '25-macsec.netdev',
944 '25-macsec.network',
811f33d0 945 '25-nlmon.netdev',
42a29fcb 946 '25-sit-tunnel-any-any.netdev',
6a97a864
YW
947 '25-sit-tunnel-local-any.netdev',
948 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
949 '25-sit-tunnel.netdev',
950 '25-tap.netdev',
951 '25-tun.netdev',
5cf52d90 952 '25-tunnel-any-any.network',
11309591
YW
953 '25-tunnel-local-any.network',
954 '25-tunnel-remote-any.network',
955 '25-tunnel.network',
09ea6724
YW
956 '25-vcan.netdev',
957 '25-veth.netdev',
958 '25-vrf.netdev',
42a29fcb 959 '25-vti6-tunnel-any-any.netdev',
6a97a864
YW
960 '25-vti6-tunnel-local-any.netdev',
961 '25-vti6-tunnel-remote-any.netdev',
09ea6724 962 '25-vti6-tunnel.netdev',
42a29fcb 963 '25-vti-tunnel-any-any.netdev',
6a97a864
YW
964 '25-vti-tunnel-local-any.netdev',
965 '25-vti-tunnel-remote-any.netdev',
09ea6724 966 '25-vti-tunnel.netdev',
f63b14d3 967 '25-vxcan.netdev',
039971ea 968 '25-vxlan-independent.netdev',
cca07d91 969 '25-vxlan-ipv6.netdev',
09ea6724 970 '25-vxlan.netdev',
da44fb8a
YW
971 '25-wireguard-23-peers.netdev',
972 '25-wireguard-23-peers.network',
da3509f0
YW
973 '25-wireguard-no-peer.netdev',
974 '25-wireguard-no-peer.network',
9e5d79e7 975 '25-wireguard-preshared-key.txt',
39bcff3b 976 '25-wireguard-private-key.txt',
09ea6724 977 '25-wireguard.netdev',
5a0bd90b 978 '25-wireguard.network',
e64dc406
YW
979 '25-xfrm.netdev',
980 '25-xfrm-independent.netdev',
09ea6724 981 '6rd.network',
6730a1f3 982 'erspan.network',
09ea6724
YW
983 'gre.network',
984 'gretap.network',
985 'gretun.network',
986 'ip6gretap.network',
6a97a864 987 'ip6gretun.network',
09ea6724
YW
988 'ip6tnl.network',
989 'ipip.network',
990 'ipvlan.network',
956c8fec 991 'ipvtap.network',
09ea6724 992 'isatap.network',
02849d8b 993 'macsec.network',
09ea6724
YW
994 'macvlan.network',
995 'macvtap.network',
077f9abc 996 'netdev-link-local-addressing-yes.network',
09ea6724
YW
997 'sit.network',
998 'vti6.network',
999 'vti.network',
cca07d91 1000 'vxlan-ipv6.network',
1c862fe0 1001 'vxlan-test1.network',
e64dc406
YW
1002 'vxlan.network',
1003 'xfrm.network',
1004 ]
1f0e3109 1005
def9fc0d
YW
1006 fou_ports = [
1007 '55555',
1008 '55556']
1009
1f0e3109 1010 def setUp(self):
ec38833c 1011 remove_fou_ports(self.fou_ports)
e64dc406 1012 remove_links(self.links_remove_earlier)
ec38833c 1013 remove_links(self.links)
aaae5713 1014 stop_networkd(show_logs=False)
1f0e3109
SS
1015
1016 def tearDown(self):
ec38833c 1017 remove_fou_ports(self.fou_ports)
e64dc406 1018 remove_links(self.links_remove_earlier)
ec38833c
ZJS
1019 remove_links(self.links)
1020 remove_unit_from_networkd_path(self.units)
aaae5713 1021 stop_networkd(show_logs=True)
1f0e3109 1022
1ca44d7d 1023 def test_dropin_and_name_conflict(self):
ec38833c 1024 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
2cf6fdff 1025 start_networkd()
d80734f7 1026
e2aea43f 1027 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
d80734f7 1028
371810d1 1029 output = check_output('ip link show dropin-test')
d80734f7
YW
1030 print(output)
1031 self.assertRegex(output, '00:50:56:c0:00:28')
1032
6b9518a0
YW
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()
e2aea43f 1036 self.wait_online(['dummy98:routable'])
6b9518a0 1037
fc79e6ff 1038 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6b9518a0
YW
1039 print(output)
1040 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
1041
03db80b2 1042 def test_wait_online_any(self):
ec38833c 1043 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
2cf6fdff 1044 start_networkd()
03db80b2 1045
e2aea43f 1046 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 1047
19cf3143
DS
1048 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
1049 self.wait_operstate('test1', 'degraded')
03db80b2 1050
13060471
YW
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
c0267a59
AW
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
1f0e3109 1074 def test_bridge(self):
1285edf3 1075 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
2cf6fdff 1076 start_networkd()
1f0e3109 1077
e2aea43f 1078 self.wait_online(['bridge99:no-carrier'])
1f0e3109 1079
3d165124 1080 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
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))
c9047092
YW
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')))
1f0e3109 1090
fc79e6ff 1091 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
36bc2ffb
YW
1092 print(output)
1093 self.assertRegex(output, 'Priority: 9')
1094 self.assertRegex(output, 'STP: yes')
1095 self.assertRegex(output, 'Multicast IGMP Version: 3')
1096
1f0e3109 1097 def test_bond(self):
ec38833c 1098 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
2cf6fdff 1099 start_networkd()
ec38833c 1100
e2aea43f 1101 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
ec38833c
ZJS
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'))
fde60a42 1117
1f0e3109 1118 def test_vlan(self):
ec38833c
ZJS
1119 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
1120 '21-vlan.network', '21-vlan-test1.network')
2cf6fdff 1121 start_networkd()
1f0e3109 1122
e2aea43f 1123 self.wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 1124
371810d1 1125 output = check_output('ip -d link show test1')
72b7f1b9 1126 print(output)
7d7be1b9 1127 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1128
371810d1 1129 output = check_output('ip -d link show vlan99')
14ecd604 1130 print(output)
06895a1d
YW
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 ')
1f0e3109 1137
371810d1 1138 output = check_output('ip -4 address show dev test1')
7f45d738
YW
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
371810d1 1143 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
1144 print(output)
1145 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
1146
1f0e3109 1147 def test_macvtap(self):
460feb61
YW
1148 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1149 with self.subTest(mode=mode):
1150 if mode != 'private':
1151 self.tearDown()
ec38833c
ZJS
1152 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
1153 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
1154 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
1155 f.write('[MACVTAP]\nMode=' + mode)
2cf6fdff 1156 start_networkd()
1f0e3109 1157
e2aea43f 1158 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
460feb61 1159
371810d1 1160 output = check_output('ip -d link show macvtap99')
460feb61
YW
1161 print(output)
1162 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
1163
1164 def test_macvlan(self):
dff9792b
YW
1165 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1166 with self.subTest(mode=mode):
1167 if mode != 'private':
1168 self.tearDown()
ec38833c
ZJS
1169 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
1170 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
1171 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
1172 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 1173 start_networkd()
dff9792b 1174
e2aea43f 1175 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
dff9792b 1176
371810d1 1177 output = check_output('ip -d link show test1')
dff9792b
YW
1178 print(output)
1179 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1180
371810d1 1181 output = check_output('ip -d link show macvlan99')
dff9792b
YW
1182 print(output)
1183 self.assertRegex(output, ' mtu 2000 ')
1184 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 1185
1d0c9bd7
YW
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
7a0a37b2 1205 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 1206 def test_ipvlan(self):
bc6dff6e
YW
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()
ec38833c
ZJS
1211 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1212 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
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)
1f0e3109 1215
2cf6fdff 1216 start_networkd()
e2aea43f 1217 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 1218
371810d1 1219 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
1220 print(output)
1221 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 1222
956c8fec
YW
1223 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1224 def test_ipvtap(self):
40921f08
YW
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()
ec38833c
ZJS
1229 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1230 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
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
2cf6fdff 1234 start_networkd()
e2aea43f 1235 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 1236
371810d1 1237 output = check_output('ip -d link show ipvtap99')
40921f08
YW
1238 print(output)
1239 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 1240
1f0e3109 1241 def test_veth(self):
ec38833c 1242 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1243 start_networkd()
1f0e3109 1244
e2aea43f 1245 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 1246
371810d1 1247 output = check_output('ip -d link show veth99')
671dacdf
YW
1248 print(output)
1249 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 1250 output = check_output('ip -d link show veth-peer')
671dacdf
YW
1251 print(output)
1252 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 1253
1f0e3109 1254 def test_tun(self):
ec38833c 1255 copy_unit_to_networkd_unit_path('25-tun.netdev')
2cf6fdff 1256 start_networkd()
1f0e3109 1257
e2aea43f 1258 self.wait_online(['tun99:off'], setup_state='unmanaged')
1f0e3109 1259
371810d1 1260 output = check_output('ip -d link show tun99')
2746d307
YW
1261 print(output)
1262 # Old ip command does not support IFF_ flags
426654d7 1263 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1264
1f0e3109 1265 def test_tap(self):
ec38833c 1266 copy_unit_to_networkd_unit_path('25-tap.netdev')
2cf6fdff 1267 start_networkd()
1f0e3109 1268
e2aea43f 1269 self.wait_online(['tap99:off'], setup_state='unmanaged')
1f0e3109 1270
371810d1 1271 output = check_output('ip -d link show tap99')
2746d307
YW
1272 print(output)
1273 # Old ip command does not support IFF_ flags
426654d7 1274 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1275
7a0a37b2 1276 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 1277 def test_vrf(self):
ec38833c 1278 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1279 start_networkd()
1f0e3109 1280
e2aea43f 1281 self.wait_online(['vrf99:carrier'])
1f0e3109 1282
7a0a37b2 1283 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1284 def test_vcan(self):
ec38833c 1285 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1286 start_networkd()
1f0e3109 1287
e2aea43f 1288 self.wait_online(['vcan99:carrier'])
1f0e3109 1289
f63b14d3
YW
1290 @expectedFailureIfModuleIsNotAvailable('vxcan')
1291 def test_vxcan(self):
ec38833c 1292 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1293 start_networkd()
f63b14d3 1294
e2aea43f 1295 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1296
7a3bc5a8
EV
1297 @expectedFailureIfModuleIsNotAvailable('wireguard')
1298 def test_wireguard(self):
ec38833c
ZJS
1299 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1300 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
da3509f0
YW
1301 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
1302 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
2cf6fdff 1303 start_networkd()
84d32bf5
YW
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)
5a0bd90b 1309
045db4fa
YW
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
7a3bc5a8 1318 if shutil.which('wg'):
371810d1 1319 call('wg')
5a0bd90b 1320
371810d1 1321 output = check_output('wg show wg99 listen-port')
84d32bf5 1322 self.assertEqual(output, '51820')
371810d1 1323 output = check_output('wg show wg99 fwmark')
84d32bf5
YW
1324 self.assertEqual(output, '0x4d2')
1325 output = check_output('wg show wg99 private-key')
1326 self.assertEqual(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
371810d1 1327 output = check_output('wg show wg99 allowed-ips')
84d32bf5
YW
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)
371810d1 1332 output = check_output('wg show wg99 persistent-keepalive')
84d32bf5
YW
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)
371810d1 1337 output = check_output('wg show wg99 endpoints')
84d32bf5
YW
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)
371810d1 1342 output = check_output('wg show wg99 preshared-keys')
84d32bf5
YW
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)
7a3bc5a8 1347
371810d1 1348 output = check_output('wg show wg98 private-key')
84d32bf5 1349 self.assertEqual(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
da44fb8a 1350
da3509f0 1351 output = check_output('wg show wg97 listen-port')
84d32bf5 1352 self.assertEqual(output, '51821')
da3509f0 1353 output = check_output('wg show wg97 fwmark')
84d32bf5 1354 self.assertEqual(output, '0x4d3')
da3509f0 1355
1f0e3109 1356 def test_geneve(self):
ec38833c 1357 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1358 start_networkd()
1f0e3109 1359
e2aea43f 1360 self.wait_online(['geneve99:degraded'])
1f0e3109 1361
371810d1 1362 output = check_output('ip -d link show geneve99')
14ecd604 1363 print(output)
06895a1d
YW
1364 self.assertRegex(output, '192.168.22.1')
1365 self.assertRegex(output, '6082')
1366 self.assertRegex(output, 'udpcsum')
1367 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1368
1369 def test_ipip_tunnel(self):
ec38833c
ZJS
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',
42a29fcb
YW
1373 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1374 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1375 start_networkd()
e2aea43f 1376 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1377
371810d1 1378 output = check_output('ip -d link show ipiptun99')
6a97a864 1379 print(output)
426654d7 1380 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1381 output = check_output('ip -d link show ipiptun98')
6a97a864 1382 print(output)
426654d7 1383 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1384 output = check_output('ip -d link show ipiptun97')
6a97a864 1385 print(output)
426654d7 1386 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1387 output = check_output('ip -d link show ipiptun96')
1388 print(output)
426654d7 1389 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1390
1391 def test_gre_tunnel(self):
ec38833c
ZJS
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',
42a29fcb
YW
1395 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1396 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1397 start_networkd()
e2aea43f 1398 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1399
371810d1 1400 output = check_output('ip -d link show gretun99')
6a97a864
YW
1401 print(output)
1402 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
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')
371810d1 1407 output = check_output('ip -d link show gretun98')
6a97a864
YW
1408 print(output)
1409 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
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')
371810d1 1414 output = check_output('ip -d link show gretun97')
6a97a864
YW
1415 print(output)
1416 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
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')
42a29fcb
YW
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')
6a97a864
YW
1428
1429 def test_ip6gre_tunnel(self):
ec38833c
ZJS
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',
42a29fcb
YW
1433 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1434 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
01943d43 1435 start_networkd(5)
6a97a864 1436
17bcf0a0
YW
1437 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1438
e39cc445
YW
1439 self.check_link_exists('dummy98')
1440 self.check_link_exists('ip6gretun99')
1441 self.check_link_exists('ip6gretun98')
1442 self.check_link_exists('ip6gretun97')
42a29fcb 1443 self.check_link_exists('ip6gretun96')
6a97a864 1444
371810d1 1445 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1446 print(output)
1447 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1448 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1449 print(output)
1450 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1451 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1452 print(output)
1453 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1454 output = check_output('ip -d link show ip6gretun96')
1455 print(output)
1456 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1457
11309591 1458 def test_gretap_tunnel(self):
ec38833c
ZJS
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')
2cf6fdff 1462 start_networkd()
e2aea43f 1463 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1464
371810d1 1465 output = check_output('ip -d link show gretap99')
6a97a864
YW
1466 print(output)
1467 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
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')
371810d1 1472 output = check_output('ip -d link show gretap98')
6a97a864
YW
1473 print(output)
1474 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
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')
1f0e3109
SS
1479
1480 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
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')
2cf6fdff 1484 start_networkd()
e2aea43f 1485 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1486
371810d1 1487 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1488 print(output)
1489 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1490 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1491 print(output)
1492 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1493
1494 def test_vti_tunnel(self):
ec38833c
ZJS
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',
42a29fcb
YW
1498 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1499 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1500 start_networkd()
e2aea43f 1501 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1502
371810d1 1503 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1504 print(output)
1505 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1506 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1507 print(output)
1508 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1509 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1510 print(output)
1511 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1512 output = check_output('ip -d link show vtitun96')
1513 print(output)
1514 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1515
1516 def test_vti6_tunnel(self):
ec38833c
ZJS
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')
2cf6fdff 1521 start_networkd()
e2aea43f 1522 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1523
371810d1 1524 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1525 print(output)
1526 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1527 output = check_output('ip -d link show vti6tun98')
6a97a864 1528 print(output)
426654d7 1529 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1530 output = check_output('ip -d link show vti6tun97')
6a97a864 1531 print(output)
426654d7 1532 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1533
1534 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
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')
2cf6fdff 1539 start_networkd()
e2aea43f 1540 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 1541
371810d1 1542 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
1543 print(output)
1544 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1545 output = check_output('ip -d link show ip6tnl98')
6a97a864 1546 print(output)
426654d7 1547 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1548 output = check_output('ip -d link show ip6tnl97')
6a97a864 1549 print(output)
426654d7 1550 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1551
1552 def test_sit_tunnel(self):
ec38833c
ZJS
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',
42a29fcb
YW
1556 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1557 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1558 start_networkd()
e2aea43f 1559 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1560
371810d1 1561 output = check_output('ip -d link show sittun99')
6a97a864 1562 print(output)
426654d7 1563 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1564 output = check_output('ip -d link show sittun98')
6a97a864 1565 print(output)
426654d7 1566 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1567 output = check_output('ip -d link show sittun97')
6a97a864 1568 print(output)
426654d7 1569 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1570 output = check_output('ip -d link show sittun96')
1571 print(output)
426654d7 1572 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1573
d0e728b6 1574 def test_isatap_tunnel(self):
ec38833c
ZJS
1575 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1576 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1577 start_networkd()
e2aea43f 1578 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1579
371810d1 1580 output = check_output('ip -d link show isataptun99')
14ecd604 1581 print(output)
d0e728b6
SS
1582 self.assertRegex(output, "isatap ")
1583
d29dc4f1 1584 def test_6rd_tunnel(self):
ec38833c
ZJS
1585 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1586 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1587 start_networkd()
e2aea43f 1588 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1589
371810d1 1590 output = check_output('ip -d link show sittun99')
6a97a864
YW
1591 print(output)
1592 self.assertRegex(output, '6rd-prefix 2602::/24')
1593
7bea7f9b 1594 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1595 def test_erspan_tunnel(self):
ec38833c
ZJS
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')
2cf6fdff 1599 start_networkd()
e2aea43f 1600 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1601
371810d1 1602 output = check_output('ip -d link show erspan99')
6a97a864
YW
1603 print(output)
1604 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
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')
371810d1 1609 output = check_output('ip -d link show erspan98')
2266864b 1610 print(output)
6a97a864
YW
1611 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1612 self.assertRegex(output, '102')
38f4bb44
YW
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')
2266864b 1617
1f0e3109 1618 def test_tunnel_independent(self):
ec38833c 1619 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1620 start_networkd()
e40a58b5 1621
e2aea43f 1622 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1623
95082dbe
YW
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
e2aea43f 1628 self.wait_online(['ipiptun99:carrier'])
95082dbe 1629
e64dc406
YW
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
e2aea43f 1636 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
e64dc406
YW
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
e2aea43f 1646 self.wait_online(['xfrm99:degraded'])
e64dc406 1647
4b6a6d1e
YW
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
ec38833c
ZJS
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')
2cf6fdff 1657 start_networkd()
4b6a6d1e 1658
e2aea43f 1659 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1660
371810d1 1661 output = check_output('ip fou show')
4b6a6d1e
YW
1662 print(output)
1663 self.assertRegex(output, 'port 55555 ipproto 4')
1664 self.assertRegex(output, 'port 55556 ipproto 47')
1665
371810d1 1666 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1667 print(output)
1668 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1669 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1670 print(output)
1671 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1672 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1673 print(output)
1674 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1675 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1676 print(output)
1677 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1678
1f0e3109 1679 def test_vxlan(self):
ec38833c 1680 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
cca07d91 1681 '25-vxlan-ipv6.netdev', 'vxlan-ipv6.network',
039971ea 1682 '25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network',
ec38833c 1683 '11-dummy.netdev', 'vxlan-test1.network')
2cf6fdff 1684 start_networkd()
1f0e3109 1685
cca07d91 1686 self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded'])
1f0e3109 1687
371810d1 1688 output = check_output('ip -d link show vxlan99')
14ecd604 1689 print(output)
cca07d91
YW
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)
1f0e3109 1700
371810d1 1701 output = check_output('bridge fdb show dev vxlan99')
1c862fe0 1702 print(output)
cca07d91
YW
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)
1c862fe0 1706
fc79e6ff 1707 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb 1708 print(output)
cca07d91
YW
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)
36bc2ffb 1718
02849d8b 1719 def test_macsec(self):
ec38833c
ZJS
1720 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1721 'macsec.network', '12-dummy.netdev')
2cf6fdff 1722 start_networkd()
02849d8b 1723
e2aea43f 1724 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1725
371810d1 1726 output = check_output('ip -d link show macsec99')
02849d8b
YW
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
371810d1 1732 output = check_output('ip macsec show macsec99')
02849d8b
YW
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
811f33d0 1747 def test_nlmon(self):
ec38833c 1748 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1749 start_networkd()
811f33d0 1750
e2aea43f 1751 self.wait_online(['nlmon99:carrier'])
02849d8b 1752
b076d5d7
YW
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
cff83db9
YW
1760class 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',
e2aea43f 1772 '25-l2tp.network',
cff83db9
YW
1773 '25-l2tp-ip.netdev',
1774 '25-l2tp-udp.netdev']
1775
1776 l2tp_tunnel_ids = [ '10' ]
1777
1778 def setUp(self):
ad78d7b0 1779 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1780 remove_links(self.links)
aaae5713 1781 stop_networkd(show_logs=False)
cff83db9
YW
1782
1783 def tearDown(self):
ad78d7b0 1784 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1785 remove_links(self.links)
1786 remove_unit_from_networkd_path(self.units)
aaae5713 1787 stop_networkd(show_logs=True)
cff83db9
YW
1788
1789 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1790 def test_l2tp_udp(self):
e2aea43f
YW
1791 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1792 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 1793 start_networkd()
cff83db9 1794
e2aea43f 1795 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 1796
371810d1 1797 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
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
371810d1 1805 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
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
371810d1 1811 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
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):
e2aea43f
YW
1819 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1820 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 1821 start_networkd()
cff83db9 1822
e2aea43f 1823 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 1824
371810d1 1825 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
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
371810d1 1831 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
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
371810d1 1837 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
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
be68c2c9 1843class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1844 links = [
1845 'bond199',
1846 'dummy98',
cd65d067 1847 'dummy99',
74761cf3 1848 'gretun97',
fb2ba330 1849 'ip6gretun97',
086bcf5d 1850 'test1',
70448bb1 1851 'veth-peer',
086bcf5d 1852 'veth99',
40afe491 1853 'vrf99',
74761cf3 1854 ]
09ea6724
YW
1855
1856 units = [
1857 '11-dummy.netdev',
1858 '12-dummy.netdev',
61764fe4 1859 '12-dummy.network',
09ea6724 1860 '23-active-slave.network',
1e498853 1861 '24-keep-configuration-static.network',
fdcd1ec5 1862 '24-search-domain.network',
44924431 1863 '25-address-ipv4acd-veth99.network',
09ea6724 1864 '25-address-link-section.network',
21266e60 1865 '25-address-peer-ipv4.network',
b8102725 1866 '25-address-static.network',
2236d75d 1867 '25-activation-policy.network',
cd65d067 1868 '25-bind-carrier.network',
09ea6724
YW
1869 '25-bond-active-backup-slave.netdev',
1870 '25-fibrule-invert.network',
1871 '25-fibrule-port-range.network',
6be8e78e 1872 '25-fibrule-uidrange.network',
74761cf3 1873 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1874 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1875 '25-ipv6-address-label-section.network',
cff0cadc 1876 '25-ipv6-proxy-ndp.network',
ef3c8a92
YW
1877 '25-link-local-addressing-no.network',
1878 '25-link-local-addressing-yes.network',
1879 '25-link-section-unmanaged.network',
e4a71bf3 1880 '25-neighbor-section.network',
d1bdafd2 1881 '25-neighbor-next.network',
fb2ba330 1882 '25-neighbor-ipv6.network',
74761cf3
YW
1883 '25-neighbor-ip-dummy.network',
1884 '25-neighbor-ip.network',
9c8f90d0 1885 '25-nexthop-dummy.network',
9947c7ba 1886 '25-nexthop-nothing.network',
086bcf5d 1887 '25-nexthop.network',
f6c6af38 1888 '25-qdisc-cake.network',
f1de1eb3 1889 '25-qdisc-clsact-and-htb.network',
557fa421 1890 '25-qdisc-drr.network',
b753e835 1891 '25-qdisc-ets.network',
1578266b 1892 '25-qdisc-fq_pie.network',
970ab1fc 1893 '25-qdisc-hhf.network',
ab9dc1db 1894 '25-qdisc-ingress-netem-compat.network',
be94e591 1895 '25-qdisc-pie.network',
891ff963 1896 '25-qdisc-qfq.network',
c9d223e8
YW
1897 '25-prefix-route-with-vrf.network',
1898 '25-prefix-route-without-vrf.network',
20ca06a6 1899 '25-route-ipv6-src.network',
0ef830cf 1900 '25-route-static.network',
297f9d86 1901 '25-route-via-ipv6.network',
40afe491 1902 '25-route-vrf.network',
0b1cd3e2
WKI
1903 '25-gateway-static.network',
1904 '25-gateway-next-static.network',
3d2c2692 1905 '25-sriov.network',
4da33154 1906 '25-sysctl-disable-ipv6.network',
09ea6724 1907 '25-sysctl.network',
9bacf431 1908 '25-test1.network',
086bcf5d
YW
1909 '25-veth-peer.network',
1910 '25-veth.netdev',
40afe491 1911 '25-vrf.netdev',
c9d223e8 1912 '25-vrf.network',
7b3770a7 1913 '26-link-local-addressing-ipv6.network',
70448bb1
L
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',
b677774d 1918 'routing-policy-rule-dummy98.network',
87adeabf 1919 'routing-policy-rule-test1.network',
49ff3f34
YW
1920 'routing-policy-rule-reconfigure1.network',
1921 'routing-policy-rule-reconfigure2.network',
87adeabf 1922 ]
1f0e3109 1923
1d26d4cd
YW
1924 networkd_conf_dropins = [
1925 'networkd-manage-foreign-routes-no.conf',
1926 ]
1927
2e8a32af 1928 routing_policy_rule_tables = ['7', '8', '9', '10', '1011']
5f68a6a4 1929 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1930
1f0e3109 1931 def setUp(self):
69a91c70 1932 remove_blackhole_nexthops()
ec38833c
ZJS
1933 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1934 remove_routes(self.routes)
1935 remove_links(self.links)
aaae5713 1936 stop_networkd(show_logs=False)
44924431 1937 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109
SS
1938
1939 def tearDown(self):
69a91c70 1940 remove_blackhole_nexthops()
ec38833c
ZJS
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)
1d26d4cd 1945 remove_networkd_conf_dropin(self.networkd_conf_dropins)
aaae5713 1946 stop_networkd(show_logs=True)
44924431 1947 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109 1948
b8102725 1949 def test_address_static(self):
ec38833c 1950 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 1951 start_networkd()
b8102725 1952
e2aea43f 1953 self.wait_online(['dummy98:routable'])
b8102725 1954
371810d1 1955 output = check_output('ip -4 address show dev dummy98')
b8102725 1956 print(output)
4a704501
YW
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)
045db4fa 1961 self.assertIn('inet 10.8.8.1/16 scope global dummy98', output)
b8102725 1962
766f8f38
YW
1963 # test for ENOBUFS issue #17012
1964 for i in range(1,254):
4a704501 1965 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
766f8f38 1966
b8102725 1967 # invalid sections
4a704501
YW
1968 self.assertNotIn('10.10.0.1/16', output)
1969 self.assertNotIn('10.10.0.2/16', output)
b8102725 1970
371810d1 1971 output = check_output('ip -4 address show dev dummy98 label 32')
4a704501 1972 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
b8102725 1973
371810d1 1974 output = check_output('ip -4 address show dev dummy98 label 33')
4a704501 1975 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
b8102725 1976
371810d1 1977 output = check_output('ip -4 address show dev dummy98 label 34')
4a704501 1978 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
b8102725 1979
371810d1 1980 output = check_output('ip -4 address show dev dummy98 label 35')
4a704501 1981 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
b8102725 1982
371810d1 1983 output = check_output('ip -6 address show dev dummy98')
b8102725 1984 print(output)
4a704501
YW
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')
b8102725 1992
766f8f38
YW
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):
4a704501 1999 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
e4783b54 2000
44924431
YW
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)
dc7d3c5f 2010 start_networkd()
44924431 2011 self.wait_online(['veth99:routable'])
dc7d3c5f
YW
2012
2013 output = check_output('ip -4 address show dev veth99')
2014 print(output)
44924431
YW
2015 self.assertNotIn('192.168.100.10/24', output)
2016 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2017
44924431
YW
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')
dc7d3c5f 2025 print(output)
44924431
YW
2026 self.assertNotIn('192.168.100.10/24', output)
2027 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2028
21266e60
YW
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
c9d223e8
YW
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')
beb75dd3 2081 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8
YW
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')
beb75dd3 2113 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8 2114
1f0e3109 2115 def test_configure_without_carrier(self):
9bacf431 2116 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2cf6fdff 2117 start_networkd()
9bacf431
DS
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}')
705c7b18 2131 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
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])
e40a58b5 2138
9bacf431
DS
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}')
705c7b18 2155 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
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])
1f0e3109 2166
1f0e3109 2167 def test_routing_policy_rule(self):
ec38833c 2168 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 2169 start_networkd()
e2aea43f 2170 self.wait_online(['test1:degraded'])
e40a58b5 2171
65c24cd0 2172 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 2173 print(output)
65c24cd0 2174 self.assertRegex(output, '111:')
1f0e3109 2175 self.assertRegex(output, 'from 192.168.100.18')
426654d7 2176 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
2177 self.assertRegex(output, 'iif test1')
2178 self.assertRegex(output, 'oif test1')
2179 self.assertRegex(output, 'lookup 7')
2180
65c24cd0
YW
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
2e8a32af
HV
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
b677774d 2202 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
2203 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
2204 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 2205
b677774d
YW
2206 for trial in range(3):
2207 # Remove state files only first time
e2aea43f
YW
2208 start_networkd(3)
2209 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 2210 time.sleep(1)
b677774d 2211
371810d1 2212 output = check_output('ip rule list table 7')
b677774d 2213 print(output)
426654d7 2214 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 2215
371810d1 2216 output = check_output('ip rule list table 8')
b677774d 2217 print(output)
426654d7 2218 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 2219
aaae5713
YW
2220 stop_networkd(remove_state_files=False)
2221
87adeabf 2222 def test_routing_policy_rule_reconfigure(self):
49ff3f34 2223 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
87adeabf
YW
2224 start_networkd()
2225 self.wait_online(['test1:degraded'])
2226
2227 output = check_output('ip rule list table 1011')
2228 print(output)
49ff3f34
YW
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)
87adeabf
YW
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')
49ff3f34 2259 run('ip -6 rule delete priority 10113')
87adeabf
YW
2260
2261 output = check_output('ip rule list table 1011')
2262 print(output)
2263 self.assertEqual(output, '')
2264
49ff3f34
YW
2265 output = check_output('ip -6 rule list table 1011')
2266 print(output)
2267 self.assertEqual(output, '')
87adeabf 2268
49ff3f34 2269 run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
87adeabf
YW
2270 self.wait_online(['test1:degraded'])
2271
2272 output = check_output('ip rule list table 1011')
2273 print(output)
49ff3f34
YW
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)
87adeabf 2282
d586a2c3 2283 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 2284 def test_routing_policy_rule_port_range(self):
ec38833c 2285 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 2286 start_networkd()
e2aea43f 2287 self.wait_online(['test1:degraded'])
e40a58b5 2288
371810d1 2289 output = check_output('ip rule')
926062f0
SS
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')
1f0e3109 2297
d586a2c3 2298 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 2299 def test_routing_policy_rule_invert(self):
ec38833c 2300 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 2301 start_networkd()
e2aea43f 2302 self.wait_online(['test1:degraded'])
e40a58b5 2303
371810d1 2304 output = check_output('ip rule')
efecf9cd 2305 print(output)
efecf9cd
SS
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
6be8e78e
YW
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
1d26d4cd
YW
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
ec38833c 2328 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 2329 start_networkd()
e2aea43f
YW
2330 self.wait_online(['dummy98:routable'])
2331
fc79e6ff 2332 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 2333 print(output)
0d34228f 2334
6d60f9db 2335 print('### ip -6 route show dev dummy98')
371810d1 2336 output = check_output('ip -6 route show dev dummy98')
0d34228f 2337 print(output)
0b5dc249
YW
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)
180c5116 2340 self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output)
1f0e3109 2341
d9005dec
YW
2342 print('### ip -6 route show default')
2343 output = check_output('ip -6 route show default')
6d60f9db 2344 print(output)
0b5dc249
YW
2345 self.assertIn('default', output)
2346 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output)
1f0e3109 2347
6d60f9db 2348 print('### ip -4 route show dev dummy98')
371810d1 2349 output = check_output('ip -4 route show dev dummy98')
1f0e3109 2350 print(output)
0b5dc249
YW
2351 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output)
2352 self.assertIn('149.10.124.64 proto static scope link', output)
2353 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output)
2354 self.assertIn('192.168.1.1 proto static initcwnd 20', output)
2355 self.assertIn('192.168.1.2 proto static initrwnd 30', output)
2356 self.assertIn('192.168.1.3 proto static advmss 30', output)
2357 self.assertIn('multicast 149.10.123.4 proto static', output)
1f0e3109 2358
6d60f9db 2359 print('### ip -4 route show dev dummy98 default')
371810d1 2360 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 2361 print(output)
0b5dc249
YW
2362 self.assertIn('default via 149.10.125.65 proto static onlink', output)
2363 self.assertIn('default via 149.10.124.64 proto static', output)
2364 self.assertIn('default proto static', output)
1f0e3109 2365
6d60f9db
YW
2366 print('### ip -4 route show table local dev dummy98')
2367 output = check_output('ip -4 route show table local dev dummy98')
2368 print(output)
0b5dc249
YW
2369 self.assertIn('local 149.10.123.1 proto static scope host', output)
2370 self.assertIn('anycast 149.10.123.2 proto static scope link', output)
2371 self.assertIn('broadcast 149.10.123.3 proto static scope link', output)
6d60f9db
YW
2372
2373 print('### ip route show type blackhole')
371810d1 2374 output = check_output('ip route show type blackhole')
1f0e3109 2375 print(output)
0b5dc249 2376 self.assertIn('blackhole 202.54.1.2 proto static', output)
f5050e48 2377
6d60f9db 2378 print('### ip route show type unreachable')
371810d1 2379 output = check_output('ip route show type unreachable')
f5050e48 2380 print(output)
0b5dc249 2381 self.assertIn('unreachable 202.54.1.3 proto static', output)
f5050e48 2382
6d60f9db 2383 print('### ip route show type prohibit')
371810d1 2384 output = check_output('ip route show type prohibit')
f5050e48 2385 print(output)
0b5dc249 2386 self.assertIn('prohibit 202.54.1.4 proto static', output)
f5050e48 2387
452d86a5
YW
2388 print('### ip -6 route show type blackhole')
2389 output = check_output('ip -6 route show type blackhole')
2390 print(output)
2391 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2392
2393 print('### ip -6 route show type unreachable')
2394 output = check_output('ip -6 route show type unreachable')
2395 print(output)
2396 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2397
2398 print('### ip -6 route show type prohibit')
2399 output = check_output('ip -6 route show type prohibit')
2400 print(output)
2401 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2402
a0ce990e
YW
2403 print('### ip route show 192.168.10.1')
2404 output = check_output('ip route show 192.168.10.1')
2405 print(output)
0b5dc249
YW
2406 self.assertIn('192.168.10.1 proto static', output)
2407 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output)
2408 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output)
a0ce990e
YW
2409
2410 print('### ip route show 192.168.10.2')
2411 output = check_output('ip route show 192.168.10.2')
2412 print(output)
2413 # old ip command does not show IPv6 gateways...
0b5dc249
YW
2414 self.assertIn('192.168.10.2 proto static', output)
2415 self.assertIn('nexthop', output)
2416 self.assertIn('dev dummy98 weight 10', output)
2417 self.assertIn('dev dummy98 weight 5', output)
a0ce990e
YW
2418
2419 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2420 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2421 print(output)
2422 # old ip command does not show 'nexthop' keyword and weight...
0b5dc249
YW
2423 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output)
2424 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
2425 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
a0ce990e 2426
43d4bc9f
YW
2427 copy_unit_to_networkd_unit_path('25-address-static.network')
2428 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2429 time.sleep(1)
43d4bc9f
YW
2430 self.wait_online(['dummy98:routable'])
2431
2432 # check all routes managed by Manager are removed
2433 print('### ip route show type blackhole')
2434 output = check_output('ip route show type blackhole')
2435 print(output)
2436 self.assertEqual(output, '')
2437
2438 print('### ip route show type unreachable')
2439 output = check_output('ip route show type unreachable')
2440 print(output)
2441 self.assertEqual(output, '')
2442
2443 print('### ip route show type prohibit')
2444 output = check_output('ip route show type prohibit')
2445 print(output)
2446 self.assertEqual(output, '')
2447
452d86a5
YW
2448 print('### ip -6 route show type blackhole')
2449 output = check_output('ip -6 route show type blackhole')
2450 print(output)
2451 self.assertEqual(output, '')
2452
2453 print('### ip -6 route show type unreachable')
2454 output = check_output('ip -6 route show type unreachable')
2455 print(output)
2456 self.assertEqual(output, '')
2457
2458 print('### ip -6 route show type prohibit')
2459 output = check_output('ip -6 route show type prohibit')
2460 print(output)
2461 self.assertEqual(output, '')
2462
43d4bc9f
YW
2463 remove_unit_from_networkd_path(['25-address-static.network'])
2464 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2465 time.sleep(1)
43d4bc9f
YW
2466 self.wait_online(['dummy98:routable'])
2467
2468 # check all routes managed by Manager are reconfigured
2469 print('### ip route show type blackhole')
2470 output = check_output('ip route show type blackhole')
2471 print(output)
0b5dc249 2472 self.assertIn('blackhole 202.54.1.2 proto static', output)
43d4bc9f
YW
2473
2474 print('### ip route show type unreachable')
2475 output = check_output('ip route show type unreachable')
2476 print(output)
0b5dc249 2477 self.assertIn('unreachable 202.54.1.3 proto static', output)
43d4bc9f
YW
2478
2479 print('### ip route show type prohibit')
2480 output = check_output('ip route show type prohibit')
2481 print(output)
0b5dc249 2482 self.assertIn('prohibit 202.54.1.4 proto static', output)
43d4bc9f 2483
452d86a5
YW
2484 print('### ip -6 route show type blackhole')
2485 output = check_output('ip -6 route show type blackhole')
2486 print(output)
2487 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2488
2489 print('### ip -6 route show type unreachable')
2490 output = check_output('ip -6 route show type unreachable')
2491 print(output)
2492 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2493
2494 print('### ip -6 route show type prohibit')
2495 output = check_output('ip -6 route show type prohibit')
2496 print(output)
2497 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2498
43d4bc9f
YW
2499 rc = call("ip link del dummy98")
2500 self.assertEqual(rc, 0)
2501 time.sleep(2)
2502
2503 # check all routes managed by Manager are removed
2504 print('### ip route show type blackhole')
2505 output = check_output('ip route show type blackhole')
2506 print(output)
2507 self.assertEqual(output, '')
2508
2509 print('### ip route show type unreachable')
2510 output = check_output('ip route show type unreachable')
2511 print(output)
2512 self.assertEqual(output, '')
2513
2514 print('### ip route show type prohibit')
2515 output = check_output('ip route show type prohibit')
2516 print(output)
2517 self.assertEqual(output, '')
2518
452d86a5
YW
2519 print('### ip -6 route show type blackhole')
2520 output = check_output('ip -6 route show type blackhole')
2521 print(output)
2522 self.assertEqual(output, '')
2523
2524 print('### ip -6 route show type unreachable')
2525 output = check_output('ip -6 route show type unreachable')
2526 print(output)
2527 self.assertEqual(output, '')
2528
2529 print('### ip -6 route show type prohibit')
2530 output = check_output('ip -6 route show type prohibit')
2531 print(output)
2532 self.assertEqual(output, '')
2533
1d26d4cd
YW
2534 self.tearDown()
2535
2536 def test_route_static(self):
2537 for manage_foreign_routes in [True, False]:
2538 with self.subTest(manage_foreign_routes=manage_foreign_routes):
2539 self._test_route_static(manage_foreign_routes)
2540
297f9d86
YW
2541 @expectedFailureIfRTA_VIAIsNotSupported()
2542 def test_route_via_ipv6(self):
2543 copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
2544 start_networkd()
2545 self.wait_online(['dummy98:routable'])
2546
2547 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2548 print(output)
2549
2550 print('### ip -6 route show dev dummy98')
2551 output = check_output('ip -6 route show dev dummy98')
2552 print(output)
2553 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
2554 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
2555
2556 print('### ip -4 route show dev dummy98')
2557 output = check_output('ip -4 route show dev dummy98')
2558 print(output)
2559 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
2560 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
2561
40afe491
YW
2562 @expectedFailureIfModuleIsNotAvailable('vrf')
2563 def test_route_vrf(self):
2564 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
2565 '25-vrf.netdev', '25-vrf.network')
2566 start_networkd()
2567 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2568
2569 output = check_output('ip route show vrf vrf99')
2570 print(output)
2571 self.assertRegex(output, 'default via 192.168.100.1')
2572
2573 output = check_output('ip route show')
2574 print(output)
2575 self.assertNotRegex(output, 'default via 192.168.100.1')
2576
0b1cd3e2
WKI
2577 def test_gateway_reconfigure(self):
2578 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
2579 start_networkd()
2580 self.wait_online(['dummy98:routable'])
2581 print('### ip -4 route show dev dummy98 default')
2582 output = check_output('ip -4 route show dev dummy98 default')
2583 print(output)
2584 self.assertRegex(output, 'default via 149.10.124.59 proto static')
2585 self.assertNotRegex(output, '149.10.124.60')
2586
2587 remove_unit_from_networkd_path(['25-gateway-static.network'])
2588 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
2589 restart_networkd(3)
2590 self.wait_online(['dummy98:routable'])
2591 print('### ip -4 route show dev dummy98 default')
2592 output = check_output('ip -4 route show dev dummy98 default')
2593 print(output)
2594 self.assertNotRegex(output, '149.10.124.59')
2595 self.assertRegex(output, 'default via 149.10.124.60 proto static')
2596
20ca06a6
DA
2597 def test_ip_route_ipv6_src_route(self):
2598 # a dummy device does not make the addresses go through tentative state, so we
2599 # reuse a bond from an earlier test, which does make the addresses go through
2600 # tentative state, and do our test on that
ec38833c 2601 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2602 start_networkd()
e2aea43f 2603 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 2604
371810d1 2605 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
2606 print(output)
2607 self.assertRegex(output, 'abcd::/16')
2608 self.assertRegex(output, 'src')
2609 self.assertRegex(output, '2001:1234:56:8f63::2')
2610
1f0e3109 2611 def test_ip_link_mac_address(self):
ec38833c 2612 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 2613 start_networkd()
e2aea43f 2614 self.wait_online(['dummy98:degraded'])
1f0e3109 2615
371810d1 2616 output = check_output('ip link show dummy98')
1f0e3109
SS
2617 print(output)
2618 self.assertRegex(output, '00:01:02:aa:bb:cc')
2619
2620 def test_ip_link_unmanaged(self):
ec38833c 2621 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 2622 start_networkd(5)
1f0e3109 2623
e39cc445 2624 self.check_link_exists('dummy98')
1f0e3109 2625
19cf3143 2626 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2627
2628 def test_ipv6_address_label(self):
ec38833c 2629 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2630 start_networkd()
e2aea43f 2631 self.wait_online(['dummy98:degraded'])
1f0e3109 2632
371810d1 2633 output = check_output('ip addrlabel list')
1f0e3109
SS
2634 print(output)
2635 self.assertRegex(output, '2004:da8:1::/64')
2636
cff0cadc
YW
2637 def test_ipv6_proxy_ndp(self):
2638 copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
2639 start_networkd()
2640
2641 self.wait_online(['dummy98:routable'])
2642
2643 output = check_output('ip neighbor show proxy dev dummy98')
2644 print(output)
2645 for i in range(1,5):
2646 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
2647
d86f5c19 2648 def test_neighbor_section(self):
ec38833c 2649 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2650 start_networkd()
e2aea43f 2651 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2652
d1bdafd2 2653 print('### ip neigh list dev dummy98')
df7f9afa 2654 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2655 print(output)
2656 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2657 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2658
d1bdafd2
WKI
2659 def test_neighbor_reconfigure(self):
2660 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2661 start_networkd()
2662 self.wait_online(['dummy98:degraded'], timeout='40s')
2663
2664 print('### ip neigh list dev dummy98')
2665 output = check_output('ip neigh list dev dummy98')
2666 print(output)
2667 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2668 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2669
2670 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2671 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2672 restart_networkd(3)
2673 self.wait_online(['dummy98:degraded'], timeout='40s')
2674 print('### ip neigh list dev dummy98')
2675 output = check_output('ip neigh list dev dummy98')
2676 print(output)
2677 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2678 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2679 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2680
74761cf3 2681 def test_neighbor_gre(self):
fb2ba330
YW
2682 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2683 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2684 start_networkd()
fb2ba330 2685 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2686
2687 output = check_output('ip neigh list dev gretun97')
2688 print(output)
2689 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2690
2691 output = check_output('ip neigh list dev ip6gretun97')
2692 print(output)
2693 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2694
05514ae1 2695 def test_link_local_addressing(self):
ec38833c
ZJS
2696 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2697 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2698 start_networkd()
e2aea43f 2699 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2700
371810d1 2701 output = check_output('ip address show dev test1')
05514ae1
YW
2702 print(output)
2703 self.assertRegex(output, 'inet .* scope link')
2704 self.assertRegex(output, 'inet6 .* scope link')
2705
371810d1 2706 output = check_output('ip address show dev dummy98')
05514ae1
YW
2707 print(output)
2708 self.assertNotRegex(output, 'inet6* .* scope link')
2709
05514ae1
YW
2710 '''
2711 Documentation/networking/ip-sysctl.txt
2712
2713 addr_gen_mode - INTEGER
2714 Defines how link-local and autoconf addresses are generated.
2715
2716 0: generate address based on EUI64 (default)
2717 1: do no generate a link-local address, use EUI64 for addresses generated
2718 from autoconf
2719 2: generate stable privacy addresses, using the secret from
2720 stable_secret (RFC7217)
2721 3: generate stable privacy addresses, using a random secret if unset
2722 '''
2723
4681ab55
YW
2724 self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
2725 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2')
2726 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2727
7b3770a7
YW
2728 def test_link_local_addressing_remove_ipv6ll(self):
2729 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2730 start_networkd()
2731 self.wait_online(['dummy98:degraded'])
2732
2733 output = check_output('ip address show dev dummy98')
2734 print(output)
2735 self.assertRegex(output, 'inet6 .* scope link')
2736
2737 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2738 restart_networkd(1)
2739 self.wait_online(['dummy98:carrier'])
2740
2741 output = check_output('ip address show dev dummy98')
2742 print(output)
2743 self.assertNotRegex(output, 'inet6* .* scope link')
2744
1f0e3109 2745 def test_sysctl(self):
ec38833c 2746 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2747 start_networkd()
e2aea43f 2748 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2749
2750 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2751 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2752 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2753 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2754 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2755 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2756 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
29f69c57 2757 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
1f0e3109 2758
4da33154 2759 def test_sysctl_disable_ipv6(self):
ec38833c 2760 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2761
2762 print('## Disable ipv6')
cefd6b3d
ZJS
2763 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2764 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2765
2cf6fdff 2766 start_networkd()
e2aea43f 2767 self.wait_online(['dummy98:routable'])
4da33154 2768
371810d1 2769 output = check_output('ip -4 address show dummy98')
4da33154
YW
2770 print(output)
2771 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2772 output = check_output('ip -6 address show dummy98')
4da33154 2773 print(output)
57ad7607
ZJS
2774 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2775 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2776 output = check_output('ip -4 route show dev dummy98')
2777 print(output)
3d2c2692 2778 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2779 output = check_output('ip -6 route show default')
4933b97d 2780 print(output)
d9005dec
YW
2781 self.assertRegex(output, 'default')
2782 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2783
cefd6b3d 2784 check_output('ip link del dummy98')
4da33154
YW
2785
2786 print('## Enable ipv6')
cefd6b3d
ZJS
2787 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2788 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2789
e2aea43f
YW
2790 restart_networkd(3)
2791 self.wait_online(['dummy98:routable'])
4da33154 2792
371810d1 2793 output = check_output('ip -4 address show dummy98')
4da33154
YW
2794 print(output)
2795 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2796 output = check_output('ip -6 address show dummy98')
4da33154 2797 print(output)
4933b97d 2798 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2799 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2800 output = check_output('ip -4 route show dev dummy98')
2801 print(output)
3d2c2692 2802 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2803 output = check_output('ip -6 route show default')
4933b97d 2804 print(output)
d9005dec 2805 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2806
cd65d067 2807 def test_bind_carrier(self):
bc942f69
YW
2808 check_output('ip link add dummy98 type dummy')
2809 check_output('ip link set dummy98 up')
2810 time.sleep(2)
2811
ec38833c 2812 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2813 start_networkd()
e2aea43f 2814 self.wait_online(['test1:routable'])
cd65d067 2815
371810d1 2816 output = check_output('ip address show test1')
cd65d067
YW
2817 print(output)
2818 self.assertRegex(output, 'UP,LOWER_UP')
2819 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2820 self.wait_operstate('test1', 'routable')
cd65d067 2821
cefd6b3d
ZJS
2822 check_output('ip link add dummy99 type dummy')
2823 check_output('ip link set dummy99 up')
b117044c 2824 time.sleep(2)
371810d1 2825 output = check_output('ip address show test1')
cd65d067
YW
2826 print(output)
2827 self.assertRegex(output, 'UP,LOWER_UP')
2828 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2829 self.wait_operstate('test1', 'routable')
cd65d067 2830
cefd6b3d 2831 check_output('ip link del dummy98')
b117044c 2832 time.sleep(2)
371810d1 2833 output = check_output('ip address show test1')
cd65d067
YW
2834 print(output)
2835 self.assertRegex(output, 'UP,LOWER_UP')
2836 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2837 self.wait_operstate('test1', 'routable')
cd65d067 2838
bc942f69 2839 check_output('ip link set dummy99 down')
b117044c 2840 time.sleep(2)
371810d1 2841 output = check_output('ip address show test1')
cd65d067
YW
2842 print(output)
2843 self.assertNotRegex(output, 'UP,LOWER_UP')
2844 self.assertRegex(output, 'DOWN')
2845 self.assertNotRegex(output, '192.168.10')
19cf3143 2846 self.wait_operstate('test1', 'off')
cd65d067 2847
bc942f69 2848 check_output('ip link set dummy99 up')
b117044c 2849 time.sleep(2)
371810d1 2850 output = check_output('ip address show test1')
cd65d067
YW
2851 print(output)
2852 self.assertRegex(output, 'UP,LOWER_UP')
2853 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2854 self.wait_operstate('test1', 'routable')
cd65d067 2855
2236d75d
DS
2856 def _test_activation_policy(self, test):
2857 self.setUp()
2858 conffile = '25-activation-policy.network'
2859 if test:
2860 conffile = f'{conffile}.d/{test}.conf'
2861 copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
2862 start_networkd()
2863
2864 always = test.startswith('always')
2865 if test == 'manual':
2866 initial_up = 'UP' in check_output('ip link show test1')
2867 else:
2868 initial_up = not test.endswith('down') # note: default is up
2869 expect_up = initial_up
2870 next_up = not expect_up
2871
2236d75d
DS
2872 for iteration in range(4):
2873 with self.subTest(iteration=iteration, expect_up=expect_up):
2874 operstate = 'routable' if expect_up else 'off'
618da3e7 2875 setup_state = 'configured' if expect_up else ('configuring' if iteration == 0 else None)
2236d75d 2876 self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
2236d75d
DS
2877
2878 if expect_up:
2879 self.assertIn('UP', check_output('ip link show test1'))
2880 self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
1ef2eedc 2881 self.assertIn('default via 192.168.10.1', check_output('ip route show dev test1'))
2236d75d
DS
2882 else:
2883 self.assertIn('DOWN', check_output('ip link show test1'))
2884
2885 if next_up:
2886 check_output('ip link set dev test1 up')
2887 else:
2888 check_output('ip link set dev test1 down')
2889 expect_up = initial_up if always else next_up
2890 next_up = not next_up
2891
2892 self.tearDown()
2893
2894 def test_activation_policy(self):
2895 for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
2896 with self.subTest(test=test):
2897 self._test_activation_policy(test)
2898
61764fe4
DS
2899 def _test_activation_policy_required_for_online(self, policy, required):
2900 self.setUp()
2901 conffile = '25-activation-policy.network'
2902 units = ['11-dummy.netdev', '12-dummy.netdev', '12-dummy.network', conffile]
2903 if policy:
2904 units += [f'{conffile}.d/{policy}.conf']
2905 if required:
2906 units += [f'{conffile}.d/required-{required}.conf']
2907 copy_unit_to_networkd_unit_path(*units, dropins=False)
2908 start_networkd()
2909
2910 if policy.endswith('down') or policy == 'manual':
2911 self.wait_operstate('test1', 'off', setup_state='configuring')
2912 else:
2913 self.wait_online(['test1'])
2914
2915 if policy == 'always-down':
2916 # if always-down, required for online is forced to no
2917 expected = False
2918 elif required:
2919 # otherwise if required for online is specified, it should match that
2920 expected = required == 'yes'
2921 elif policy:
2922 # otherwise if only policy specified, required for online defaults to
2923 # true if policy is up, always-up, or bound
2924 expected = policy.endswith('up') or policy == 'bound'
2925 else:
2926 # default is true, if neither are specified
2927 expected = True
2928
2929 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2930 print(output)
2931
2932 yesno = 'yes' if expected else 'no'
2933 self.assertRegex(output, f'Required For Online: {yesno}')
2934
2935 self.tearDown()
2936
2937 def test_activation_policy_required_for_online(self):
2938 for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']:
2939 for required in ['yes', 'no', '']:
2940 with self.subTest(policy=policy, required=required):
2941 self._test_activation_policy_required_for_online(policy, required)
2942
fdcd1ec5 2943 def test_domain(self):
ec38833c 2944 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2945 start_networkd()
e2aea43f 2946 self.wait_online(['dummy98:routable'])
fdcd1ec5 2947
fc79e6ff 2948 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2949 print(output)
2950 self.assertRegex(output, 'Address: 192.168.42.100')
2951 self.assertRegex(output, 'DNS: 192.168.42.1')
2952 self.assertRegex(output, 'Search Domains: one')
2953
1e498853 2954 def test_keep_configuration_static(self):
3aa645f0
MB
2955 check_output('systemctl stop systemd-networkd.socket')
2956 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
2957
2958 check_output('ip link add name dummy98 type dummy')
2959 check_output('ip address add 10.1.2.3/16 dev dummy98')
2960 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2961 output = check_output('ip address show dummy98')
2962 print(output)
2963 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2964 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2965 output = check_output('ip route show dev dummy98')
2966 print(output)
2967
2968 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2969 start_networkd()
e2aea43f 2970 self.wait_online(['dummy98:routable'])
1e498853
YW
2971
2972 output = check_output('ip address show dummy98')
2973 print(output)
2974 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2975 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2976
086bcf5d
YW
2977 @expectedFailureIfNexthopIsNotAvailable()
2978 def test_nexthop(self):
9c8f90d0
YW
2979 def check_nexthop(self):
2980 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
086bcf5d 2981
9c8f90d0
YW
2982 output = check_output('ip nexthop list dev veth99')
2983 print(output)
2984 self.assertIn('id 1 via 192.168.5.1 dev veth99', output)
2985 self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output)
2986 self.assertIn('id 3 dev veth99', output)
2987 self.assertIn('id 4 dev veth99', output)
2988 self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink')
180c5116 2989 self.assertIn('id 8 via fe80:0:222:4dff:ff:ff:ff:ff dev veth99', output)
9c8f90d0
YW
2990 self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
2991
2992 output = check_output('ip nexthop list dev dummy98')
2993 print(output)
2994 self.assertIn('id 20 via 192.168.20.1 dev dummy98', output)
086bcf5d 2995
9c8f90d0
YW
2996 # kernel manages blackhole nexthops on lo
2997 output = check_output('ip nexthop list dev lo')
2998 print(output)
2999 self.assertIn('id 6 blackhole', output)
3000 self.assertIn('id 7 blackhole', output)
69a91c70 3001
9c8f90d0
YW
3002 # group nexthops are shown with -0 option
3003 output = check_output('ip -0 nexthop list id 21')
3004 print(output)
3005 self.assertRegex(output, r'id 21 group (1,3/20|20/1,3)')
cee0f719 3006
9c8f90d0
YW
3007 output = check_output('ip route show dev veth99 10.10.10.10')
3008 print(output)
3009 self.assertEqual('10.10.10.10 nhid 1 via 192.168.5.1 proto static', output)
cee0f719 3010
9c8f90d0
YW
3011 output = check_output('ip route show dev veth99 10.10.10.11')
3012 print(output)
3013 self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output)
e2d9bc5c 3014
9c8f90d0
YW
3015 output = check_output('ip route show dev veth99 10.10.10.12')
3016 print(output)
3017 self.assertEqual('10.10.10.12 nhid 5 via 192.168.10.1 proto static onlink', output)
cee0f719 3018
9c8f90d0
YW
3019 output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1')
3020 print(output)
3021 self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output)
69a91c70 3022
9c8f90d0
YW
3023 output = check_output('ip route show 10.10.10.13')
3024 print(output)
3025 self.assertEqual('blackhole 10.10.10.13 nhid 6 dev lo proto static', output)
3026
3027 output = check_output('ip -6 route show 2001:1234:5:8f62::2')
3028 print(output)
3029 self.assertEqual('blackhole 2001:1234:5:8f62::2 nhid 7 dev lo proto static metric 1024 pref medium', output)
3030
3031 output = check_output('ip route show 10.10.10.14')
3032 print(output)
3033 self.assertIn('10.10.10.14 nhid 21 proto static', output)
3034 self.assertIn('nexthop via 192.168.20.1 dev dummy98 weight 1', output)
3035 self.assertIn('nexthop via 192.168.5.1 dev veth99 weight 3', output)
3036
3037 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
3038 '12-dummy.netdev', '25-nexthop-dummy.network')
3039 start_networkd()
3040
3041 check_nexthop(self)
69a91c70 3042
9947c7ba
YW
3043 remove_unit_from_networkd_path(['25-nexthop.network'])
3044 copy_unit_to_networkd_unit_path('25-nexthop-nothing.network')
3045 rc = call(*networkctl_cmd, 'reload', env=env)
3046 self.assertEqual(rc, 0)
3047 time.sleep(1)
3048
932e157b
YW
3049 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3050
9947c7ba
YW
3051 output = check_output('ip nexthop list dev veth99')
3052 print(output)
3053 self.assertEqual(output, '')
3054 output = check_output('ip nexthop list dev lo')
3055 print(output)
3056 self.assertEqual(output, '')
3057
3058 remove_unit_from_networkd_path(['25-nexthop-nothing.network'])
3059 copy_unit_to_networkd_unit_path('25-nexthop.network')
9c8f90d0
YW
3060 rc = call(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
3061 self.assertEqual(rc, 0)
9947c7ba
YW
3062 rc = call(*networkctl_cmd, 'reload', env=env)
3063 self.assertEqual(rc, 0)
3064 time.sleep(1)
3065
9c8f90d0 3066 check_nexthop(self)
932e157b 3067
9947c7ba
YW
3068 rc = call('ip link del veth99')
3069 self.assertEqual(rc, 0)
3070 time.sleep(2)
3071
3072 output = check_output('ip nexthop list dev lo')
3073 print(output)
3074 self.assertEqual(output, '')
3075
ef3c8a92 3076 def test_qdisc(self):
f1de1eb3
YW
3077 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
3078 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
3079 check_output('modprobe sch_teql max_equalizers=2')
ef3c8a92
YW
3080 start_networkd()
3081
1b628c4f 3082 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92 3083
f1de1eb3
YW
3084 output = check_output('tc qdisc show dev test1')
3085 print(output)
3086 self.assertRegex(output, 'qdisc netem')
7887e580 3087 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
f1de1eb3
YW
3088 self.assertRegex(output, 'qdisc ingress')
3089
ef3c8a92
YW
3090 output = check_output('tc qdisc show dev dummy98')
3091 print(output)
f1de1eb3
YW
3092 self.assertRegex(output, 'qdisc clsact')
3093
3094 self.assertRegex(output, 'qdisc htb 2: root')
3095 self.assertRegex(output, r'default (0x30|30)')
3096
3097 self.assertRegex(output, 'qdisc netem 30: parent 2:30')
7887e580 3098 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
40821c2a 3099 self.assertRegex(output, 'qdisc fq_codel')
7887e580 3100 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')
ef3c8a92 3101
f1de1eb3 3102 self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
0baddbd5 3103
f1de1eb3 3104 self.assertRegex(output, 'qdisc fq 32: parent 2:32')
a05a6e8b
YW
3105 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
3106 self.assertRegex(output, 'quantum 1500')
3107 self.assertRegex(output, 'initial_quantum 13000')
3108 self.assertRegex(output, 'maxrate 1Mbit')
ab9dc1db 3109
f1de1eb3 3110 self.assertRegex(output, 'qdisc codel 33: parent 2:33')
7887e580 3111 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
ab9dc1db 3112
f1de1eb3 3113 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
7887e580 3114 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')
ab9dc1db 3115
f1de1eb3 3116 self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
7887e580 3117 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
ab9dc1db 3118
f1de1eb3
YW
3119 self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
3120 self.assertRegex(output, 'perturb 5sec')
3d55b5a9 3121
bc0769c9
YW
3122 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
3123 self.assertRegex(output, 'limit 100000p')
3124
95edcf3f
YW
3125 self.assertRegex(output, 'qdisc gred 38: parent 2:38')
3126 self.assertRegex(output, 'vqs 12 default 10 grio')
3127
f2c5c129
YW
3128 self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
3129 self.assertRegex(output, 'limit 200000')
3130
7b1a31a3
YW
3131 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
3132 self.assertRegex(output, 'limit 1000000')
3133
73136507
YW
3134 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b')
3135 self.assertRegex(output, 'limit 1023p')
3136
41bb371b
YW
3137 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c')
3138
2ee7e54b 3139 output = check_output('tc -d class show dev dummy98')
ab9dc1db 3140 print(output)
f1de1eb3
YW
3141 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
3142 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
3143 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
3144 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
3145 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
3146 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
3147 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
bc0769c9 3148 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
95edcf3f 3149 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
f2c5c129 3150 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
7b1a31a3 3151 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
73136507 3152 self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
41bb371b 3153 self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
2ee7e54b
YW
3154 self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit')
3155 self.assertRegex(output, 'burst 123456')
3156 self.assertRegex(output, 'cburst 123457')
0baddbd5 3157
557fa421 3158 def test_qdisc2(self):
891ff963
YW
3159 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
3160 '25-qdisc-qfq.network', '11-dummy.netdev')
557fa421
YW
3161 start_networkd()
3162
891ff963 3163 self.wait_online(['dummy98:routable', 'test1:routable'])
557fa421
YW
3164
3165 output = check_output('tc qdisc show dev dummy98')
3166 print(output)
3167 self.assertRegex(output, 'qdisc drr 2: root')
3168 output = check_output('tc class show dev dummy98')
3169 print(output)
3170 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
3171
891ff963
YW
3172 output = check_output('tc qdisc show dev test1')
3173 print(output)
3174 self.assertRegex(output, 'qdisc qfq 2: root')
3175 output = check_output('tc class show dev test1')
3176 print(output)
3177 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
3178 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
3179
f6c6af38
YW
3180 @expectedFailureIfCAKEIsNotAvailable()
3181 def test_qdisc_cake(self):
3182 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
3d55b5a9 3183 start_networkd()
3d55b5a9
YW
3184 self.wait_online(['dummy98:routable'])
3185
3186 output = check_output('tc qdisc show dev dummy98')
3187 print(output)
f6c6af38
YW
3188 self.assertRegex(output, 'qdisc cake 3a: root')
3189 self.assertRegex(output, 'bandwidth 500Mbit')
3190 self.assertRegex(output, 'overhead 128')
3d55b5a9 3191
be94e591
YW
3192 @expectedFailureIfPIEIsNotAvailable()
3193 def test_qdisc_pie(self):
3194 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
3195 start_networkd()
3196 self.wait_online(['dummy98:routable'])
3197
3198 output = check_output('tc qdisc show dev dummy98')
3199 print(output)
3200 self.assertRegex(output, 'qdisc pie 3a: root')
3201 self.assertRegex(output, 'limit 200000')
3202
970ab1fc
YW
3203 @expectedFailureIfHHFIsNotAvailable()
3204 def test_qdisc_hhf(self):
3205 copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev')
3206 start_networkd()
3207 self.wait_online(['dummy98:routable'])
3208
3209 output = check_output('tc qdisc show dev dummy98')
3210 print(output)
3211 self.assertRegex(output, 'qdisc hhf 3a: root')
3212 self.assertRegex(output, 'limit 1022p')
3213
b753e835
YW
3214 @expectedFailureIfETSIsNotAvailable()
3215 def test_qdisc_ets(self):
3216 copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev')
3217 start_networkd()
3218 self.wait_online(['dummy98:routable'])
3219
3220 output = check_output('tc qdisc show dev dummy98')
3221 print(output)
1578266b 3222
b753e835
YW
3223 self.assertRegex(output, 'qdisc ets 3a: root')
3224 self.assertRegex(output, 'bands 10 strict 3')
3225 self.assertRegex(output, 'quanta 1 2 3 4 5')
3226 self.assertRegex(output, 'priomap 3 4 5 6 7')
3227
1578266b
YW
3228 @expectedFailureIfFQPIEIsNotAvailable()
3229 def test_qdisc_fq_pie(self):
3230 copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev')
3231 start_networkd()
3232 self.wait_online(['dummy98:routable'])
3233
3234 output = check_output('tc qdisc show dev dummy98')
3235 print(output)
3236
3237 self.assertRegex(output, 'qdisc fq_pie 3a: root')
3238 self.assertRegex(output, 'limit 200000p')
3239
3d2c2692
YW
3240 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
3241 def test_sriov(self):
3242 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
3243 call('modprobe netdevsim', stderr=subprocess.DEVNULL)
3244 with open('/sys/bus/netdevsim/new_device', mode='w') as f:
3245 f.write('99 1')
3246
3247 call('udevadm settle')
3248 call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
3249 with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f:
3250 f.write('3')
3251
3252 copy_unit_to_networkd_unit_path('25-sriov.network')
3253 start_networkd()
3254 self.wait_online(['eni99np1:routable'])
3255
3256 output = check_output('ip link show dev eni99np1')
3257 print(output)
3258 self.assertRegex(output,
3259 '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 *'
3260 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
3261 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
3262 )
3263
3264 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
3265
70448bb1
L
3266 def test_wait_online_ipv4(self):
3267 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
3268 start_networkd()
3269
3270 self.wait_online(['veth99:routable'], ipv4=True)
3271
3272 self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1)
3273
3274 def test_wait_online_ipv6(self):
3275 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix-with-delay.network', 'ipv6ra-prefix-client-with-static-ipv4-address.network')
3276 start_networkd()
3277
3278 self.wait_online(['veth99:routable'], ipv6=True)
3279
3280 self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1)
3281
336d18f0
YW
3282class NetworkdStateFileTests(unittest.TestCase, Utilities):
3283 links = [
3284 'dummy98',
3285 ]
3286
3287 units = [
3288 '12-dummy.netdev',
3289 'state-file-tests.network',
3290 ]
3291
3292 def setUp(self):
3293 remove_links(self.links)
3294 stop_networkd(show_logs=False)
3295
3296 def tearDown(self):
3297 remove_links(self.links)
3298 remove_unit_from_networkd_path(self.units)
3299 stop_networkd(show_logs=True)
3300
3301 def test_state_file(self):
3302 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
3303 start_networkd()
3304 self.wait_online(['dummy98:routable'])
3305
3306 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
3307 print(output)
3308 ifindex = output.split()[0]
3309
3310 path = os.path.join('/run/systemd/netif/links/', ifindex)
3311 self.assertTrue(os.path.exists(path))
f91b2340
YW
3312
3313 # make link state file updated
3314 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3315
3316 with open(path) as f:
3317 data = f.read()
70448bb1
L
3318 self.assertRegex(data, r'IPV4_ADDRESS_STATE=routable')
3319 self.assertRegex(data, r'IPV6_ADDRESS_STATE=routable')
336d18f0
YW
3320 self.assertRegex(data, r'ADMIN_STATE=configured')
3321 self.assertRegex(data, r'OPER_STATE=routable')
3322 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
3323 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
70448bb1 3324 self.assertRegex(data, r'REQUIRED_FAMILY_FOR_ONLINE=both')
a853652a 3325 self.assertRegex(data, r'ACTIVATION_POLICY=up')
336d18f0 3326 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
66479677 3327 self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com')
336d18f0
YW
3328 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3329 self.assertRegex(data, r'DOMAINS=hogehoge')
3330 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3331 self.assertRegex(data, r'LLMNR=no')
3332 self.assertRegex(data, r'MDNS=yes')
3333 self.assertRegex(data, r'DNSSEC=no')
336d18f0 3334
66479677 3335 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env)
336d18f0
YW
3336 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
3337 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
3338 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
3339 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
3340 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
336d18f0
YW
3341
3342 with open(path) as f:
3343 data = f.read()
66479677 3344 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3345 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
3346 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3347 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3348 self.assertRegex(data, r'LLMNR=yes')
3349 self.assertRegex(data, r'MDNS=no')
3350 self.assertRegex(data, r'DNSSEC=yes')
3351
3352 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3353
3354 with open(path) as f:
3355 data = f.read()
66479677 3356 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3357 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3358 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3359 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3360 self.assertRegex(data, r'LLMNR=yes')
3361 self.assertRegex(data, r'MDNS=no')
3362 self.assertRegex(data, r'DNSSEC=yes')
3363
3364 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3365
3366 with open(path) as f:
3367 data = f.read()
66479677 3368 self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com')
336d18f0
YW
3369 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3370 self.assertRegex(data, r'DOMAINS=hogehoge')
3371 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3372 self.assertRegex(data, r'LLMNR=no')
3373 self.assertRegex(data, r'MDNS=yes')
3374 self.assertRegex(data, r'DNSSEC=no')
3375
be68c2c9 3376class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 3377 links = [
c2990ec3 3378 'bond199',
c3a8853f 3379 'bond99',
cc3e488c
YW
3380 'dummy98',
3381 'test1']
c3a8853f
YW
3382
3383 units = [
cc3e488c
YW
3384 '11-dummy.netdev',
3385 '12-dummy.netdev',
c2990ec3
YW
3386 '23-active-slave.network',
3387 '23-bond199.network',
3388 '23-primary-slave.network',
c2990ec3 3389 '25-bond-active-backup-slave.netdev',
c3a8853f 3390 '25-bond.netdev',
c3a8853f 3391 'bond99.network',
cc3e488c 3392 'bond-slave.network']
c3a8853f
YW
3393
3394 def setUp(self):
ec38833c 3395 remove_links(self.links)
aaae5713 3396 stop_networkd(show_logs=False)
c3a8853f
YW
3397
3398 def tearDown(self):
ec38833c
ZJS
3399 remove_links(self.links)
3400 remove_unit_from_networkd_path(self.units)
aaae5713 3401 stop_networkd(show_logs=True)
c3a8853f 3402
c2990ec3 3403 def test_bond_active_slave(self):
ec38833c 3404 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3405 start_networkd()
e2aea43f 3406 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3407
371810d1 3408 output = check_output('ip -d link show bond199')
c2990ec3
YW
3409 print(output)
3410 self.assertRegex(output, 'active_slave dummy98')
3411
3412 def test_bond_primary_slave(self):
35a78c51 3413 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3414 start_networkd()
e2aea43f 3415 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3416
371810d1 3417 output = check_output('ip -d link show bond199')
c2990ec3 3418 print(output)
35a78c51 3419 self.assertRegex(output, 'primary dummy98')
c2990ec3 3420
cc3e488c 3421 def test_bond_operstate(self):
ec38833c
ZJS
3422 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
3423 'bond99.network','bond-slave.network')
2cf6fdff 3424 start_networkd()
e2aea43f 3425 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 3426
371810d1 3427 output = check_output('ip -d link show dummy98')
c3a8853f 3428 print(output)
cc3e488c 3429 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 3430
371810d1 3431 output = check_output('ip -d link show test1')
c3a8853f
YW
3432 print(output)
3433 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
3434
371810d1 3435 output = check_output('ip -d link show bond99')
c3a8853f
YW
3436 print(output)
3437 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
3438
19cf3143
DS
3439 self.wait_operstate('dummy98', 'enslaved')
3440 self.wait_operstate('test1', 'enslaved')
3441 self.wait_operstate('bond99', 'routable')
c3a8853f 3442
cefd6b3d 3443 check_output('ip link set dummy98 down')
c3a8853f 3444
19cf3143
DS
3445 self.wait_operstate('dummy98', 'off')
3446 self.wait_operstate('test1', 'enslaved')
3447 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 3448
cefd6b3d 3449 check_output('ip link set dummy98 up')
c3a8853f 3450
19cf3143
DS
3451 self.wait_operstate('dummy98', 'enslaved')
3452 self.wait_operstate('test1', 'enslaved')
3453 self.wait_operstate('bond99', 'routable')
c3a8853f 3454
cefd6b3d
ZJS
3455 check_output('ip link set dummy98 down')
3456 check_output('ip link set test1 down')
cc3e488c 3457
19cf3143
DS
3458 self.wait_operstate('dummy98', 'off')
3459 self.wait_operstate('test1', 'off')
2700d2c7 3460
a4632dc7 3461 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
3462 # Huh? Kernel does not recognize that all slave interfaces are down?
3463 # Let's confirm that networkd's operstate is consistent with ip's result.
3464 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 3465
be68c2c9 3466class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
3467 links = [
3468 'bridge99',
3469 'dummy98',
988b0660
YW
3470 'test1',
3471 'vlan99',
3472 ]
09ea6724
YW
3473
3474 units = [
3475 '11-dummy.netdev',
3476 '12-dummy.netdev',
988b0660
YW
3477 '21-vlan.netdev',
3478 '21-vlan.network',
09ea6724 3479 '26-bridge.netdev',
0fc0d85f 3480 '26-bridge-configure-without-carrier.network',
988b0660 3481 '26-bridge-issue-20373.netdev',
cc0276cc
YW
3482 '26-bridge-mdb-master.network',
3483 '26-bridge-mdb-slave.network',
09ea6724
YW
3484 '26-bridge-slave-interface-1.network',
3485 '26-bridge-slave-interface-2.network',
988b0660 3486 '26-bridge-vlan-master-issue-20373.network',
6f943798 3487 '26-bridge-vlan-master.network',
988b0660 3488 '26-bridge-vlan-slave-issue-20373.network',
6f943798 3489 '26-bridge-vlan-slave.network',
804b6cd2 3490 'bridge99-ignore-carrier-loss.network',
988b0660
YW
3491 'bridge99.network'
3492 ]
1f0e3109 3493
8d17c386
YW
3494 routing_policy_rule_tables = ['100']
3495
1f0e3109 3496 def setUp(self):
8d17c386 3497 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 3498 remove_links(self.links)
aaae5713 3499 stop_networkd(show_logs=False)
1f0e3109
SS
3500
3501 def tearDown(self):
8d17c386 3502 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
3503 remove_links(self.links)
3504 remove_unit_from_networkd_path(self.units)
aaae5713 3505 stop_networkd(show_logs=True)
1f0e3109 3506
6f943798
YW
3507 def test_bridge_vlan(self):
3508 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
3509 '26-bridge.netdev', '26-bridge-vlan-master.network')
3510 start_networkd()
e2aea43f 3511 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
3512
3513 output = check_output('bridge vlan show dev test1')
3514 print(output)
3515 self.assertNotRegex(output, '4063')
3516 for i in range(4064, 4095):
3517 self.assertRegex(output, f'{i}')
3518 self.assertNotRegex(output, '4095')
3519
3520 output = check_output('bridge vlan show dev bridge99')
3521 print(output)
3522 self.assertNotRegex(output, '4059')
3523 for i in range(4060, 4095):
3524 self.assertRegex(output, f'{i}')
3525 self.assertNotRegex(output, '4095')
3526
988b0660
YW
3527 def test_bridge_vlan_issue_20373(self):
3528 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network',
3529 '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network',
3530 '21-vlan.netdev', '21-vlan.network')
3531 start_networkd()
3532 self.wait_online(['test1:enslaved', 'bridge99:degraded', 'vlan99:routable'])
3533
3534 output = check_output('bridge vlan show dev test1')
3535 print(output)
3536 self.assertIn('100 PVID Egress Untagged', output)
3537 self.assertIn('560', output)
3538 self.assertIn('600', output)
3539
3540 output = check_output('bridge vlan show dev bridge99')
3541 print(output)
3542 self.assertIn('1 PVID Egress Untagged', output)
3543 self.assertIn('100', output)
3544 self.assertIn('600', output)
3545
cc0276cc
YW
3546 def test_bridge_mdb(self):
3547 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network',
3548 '26-bridge.netdev', '26-bridge-mdb-master.network')
3549 start_networkd()
3550 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
3551
3552 output = check_output('bridge mdb show dev bridge99')
3553 print(output)
3554 self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064')
3555 self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065')
3556
9f773037
YW
3557 # Old kernel may not support bridge MDB entries on bridge master
3558 if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0:
3559 self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
3560 self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
3561
1f0e3109 3562 def test_bridge_property(self):
ec38833c
ZJS
3563 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3564 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3565 'bridge99.network')
2cf6fdff 3566 start_networkd()
e2aea43f 3567 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 3568
371810d1 3569 output = check_output('ip -d link show test1')
1f0e3109
SS
3570 print(output)
3571 self.assertRegex(output, 'master')
3572 self.assertRegex(output, 'bridge')
3573
371810d1 3574 output = check_output('ip -d link show dummy98')
1f0e3109
SS
3575 print(output)
3576 self.assertRegex(output, 'master')
3577 self.assertRegex(output, 'bridge')
3578
371810d1 3579 output = check_output('ip addr show bridge99')
1f0e3109 3580 print(output)
2be6c5d2 3581 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 3582
371810d1 3583 output = check_output('bridge -d link show dummy98')
1f0e3109 3584 print(output)
ec38833c 3585 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
3586 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
3587 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
3588 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
3589 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
3590 # CONFIG_BRIDGE_IGMP_SNOOPING=y
3591 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
3592 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 3593 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
3594 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
3595 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
3596 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
3597 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
3598 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 3599
5424fd95
YW
3600 output = check_output('bridge -d link show test1')
3601 print(output)
3602 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 3603
371810d1 3604 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3605 time.sleep(1)
3606
371810d1 3607 output = check_output('ip addr show bridge99')
2be6c5d2
YW
3608 print(output)
3609 self.assertRegex(output, '192.168.0.16/24')
3610
e3cbaeab
YW
3611 # for issue #6088
3612 print('### ip -6 route list table all dev bridge99')
3613 output = check_output('ip -6 route list table all dev bridge99')
3614 print(output)
beb75dd3 3615 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3616
371810d1 3617 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 3618
19cf3143 3619 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 3620
cefd6b3d 3621 check_output('ip link del dummy98')
804b6cd2 3622
19cf3143 3623 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 3624
371810d1 3625 output = check_output('ip address show bridge99')
804b6cd2
YW
3626 print(output)
3627 self.assertRegex(output, 'NO-CARRIER')
3628 self.assertNotRegex(output, '192.168.0.15/24')
3629 self.assertNotRegex(output, '192.168.0.16/24')
3630
e3cbaeab
YW
3631 print('### ip -6 route list table all dev bridge99')
3632 output = check_output('ip -6 route list table all dev bridge99')
3633 print(output)
beb75dd3 3634 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3635
0fc0d85f
DS
3636 def test_bridge_configure_without_carrier(self):
3637 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
3638 '11-dummy.netdev')
3639 start_networkd()
3640
3641 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
3642 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
3643 with self.subTest(test=test):
3644 if test == 'no-slave':
3645 # bridge has no slaves; it's up but *might* not have carrier
001c07cf 3646 self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30)
0fc0d85f
DS
3647 # due to a bug in the kernel, newly-created bridges are brought up
3648 # *with* carrier, unless they have had any setting changed; e.g.
3649 # their mac set, priority set, etc. Then, they will lose carrier
3650 # as soon as a (down) slave interface is added, and regain carrier
3651 # again once the slave interface is brought up.
3652 #self.check_link_attr('bridge99', 'carrier', '0')
3653 elif test == 'add-slave':
3654 # add slave to bridge, but leave it down; bridge is definitely no-carrier
3655 self.check_link_attr('test1', 'operstate', 'down')
3656 check_output('ip link set dev test1 master bridge99')
001c07cf 3657 self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None)
0fc0d85f
DS
3658 self.check_link_attr('bridge99', 'carrier', '0')
3659 elif test == 'slave-up':
3660 # bring up slave, which will have carrier; bridge gains carrier
3661 check_output('ip link set dev test1 up')
3662 self.wait_online(['bridge99:routable'])
3663 self.check_link_attr('bridge99', 'carrier', '1')
3664 elif test == 'slave-no-carrier':
3665 # drop slave carrier; bridge loses carrier
3666 check_output('ip link set dev test1 carrier off')
3667 self.wait_online(['bridge99:no-carrier:no-carrier'])
3668 self.check_link_attr('bridge99', 'carrier', '0')
3669 elif test == 'slave-carrier':
3670 # restore slave carrier; bridge gains carrier
3671 check_output('ip link set dev test1 carrier on')
3672 self.wait_online(['bridge99:routable'])
3673 self.check_link_attr('bridge99', 'carrier', '1')
3674 elif test == 'slave-down':
3675 # bring down slave; bridge loses carrier
3676 check_output('ip link set dev test1 down')
3677 self.wait_online(['bridge99:no-carrier:no-carrier'])
3678 self.check_link_attr('bridge99', 'carrier', '0')
3679
3680 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
0fc0d85f
DS
3681 self.assertRegex(output, '10.1.2.3')
3682 self.assertRegex(output, '10.1.2.1')
3683
804b6cd2 3684 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
3685 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3686 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3687 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3688 start_networkd()
e2aea43f 3689 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 3690
371810d1 3691 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3692 time.sleep(1)
3693
371810d1
ZJS
3694 check_output('ip link del test1')
3695 check_output('ip link del dummy98')
804b6cd2
YW
3696 time.sleep(3)
3697
371810d1 3698 output = check_output('ip address show bridge99')
804b6cd2
YW
3699 print(output)
3700 self.assertRegex(output, 'NO-CARRIER')
3701 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3702 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
3703
6609924c 3704 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
3705 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
3706 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3707 start_networkd()
e2aea43f 3708 self.wait_online(['bridge99:no-carrier'])
6609924c 3709
90e3bcbd
YW
3710 for trial in range(4):
3711 check_output('ip link add dummy98 type dummy')
3712 check_output('ip link set dummy98 up')
3713 if trial < 3:
3714 check_output('ip link del dummy98')
6609924c 3715
e2aea43f 3716 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 3717
371810d1 3718 output = check_output('ip address show bridge99')
6609924c
YW
3719 print(output)
3720 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3721
371810d1 3722 output = check_output('ip rule list table 100')
6609924c 3723 print(output)
c4f7a347 3724 self.assertIn('from all to 8.8.8.8 lookup 100', output)
6609924c 3725
be68c2c9 3726class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
3727 links = ['veth99']
3728
09ea6724
YW
3729 units = [
3730 '23-emit-lldp.network',
3731 '24-lldp.network',
3732 '25-veth.netdev']
1f0e3109
SS
3733
3734 def setUp(self):
ec38833c 3735 remove_links(self.links)
aaae5713 3736 stop_networkd(show_logs=False)
1f0e3109
SS
3737
3738 def tearDown(self):
ec38833c
ZJS
3739 remove_links(self.links)
3740 remove_unit_from_networkd_path(self.units)
aaae5713 3741 stop_networkd(show_logs=True)
1f0e3109
SS
3742
3743 def test_lldp(self):
ec38833c 3744 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 3745 start_networkd()
e2aea43f 3746 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 3747
f0d87798
YW
3748 for trial in range(10):
3749 if trial > 0:
3750 time.sleep(1)
3751
3752 output = check_output(*networkctl_cmd, 'lldp', env=env)
3753 print(output)
3754 if re.search(r'veth99 .* veth-peer', output):
3755 break
3756 else:
3757 self.fail()
1f0e3109 3758
be68c2c9 3759class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
3760 links = ['veth99']
3761
09ea6724
YW
3762 units = [
3763 '25-veth.netdev',
3764 'ipv6-prefix.network',
87bbebea 3765 'ipv6-prefix-veth.network',
e2c4070e 3766 'ipv6-prefix-veth-token-static.network',
68248f43
YW
3767 'ipv6-prefix-veth-token-prefixstable.network',
3768 'ipv6-prefix-veth-token-prefixstable-without-address.network']
1f0e3109
SS
3769
3770 def setUp(self):
ec38833c 3771 remove_links(self.links)
aaae5713 3772 stop_networkd(show_logs=False)
1f0e3109
SS
3773
3774 def tearDown(self):
ec38833c
ZJS
3775 remove_links(self.links)
3776 remove_unit_from_networkd_path(self.units)
aaae5713 3777 stop_networkd(show_logs=True)
1f0e3109
SS
3778
3779 def test_ipv6_prefix_delegation(self):
ec38833c 3780 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 3781 start_networkd()
e2aea43f 3782 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 3783
41fd8fe7
YW
3784 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3785 print(output)
3786 self.assertRegex(output, 'fe80::')
3787 self.assertRegex(output, '2002:da8:1::1')
3788
80762ccc
YW
3789 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3790 print(output)
3791 self.assertIn('hogehoge.test', output)
3792
fc79e6ff 3793 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3794 print(output)
3795 self.assertRegex(output, '2002:da8:1:0')
3796
e2c4070e
YW
3797 def test_ipv6_token_static(self):
3798 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 3799 start_networkd()
b241fa00
KF
3800 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3801
3802 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3803 print(output)
3804 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
68248f43
YW
3805 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
3806 self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d')
3807 self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe')
b241fa00 3808
68248f43
YW
3809 def test_ipv6_token_prefixstable(self):
3810 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
c24c83dc
KF
3811 start_networkd()
3812 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3813
3814 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3815 print(output)
68248f43
YW
3816 self.assertRegex(output, '2002:da8:1:0')
3817 self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI
c24c83dc 3818
68248f43
YW
3819 def test_ipv6_token_prefixstable_without_address(self):
3820 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network')
87bbebea
YW
3821 start_networkd()
3822 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3823
3824 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3825 print(output)
3826 self.assertRegex(output, '2002:da8:1:0')
68248f43 3827 self.assertRegex(output, '2002:da8:2:0')
87bbebea 3828
be68c2c9 3829class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
4e0006cc
YW
3830 links = [
3831 'dummy98',
3832 'veth99',
3833 ]
09ea6724
YW
3834
3835 units = [
4e0006cc 3836 '12-dummy.netdev',
09ea6724
YW
3837 '25-veth.netdev',
3838 'dhcp-client.network',
ffaece68 3839 'dhcp-client-static-lease.network',
09ea6724
YW
3840 'dhcp-client-timezone-router.network',
3841 'dhcp-server.network',
ffaece68 3842 'dhcp-server-static-lease.network',
4e0006cc
YW
3843 'dhcp-server-timezone-router.network',
3844 'dhcp-server-uplink.network',
3845 ]
1f0e3109
SS
3846
3847 def setUp(self):
ec38833c 3848 remove_links(self.links)
aaae5713 3849 stop_networkd(show_logs=False)
1f0e3109
SS
3850
3851 def tearDown(self):
ec38833c
ZJS
3852 remove_links(self.links)
3853 remove_unit_from_networkd_path(self.units)
aaae5713 3854 stop_networkd(show_logs=True)
1f0e3109
SS
3855
3856 def test_dhcp_server(self):
4e0006cc
YW
3857 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network',
3858 '12-dummy.netdev', 'dhcp-server-uplink.network')
2cf6fdff 3859 start_networkd()
e2aea43f 3860 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3861
fc79e6ff 3862 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3863 print(output)
3864 self.assertRegex(output, '192.168.5.*')
3865 self.assertRegex(output, 'Gateway: 192.168.5.1')
3866 self.assertRegex(output, 'DNS: 192.168.5.1')
3867 self.assertRegex(output, 'NTP: 192.168.5.1')
3868
1f0e3109 3869 def test_emit_router_timezone(self):
ec38833c 3870 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 3871 start_networkd()
e2aea43f 3872 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3873
fc79e6ff 3874 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3875 print(output)
3876 self.assertRegex(output, 'Gateway: 192.168.5.*')
3877 self.assertRegex(output, '192.168.5.*')
3878 self.assertRegex(output, 'Europe/Berlin')
3879
ffaece68 3880 def test_dhcp_server_static_lease(self):
3881 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-static-lease.network', 'dhcp-server-static-lease.network')
3882 start_networkd()
3883 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3884
3885 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3886 print(output)
af0d4e6e 3887 self.assertIn('10.1.1.200 (DHCP4 via 10.1.1.1)', output)
ffaece68 3888
c95df587
YA
3889class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
3890 links = [
3891 'client',
3892 'server',
3893 'client-peer',
3894 'server-peer',
3895 ]
3896
3897 units = [
3898 'agent-veth-client.netdev',
3899 'agent-veth-server.netdev',
3900 'agent-client.network',
3901 'agent-server.network',
3902 'agent-client-peer.network',
3903 'agent-server-peer.network',
3904 ]
3905
3906 def setUp(self):
3907 remove_links(self.links)
3908 stop_networkd(show_logs=False)
3909
3910 def tearDown(self):
3911 remove_links(self.links)
3912 remove_unit_from_networkd_path(self.units)
3913 stop_networkd(show_logs=True)
3914
3915 def test_relay_agent(self):
3916 copy_unit_to_networkd_unit_path(*self.units)
3917 start_networkd()
3918
c95df587
YA
3919 self.wait_online(['client:routable'])
3920
3921 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env)
3922 print(output)
3923 self.assertRegex(output, 'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
3924
be68c2c9 3925class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 3926 links = [
18c613dc
YW
3927 'veth99',
3928 'vrf99']
09ea6724
YW
3929
3930 units = [
3931 '25-veth.netdev',
18c613dc
YW
3932 '25-vrf.netdev',
3933 '25-vrf.network',
09ea6724 3934 'dhcp-client-anonymize.network',
0fd8b718 3935 'dhcp-client-decline.network',
214c5bae
YW
3936 'dhcp-client-gateway-ipv4.network',
3937 'dhcp-client-gateway-ipv6.network',
af3b1498 3938 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
3939 'dhcp-client-ipv4-dhcp-settings.network',
3940 'dhcp-client-ipv4-only-ipv6-disabled.network',
3941 'dhcp-client-ipv4-only.network',
7c0d36ff 3942 'dhcp-client-ipv4-use-routes-use-gateway.network',
09ea6724
YW
3943 'dhcp-client-ipv6-only.network',
3944 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
3945 'dhcp-client-keep-configuration-dhcp-on-stop.network',
3946 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 3947 'dhcp-client-listen-port.network',
c1b01a62
YW
3948 'dhcp-client-reassign-static-routes-ipv4.network',
3949 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
3950 'dhcp-client-route-metric.network',
3951 'dhcp-client-route-table.network',
e2d5aab3
YW
3952 'dhcp-client-use-dns-ipv4-and-ra.network',
3953 'dhcp-client-use-dns-ipv4.network',
3954 'dhcp-client-use-dns-no.network',
3955 'dhcp-client-use-dns-yes.network',
e0c1341d 3956 'dhcp-client-use-domains.network',
18c613dc 3957 'dhcp-client-vrf.network',
240e4137 3958 'dhcp-client-with-ipv4ll.network',
4c882c16 3959 'dhcp-client-with-static-address.network',
3e9d5552 3960 'dhcp-client.network',
0fd8b718 3961 'dhcp-server-decline.network',
09ea6724 3962 'dhcp-server-veth-peer.network',
30d3b54e
YW
3963 'dhcp-v4-server-veth-peer.network',
3964 'static.network']
1f0e3109
SS
3965
3966 def setUp(self):
ec38833c
ZJS
3967 stop_dnsmasq(dnsmasq_pid_file)
3968 remove_links(self.links)
aaae5713 3969 stop_networkd(show_logs=False)
1f0e3109
SS
3970
3971 def tearDown(self):
ec38833c
ZJS
3972 stop_dnsmasq(dnsmasq_pid_file)
3973 remove_lease_file()
3974 remove_log_file()
3975 remove_links(self.links)
3976 remove_unit_from_networkd_path(self.units)
aaae5713 3977 stop_networkd(show_logs=True)
1f0e3109
SS
3978
3979 def test_dhcp_client_ipv6_only(self):
ec38833c 3980 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 3981
2cf6fdff 3982 start_networkd()
e2aea43f 3983 self.wait_online(['veth-peer:carrier'])
ec38833c 3984 start_dnsmasq()
e2aea43f 3985 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3986
fc79e6ff 3987 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3988 print(output)
3989 self.assertRegex(output, '2600::')
3990 self.assertNotRegex(output, '192.168.5')
3991
c5fcd8a7
YW
3992 output = check_output('ip addr show dev veth99')
3993 print(output)
3994 self.assertRegex(output, '2600::')
3995 self.assertNotRegex(output, '192.168.5')
3996 self.assertNotRegex(output, 'tentative')
3997
3a956d38 3998 # Confirm that ipv6 token is not set in the kernel
371810d1 3999 output = check_output('ip token show dev veth99')
3a956d38
YW
4000 print(output)
4001 self.assertRegex(output, 'token :: dev veth99')
4002
1f0e3109 4003 def test_dhcp_client_ipv4_only(self):
ec38833c 4004 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 4005
2cf6fdff 4006 start_networkd()
e2aea43f 4007 self.wait_online(['veth-peer:carrier'])
195a18c1 4008 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 4009 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4010
fc79e6ff 4011 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4012 print(output)
4013 self.assertNotRegex(output, '2600::')
4014 self.assertRegex(output, '192.168.5')
195a18c1
YW
4015 self.assertRegex(output, '192.168.5.6')
4016 self.assertRegex(output, '192.168.5.7')
4017
4018 # checking routes to DNS servers
4019 output = check_output('ip route show dev veth99')
4020 print(output)
4021 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4022 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
4023 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4024
4025 stop_dnsmasq(dnsmasq_pid_file)
4026 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
4027
4028 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4029 print('Wait for the dynamic address to be renewed')
4030 time.sleep(125)
4031
4032 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4033
fc79e6ff 4034 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
4035 print(output)
4036 self.assertNotRegex(output, '2600::')
4037 self.assertRegex(output, '192.168.5')
4038 self.assertNotRegex(output, '192.168.5.6')
4039 self.assertRegex(output, '192.168.5.7')
4040 self.assertRegex(output, '192.168.5.8')
4041
4042 # checking routes to DNS servers
4043 output = check_output('ip route show dev veth99')
4044 print(output)
4045 self.assertNotRegex(output, r'192.168.5.6')
4046 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4047 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4048 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 4049
7c0d36ff 4050 def test_dhcp_client_ipv4_use_routes_gateway(self):
e1220a70 4051 for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
7c0d36ff 4052 self.setUp()
e1220a70
YW
4053 with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
4054 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
7c0d36ff
DS
4055 self.tearDown()
4056
e1220a70 4057 def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
7c0d36ff
DS
4058 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
4059 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
625772c9
YW
4060 testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf');
4061 testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf');
e1220a70 4062 testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf');
7c0d36ff 4063 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
4c2e1833
YW
4064
4065 start_networkd()
4066 self.wait_online(['veth-peer:carrier'])
e1220a70 4067 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'
625772c9
YW
4068 if classless:
4069 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'
4070 start_dnsmasq(additional_options=additional_options, lease_time='2m')
4c2e1833
YW
4071 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4072
625772c9 4073 output = check_output('ip -4 route show dev veth99')
4c2e1833 4074 print(output)
4c2e1833 4075
7c0d36ff 4076 # Check UseRoutes=
625772c9
YW
4077 if use_routes:
4078 if classless:
4079 self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4080 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4081 self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4082 self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4083 else:
4084 self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4085 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4086 self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4087 else:
625772c9
YW
4088 self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4089 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4090 self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4091 self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4092 self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4093 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4094 self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
0d7bd445 4095
7c0d36ff 4096 # Check UseGateway=
625772c9
YW
4097 if use_gateway and (not classless or not use_routes):
4098 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4099 else:
625772c9 4100 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32
YW
4101
4102 # Check route to gateway
4103 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes):
4104 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4105 else:
625772c9 4106 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4107
e1220a70
YW
4108 # Check RoutesToDNS= and RoutesToNTP=
4109 if dns_and_ntp_routes:
625772c9 4110 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4111 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9
YW
4112 if classless and use_routes:
4113 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4114 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32 4115 else:
625772c9 4116 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4117 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4118 else:
625772c9 4119 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4120 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9 4121 self.assertNotRegex(output, r'8.8.8.8 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4122 self.assertNotRegex(output, r'9.9.9.9 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
0d7bd445 4123
1f0e3109 4124 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
4125 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
4126 'dhcp-client-ipv4-only.network')
2cf6fdff 4127 start_networkd()
e2aea43f 4128 self.wait_online(['veth-peer:carrier'])
ec38833c 4129 start_dnsmasq()
e2aea43f 4130 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4131
4132 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4133 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4134 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 4135
fc79e6ff 4136 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4137 print(output)
4138 self.assertRegex(output, '2600::')
4139 self.assertRegex(output, '192.168.5')
4140
4141 def test_dhcp_client_settings(self):
ec38833c 4142 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 4143
2cf6fdff 4144 start_networkd()
e2aea43f 4145 self.wait_online(['veth-peer:carrier'])
ec38833c 4146 start_dnsmasq()
e2aea43f 4147 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4148
0ae7a66d 4149 print('## ip address show dev veth99')
371810d1 4150 output = check_output('ip address show dev veth99')
1f0e3109
SS
4151 print(output)
4152 self.assertRegex(output, '12:34:56:78:9a:bc')
4153 self.assertRegex(output, '192.168.5')
4154 self.assertRegex(output, '1492')
d419ef02 4155 self.assertRegex(output, 'test-label')
1f0e3109 4156
0ae7a66d 4157 print('## ip route show table main dev veth99')
371810d1 4158 output = check_output('ip route show table main dev veth99')
1f0e3109 4159 print(output)
156ddf8d 4160 # See issue #8726
dd9b10c8
YW
4161 main_table_is_empty = output == ''
4162 if not main_table_is_empty:
4163 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 4164
0ae7a66d 4165 print('## ip route show table 211 dev veth99')
371810d1 4166 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
4167 print(output)
4168 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
4169 if main_table_is_empty:
4170 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
4171 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
4172
4173 print('## dnsmasq log')
ec38833c
ZJS
4174 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
4175 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
4176 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
4177 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4178
4179 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 4180 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 4181 start_networkd()
e2aea43f 4182 self.wait_online(['veth-peer:carrier'])
ec38833c 4183 start_dnsmasq()
e2aea43f 4184 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4185
371810d1 4186 output = check_output('ip address show dev veth99')
1f0e3109
SS
4187 print(output)
4188 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4189 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4190
4191 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 4192 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 4193 start_networkd()
e2aea43f 4194 self.wait_online(['veth-peer:carrier'])
ec38833c 4195 start_dnsmasq()
e2aea43f 4196 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4197
371810d1 4198 output = check_output('ip address show dev veth99')
1f0e3109
SS
4199 print(output)
4200 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4201 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4202
4203 def test_dhcp_client_settings_anonymize(self):
ec38833c 4204 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 4205 start_networkd()
e2aea43f 4206 self.wait_online(['veth-peer:carrier'])
ec38833c 4207 start_dnsmasq()
e2aea43f 4208 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4209
ec38833c
ZJS
4210 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
4211 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
4212 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4213
4214 def test_dhcp_client_listen_port(self):
ec38833c 4215 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 4216 start_networkd()
e2aea43f 4217 self.wait_online(['veth-peer:carrier'])
ec38833c 4218 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 4219 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 4220
371810d1 4221 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
4222 print(output)
4223 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 4224
4c882c16
YW
4225 def test_dhcp_client_with_static_address(self):
4226 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
4227 'dhcp-client-with-static-address.network')
4228 start_networkd()
e2aea43f 4229 self.wait_online(['veth-peer:carrier'])
4c882c16 4230 start_dnsmasq()
e2aea43f 4231 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
4232
4233 output = check_output('ip address show dev veth99 scope global')
4234 print(output)
4235 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3e726c15 4236 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic veth99')
4c882c16
YW
4237
4238 output = check_output('ip route show dev veth99')
4239 print(output)
4240 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
4241 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
4c882c16
YW
4242 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4243
1f0e3109 4244 def test_dhcp_route_table_id(self):
ec38833c 4245 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 4246 start_networkd()
e2aea43f 4247 self.wait_online(['veth-peer:carrier'])
ec38833c 4248 start_dnsmasq()
e2aea43f 4249 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4250
371810d1 4251 output = check_output('ip route show table 12')
1f0e3109 4252 print(output)
1f0e3109
SS
4253 self.assertRegex(output, 'veth99 proto dhcp')
4254 self.assertRegex(output, '192.168.5.1')
4255
4256 def test_dhcp_route_metric(self):
ec38833c 4257 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 4258 start_networkd()
e2aea43f 4259 self.wait_online(['veth-peer:carrier'])
ec38833c 4260 start_dnsmasq()
e2aea43f 4261 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4262
371810d1 4263 output = check_output('ip route show dev veth99')
1f0e3109 4264 print(output)
3e726c15
YW
4265 self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output)
4266 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output)
4267 self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output)
1f0e3109 4268
c1b01a62 4269 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 4270 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 4271 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 4272 start_networkd()
e2aea43f 4273 self.wait_online(['veth-peer:carrier'])
c38d2d4d 4274 start_dnsmasq(lease_time='2m')
e2aea43f 4275 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
4276
4277 output = check_output('ip address show dev veth99 scope global')
4278 print(output)
3e726c15 4279 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
c38d2d4d
YW
4280
4281 output = check_output('ip route show dev veth99')
4282 print(output)
4283 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4284 self.assertRegex(output, r'192.168.5.0/24 proto static')
4285 self.assertRegex(output, r'192.168.6.0/24 proto static')
4286 self.assertRegex(output, r'192.168.7.0/24 proto static')
4287
c1b01a62
YW
4288 stop_dnsmasq(dnsmasq_pid_file)
4289 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
4290
c38d2d4d
YW
4291 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4292 print('Wait for the dynamic address to be renewed')
4293 time.sleep(125)
4294
e2aea43f 4295 self.wait_online(['veth99:routable'])
c38d2d4d
YW
4296
4297 output = check_output('ip route show dev veth99')
4298 print(output)
4299 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4300 self.assertRegex(output, r'192.168.5.0/24 proto static')
4301 self.assertRegex(output, r'192.168.6.0/24 proto static')
4302 self.assertRegex(output, r'192.168.7.0/24 proto static')
4303
c1b01a62
YW
4304 def test_dhcp_client_reassign_static_routes_ipv6(self):
4305 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4306 'dhcp-client-reassign-static-routes-ipv6.network')
4307 start_networkd()
e2aea43f 4308 self.wait_online(['veth-peer:carrier'])
c1b01a62 4309 start_dnsmasq(lease_time='2m')
e2aea43f 4310 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
4311
4312 output = check_output('ip address show dev veth99 scope global')
4313 print(output)
426654d7 4314 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
4315
4316 output = check_output('ip -6 route show dev veth99')
4317 print(output)
4318 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4319 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4320
4321 stop_dnsmasq(dnsmasq_pid_file)
4322 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
4323
4324 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4325 print('Wait for the dynamic address to be renewed')
4326 time.sleep(125)
4327
e2aea43f 4328 self.wait_online(['veth99:routable'])
c1b01a62
YW
4329
4330 output = check_output('ip -6 route show dev veth99')
4331 print(output)
4332 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4333 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4334
1e498853
YW
4335 def test_dhcp_keep_configuration_dhcp(self):
4336 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 4337 start_networkd()
e2aea43f 4338 self.wait_online(['veth-peer:carrier'])
1e498853 4339 start_dnsmasq(lease_time='2m')
e2aea43f 4340 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4341
1e498853
YW
4342 output = check_output('ip address show dev veth99 scope global')
4343 print(output)
4344 self.assertRegex(output, r'192.168.5.*')
4345
fc79e6ff 4346 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4347 print(output)
1e498853 4348 self.assertRegex(output, r'192.168.5.*')
e40a58b5 4349
5238e957 4350 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 4351 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
4352
4353 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 4354 print('Wait for the dynamic address to be expired')
1f0e3109
SS
4355 time.sleep(125)
4356
1e498853
YW
4357 print('The lease address should be kept after lease expired')
4358 output = check_output('ip address show dev veth99 scope global')
4359 print(output)
4360 self.assertRegex(output, r'192.168.5.*')
4361
fc79e6ff 4362 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4363 print(output)
1e498853
YW
4364 self.assertRegex(output, r'192.168.5.*')
4365
3aa645f0
MB
4366 check_output('systemctl stop systemd-networkd.socket')
4367 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4368
4369 print('The lease address should be kept after networkd stopped')
4370 output = check_output('ip address show dev veth99 scope global')
4371 print(output)
4372 self.assertRegex(output, r'192.168.5.*')
4373
fc79e6ff 4374 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4375 print(output)
4376 self.assertRegex(output, r'192.168.5.*')
4377
e2aea43f
YW
4378 start_networkd(3)
4379 self.wait_online(['veth-peer:routable'])
1e498853
YW
4380
4381 print('Still the lease address should be kept after networkd restarted')
4382 output = check_output('ip address show dev veth99 scope global')
4383 print(output)
4384 self.assertRegex(output, r'192.168.5.*')
4385
fc79e6ff 4386 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4387 print(output)
4388 self.assertRegex(output, r'192.168.5.*')
4389
4390 def test_dhcp_keep_configuration_dhcp_on_stop(self):
4391 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4392 start_networkd()
e2aea43f 4393 self.wait_online(['veth-peer:carrier'])
1e498853 4394 start_dnsmasq(lease_time='2m')
e2aea43f 4395 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4396
4397 output = check_output('ip address show dev veth99 scope global')
4398 print(output)
4399 self.assertRegex(output, r'192.168.5.*')
4400
4401 stop_dnsmasq(dnsmasq_pid_file)
3aa645f0
MB
4402 check_output('systemctl stop systemd-networkd.socket')
4403 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4404
4405 output = check_output('ip address show dev veth99 scope global')
4406 print(output)
4407 self.assertRegex(output, r'192.168.5.*')
4408
e2aea43f
YW
4409 restart_networkd(3)
4410 self.wait_online(['veth-peer:routable'])
1e498853
YW
4411
4412 output = check_output('ip address show dev veth99 scope global')
4413 print(output)
4414 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 4415
30d3b54e 4416 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 4417 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 4418 start_networkd()
e2aea43f 4419 self.wait_online(['veth-peer:carrier'])
ec38833c 4420 start_dnsmasq()
e2aea43f 4421 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4422
4423 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4424 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4425 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4426
371810d1 4427 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
4428 print(output)
4429 self.assertRegex(output, '192.168.5')
4430 self.assertRegex(output, '2600::')
4431
2629df47
YW
4432 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
4433 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
4434 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
4435 print(static_network)
4436
ec38833c 4437 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
4438
4439 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
4440 f.write(static_network)
4441
2629df47
YW
4442 # When networkd started, the links are already configured, so let's wait for 5 seconds
4443 # the links to be re-configured.
aaae5713 4444 restart_networkd(5)
e2aea43f 4445 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 4446
371810d1 4447 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
4448 print(output)
4449 self.assertRegex(output, '192.168.5')
4450 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4451
371810d1 4452 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
4453 print(output)
4454 self.assertRegex(output, '2600::')
4455 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4456
18c613dc
YW
4457 @expectedFailureIfModuleIsNotAvailable('vrf')
4458 def test_dhcp_client_vrf(self):
ec38833c
ZJS
4459 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
4460 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4461 start_networkd()
e2aea43f 4462 self.wait_online(['veth-peer:carrier'])
ec38833c 4463 start_dnsmasq()
e2aea43f 4464 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4465
4466 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4467 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4468 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4469
4470 print('## ip -d link show dev vrf99')
371810d1 4471 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4472 print(output)
4473 self.assertRegex(output, 'vrf table 42')
4474
4475 print('## ip address show vrf vrf99')
371810d1 4476 output = check_output('ip address show vrf vrf99')
d90f4f7d 4477 print(output)
3e726c15 4478 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4479 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4480 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4481
4482 print('## ip address show dev veth99')
371810d1 4483 output = check_output('ip address show dev veth99')
18c613dc 4484 print(output)
3e726c15 4485 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4486 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4487 self.assertRegex(output, 'inet6 .* scope link')
4488
4489 print('## ip route show vrf vrf99')
371810d1 4490 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4491 print(output)
4492 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc 4493 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
18c613dc
YW
4494 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4495
4496 print('## ip route show table main dev veth99')
371810d1 4497 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4498 print(output)
4499 self.assertEqual(output, '')
4500
214c5bae
YW
4501 def test_dhcp_client_gateway_ipv4(self):
4502 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4503 'dhcp-client-gateway-ipv4.network')
4504 start_networkd()
4505 self.wait_online(['veth-peer:carrier'])
4506 start_dnsmasq()
4507 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4508
4df8a8e8 4509 output = check_output('ip route list dev veth99')
214c5bae 4510 print(output)
4df8a8e8
YW
4511 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4512 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4513
4514 with open(os.path.join(network_unit_file_path, 'dhcp-client-gateway-ipv4.network'), mode='a') as f:
4515 f.write('[DHCPv4]\nUseGateway=no\n')
4516
4517 rc = call(*networkctl_cmd, 'reload', env=env)
4518 self.assertEqual(rc, 0)
4519
4520 time.sleep(2)
4521 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4522
4523 output = check_output('ip route list dev veth99')
4524 print(output)
4525 self.assertNotRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4526 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
214c5bae
YW
4527
4528 def test_dhcp_client_gateway_ipv6(self):
4529 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4530 'dhcp-client-gateway-ipv6.network')
4531 start_networkd()
4532 self.wait_online(['veth-peer:carrier'])
4533 start_dnsmasq()
4534 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4535
4536 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4537 print(output)
4538 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4539
af3b1498 4540 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
4541 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4542 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4543 start_networkd()
e2aea43f 4544 self.wait_online(['veth-peer:carrier'])
ec38833c 4545 start_dnsmasq()
e2aea43f 4546 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4547
fc79e6ff 4548 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4549 print(output)
4550 self.assertRegex(output, '192.168.5')
4551
371810d1 4552 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4553 print(output)
4554 self.assertRegex(output, 'onlink')
371810d1 4555 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4556 print(output)
4557 self.assertRegex(output, 'onlink')
4558
3ca1fab7 4559 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
ec38833c 4560 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4561 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4562 start_networkd()
e2aea43f 4563 self.wait_online(['veth-peer:carrier'])
ec38833c 4564 start_dnsmasq(lease_time='2m')
e2aea43f 4565 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 4566
371810d1 4567 output = check_output('ip address show dev veth99')
63c598ed
YW
4568 print(output)
4569
371810d1 4570 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4571 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4572 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4573 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4574 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4575 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4576 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4577 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed
YW
4578
4579 print('Wait for the dynamic address to be expired')
4580 time.sleep(130)
4581
371810d1 4582 output = check_output('ip address show dev veth99')
63c598ed
YW
4583 print(output)
4584
371810d1 4585 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4586 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4587 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4588 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4589 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4590 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4591 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4592 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed 4593
ec38833c 4594 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 4595
3ca1fab7 4596 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
ec38833c 4597 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4598 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4599 start_networkd()
b226c15c
DS
4600 # we need to increase timeout above default, as this will need to wait for
4601 # systemd-networkd to get the dhcpv4 transient failure event
4602 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
117a55c7 4603
371810d1 4604 output = check_output('ip address show dev veth99')
117a55c7
YW
4605 print(output)
4606
371810d1 4607 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4608 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4609 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4610 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4611 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4612 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4613 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4614 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
240e4137
YW
4615
4616 start_dnsmasq(lease_time='2m')
3e726c15
YW
4617 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4618 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')
117a55c7 4619
b6efd661 4620 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
4621 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4622 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 4623 start_networkd()
e2aea43f 4624 self.wait_online(['veth-peer:carrier'])
ec38833c 4625 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 4626 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
4627
4628 # test for issue #12490
4629
371810d1 4630 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4631 print(output)
3e726c15 4632 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4633 address1=None
4634 for line in output.splitlines():
4635 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
4636 address1 = line.split()[1].split('/')[0]
4637 break
4638
371810d1 4639 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4640 print(output)
4641 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4642 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4643
ec38833c
ZJS
4644 stop_dnsmasq(dnsmasq_pid_file)
4645 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
4646
4647 print('Wait for the dynamic address to be expired')
4648 time.sleep(130)
4649
371810d1 4650 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4651 print(output)
3e726c15 4652 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4653 address2=None
4654 for line in output.splitlines():
3e726c15 4655 if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line:
b6efd661
YW
4656 address2 = line.split()[1].split('/')[0]
4657 break
4658
4659 self.assertNotEqual(address1, address2)
4660
371810d1 4661 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4662 print(output)
4663 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4664 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4665 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
4666 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
4667
e2d5aab3
YW
4668 def test_dhcp_client_use_dns_yes(self):
4669 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
4670
4671 start_networkd()
e2aea43f 4672 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4673 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4674 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4675
4676 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4677 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4678 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4679
693283cd 4680 time.sleep(3)
e2d5aab3
YW
4681 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4682 print(output)
4683 self.assertRegex(output, '192.168.5.1')
4684 self.assertRegex(output, '2600::1')
4685
4686 def test_dhcp_client_use_dns_no(self):
4687 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
4688
4689 start_networkd()
e2aea43f 4690 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4691 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4692 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4693
4694 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4695 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4696 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4697
693283cd 4698 time.sleep(3)
e2d5aab3
YW
4699 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4700 print(output)
4701 self.assertNotRegex(output, '192.168.5.1')
4702 self.assertNotRegex(output, '2600::1')
4703
4704 def test_dhcp_client_use_dns_ipv4(self):
4705 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
4706
4707 start_networkd()
e2aea43f 4708 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4709 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4710 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4711
4712 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4713 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4714 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4715
693283cd 4716 time.sleep(3)
e2d5aab3
YW
4717 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4718 print(output)
4719 self.assertRegex(output, '192.168.5.1')
4720 self.assertNotRegex(output, '2600::1')
4721
4722 def test_dhcp_client_use_dns_ipv4_and_ra(self):
4723 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
4724
4725 start_networkd()
e2aea43f 4726 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4727 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4728 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4729
4730 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4731 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4732 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4733
693283cd 4734 time.sleep(3)
e2d5aab3
YW
4735 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4736 print(output)
4737 self.assertRegex(output, '192.168.5.1')
4738 self.assertRegex(output, '2600::1')
4739
e0c1341d
YW
4740 def test_dhcp_client_use_domains(self):
4741 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
4742
4743 start_networkd()
e2aea43f 4744 self.wait_online(['veth-peer:carrier'])
e0c1341d 4745 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 4746 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 4747
fc79e6ff 4748 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
4749 print(output)
4750 self.assertRegex(output, 'Search Domains: example.com')
4751
4752 time.sleep(3)
4753 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
4754 print(output)
4755 self.assertRegex(output, 'example.com')
4756
0fd8b718
YW
4757 def test_dhcp_client_decline(self):
4758 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
4759
4760 start_networkd()
44924431
YW
4761 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4762
4763 output = check_output('ip -4 address show dev veth99 scope global dynamic')
4764 print(output)
4765 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
0fd8b718 4766
9633f977 4767class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
4a906586
YW
4768 links = [
4769 'dummy98',
4770 'veth99',
4771 ]
9633f977
SS
4772
4773 units = [
4a906586 4774 '12-dummy.netdev',
9633f977 4775 '25-veth.netdev',
635f2a66 4776 'ipv6ra-prefix-client-deny-list.network',
9633f977 4777 'ipv6ra-prefix-client.network',
4a906586
YW
4778 'ipv6ra-prefix.network',
4779 'ipv6ra-uplink.network',
4780 ]
9633f977
SS
4781
4782 def setUp(self):
4783 remove_links(self.links)
4784 stop_networkd(show_logs=False)
4785
4786 def tearDown(self):
4787 remove_log_file()
4788 remove_links(self.links)
4789 remove_unit_from_networkd_path(self.units)
4790 stop_networkd(show_logs=True)
4791
4792 def test_ipv6_route_prefix(self):
4a906586
YW
4793 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network',
4794 '12-dummy.netdev', 'ipv6ra-uplink.network')
9633f977
SS
4795
4796 start_networkd()
4a906586 4797 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
9633f977 4798
635f2a66
YW
4799 output = check_output('ip address show dev veth-peer')
4800 print(output)
4801 self.assertIn('inet6 2001:db8:0:1:', output)
4802 self.assertNotIn('inet6 2001:db8:0:2:', output)
4803
3c874fd7 4804 output = check_output('ip -6 route show dev veth-peer')
9633f977 4805 print(output)
635f2a66
YW
4806 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4807 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4808 self.assertIn('2001:db0:fff::/64 via ', output)
4809 self.assertNotIn('2001:db1:fff::/64 via ', output)
9633f977 4810
635f2a66
YW
4811 output = check_output('ip address show dev veth99')
4812 print(output)
4813 self.assertNotIn('inet6 2001:db8:0:1:', output)
4814 self.assertIn('inet6 2001:db8:0:2:', output)
4815
4a906586
YW
4816 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
4817 print(output)
4818 self.assertRegex(output, '2001:db8:1:1::2')
4819
4820 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
4821 print(output)
4822 self.assertIn('example.com', output)
4823
635f2a66 4824 def test_ipv6_route_prefix_deny_list(self):
4a906586
YW
4825 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network',
4826 '12-dummy.netdev', 'ipv6ra-uplink.network')
635f2a66
YW
4827
4828 start_networkd()
4a906586 4829 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
635f2a66
YW
4830
4831 output = check_output('ip address show dev veth-peer')
4832 print(output)
4833 self.assertIn('inet6 2001:db8:0:1:', output)
4834 self.assertNotIn('inet6 2001:db8:0:2:', output)
4835
4836 output = check_output('ip -6 route show dev veth-peer')
4837 print(output)
4838 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4839 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4840 self.assertIn('2001:db0:fff::/64 via ', output)
4841 self.assertNotIn('2001:db1:fff::/64 via ', output)
4842
4843 output = check_output('ip address show dev veth99')
3c874fd7 4844 print(output)
635f2a66
YW
4845 self.assertNotIn('inet6 2001:db8:0:1:', output)
4846 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 4847
4a906586
YW
4848 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
4849 print(output)
4850 self.assertRegex(output, '2001:db8:1:1::2')
4851
4852 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
4853 print(output)
4854 self.assertIn('example.com', output)
4855
7db05447
DS
4856class NetworkdMTUTests(unittest.TestCase, Utilities):
4857 links = ['dummy98']
4858
4859 units = [
4860 '12-dummy.netdev',
4861 '12-dummy-mtu.netdev',
4862 '12-dummy-mtu.link',
4863 '12-dummy.network',
4864 ]
4865
4866 def setUp(self):
4867 remove_links(self.links)
4868 stop_networkd(show_logs=False)
4869
4870 def tearDown(self):
4871 remove_log_file()
4872 remove_links(self.links)
4873 remove_unit_from_networkd_path(self.units)
4874 stop_networkd(show_logs=True)
4875
4876 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
4877 if not ipv6_mtu:
4878 ipv6_mtu = mtu
4879
4880 # test normal start
4881 start_networkd()
4882 self.wait_online(['dummy98:routable'])
4883 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4884 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4885
4886 # test normal restart
4887 restart_networkd()
4888 self.wait_online(['dummy98:routable'])
4889 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4890 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4891
4892 if reset:
4893 self.reset_check_mtu(mtu, ipv6_mtu)
4894
4895 def reset_check_mtu(self, mtu, ipv6_mtu=None):
4896 ''' test setting mtu/ipv6_mtu with interface already up '''
4897 stop_networkd()
4898
4899 # note - changing the device mtu resets the ipv6 mtu
4900 run('ip link set up mtu 1501 dev dummy98')
4901 run('ip link set up mtu 1500 dev dummy98')
4902 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
4903 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
4904
4905 self.check_mtu(mtu, ipv6_mtu, reset=False)
4906
4907 def test_mtu_network(self):
4908 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
4909 self.check_mtu('1600')
4910
4911 def test_mtu_netdev(self):
4912 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
4913 # note - MTU set by .netdev happens ONLY at device creation!
4914 self.check_mtu('1600', reset=False)
4915
4916 def test_mtu_link(self):
4917 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
4918 # must reload udev because it only picks up new files after 3 second delay
4919 call('udevadm control --reload')
4920 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
4921 self.check_mtu('1600', reset=False)
4922
4923 def test_ipv6_mtu(self):
4924 ''' set ipv6 mtu without setting device mtu '''
4925 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
4926 self.check_mtu('1500', '1400')
4927
4928 def test_ipv6_mtu_toolarge(self):
4929 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
4930 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4931 self.check_mtu('1500', '1500')
4932
4933 def test_mtu_network_ipv6_mtu(self):
4934 ''' set ipv6 mtu and set device mtu via network file '''
4935 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
4936 self.check_mtu('1600', '1550')
4937
4938 def test_mtu_netdev_ipv6_mtu(self):
4939 ''' set ipv6 mtu and set device mtu via netdev file '''
4940 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4941 self.check_mtu('1600', '1550', reset=False)
4942
4943 def test_mtu_link_ipv6_mtu(self):
4944 ''' set ipv6 mtu and set device mtu via link file '''
4945 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
4946 # must reload udev because it only picks up new files after 3 second delay
4947 call('udevadm control --reload')
4948 self.check_mtu('1600', '1550', reset=False)
4949
4950
1f0e3109 4951if __name__ == '__main__':
9c1ae484
YW
4952 parser = argparse.ArgumentParser()
4953 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
4954 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 4955 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 4956 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
4957 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
4958 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
4959 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
4960 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
4961 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
4962 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 4963 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 4964 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 4965 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
4966 ns, args = parser.parse_known_args(namespace=unittest)
4967
4968 if ns.build_dir:
641aa412 4969 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:
b6d587d1 4970 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 4971 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 4972 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 4973 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
4974 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
4975 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
4976 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
4977 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
4978 else:
4979 if ns.networkd_bin:
4980 networkd_bin = ns.networkd_bin
b6d587d1
YW
4981 if ns.resolved_bin:
4982 resolved_bin = ns.resolved_bin
641aa412
YW
4983 if ns.udevd_bin:
4984 udevd_bin = ns.udevd_bin
9c1ae484
YW
4985 if ns.wait_online_bin:
4986 wait_online_bin = ns.wait_online_bin
4987 if ns.networkctl_bin:
4988 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
4989 if ns.resolvectl_bin:
4990 resolvectl_bin = ns.resolvectl_bin
4991 if ns.timedatectl_bin:
4992 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
4993
4994 use_valgrind = ns.use_valgrind
4995 enable_debug = ns.enable_debug
94c03122 4996 asan_options = ns.asan_options
fa4c6095 4997 lsan_options = ns.lsan_options
94c03122 4998 ubsan_options = ns.ubsan_options
9c1ae484
YW
4999
5000 if use_valgrind:
5001 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
5002 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
5003 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
5004 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
5005 else:
5006 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
5007 resolvectl_cmd = [resolvectl_bin]
5008 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
5009 wait_online_cmd = [wait_online_bin]
5010
5011 if enable_debug:
5012 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
5013 if asan_options:
5014 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
5015 if lsan_options:
5016 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
5017 if ubsan_options:
5018 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
5019
5020 sys.argv[1:] = args
1f0e3109
SS
5021 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
5022 verbosity=3))