]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: introduce KeepMaster= setting
[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
c918b70a
TY
1158 self.wait_online(['macvtap99:degraded',
1159 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
460feb61 1160
371810d1 1161 output = check_output('ip -d link show macvtap99')
460feb61
YW
1162 print(output)
1163 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
1164
1165 def test_macvlan(self):
dff9792b
YW
1166 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1167 with self.subTest(mode=mode):
1168 if mode != 'private':
1169 self.tearDown()
ec38833c
ZJS
1170 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
1171 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
1172 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
1173 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 1174 start_networkd()
dff9792b 1175
c918b70a
TY
1176 self.wait_online(['macvlan99:degraded',
1177 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
dff9792b 1178
371810d1 1179 output = check_output('ip -d link show test1')
dff9792b
YW
1180 print(output)
1181 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1182
371810d1 1183 output = check_output('ip -d link show macvlan99')
dff9792b
YW
1184 print(output)
1185 self.assertRegex(output, ' mtu 2000 ')
1186 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 1187
1d0c9bd7
YW
1188 rc = call("ip link del test1")
1189 self.assertEqual(rc, 0)
1190 time.sleep(1)
1191
1192 rc = call("ip link add test1 type dummy")
1193 self.assertEqual(rc, 0)
1194 time.sleep(1)
1195
c918b70a
TY
1196 self.wait_online(['macvlan99:degraded',
1197 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
1d0c9bd7
YW
1198
1199 output = check_output('ip -d link show test1')
1200 print(output)
1201 self.assertRegex(output, ' mtu 2000 ')
1202
1203 output = check_output('ip -d link show macvlan99')
1204 print(output)
1205 self.assertRegex(output, ' mtu 2000 ')
1206 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
1207
7a0a37b2 1208 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 1209 def test_ipvlan(self):
bc6dff6e
YW
1210 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1211 with self.subTest(mode=mode, flag=flag):
1212 if mode != 'L2':
1213 self.tearDown()
ec38833c
ZJS
1214 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1215 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
1216 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
1217 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 1218
2cf6fdff 1219 start_networkd()
e2aea43f 1220 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 1221
371810d1 1222 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
1223 print(output)
1224 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 1225
956c8fec
YW
1226 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1227 def test_ipvtap(self):
40921f08
YW
1228 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1229 with self.subTest(mode=mode, flag=flag):
1230 if mode != 'L2':
1231 self.tearDown()
ec38833c
ZJS
1232 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1233 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
1234 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
1235 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
1236
2cf6fdff 1237 start_networkd()
e2aea43f 1238 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 1239
371810d1 1240 output = check_output('ip -d link show ipvtap99')
40921f08
YW
1241 print(output)
1242 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 1243
1f0e3109 1244 def test_veth(self):
ec38833c 1245 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1246 start_networkd()
1f0e3109 1247
e2aea43f 1248 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 1249
371810d1 1250 output = check_output('ip -d link show veth99')
671dacdf
YW
1251 print(output)
1252 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 1253 output = check_output('ip -d link show veth-peer')
671dacdf
YW
1254 print(output)
1255 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 1256
1f0e3109 1257 def test_tun(self):
ec38833c 1258 copy_unit_to_networkd_unit_path('25-tun.netdev')
2cf6fdff 1259 start_networkd()
1f0e3109 1260
e2aea43f 1261 self.wait_online(['tun99:off'], setup_state='unmanaged')
1f0e3109 1262
371810d1 1263 output = check_output('ip -d link show tun99')
2746d307
YW
1264 print(output)
1265 # Old ip command does not support IFF_ flags
426654d7 1266 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1267
1f0e3109 1268 def test_tap(self):
ec38833c 1269 copy_unit_to_networkd_unit_path('25-tap.netdev')
2cf6fdff 1270 start_networkd()
1f0e3109 1271
e2aea43f 1272 self.wait_online(['tap99:off'], setup_state='unmanaged')
1f0e3109 1273
371810d1 1274 output = check_output('ip -d link show tap99')
2746d307
YW
1275 print(output)
1276 # Old ip command does not support IFF_ flags
426654d7 1277 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1278
7a0a37b2 1279 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 1280 def test_vrf(self):
ec38833c 1281 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1282 start_networkd()
1f0e3109 1283
e2aea43f 1284 self.wait_online(['vrf99:carrier'])
1f0e3109 1285
7a0a37b2 1286 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1287 def test_vcan(self):
ec38833c 1288 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1289 start_networkd()
1f0e3109 1290
e2aea43f 1291 self.wait_online(['vcan99:carrier'])
1f0e3109 1292
f63b14d3
YW
1293 @expectedFailureIfModuleIsNotAvailable('vxcan')
1294 def test_vxcan(self):
ec38833c 1295 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1296 start_networkd()
f63b14d3 1297
e2aea43f 1298 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1299
7a3bc5a8
EV
1300 @expectedFailureIfModuleIsNotAvailable('wireguard')
1301 def test_wireguard(self):
ec38833c
ZJS
1302 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1303 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
da3509f0
YW
1304 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
1305 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
2cf6fdff 1306 start_networkd()
84d32bf5
YW
1307 self.wait_online(['wg99:routable', 'wg98:routable', 'wg97:carrier'])
1308
1309 output = check_output('ip -4 address show dev wg99')
1310 print(output)
1311 self.assertIn('inet 192.168.124.1/24 scope global wg99', output)
5a0bd90b 1312
045db4fa
YW
1313 output = check_output('ip -4 address show dev wg98')
1314 print(output)
1315 self.assertIn('inet 192.168.123.123/24 scope global wg98', output)
1316
1317 output = check_output('ip -6 address show dev wg98')
1318 print(output)
1319 self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output)
1320
7a3bc5a8 1321 if shutil.which('wg'):
371810d1 1322 call('wg')
5a0bd90b 1323
371810d1 1324 output = check_output('wg show wg99 listen-port')
84d32bf5 1325 self.assertEqual(output, '51820')
371810d1 1326 output = check_output('wg show wg99 fwmark')
84d32bf5
YW
1327 self.assertEqual(output, '0x4d2')
1328 output = check_output('wg show wg99 private-key')
1329 self.assertEqual(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
371810d1 1330 output = check_output('wg show wg99 allowed-ips')
84d32bf5
YW
1331 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t192.168.124.3/32', output)
1332 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t192.168.124.2/32', output)
1333 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128', output)
1334 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48', output)
371810d1 1335 output = check_output('wg show wg99 persistent-keepalive')
84d32bf5
YW
1336 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\toff', output)
1337 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\toff', output)
1338 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\toff', output)
1339 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20', output)
371810d1 1340 output = check_output('wg show wg99 endpoints')
84d32bf5
YW
1341 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t(none)', output)
1342 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t(none)', output)
1343 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\t(none)', output)
1344 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820', output)
371810d1 1345 output = check_output('wg show wg99 preshared-keys')
84d32bf5
YW
1346 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t6Fsg8XN0DE6aPQgAX4r2oazEYJOGqyHUz3QRH/jCB+I=', output)
1347 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\tit7nd33chCT/tKT2ZZWfYyp43Zs+6oif72hexnSNMqA=', output)
1348 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tcPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=', output)
1349 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\tIIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=', output)
7a3bc5a8 1350
371810d1 1351 output = check_output('wg show wg98 private-key')
84d32bf5 1352 self.assertEqual(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
da44fb8a 1353
da3509f0 1354 output = check_output('wg show wg97 listen-port')
84d32bf5 1355 self.assertEqual(output, '51821')
da3509f0 1356 output = check_output('wg show wg97 fwmark')
84d32bf5 1357 self.assertEqual(output, '0x4d3')
da3509f0 1358
1f0e3109 1359 def test_geneve(self):
ec38833c 1360 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1361 start_networkd()
1f0e3109 1362
e2aea43f 1363 self.wait_online(['geneve99:degraded'])
1f0e3109 1364
371810d1 1365 output = check_output('ip -d link show geneve99')
14ecd604 1366 print(output)
06895a1d
YW
1367 self.assertRegex(output, '192.168.22.1')
1368 self.assertRegex(output, '6082')
1369 self.assertRegex(output, 'udpcsum')
1370 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1371
1372 def test_ipip_tunnel(self):
ec38833c
ZJS
1373 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1374 '25-ipip-tunnel.netdev', '25-tunnel.network',
1375 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1376 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1377 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1378 start_networkd()
e2aea43f 1379 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1380
371810d1 1381 output = check_output('ip -d link show ipiptun99')
6a97a864 1382 print(output)
426654d7 1383 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1384 output = check_output('ip -d link show ipiptun98')
6a97a864 1385 print(output)
426654d7 1386 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1387 output = check_output('ip -d link show ipiptun97')
6a97a864 1388 print(output)
426654d7 1389 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1390 output = check_output('ip -d link show ipiptun96')
1391 print(output)
426654d7 1392 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1393
1394 def test_gre_tunnel(self):
ec38833c
ZJS
1395 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1396 '25-gre-tunnel.netdev', '25-tunnel.network',
1397 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1398 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1399 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1400 start_networkd()
e2aea43f 1401 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1402
371810d1 1403 output = check_output('ip -d link show gretun99')
6a97a864
YW
1404 print(output)
1405 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1406 self.assertRegex(output, 'ikey 1.2.3.103')
1407 self.assertRegex(output, 'okey 1.2.4.103')
1408 self.assertRegex(output, 'iseq')
1409 self.assertRegex(output, 'oseq')
371810d1 1410 output = check_output('ip -d link show gretun98')
6a97a864
YW
1411 print(output)
1412 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1413 self.assertRegex(output, 'ikey 0.0.0.104')
1414 self.assertRegex(output, 'okey 0.0.0.104')
1415 self.assertNotRegex(output, 'iseq')
1416 self.assertNotRegex(output, 'oseq')
371810d1 1417 output = check_output('ip -d link show gretun97')
6a97a864
YW
1418 print(output)
1419 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
1420 self.assertRegex(output, 'ikey 0.0.0.105')
1421 self.assertRegex(output, 'okey 0.0.0.105')
1422 self.assertNotRegex(output, 'iseq')
1423 self.assertNotRegex(output, 'oseq')
42a29fcb
YW
1424 output = check_output('ip -d link show gretun96')
1425 print(output)
1426 self.assertRegex(output, 'gre remote any local any dev dummy98')
1427 self.assertRegex(output, 'ikey 0.0.0.106')
1428 self.assertRegex(output, 'okey 0.0.0.106')
1429 self.assertNotRegex(output, 'iseq')
1430 self.assertNotRegex(output, 'oseq')
6a97a864
YW
1431
1432 def test_ip6gre_tunnel(self):
ec38833c
ZJS
1433 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1434 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1435 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1436 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1437 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
01943d43 1438 start_networkd(5)
6a97a864 1439
17bcf0a0
YW
1440 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1441
e39cc445
YW
1442 self.check_link_exists('dummy98')
1443 self.check_link_exists('ip6gretun99')
1444 self.check_link_exists('ip6gretun98')
1445 self.check_link_exists('ip6gretun97')
42a29fcb 1446 self.check_link_exists('ip6gretun96')
6a97a864 1447
371810d1 1448 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1449 print(output)
1450 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1451 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1452 print(output)
1453 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1454 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1455 print(output)
1456 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1457 output = check_output('ip -d link show ip6gretun96')
1458 print(output)
1459 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1460
11309591 1461 def test_gretap_tunnel(self):
ec38833c
ZJS
1462 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1463 '25-gretap-tunnel.netdev', '25-tunnel.network',
1464 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1465 start_networkd()
e2aea43f 1466 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1467
371810d1 1468 output = check_output('ip -d link show gretap99')
6a97a864
YW
1469 print(output)
1470 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1471 self.assertRegex(output, 'ikey 0.0.0.106')
1472 self.assertRegex(output, 'okey 0.0.0.106')
1473 self.assertRegex(output, 'iseq')
1474 self.assertRegex(output, 'oseq')
371810d1 1475 output = check_output('ip -d link show gretap98')
6a97a864
YW
1476 print(output)
1477 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1478 self.assertRegex(output, 'ikey 0.0.0.107')
1479 self.assertRegex(output, 'okey 0.0.0.107')
1480 self.assertRegex(output, 'iseq')
1481 self.assertRegex(output, 'oseq')
1f0e3109
SS
1482
1483 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
1484 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1485 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1486 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1487 start_networkd()
e2aea43f 1488 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1489
371810d1 1490 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1491 print(output)
1492 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1493 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1494 print(output)
1495 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1496
1497 def test_vti_tunnel(self):
ec38833c
ZJS
1498 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1499 '25-vti-tunnel.netdev', '25-tunnel.network',
1500 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1501 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1502 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1503 start_networkd()
e2aea43f 1504 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1505
371810d1 1506 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1507 print(output)
1508 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1509 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1510 print(output)
1511 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1512 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1513 print(output)
1514 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1515 output = check_output('ip -d link show vtitun96')
1516 print(output)
1517 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1518
1519 def test_vti6_tunnel(self):
ec38833c
ZJS
1520 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1521 '25-vti6-tunnel.netdev', '25-tunnel.network',
1522 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1523 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1524 start_networkd()
e2aea43f 1525 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1526
371810d1 1527 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1528 print(output)
1529 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1530 output = check_output('ip -d link show vti6tun98')
6a97a864 1531 print(output)
426654d7 1532 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1533 output = check_output('ip -d link show vti6tun97')
6a97a864 1534 print(output)
426654d7 1535 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1536
1537 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
1538 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1539 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1540 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1541 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1542 start_networkd()
e2aea43f 1543 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 1544
371810d1 1545 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
1546 print(output)
1547 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1548 output = check_output('ip -d link show ip6tnl98')
6a97a864 1549 print(output)
426654d7 1550 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1551 output = check_output('ip -d link show ip6tnl97')
6a97a864 1552 print(output)
426654d7 1553 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1554
1555 def test_sit_tunnel(self):
ec38833c
ZJS
1556 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1557 '25-sit-tunnel.netdev', '25-tunnel.network',
1558 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1559 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1560 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1561 start_networkd()
e2aea43f 1562 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1563
371810d1 1564 output = check_output('ip -d link show sittun99')
6a97a864 1565 print(output)
426654d7 1566 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1567 output = check_output('ip -d link show sittun98')
6a97a864 1568 print(output)
426654d7 1569 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1570 output = check_output('ip -d link show sittun97')
6a97a864 1571 print(output)
426654d7 1572 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1573 output = check_output('ip -d link show sittun96')
1574 print(output)
426654d7 1575 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1576
d0e728b6 1577 def test_isatap_tunnel(self):
ec38833c
ZJS
1578 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1579 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1580 start_networkd()
e2aea43f 1581 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1582
371810d1 1583 output = check_output('ip -d link show isataptun99')
14ecd604 1584 print(output)
d0e728b6
SS
1585 self.assertRegex(output, "isatap ")
1586
d29dc4f1 1587 def test_6rd_tunnel(self):
ec38833c
ZJS
1588 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1589 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1590 start_networkd()
e2aea43f 1591 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1592
371810d1 1593 output = check_output('ip -d link show sittun99')
6a97a864
YW
1594 print(output)
1595 self.assertRegex(output, '6rd-prefix 2602::/24')
1596
7bea7f9b 1597 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1598 def test_erspan_tunnel(self):
ec38833c
ZJS
1599 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1600 '25-erspan-tunnel.netdev', '25-tunnel.network',
1601 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1602 start_networkd()
e2aea43f 1603 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1604
371810d1 1605 output = check_output('ip -d link show erspan99')
6a97a864
YW
1606 print(output)
1607 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1608 self.assertRegex(output, 'ikey 0.0.0.101')
1609 self.assertRegex(output, 'okey 0.0.0.101')
1610 self.assertRegex(output, 'iseq')
1611 self.assertRegex(output, 'oseq')
371810d1 1612 output = check_output('ip -d link show erspan98')
2266864b 1613 print(output)
6a97a864
YW
1614 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1615 self.assertRegex(output, '102')
38f4bb44
YW
1616 self.assertRegex(output, 'ikey 0.0.0.102')
1617 self.assertRegex(output, 'okey 0.0.0.102')
1618 self.assertRegex(output, 'iseq')
1619 self.assertRegex(output, 'oseq')
2266864b 1620
1f0e3109 1621 def test_tunnel_independent(self):
ec38833c 1622 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1623 start_networkd()
e40a58b5 1624
e2aea43f 1625 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1626
95082dbe
YW
1627 def test_tunnel_independent_loopback(self):
1628 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1629 start_networkd()
1630
e2aea43f 1631 self.wait_online(['ipiptun99:carrier'])
95082dbe 1632
e64dc406
YW
1633 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1634 def test_xfrm(self):
1635 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1636 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1637 start_networkd()
1638
e2aea43f 1639 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
e64dc406
YW
1640
1641 output = check_output('ip link show dev xfrm99')
1642 print(output)
1643
1644 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1645 def test_xfrm_independent(self):
1646 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1647 start_networkd()
1648
e2aea43f 1649 self.wait_online(['xfrm99:degraded'])
e64dc406 1650
4b6a6d1e
YW
1651 @expectedFailureIfModuleIsNotAvailable('fou')
1652 def test_fou(self):
1653 # The following redundant check is necessary for CentOS CI.
1654 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1655 self.assertTrue(is_module_available('fou'))
1656
ec38833c
ZJS
1657 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1658 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1659 '25-fou-gre.netdev', '25-fou-gretap.netdev')
2cf6fdff 1660 start_networkd()
4b6a6d1e 1661
e2aea43f 1662 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1663
371810d1 1664 output = check_output('ip fou show')
4b6a6d1e
YW
1665 print(output)
1666 self.assertRegex(output, 'port 55555 ipproto 4')
1667 self.assertRegex(output, 'port 55556 ipproto 47')
1668
371810d1 1669 output = check_output('ip -d link show ipiptun96')
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 sittun96')
4b6a6d1e
YW
1673 print(output)
1674 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1675 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1676 print(output)
1677 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1678 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1679 print(output)
1680 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1681
1f0e3109 1682 def test_vxlan(self):
ec38833c 1683 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
cca07d91 1684 '25-vxlan-ipv6.netdev', 'vxlan-ipv6.network',
039971ea 1685 '25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network',
ec38833c 1686 '11-dummy.netdev', 'vxlan-test1.network')
2cf6fdff 1687 start_networkd()
1f0e3109 1688
cca07d91 1689 self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded'])
1f0e3109 1690
371810d1 1691 output = check_output('ip -d link show vxlan99')
14ecd604 1692 print(output)
cca07d91
YW
1693 self.assertIn('999', output)
1694 self.assertIn('5555', output)
1695 self.assertIn('l2miss', output)
1696 self.assertIn('l3miss', output)
1697 self.assertIn('udpcsum', output)
1698 self.assertIn('udp6zerocsumtx', output)
1699 self.assertIn('udp6zerocsumrx', output)
1700 self.assertIn('remcsumtx', output)
1701 self.assertIn('remcsumrx', output)
1702 self.assertIn('gbp', output)
1f0e3109 1703
371810d1 1704 output = check_output('bridge fdb show dev vxlan99')
1c862fe0 1705 print(output)
cca07d91
YW
1706 self.assertIn('00:11:22:33:44:55 dst 10.0.0.5 self permanent', output)
1707 self.assertIn('00:11:22:33:44:66 dst 10.0.0.6 self permanent', output)
1708 self.assertIn('00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent', output)
1c862fe0 1709
fc79e6ff 1710 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb 1711 print(output)
cca07d91
YW
1712 self.assertIn('VNI: 999', output)
1713 self.assertIn('Destination Port: 5555', output)
1714 self.assertIn('Underlying Device: test1', output)
1715
1716 output = check_output('bridge fdb show dev vxlan97')
1717 print(output)
1718 self.assertIn('00:00:00:00:00:00 dst fe80::23b:d2ff:fe95:967f via test1 self permanent', output)
1719 self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output)
1720 self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output)
36bc2ffb 1721
02849d8b 1722 def test_macsec(self):
ec38833c
ZJS
1723 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1724 'macsec.network', '12-dummy.netdev')
2cf6fdff 1725 start_networkd()
02849d8b 1726
e2aea43f 1727 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1728
371810d1 1729 output = check_output('ip -d link show macsec99')
02849d8b
YW
1730 print(output)
1731 self.assertRegex(output, 'macsec99@dummy98')
1732 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1733 self.assertRegex(output, 'encrypt on')
1734
371810d1 1735 output = check_output('ip macsec show macsec99')
02849d8b
YW
1736 print(output)
1737 self.assertRegex(output, 'encrypt on')
1738 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1739 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1740 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1741 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1742 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1743 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1744 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1745 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1746 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1747 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1748 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1749
811f33d0 1750 def test_nlmon(self):
ec38833c 1751 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1752 start_networkd()
811f33d0 1753
e2aea43f 1754 self.wait_online(['nlmon99:carrier'])
02849d8b 1755
b076d5d7
YW
1756 @expectedFailureIfModuleIsNotAvailable('ifb')
1757 def test_ifb(self):
1758 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1759 start_networkd()
1760
1761 self.wait_online(['ifb99:degraded'])
1762
cff83db9
YW
1763class NetworkdL2TPTests(unittest.TestCase, Utilities):
1764
1765 links =[
1766 'l2tp-ses1',
1767 'l2tp-ses2',
1768 'l2tp-ses3',
1769 'l2tp-ses4',
1770 'test1']
1771
1772 units = [
1773 '11-dummy.netdev',
1774 '25-l2tp-dummy.network',
e2aea43f 1775 '25-l2tp.network',
cff83db9
YW
1776 '25-l2tp-ip.netdev',
1777 '25-l2tp-udp.netdev']
1778
1779 l2tp_tunnel_ids = [ '10' ]
1780
1781 def setUp(self):
ad78d7b0 1782 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1783 remove_links(self.links)
aaae5713 1784 stop_networkd(show_logs=False)
cff83db9
YW
1785
1786 def tearDown(self):
ad78d7b0 1787 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1788 remove_links(self.links)
1789 remove_unit_from_networkd_path(self.units)
aaae5713 1790 stop_networkd(show_logs=True)
cff83db9
YW
1791
1792 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1793 def test_l2tp_udp(self):
e2aea43f
YW
1794 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1795 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 1796 start_networkd()
cff83db9 1797
e2aea43f 1798 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 1799
371810d1 1800 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1801 print(output)
1802 self.assertRegex(output, "Tunnel 10, encap UDP")
1803 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1804 self.assertRegex(output, "Peer tunnel 11")
1805 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1806 self.assertRegex(output, "UDP checksum: enabled")
1807
371810d1 1808 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1809 print(output)
1810 self.assertRegex(output, "Session 15 in tunnel 10")
1811 self.assertRegex(output, "Peer session 16, tunnel 11")
1812 self.assertRegex(output, "interface name: l2tp-ses1")
1813
371810d1 1814 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1815 print(output)
1816 self.assertRegex(output, "Session 17 in tunnel 10")
1817 self.assertRegex(output, "Peer session 18, tunnel 11")
1818 self.assertRegex(output, "interface name: l2tp-ses2")
1819
1820 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1821 def test_l2tp_ip(self):
e2aea43f
YW
1822 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1823 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 1824 start_networkd()
cff83db9 1825
e2aea43f 1826 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 1827
371810d1 1828 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1829 print(output)
1830 self.assertRegex(output, "Tunnel 10, encap IP")
1831 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1832 self.assertRegex(output, "Peer tunnel 12")
1833
371810d1 1834 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
1835 print(output)
1836 self.assertRegex(output, "Session 25 in tunnel 10")
1837 self.assertRegex(output, "Peer session 26, tunnel 12")
1838 self.assertRegex(output, "interface name: l2tp-ses3")
1839
371810d1 1840 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
1841 print(output)
1842 self.assertRegex(output, "Session 27 in tunnel 10")
1843 self.assertRegex(output, "Peer session 28, tunnel 12")
1844 self.assertRegex(output, "interface name: l2tp-ses4")
1845
be68c2c9 1846class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1847 links = [
1848 'bond199',
1849 'dummy98',
cd65d067 1850 'dummy99',
74761cf3 1851 'gretun97',
fb2ba330 1852 'ip6gretun97',
086bcf5d 1853 'test1',
70448bb1 1854 'veth-peer',
086bcf5d 1855 'veth99',
40afe491 1856 'vrf99',
74761cf3 1857 ]
09ea6724
YW
1858
1859 units = [
1860 '11-dummy.netdev',
1861 '12-dummy.netdev',
61764fe4 1862 '12-dummy.network',
09ea6724 1863 '23-active-slave.network',
1e498853 1864 '24-keep-configuration-static.network',
fdcd1ec5 1865 '24-search-domain.network',
44924431 1866 '25-address-ipv4acd-veth99.network',
09ea6724 1867 '25-address-link-section.network',
21266e60 1868 '25-address-peer-ipv4.network',
b8102725 1869 '25-address-static.network',
2236d75d 1870 '25-activation-policy.network',
cd65d067 1871 '25-bind-carrier.network',
09ea6724
YW
1872 '25-bond-active-backup-slave.netdev',
1873 '25-fibrule-invert.network',
1874 '25-fibrule-port-range.network',
6be8e78e 1875 '25-fibrule-uidrange.network',
74761cf3 1876 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1877 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1878 '25-ipv6-address-label-section.network',
cff0cadc 1879 '25-ipv6-proxy-ndp.network',
ef3c8a92
YW
1880 '25-link-local-addressing-no.network',
1881 '25-link-local-addressing-yes.network',
1882 '25-link-section-unmanaged.network',
e4a71bf3 1883 '25-neighbor-section.network',
d1bdafd2 1884 '25-neighbor-next.network',
fb2ba330 1885 '25-neighbor-ipv6.network',
74761cf3
YW
1886 '25-neighbor-ip-dummy.network',
1887 '25-neighbor-ip.network',
9c8f90d0 1888 '25-nexthop-dummy.network',
9947c7ba 1889 '25-nexthop-nothing.network',
086bcf5d 1890 '25-nexthop.network',
f6c6af38 1891 '25-qdisc-cake.network',
f1de1eb3 1892 '25-qdisc-clsact-and-htb.network',
557fa421 1893 '25-qdisc-drr.network',
b753e835 1894 '25-qdisc-ets.network',
1578266b 1895 '25-qdisc-fq_pie.network',
970ab1fc 1896 '25-qdisc-hhf.network',
ab9dc1db 1897 '25-qdisc-ingress-netem-compat.network',
be94e591 1898 '25-qdisc-pie.network',
891ff963 1899 '25-qdisc-qfq.network',
c9d223e8
YW
1900 '25-prefix-route-with-vrf.network',
1901 '25-prefix-route-without-vrf.network',
20ca06a6 1902 '25-route-ipv6-src.network',
0ef830cf 1903 '25-route-static.network',
297f9d86 1904 '25-route-via-ipv6.network',
40afe491 1905 '25-route-vrf.network',
0b1cd3e2
WKI
1906 '25-gateway-static.network',
1907 '25-gateway-next-static.network',
3d2c2692 1908 '25-sriov.network',
4da33154 1909 '25-sysctl-disable-ipv6.network',
09ea6724 1910 '25-sysctl.network',
9bacf431 1911 '25-test1.network',
086bcf5d
YW
1912 '25-veth-peer.network',
1913 '25-veth.netdev',
40afe491 1914 '25-vrf.netdev',
c9d223e8 1915 '25-vrf.network',
7b3770a7 1916 '26-link-local-addressing-ipv6.network',
70448bb1
L
1917 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network',
1918 'dhcp-server-with-ipv6-prefix.network',
1919 'ipv6ra-prefix-client-with-static-ipv4-address.network',
1920 'ipv6-prefix-with-delay.network',
b677774d 1921 'routing-policy-rule-dummy98.network',
87adeabf 1922 'routing-policy-rule-test1.network',
49ff3f34
YW
1923 'routing-policy-rule-reconfigure1.network',
1924 'routing-policy-rule-reconfigure2.network',
87adeabf 1925 ]
1f0e3109 1926
1d26d4cd
YW
1927 networkd_conf_dropins = [
1928 'networkd-manage-foreign-routes-no.conf',
1929 ]
1930
2e8a32af 1931 routing_policy_rule_tables = ['7', '8', '9', '10', '1011']
5f68a6a4 1932 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1933
1f0e3109 1934 def setUp(self):
69a91c70 1935 remove_blackhole_nexthops()
ec38833c
ZJS
1936 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1937 remove_routes(self.routes)
1938 remove_links(self.links)
aaae5713 1939 stop_networkd(show_logs=False)
44924431 1940 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109
SS
1941
1942 def tearDown(self):
69a91c70 1943 remove_blackhole_nexthops()
ec38833c
ZJS
1944 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1945 remove_routes(self.routes)
1946 remove_links(self.links)
1947 remove_unit_from_networkd_path(self.units)
1d26d4cd 1948 remove_networkd_conf_dropin(self.networkd_conf_dropins)
aaae5713 1949 stop_networkd(show_logs=True)
44924431 1950 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109 1951
b8102725 1952 def test_address_static(self):
ec38833c 1953 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 1954 start_networkd()
b8102725 1955
e2aea43f 1956 self.wait_online(['dummy98:routable'])
b8102725 1957
371810d1 1958 output = check_output('ip -4 address show dev dummy98')
b8102725 1959 print(output)
4a704501
YW
1960 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
1961 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
1962 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
1963 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
045db4fa 1964 self.assertIn('inet 10.8.8.1/16 scope global dummy98', output)
b8102725 1965
766f8f38
YW
1966 # test for ENOBUFS issue #17012
1967 for i in range(1,254):
4a704501 1968 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
766f8f38 1969
b8102725 1970 # invalid sections
4a704501
YW
1971 self.assertNotIn('10.10.0.1/16', output)
1972 self.assertNotIn('10.10.0.2/16', output)
b8102725 1973
371810d1 1974 output = check_output('ip -4 address show dev dummy98 label 32')
4a704501 1975 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
b8102725 1976
371810d1 1977 output = check_output('ip -4 address show dev dummy98 label 33')
4a704501 1978 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
b8102725 1979
371810d1 1980 output = check_output('ip -4 address show dev dummy98 label 34')
4a704501 1981 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
b8102725 1982
371810d1 1983 output = check_output('ip -4 address show dev dummy98 label 35')
4a704501 1984 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
b8102725 1985
371810d1 1986 output = check_output('ip -6 address show dev dummy98')
b8102725 1987 print(output)
4a704501
YW
1988 self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
1989 self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
1990 self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
1991 self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
1992 self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
1993 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
1994 self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
b8102725 1995
766f8f38
YW
1996 restart_networkd()
1997 self.wait_online(['dummy98:routable'])
1998
1999 # test for ENOBUFS issue #17012
2000 output = check_output('ip -4 address show dev dummy98')
2001 for i in range(1,254):
4a704501 2002 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
e4783b54 2003
44924431
YW
2004 def test_address_ipv4acd(self):
2005 check_output('ip netns add ns99')
2006 check_output('ip link add veth99 type veth peer veth-peer')
2007 check_output('ip link set veth-peer netns ns99')
2008 check_output('ip link set veth99 up')
2009 check_output('ip netns exec ns99 ip link set veth-peer up')
2010 check_output('ip netns exec ns99 ip address add 192.168.100.10/24 dev veth-peer')
2011
2012 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network', dropins=False)
dc7d3c5f 2013 start_networkd()
44924431 2014 self.wait_online(['veth99:routable'])
dc7d3c5f
YW
2015
2016 output = check_output('ip -4 address show dev veth99')
2017 print(output)
44924431
YW
2018 self.assertNotIn('192.168.100.10/24', output)
2019 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2020
44924431
YW
2021 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network.d/conflict-address.conf')
2022 run(*networkctl_cmd, 'reload', env=env)
2023 time.sleep(1)
2024 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
2025 self.assertTrue(rc == 1)
2026
2027 output = check_output('ip -4 address show dev veth99')
dc7d3c5f 2028 print(output)
44924431
YW
2029 self.assertNotIn('192.168.100.10/24', output)
2030 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2031
21266e60
YW
2032 def test_address_peer_ipv4(self):
2033 # test for issue #17304
2034 copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev')
2035
2036 for trial in range(2):
2037 if trial == 0:
2038 start_networkd()
2039 else:
2040 restart_networkd()
2041
2042 self.wait_online(['dummy98:routable'])
2043
2044 output = check_output('ip -4 address show dev dummy98')
2045 self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output)
2046
c9d223e8
YW
2047 @expectedFailureIfModuleIsNotAvailable('vrf')
2048 def test_prefix_route(self):
2049 copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
2050 '25-prefix-route-without-vrf.network', '11-dummy.netdev',
2051 '25-vrf.netdev', '25-vrf.network')
2052 for trial in range(2):
2053 if trial == 0:
2054 start_networkd()
2055 else:
2056 restart_networkd(3)
2057
2058 self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
2059
2060 output = check_output('ip route show table 42 dev dummy98')
2061 print('### ip route show table 42 dev dummy98')
2062 print(output)
2063 self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1')
2064 self.assertRegex(output, 'broadcast 10.20.33.0 proto kernel scope link src 10.20.33.1')
2065 self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1')
2066 self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1')
2067 self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1')
2068 self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1')
2069 self.assertRegex(output, 'broadcast 10.20.55.0 proto kernel scope link src 10.20.55.1')
2070 self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1')
2071 self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1')
2072 output = check_output('ip -6 route show table 42 dev dummy98')
2073 print('### ip -6 route show table 42 dev dummy98')
2074 print(output)
2075 if trial == 0:
2076 # Kernel's bug?
2077 self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium')
2078 #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium')
2079 self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium')
2080 self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium')
2081 self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
2082 self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
2083 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
beb75dd3 2084 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8
YW
2085
2086 print()
2087
2088 output = check_output('ip route show dev test1')
2089 print('### ip route show dev test1')
2090 print(output)
2091 self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1')
2092 output = check_output('ip route show table local dev test1')
2093 print('### ip route show table local dev test1')
2094 print(output)
2095 self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1')
2096 self.assertRegex(output, 'broadcast 10.21.33.0 proto kernel scope link src 10.21.33.1')
2097 self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1')
2098 self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1')
2099 self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1')
2100 self.assertRegex(output, 'broadcast 10.21.55.0 proto kernel scope link src 10.21.55.1')
2101 self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1')
2102 self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1')
2103 output = check_output('ip -6 route show dev test1')
2104 print('### ip -6 route show dev test1')
2105 print(output)
2106 self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium')
2107 self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium')
2108 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
2109 output = check_output('ip -6 route show table local dev test1')
2110 print('### ip -6 route show table local dev test1')
2111 print(output)
2112 self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium')
2113 self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
2114 self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
2115 self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
beb75dd3 2116 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8 2117
1f0e3109 2118 def test_configure_without_carrier(self):
9bacf431 2119 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2cf6fdff 2120 start_networkd()
9bacf431
DS
2121 self.wait_operstate('test1', 'off', '')
2122 check_output('ip link set dev test1 up carrier off')
2123
2124 copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
2125 restart_networkd()
2126 self.wait_online(['test1:no-carrier'])
2127
2128 carrier_map = {'on': '1', 'off': '0'}
2129 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2130 for carrier in ['off', 'on', 'off']:
2131 with self.subTest(carrier=carrier):
2132 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2133 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2134 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2135
2136 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2137 print(output)
2138 self.assertRegex(output, '192.168.0.15')
2139 self.assertRegex(output, '192.168.0.1')
2140 self.assertRegex(output, routable_map[carrier])
e40a58b5 2141
9bacf431
DS
2142 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
2143 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2144 start_networkd()
2145 self.wait_operstate('test1', 'off', '')
2146 check_output('ip link set dev test1 up carrier off')
2147
2148 copy_unit_to_networkd_unit_path('25-test1.network')
2149 restart_networkd()
2150 self.wait_online(['test1:no-carrier'])
2151
2152 carrier_map = {'on': '1', 'off': '0'}
2153 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2154 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
2155 with self.subTest(carrier=carrier, have_config=have_config):
2156 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2157 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2158 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2159
2160 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2161 print(output)
2162 if have_config:
2163 self.assertRegex(output, '192.168.0.15')
2164 self.assertRegex(output, '192.168.0.1')
2165 else:
2166 self.assertNotRegex(output, '192.168.0.15')
2167 self.assertNotRegex(output, '192.168.0.1')
2168 self.assertRegex(output, routable_map[carrier])
1f0e3109 2169
1f0e3109 2170 def test_routing_policy_rule(self):
ec38833c 2171 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 2172 start_networkd()
e2aea43f 2173 self.wait_online(['test1:degraded'])
e40a58b5 2174
65c24cd0 2175 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 2176 print(output)
65c24cd0 2177 self.assertRegex(output, '111:')
1f0e3109 2178 self.assertRegex(output, 'from 192.168.100.18')
426654d7 2179 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
2180 self.assertRegex(output, 'iif test1')
2181 self.assertRegex(output, 'oif test1')
2182 self.assertRegex(output, 'lookup 7')
2183
65c24cd0
YW
2184 output = check_output('ip rule list iif test1 priority 101')
2185 print(output)
2186 self.assertRegex(output, '101:')
2187 self.assertRegex(output, 'from all')
2188 self.assertRegex(output, 'iif test1')
2189 self.assertRegex(output, 'lookup 9')
2190
2191 output = check_output('ip -6 rule list iif test1 priority 100')
2192 print(output)
2193 self.assertRegex(output, '100:')
2194 self.assertRegex(output, 'from all')
2195 self.assertRegex(output, 'iif test1')
2196 self.assertRegex(output, 'lookup 8')
2197
2e8a32af
HV
2198 output = check_output('ip rule list iif test1 priority 102')
2199 print(output)
2200 self.assertRegex(output, '102:')
2201 self.assertRegex(output, 'from 0.0.0.0/8')
2202 self.assertRegex(output, 'iif test1')
2203 self.assertRegex(output, 'lookup 10')
2204
b677774d 2205 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
2206 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
2207 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 2208
b677774d
YW
2209 for trial in range(3):
2210 # Remove state files only first time
e2aea43f
YW
2211 start_networkd(3)
2212 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 2213 time.sleep(1)
b677774d 2214
371810d1 2215 output = check_output('ip rule list table 7')
b677774d 2216 print(output)
426654d7 2217 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 2218
371810d1 2219 output = check_output('ip rule list table 8')
b677774d 2220 print(output)
426654d7 2221 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 2222
aaae5713
YW
2223 stop_networkd(remove_state_files=False)
2224
87adeabf 2225 def test_routing_policy_rule_reconfigure(self):
49ff3f34 2226 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
87adeabf
YW
2227 start_networkd()
2228 self.wait_online(['test1:degraded'])
2229
2230 output = check_output('ip rule list table 1011')
2231 print(output)
49ff3f34
YW
2232 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2233 self.assertIn('10112: from all oif test1 lookup 1011', output)
2234 self.assertIn('10113: from all iif test1 lookup 1011', output)
2235 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2236
2237 output = check_output('ip -6 rule list table 1011')
2238 print(output)
2239 self.assertIn('10112: from all oif test1 lookup 1011', output)
2240
2241 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
2242 run(*networkctl_cmd, 'reload', env=env)
2243 time.sleep(1)
2244 self.wait_online(['test1:degraded'])
2245
2246 output = check_output('ip rule list table 1011')
2247 print(output)
2248 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2249 self.assertIn('10112: from all oif test1 lookup 1011', output)
2250 self.assertIn('10113: from all iif test1 lookup 1011', output)
2251 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2252
2253 output = check_output('ip -6 rule list table 1011')
2254 print(output)
2255 self.assertNotIn('10112: from all oif test1 lookup 1011', output)
2256 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf
YW
2257
2258 run('ip rule delete priority 10111')
2259 run('ip rule delete priority 10112')
2260 run('ip rule delete priority 10113')
2261 run('ip rule delete priority 10114')
49ff3f34 2262 run('ip -6 rule delete priority 10113')
87adeabf
YW
2263
2264 output = check_output('ip rule list table 1011')
2265 print(output)
2266 self.assertEqual(output, '')
2267
49ff3f34
YW
2268 output = check_output('ip -6 rule list table 1011')
2269 print(output)
2270 self.assertEqual(output, '')
87adeabf 2271
49ff3f34 2272 run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
87adeabf
YW
2273 self.wait_online(['test1:degraded'])
2274
2275 output = check_output('ip rule list table 1011')
2276 print(output)
49ff3f34
YW
2277 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2278 self.assertIn('10112: from all oif test1 lookup 1011', output)
2279 self.assertIn('10113: from all iif test1 lookup 1011', output)
2280 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2281
2282 output = check_output('ip -6 rule list table 1011')
2283 print(output)
2284 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf 2285
d586a2c3 2286 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 2287 def test_routing_policy_rule_port_range(self):
ec38833c 2288 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 2289 start_networkd()
e2aea43f 2290 self.wait_online(['test1:degraded'])
e40a58b5 2291
371810d1 2292 output = check_output('ip rule')
926062f0
SS
2293 print(output)
2294 self.assertRegex(output, '111')
2295 self.assertRegex(output, 'from 192.168.100.18')
2296 self.assertRegex(output, '1123-1150')
2297 self.assertRegex(output, '3224-3290')
2298 self.assertRegex(output, 'tcp')
2299 self.assertRegex(output, 'lookup 7')
1f0e3109 2300
d586a2c3 2301 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 2302 def test_routing_policy_rule_invert(self):
ec38833c 2303 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 2304 start_networkd()
e2aea43f 2305 self.wait_online(['test1:degraded'])
e40a58b5 2306
371810d1 2307 output = check_output('ip rule')
efecf9cd 2308 print(output)
efecf9cd
SS
2309 self.assertRegex(output, '111')
2310 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
2311 self.assertRegex(output, 'tcp')
2312 self.assertRegex(output, 'lookup 7')
2313
6be8e78e
YW
2314 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
2315 def test_routing_policy_rule_uidrange(self):
2316 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
2317 start_networkd()
2318 self.wait_online(['test1:degraded'])
2319
2320 output = check_output('ip rule')
2321 print(output)
2322 self.assertRegex(output, '111')
2323 self.assertRegex(output, 'from 192.168.100.18')
2324 self.assertRegex(output, 'lookup 7')
2325 self.assertRegex(output, 'uidrange 100-200')
2326
1d26d4cd
YW
2327 def _test_route_static(self, manage_foreign_routes):
2328 if not manage_foreign_routes:
2329 copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf')
2330
ec38833c 2331 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 2332 start_networkd()
e2aea43f
YW
2333 self.wait_online(['dummy98:routable'])
2334
fc79e6ff 2335 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 2336 print(output)
0d34228f 2337
6d60f9db 2338 print('### ip -6 route show dev dummy98')
371810d1 2339 output = check_output('ip -6 route show dev dummy98')
0d34228f 2340 print(output)
0b5dc249
YW
2341 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
2342 self.assertIn('2001:1234:5:8f63::1 proto kernel', output)
180c5116 2343 self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output)
1f0e3109 2344
d9005dec
YW
2345 print('### ip -6 route show default')
2346 output = check_output('ip -6 route show default')
6d60f9db 2347 print(output)
0b5dc249
YW
2348 self.assertIn('default', output)
2349 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output)
1f0e3109 2350
6d60f9db 2351 print('### ip -4 route show dev dummy98')
371810d1 2352 output = check_output('ip -4 route show dev dummy98')
1f0e3109 2353 print(output)
0b5dc249
YW
2354 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output)
2355 self.assertIn('149.10.124.64 proto static scope link', output)
2356 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output)
2357 self.assertIn('192.168.1.1 proto static initcwnd 20', output)
2358 self.assertIn('192.168.1.2 proto static initrwnd 30', output)
2359 self.assertIn('192.168.1.3 proto static advmss 30', output)
2360 self.assertIn('multicast 149.10.123.4 proto static', output)
1f0e3109 2361
6d60f9db 2362 print('### ip -4 route show dev dummy98 default')
371810d1 2363 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 2364 print(output)
0b5dc249
YW
2365 self.assertIn('default via 149.10.125.65 proto static onlink', output)
2366 self.assertIn('default via 149.10.124.64 proto static', output)
2367 self.assertIn('default proto static', output)
1f0e3109 2368
6d60f9db
YW
2369 print('### ip -4 route show table local dev dummy98')
2370 output = check_output('ip -4 route show table local dev dummy98')
2371 print(output)
0b5dc249
YW
2372 self.assertIn('local 149.10.123.1 proto static scope host', output)
2373 self.assertIn('anycast 149.10.123.2 proto static scope link', output)
2374 self.assertIn('broadcast 149.10.123.3 proto static scope link', output)
6d60f9db
YW
2375
2376 print('### ip route show type blackhole')
371810d1 2377 output = check_output('ip route show type blackhole')
1f0e3109 2378 print(output)
0b5dc249 2379 self.assertIn('blackhole 202.54.1.2 proto static', output)
f5050e48 2380
6d60f9db 2381 print('### ip route show type unreachable')
371810d1 2382 output = check_output('ip route show type unreachable')
f5050e48 2383 print(output)
0b5dc249 2384 self.assertIn('unreachable 202.54.1.3 proto static', output)
f5050e48 2385
6d60f9db 2386 print('### ip route show type prohibit')
371810d1 2387 output = check_output('ip route show type prohibit')
f5050e48 2388 print(output)
0b5dc249 2389 self.assertIn('prohibit 202.54.1.4 proto static', output)
f5050e48 2390
452d86a5
YW
2391 print('### ip -6 route show type blackhole')
2392 output = check_output('ip -6 route show type blackhole')
2393 print(output)
2394 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2395
2396 print('### ip -6 route show type unreachable')
2397 output = check_output('ip -6 route show type unreachable')
2398 print(output)
2399 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2400
2401 print('### ip -6 route show type prohibit')
2402 output = check_output('ip -6 route show type prohibit')
2403 print(output)
2404 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2405
a0ce990e
YW
2406 print('### ip route show 192.168.10.1')
2407 output = check_output('ip route show 192.168.10.1')
2408 print(output)
0b5dc249
YW
2409 self.assertIn('192.168.10.1 proto static', output)
2410 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output)
2411 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output)
a0ce990e
YW
2412
2413 print('### ip route show 192.168.10.2')
2414 output = check_output('ip route show 192.168.10.2')
2415 print(output)
2416 # old ip command does not show IPv6 gateways...
0b5dc249
YW
2417 self.assertIn('192.168.10.2 proto static', output)
2418 self.assertIn('nexthop', output)
2419 self.assertIn('dev dummy98 weight 10', output)
2420 self.assertIn('dev dummy98 weight 5', output)
a0ce990e
YW
2421
2422 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2423 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2424 print(output)
2425 # old ip command does not show 'nexthop' keyword and weight...
0b5dc249
YW
2426 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output)
2427 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
2428 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
a0ce990e 2429
43d4bc9f
YW
2430 copy_unit_to_networkd_unit_path('25-address-static.network')
2431 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2432 time.sleep(1)
43d4bc9f
YW
2433 self.wait_online(['dummy98:routable'])
2434
2435 # check all routes managed by Manager are removed
2436 print('### ip route show type blackhole')
2437 output = check_output('ip route show type blackhole')
2438 print(output)
2439 self.assertEqual(output, '')
2440
2441 print('### ip route show type unreachable')
2442 output = check_output('ip route show type unreachable')
2443 print(output)
2444 self.assertEqual(output, '')
2445
2446 print('### ip route show type prohibit')
2447 output = check_output('ip route show type prohibit')
2448 print(output)
2449 self.assertEqual(output, '')
2450
452d86a5
YW
2451 print('### ip -6 route show type blackhole')
2452 output = check_output('ip -6 route show type blackhole')
2453 print(output)
2454 self.assertEqual(output, '')
2455
2456 print('### ip -6 route show type unreachable')
2457 output = check_output('ip -6 route show type unreachable')
2458 print(output)
2459 self.assertEqual(output, '')
2460
2461 print('### ip -6 route show type prohibit')
2462 output = check_output('ip -6 route show type prohibit')
2463 print(output)
2464 self.assertEqual(output, '')
2465
43d4bc9f
YW
2466 remove_unit_from_networkd_path(['25-address-static.network'])
2467 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2468 time.sleep(1)
43d4bc9f
YW
2469 self.wait_online(['dummy98:routable'])
2470
2471 # check all routes managed by Manager are reconfigured
2472 print('### ip route show type blackhole')
2473 output = check_output('ip route show type blackhole')
2474 print(output)
0b5dc249 2475 self.assertIn('blackhole 202.54.1.2 proto static', output)
43d4bc9f
YW
2476
2477 print('### ip route show type unreachable')
2478 output = check_output('ip route show type unreachable')
2479 print(output)
0b5dc249 2480 self.assertIn('unreachable 202.54.1.3 proto static', output)
43d4bc9f
YW
2481
2482 print('### ip route show type prohibit')
2483 output = check_output('ip route show type prohibit')
2484 print(output)
0b5dc249 2485 self.assertIn('prohibit 202.54.1.4 proto static', output)
43d4bc9f 2486
452d86a5
YW
2487 print('### ip -6 route show type blackhole')
2488 output = check_output('ip -6 route show type blackhole')
2489 print(output)
2490 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2491
2492 print('### ip -6 route show type unreachable')
2493 output = check_output('ip -6 route show type unreachable')
2494 print(output)
2495 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2496
2497 print('### ip -6 route show type prohibit')
2498 output = check_output('ip -6 route show type prohibit')
2499 print(output)
2500 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2501
43d4bc9f
YW
2502 rc = call("ip link del dummy98")
2503 self.assertEqual(rc, 0)
2504 time.sleep(2)
2505
2506 # check all routes managed by Manager are removed
2507 print('### ip route show type blackhole')
2508 output = check_output('ip route show type blackhole')
2509 print(output)
2510 self.assertEqual(output, '')
2511
2512 print('### ip route show type unreachable')
2513 output = check_output('ip route show type unreachable')
2514 print(output)
2515 self.assertEqual(output, '')
2516
2517 print('### ip route show type prohibit')
2518 output = check_output('ip route show type prohibit')
2519 print(output)
2520 self.assertEqual(output, '')
2521
452d86a5
YW
2522 print('### ip -6 route show type blackhole')
2523 output = check_output('ip -6 route show type blackhole')
2524 print(output)
2525 self.assertEqual(output, '')
2526
2527 print('### ip -6 route show type unreachable')
2528 output = check_output('ip -6 route show type unreachable')
2529 print(output)
2530 self.assertEqual(output, '')
2531
2532 print('### ip -6 route show type prohibit')
2533 output = check_output('ip -6 route show type prohibit')
2534 print(output)
2535 self.assertEqual(output, '')
2536
1d26d4cd
YW
2537 self.tearDown()
2538
2539 def test_route_static(self):
2540 for manage_foreign_routes in [True, False]:
2541 with self.subTest(manage_foreign_routes=manage_foreign_routes):
2542 self._test_route_static(manage_foreign_routes)
2543
297f9d86
YW
2544 @expectedFailureIfRTA_VIAIsNotSupported()
2545 def test_route_via_ipv6(self):
2546 copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
2547 start_networkd()
2548 self.wait_online(['dummy98:routable'])
2549
2550 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2551 print(output)
2552
2553 print('### ip -6 route show dev dummy98')
2554 output = check_output('ip -6 route show dev dummy98')
2555 print(output)
2556 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
2557 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
2558
2559 print('### ip -4 route show dev dummy98')
2560 output = check_output('ip -4 route show dev dummy98')
2561 print(output)
2562 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
2563 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
2564
40afe491
YW
2565 @expectedFailureIfModuleIsNotAvailable('vrf')
2566 def test_route_vrf(self):
2567 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
2568 '25-vrf.netdev', '25-vrf.network')
2569 start_networkd()
2570 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2571
2572 output = check_output('ip route show vrf vrf99')
2573 print(output)
2574 self.assertRegex(output, 'default via 192.168.100.1')
2575
2576 output = check_output('ip route show')
2577 print(output)
2578 self.assertNotRegex(output, 'default via 192.168.100.1')
2579
0b1cd3e2
WKI
2580 def test_gateway_reconfigure(self):
2581 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
2582 start_networkd()
2583 self.wait_online(['dummy98:routable'])
2584 print('### ip -4 route show dev dummy98 default')
2585 output = check_output('ip -4 route show dev dummy98 default')
2586 print(output)
2587 self.assertRegex(output, 'default via 149.10.124.59 proto static')
2588 self.assertNotRegex(output, '149.10.124.60')
2589
2590 remove_unit_from_networkd_path(['25-gateway-static.network'])
2591 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
2592 restart_networkd(3)
2593 self.wait_online(['dummy98:routable'])
2594 print('### ip -4 route show dev dummy98 default')
2595 output = check_output('ip -4 route show dev dummy98 default')
2596 print(output)
2597 self.assertNotRegex(output, '149.10.124.59')
2598 self.assertRegex(output, 'default via 149.10.124.60 proto static')
2599
20ca06a6
DA
2600 def test_ip_route_ipv6_src_route(self):
2601 # a dummy device does not make the addresses go through tentative state, so we
2602 # reuse a bond from an earlier test, which does make the addresses go through
2603 # tentative state, and do our test on that
ec38833c 2604 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 2605 start_networkd()
e2aea43f 2606 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 2607
371810d1 2608 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
2609 print(output)
2610 self.assertRegex(output, 'abcd::/16')
2611 self.assertRegex(output, 'src')
2612 self.assertRegex(output, '2001:1234:56:8f63::2')
2613
1f0e3109 2614 def test_ip_link_mac_address(self):
ec38833c 2615 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 2616 start_networkd()
e2aea43f 2617 self.wait_online(['dummy98:degraded'])
1f0e3109 2618
371810d1 2619 output = check_output('ip link show dummy98')
1f0e3109
SS
2620 print(output)
2621 self.assertRegex(output, '00:01:02:aa:bb:cc')
2622
2623 def test_ip_link_unmanaged(self):
ec38833c 2624 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 2625 start_networkd(5)
1f0e3109 2626
e39cc445 2627 self.check_link_exists('dummy98')
1f0e3109 2628
19cf3143 2629 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2630
2631 def test_ipv6_address_label(self):
ec38833c 2632 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2633 start_networkd()
e2aea43f 2634 self.wait_online(['dummy98:degraded'])
1f0e3109 2635
371810d1 2636 output = check_output('ip addrlabel list')
1f0e3109
SS
2637 print(output)
2638 self.assertRegex(output, '2004:da8:1::/64')
2639
cff0cadc
YW
2640 def test_ipv6_proxy_ndp(self):
2641 copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
2642 start_networkd()
2643
2644 self.wait_online(['dummy98:routable'])
2645
2646 output = check_output('ip neighbor show proxy dev dummy98')
2647 print(output)
2648 for i in range(1,5):
2649 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
2650
d86f5c19 2651 def test_neighbor_section(self):
ec38833c 2652 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2653 start_networkd()
e2aea43f 2654 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2655
d1bdafd2 2656 print('### ip neigh list dev dummy98')
df7f9afa 2657 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2658 print(output)
2659 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2660 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2661
d1bdafd2
WKI
2662 def test_neighbor_reconfigure(self):
2663 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2664 start_networkd()
2665 self.wait_online(['dummy98:degraded'], timeout='40s')
2666
2667 print('### ip neigh list dev dummy98')
2668 output = check_output('ip neigh list dev dummy98')
2669 print(output)
2670 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2671 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2672
2673 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2674 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2675 restart_networkd(3)
2676 self.wait_online(['dummy98:degraded'], timeout='40s')
2677 print('### ip neigh list dev dummy98')
2678 output = check_output('ip neigh list dev dummy98')
2679 print(output)
2680 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2681 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2682 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2683
74761cf3 2684 def test_neighbor_gre(self):
fb2ba330
YW
2685 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2686 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2687 start_networkd()
fb2ba330 2688 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2689
2690 output = check_output('ip neigh list dev gretun97')
2691 print(output)
2692 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2693
2694 output = check_output('ip neigh list dev ip6gretun97')
2695 print(output)
2696 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2697
05514ae1 2698 def test_link_local_addressing(self):
ec38833c
ZJS
2699 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2700 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2701 start_networkd()
e2aea43f 2702 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2703
371810d1 2704 output = check_output('ip address show dev test1')
05514ae1
YW
2705 print(output)
2706 self.assertRegex(output, 'inet .* scope link')
2707 self.assertRegex(output, 'inet6 .* scope link')
2708
371810d1 2709 output = check_output('ip address show dev dummy98')
05514ae1
YW
2710 print(output)
2711 self.assertNotRegex(output, 'inet6* .* scope link')
2712
05514ae1
YW
2713 '''
2714 Documentation/networking/ip-sysctl.txt
2715
2716 addr_gen_mode - INTEGER
2717 Defines how link-local and autoconf addresses are generated.
2718
2719 0: generate address based on EUI64 (default)
2720 1: do no generate a link-local address, use EUI64 for addresses generated
2721 from autoconf
2722 2: generate stable privacy addresses, using the secret from
2723 stable_secret (RFC7217)
2724 3: generate stable privacy addresses, using a random secret if unset
2725 '''
2726
4681ab55
YW
2727 self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
2728 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2')
2729 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2730
7b3770a7
YW
2731 def test_link_local_addressing_remove_ipv6ll(self):
2732 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2733 start_networkd()
2734 self.wait_online(['dummy98:degraded'])
2735
2736 output = check_output('ip address show dev dummy98')
2737 print(output)
2738 self.assertRegex(output, 'inet6 .* scope link')
2739
2740 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2741 restart_networkd(1)
2742 self.wait_online(['dummy98:carrier'])
2743
2744 output = check_output('ip address show dev dummy98')
2745 print(output)
2746 self.assertNotRegex(output, 'inet6* .* scope link')
2747
1f0e3109 2748 def test_sysctl(self):
ec38833c 2749 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2750 start_networkd()
e2aea43f 2751 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2752
2753 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2754 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2755 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2756 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2757 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2758 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2759 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
29f69c57 2760 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
1f0e3109 2761
4da33154 2762 def test_sysctl_disable_ipv6(self):
ec38833c 2763 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2764
2765 print('## Disable ipv6')
cefd6b3d
ZJS
2766 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2767 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2768
2cf6fdff 2769 start_networkd()
e2aea43f 2770 self.wait_online(['dummy98:routable'])
4da33154 2771
371810d1 2772 output = check_output('ip -4 address show dummy98')
4da33154
YW
2773 print(output)
2774 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2775 output = check_output('ip -6 address show dummy98')
4da33154 2776 print(output)
57ad7607
ZJS
2777 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2778 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2779 output = check_output('ip -4 route show dev dummy98')
2780 print(output)
3d2c2692 2781 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2782 output = check_output('ip -6 route show default')
4933b97d 2783 print(output)
d9005dec
YW
2784 self.assertRegex(output, 'default')
2785 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2786
cefd6b3d 2787 check_output('ip link del dummy98')
4da33154
YW
2788
2789 print('## Enable ipv6')
cefd6b3d
ZJS
2790 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2791 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2792
e2aea43f
YW
2793 restart_networkd(3)
2794 self.wait_online(['dummy98:routable'])
4da33154 2795
371810d1 2796 output = check_output('ip -4 address show dummy98')
4da33154
YW
2797 print(output)
2798 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2799 output = check_output('ip -6 address show dummy98')
4da33154 2800 print(output)
4933b97d 2801 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2802 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2803 output = check_output('ip -4 route show dev dummy98')
2804 print(output)
3d2c2692 2805 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2806 output = check_output('ip -6 route show default')
4933b97d 2807 print(output)
d9005dec 2808 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2809
cd65d067 2810 def test_bind_carrier(self):
bc942f69
YW
2811 check_output('ip link add dummy98 type dummy')
2812 check_output('ip link set dummy98 up')
2813 time.sleep(2)
2814
ec38833c 2815 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2816 start_networkd()
e2aea43f 2817 self.wait_online(['test1:routable'])
cd65d067 2818
371810d1 2819 output = check_output('ip address show test1')
cd65d067
YW
2820 print(output)
2821 self.assertRegex(output, 'UP,LOWER_UP')
2822 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2823 self.wait_operstate('test1', 'routable')
cd65d067 2824
cefd6b3d
ZJS
2825 check_output('ip link add dummy99 type dummy')
2826 check_output('ip link set dummy99 up')
b117044c 2827 time.sleep(2)
371810d1 2828 output = check_output('ip address show test1')
cd65d067
YW
2829 print(output)
2830 self.assertRegex(output, 'UP,LOWER_UP')
2831 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2832 self.wait_operstate('test1', 'routable')
cd65d067 2833
cefd6b3d 2834 check_output('ip link del dummy98')
b117044c 2835 time.sleep(2)
371810d1 2836 output = check_output('ip address show test1')
cd65d067
YW
2837 print(output)
2838 self.assertRegex(output, 'UP,LOWER_UP')
2839 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2840 self.wait_operstate('test1', 'routable')
cd65d067 2841
bc942f69 2842 check_output('ip link set dummy99 down')
b117044c 2843 time.sleep(2)
371810d1 2844 output = check_output('ip address show test1')
cd65d067
YW
2845 print(output)
2846 self.assertNotRegex(output, 'UP,LOWER_UP')
2847 self.assertRegex(output, 'DOWN')
2848 self.assertNotRegex(output, '192.168.10')
19cf3143 2849 self.wait_operstate('test1', 'off')
cd65d067 2850
bc942f69 2851 check_output('ip link set dummy99 up')
b117044c 2852 time.sleep(2)
371810d1 2853 output = check_output('ip address show test1')
cd65d067
YW
2854 print(output)
2855 self.assertRegex(output, 'UP,LOWER_UP')
2856 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2857 self.wait_operstate('test1', 'routable')
cd65d067 2858
2236d75d
DS
2859 def _test_activation_policy(self, test):
2860 self.setUp()
2861 conffile = '25-activation-policy.network'
2862 if test:
2863 conffile = f'{conffile}.d/{test}.conf'
2864 copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
2865 start_networkd()
2866
2867 always = test.startswith('always')
2868 if test == 'manual':
2869 initial_up = 'UP' in check_output('ip link show test1')
2870 else:
2871 initial_up = not test.endswith('down') # note: default is up
2872 expect_up = initial_up
2873 next_up = not expect_up
2874
2236d75d
DS
2875 for iteration in range(4):
2876 with self.subTest(iteration=iteration, expect_up=expect_up):
2877 operstate = 'routable' if expect_up else 'off'
618da3e7 2878 setup_state = 'configured' if expect_up else ('configuring' if iteration == 0 else None)
2236d75d 2879 self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
2236d75d
DS
2880
2881 if expect_up:
2882 self.assertIn('UP', check_output('ip link show test1'))
2883 self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
1ef2eedc 2884 self.assertIn('default via 192.168.10.1', check_output('ip route show dev test1'))
2236d75d
DS
2885 else:
2886 self.assertIn('DOWN', check_output('ip link show test1'))
2887
2888 if next_up:
2889 check_output('ip link set dev test1 up')
2890 else:
2891 check_output('ip link set dev test1 down')
2892 expect_up = initial_up if always else next_up
2893 next_up = not next_up
2894
2895 self.tearDown()
2896
2897 def test_activation_policy(self):
2898 for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
2899 with self.subTest(test=test):
2900 self._test_activation_policy(test)
2901
61764fe4
DS
2902 def _test_activation_policy_required_for_online(self, policy, required):
2903 self.setUp()
2904 conffile = '25-activation-policy.network'
2905 units = ['11-dummy.netdev', '12-dummy.netdev', '12-dummy.network', conffile]
2906 if policy:
2907 units += [f'{conffile}.d/{policy}.conf']
2908 if required:
2909 units += [f'{conffile}.d/required-{required}.conf']
2910 copy_unit_to_networkd_unit_path(*units, dropins=False)
2911 start_networkd()
2912
2913 if policy.endswith('down') or policy == 'manual':
2914 self.wait_operstate('test1', 'off', setup_state='configuring')
2915 else:
2916 self.wait_online(['test1'])
2917
2918 if policy == 'always-down':
2919 # if always-down, required for online is forced to no
2920 expected = False
2921 elif required:
2922 # otherwise if required for online is specified, it should match that
2923 expected = required == 'yes'
2924 elif policy:
2925 # otherwise if only policy specified, required for online defaults to
2926 # true if policy is up, always-up, or bound
2927 expected = policy.endswith('up') or policy == 'bound'
2928 else:
2929 # default is true, if neither are specified
2930 expected = True
2931
2932 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2933 print(output)
2934
2935 yesno = 'yes' if expected else 'no'
2936 self.assertRegex(output, f'Required For Online: {yesno}')
2937
2938 self.tearDown()
2939
2940 def test_activation_policy_required_for_online(self):
2941 for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']:
2942 for required in ['yes', 'no', '']:
2943 with self.subTest(policy=policy, required=required):
2944 self._test_activation_policy_required_for_online(policy, required)
2945
fdcd1ec5 2946 def test_domain(self):
ec38833c 2947 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2948 start_networkd()
e2aea43f 2949 self.wait_online(['dummy98:routable'])
fdcd1ec5 2950
fc79e6ff 2951 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2952 print(output)
2953 self.assertRegex(output, 'Address: 192.168.42.100')
2954 self.assertRegex(output, 'DNS: 192.168.42.1')
2955 self.assertRegex(output, 'Search Domains: one')
2956
1e498853 2957 def test_keep_configuration_static(self):
3aa645f0
MB
2958 check_output('systemctl stop systemd-networkd.socket')
2959 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
2960
2961 check_output('ip link add name dummy98 type dummy')
2962 check_output('ip address add 10.1.2.3/16 dev dummy98')
2963 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2964 output = check_output('ip address show dummy98')
2965 print(output)
2966 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2967 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2968 output = check_output('ip route show dev dummy98')
2969 print(output)
2970
2971 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2972 start_networkd()
e2aea43f 2973 self.wait_online(['dummy98:routable'])
1e498853
YW
2974
2975 output = check_output('ip address show dummy98')
2976 print(output)
2977 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2978 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2979
086bcf5d
YW
2980 @expectedFailureIfNexthopIsNotAvailable()
2981 def test_nexthop(self):
9c8f90d0
YW
2982 def check_nexthop(self):
2983 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
086bcf5d 2984
9c8f90d0
YW
2985 output = check_output('ip nexthop list dev veth99')
2986 print(output)
2987 self.assertIn('id 1 via 192.168.5.1 dev veth99', output)
2988 self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output)
2989 self.assertIn('id 3 dev veth99', output)
2990 self.assertIn('id 4 dev veth99', output)
2991 self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink')
180c5116 2992 self.assertIn('id 8 via fe80:0:222:4dff:ff:ff:ff:ff dev veth99', output)
9c8f90d0
YW
2993 self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
2994
2995 output = check_output('ip nexthop list dev dummy98')
2996 print(output)
2997 self.assertIn('id 20 via 192.168.20.1 dev dummy98', output)
086bcf5d 2998
9c8f90d0
YW
2999 # kernel manages blackhole nexthops on lo
3000 output = check_output('ip nexthop list dev lo')
3001 print(output)
3002 self.assertIn('id 6 blackhole', output)
3003 self.assertIn('id 7 blackhole', output)
69a91c70 3004
9c8f90d0
YW
3005 # group nexthops are shown with -0 option
3006 output = check_output('ip -0 nexthop list id 21')
3007 print(output)
3008 self.assertRegex(output, r'id 21 group (1,3/20|20/1,3)')
cee0f719 3009
9c8f90d0
YW
3010 output = check_output('ip route show dev veth99 10.10.10.10')
3011 print(output)
3012 self.assertEqual('10.10.10.10 nhid 1 via 192.168.5.1 proto static', output)
cee0f719 3013
9c8f90d0
YW
3014 output = check_output('ip route show dev veth99 10.10.10.11')
3015 print(output)
3016 self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output)
e2d9bc5c 3017
9c8f90d0
YW
3018 output = check_output('ip route show dev veth99 10.10.10.12')
3019 print(output)
3020 self.assertEqual('10.10.10.12 nhid 5 via 192.168.10.1 proto static onlink', output)
cee0f719 3021
9c8f90d0
YW
3022 output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1')
3023 print(output)
3024 self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output)
69a91c70 3025
9c8f90d0
YW
3026 output = check_output('ip route show 10.10.10.13')
3027 print(output)
3028 self.assertEqual('blackhole 10.10.10.13 nhid 6 dev lo proto static', output)
3029
3030 output = check_output('ip -6 route show 2001:1234:5:8f62::2')
3031 print(output)
3032 self.assertEqual('blackhole 2001:1234:5:8f62::2 nhid 7 dev lo proto static metric 1024 pref medium', output)
3033
3034 output = check_output('ip route show 10.10.10.14')
3035 print(output)
3036 self.assertIn('10.10.10.14 nhid 21 proto static', output)
3037 self.assertIn('nexthop via 192.168.20.1 dev dummy98 weight 1', output)
3038 self.assertIn('nexthop via 192.168.5.1 dev veth99 weight 3', output)
3039
3040 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
3041 '12-dummy.netdev', '25-nexthop-dummy.network')
3042 start_networkd()
3043
3044 check_nexthop(self)
69a91c70 3045
9947c7ba
YW
3046 remove_unit_from_networkd_path(['25-nexthop.network'])
3047 copy_unit_to_networkd_unit_path('25-nexthop-nothing.network')
3048 rc = call(*networkctl_cmd, 'reload', env=env)
3049 self.assertEqual(rc, 0)
3050 time.sleep(1)
3051
932e157b
YW
3052 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3053
9947c7ba
YW
3054 output = check_output('ip nexthop list dev veth99')
3055 print(output)
3056 self.assertEqual(output, '')
3057 output = check_output('ip nexthop list dev lo')
3058 print(output)
3059 self.assertEqual(output, '')
3060
3061 remove_unit_from_networkd_path(['25-nexthop-nothing.network'])
3062 copy_unit_to_networkd_unit_path('25-nexthop.network')
9c8f90d0
YW
3063 rc = call(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
3064 self.assertEqual(rc, 0)
9947c7ba
YW
3065 rc = call(*networkctl_cmd, 'reload', env=env)
3066 self.assertEqual(rc, 0)
3067 time.sleep(1)
3068
9c8f90d0 3069 check_nexthop(self)
932e157b 3070
9947c7ba
YW
3071 rc = call('ip link del veth99')
3072 self.assertEqual(rc, 0)
3073 time.sleep(2)
3074
3075 output = check_output('ip nexthop list dev lo')
3076 print(output)
3077 self.assertEqual(output, '')
3078
ef3c8a92 3079 def test_qdisc(self):
f1de1eb3
YW
3080 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
3081 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
3082 check_output('modprobe sch_teql max_equalizers=2')
ef3c8a92
YW
3083 start_networkd()
3084
1b628c4f 3085 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92 3086
f1de1eb3
YW
3087 output = check_output('tc qdisc show dev test1')
3088 print(output)
3089 self.assertRegex(output, 'qdisc netem')
7887e580 3090 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
f1de1eb3
YW
3091 self.assertRegex(output, 'qdisc ingress')
3092
ef3c8a92
YW
3093 output = check_output('tc qdisc show dev dummy98')
3094 print(output)
f1de1eb3
YW
3095 self.assertRegex(output, 'qdisc clsact')
3096
3097 self.assertRegex(output, 'qdisc htb 2: root')
3098 self.assertRegex(output, r'default (0x30|30)')
3099
3100 self.assertRegex(output, 'qdisc netem 30: parent 2:30')
7887e580 3101 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
40821c2a 3102 self.assertRegex(output, 'qdisc fq_codel')
7887e580 3103 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 3104
f1de1eb3 3105 self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
0baddbd5 3106
f1de1eb3 3107 self.assertRegex(output, 'qdisc fq 32: parent 2:32')
a05a6e8b
YW
3108 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
3109 self.assertRegex(output, 'quantum 1500')
3110 self.assertRegex(output, 'initial_quantum 13000')
3111 self.assertRegex(output, 'maxrate 1Mbit')
ab9dc1db 3112
f1de1eb3 3113 self.assertRegex(output, 'qdisc codel 33: parent 2:33')
7887e580 3114 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
ab9dc1db 3115
f1de1eb3 3116 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
7887e580 3117 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 3118
f1de1eb3 3119 self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
7887e580 3120 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
ab9dc1db 3121
f1de1eb3
YW
3122 self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
3123 self.assertRegex(output, 'perturb 5sec')
3d55b5a9 3124
bc0769c9
YW
3125 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
3126 self.assertRegex(output, 'limit 100000p')
3127
95edcf3f
YW
3128 self.assertRegex(output, 'qdisc gred 38: parent 2:38')
3129 self.assertRegex(output, 'vqs 12 default 10 grio')
3130
f2c5c129
YW
3131 self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
3132 self.assertRegex(output, 'limit 200000')
3133
7b1a31a3
YW
3134 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
3135 self.assertRegex(output, 'limit 1000000')
3136
73136507
YW
3137 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b')
3138 self.assertRegex(output, 'limit 1023p')
3139
41bb371b
YW
3140 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c')
3141
2ee7e54b 3142 output = check_output('tc -d class show dev dummy98')
ab9dc1db 3143 print(output)
f1de1eb3
YW
3144 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
3145 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
3146 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
3147 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
3148 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
3149 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
3150 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
bc0769c9 3151 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
95edcf3f 3152 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
f2c5c129 3153 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
7b1a31a3 3154 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
73136507 3155 self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
41bb371b 3156 self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
2ee7e54b
YW
3157 self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit')
3158 self.assertRegex(output, 'burst 123456')
3159 self.assertRegex(output, 'cburst 123457')
0baddbd5 3160
557fa421 3161 def test_qdisc2(self):
891ff963
YW
3162 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
3163 '25-qdisc-qfq.network', '11-dummy.netdev')
557fa421
YW
3164 start_networkd()
3165
891ff963 3166 self.wait_online(['dummy98:routable', 'test1:routable'])
557fa421
YW
3167
3168 output = check_output('tc qdisc show dev dummy98')
3169 print(output)
3170 self.assertRegex(output, 'qdisc drr 2: root')
3171 output = check_output('tc class show dev dummy98')
3172 print(output)
3173 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
3174
891ff963
YW
3175 output = check_output('tc qdisc show dev test1')
3176 print(output)
3177 self.assertRegex(output, 'qdisc qfq 2: root')
3178 output = check_output('tc class show dev test1')
3179 print(output)
3180 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
3181 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
3182
f6c6af38
YW
3183 @expectedFailureIfCAKEIsNotAvailable()
3184 def test_qdisc_cake(self):
3185 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
3d55b5a9 3186 start_networkd()
3d55b5a9
YW
3187 self.wait_online(['dummy98:routable'])
3188
3189 output = check_output('tc qdisc show dev dummy98')
3190 print(output)
f6c6af38
YW
3191 self.assertRegex(output, 'qdisc cake 3a: root')
3192 self.assertRegex(output, 'bandwidth 500Mbit')
3193 self.assertRegex(output, 'overhead 128')
3d55b5a9 3194
be94e591
YW
3195 @expectedFailureIfPIEIsNotAvailable()
3196 def test_qdisc_pie(self):
3197 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
3198 start_networkd()
3199 self.wait_online(['dummy98:routable'])
3200
3201 output = check_output('tc qdisc show dev dummy98')
3202 print(output)
3203 self.assertRegex(output, 'qdisc pie 3a: root')
3204 self.assertRegex(output, 'limit 200000')
3205
970ab1fc
YW
3206 @expectedFailureIfHHFIsNotAvailable()
3207 def test_qdisc_hhf(self):
3208 copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev')
3209 start_networkd()
3210 self.wait_online(['dummy98:routable'])
3211
3212 output = check_output('tc qdisc show dev dummy98')
3213 print(output)
3214 self.assertRegex(output, 'qdisc hhf 3a: root')
3215 self.assertRegex(output, 'limit 1022p')
3216
b753e835
YW
3217 @expectedFailureIfETSIsNotAvailable()
3218 def test_qdisc_ets(self):
3219 copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev')
3220 start_networkd()
3221 self.wait_online(['dummy98:routable'])
3222
3223 output = check_output('tc qdisc show dev dummy98')
3224 print(output)
1578266b 3225
b753e835
YW
3226 self.assertRegex(output, 'qdisc ets 3a: root')
3227 self.assertRegex(output, 'bands 10 strict 3')
3228 self.assertRegex(output, 'quanta 1 2 3 4 5')
3229 self.assertRegex(output, 'priomap 3 4 5 6 7')
3230
1578266b
YW
3231 @expectedFailureIfFQPIEIsNotAvailable()
3232 def test_qdisc_fq_pie(self):
3233 copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev')
3234 start_networkd()
3235 self.wait_online(['dummy98:routable'])
3236
3237 output = check_output('tc qdisc show dev dummy98')
3238 print(output)
3239
3240 self.assertRegex(output, 'qdisc fq_pie 3a: root')
3241 self.assertRegex(output, 'limit 200000p')
3242
3d2c2692
YW
3243 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
3244 def test_sriov(self):
3245 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
3246 call('modprobe netdevsim', stderr=subprocess.DEVNULL)
3247 with open('/sys/bus/netdevsim/new_device', mode='w') as f:
3248 f.write('99 1')
3249
3250 call('udevadm settle')
3251 call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
3252 with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f:
3253 f.write('3')
3254
3255 copy_unit_to_networkd_unit_path('25-sriov.network')
3256 start_networkd()
3257 self.wait_online(['eni99np1:routable'])
3258
3259 output = check_output('ip link show dev eni99np1')
3260 print(output)
3261 self.assertRegex(output,
3262 '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 *'
3263 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
3264 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
3265 )
3266
3267 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
3268
70448bb1
L
3269 def test_wait_online_ipv4(self):
3270 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
3271 start_networkd()
3272
3273 self.wait_online(['veth99:routable'], ipv4=True)
3274
3275 self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1)
3276
3277 def test_wait_online_ipv6(self):
3278 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix-with-delay.network', 'ipv6ra-prefix-client-with-static-ipv4-address.network')
3279 start_networkd()
3280
3281 self.wait_online(['veth99:routable'], ipv6=True)
3282
3283 self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1)
3284
336d18f0
YW
3285class NetworkdStateFileTests(unittest.TestCase, Utilities):
3286 links = [
3287 'dummy98',
3288 ]
3289
3290 units = [
3291 '12-dummy.netdev',
3292 'state-file-tests.network',
3293 ]
3294
3295 def setUp(self):
3296 remove_links(self.links)
3297 stop_networkd(show_logs=False)
3298
3299 def tearDown(self):
3300 remove_links(self.links)
3301 remove_unit_from_networkd_path(self.units)
3302 stop_networkd(show_logs=True)
3303
3304 def test_state_file(self):
3305 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
3306 start_networkd()
3307 self.wait_online(['dummy98:routable'])
3308
3309 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
3310 print(output)
3311 ifindex = output.split()[0]
3312
3313 path = os.path.join('/run/systemd/netif/links/', ifindex)
3314 self.assertTrue(os.path.exists(path))
f91b2340
YW
3315
3316 # make link state file updated
3317 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3318
3319 with open(path) as f:
3320 data = f.read()
70448bb1
L
3321 self.assertRegex(data, r'IPV4_ADDRESS_STATE=routable')
3322 self.assertRegex(data, r'IPV6_ADDRESS_STATE=routable')
336d18f0
YW
3323 self.assertRegex(data, r'ADMIN_STATE=configured')
3324 self.assertRegex(data, r'OPER_STATE=routable')
3325 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
3326 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
70448bb1 3327 self.assertRegex(data, r'REQUIRED_FAMILY_FOR_ONLINE=both')
a853652a 3328 self.assertRegex(data, r'ACTIVATION_POLICY=up')
336d18f0 3329 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
66479677 3330 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
3331 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3332 self.assertRegex(data, r'DOMAINS=hogehoge')
3333 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3334 self.assertRegex(data, r'LLMNR=no')
3335 self.assertRegex(data, r'MDNS=yes')
3336 self.assertRegex(data, r'DNSSEC=no')
336d18f0 3337
66479677 3338 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env)
336d18f0
YW
3339 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
3340 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
3341 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
3342 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
3343 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
336d18f0
YW
3344
3345 with open(path) as f:
3346 data = f.read()
66479677 3347 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3348 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
3349 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3350 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3351 self.assertRegex(data, r'LLMNR=yes')
3352 self.assertRegex(data, r'MDNS=no')
3353 self.assertRegex(data, r'DNSSEC=yes')
3354
3355 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3356
3357 with open(path) as f:
3358 data = f.read()
66479677 3359 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3360 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3361 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3362 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3363 self.assertRegex(data, r'LLMNR=yes')
3364 self.assertRegex(data, r'MDNS=no')
3365 self.assertRegex(data, r'DNSSEC=yes')
3366
3367 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3368
3369 with open(path) as f:
3370 data = f.read()
66479677 3371 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
3372 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3373 self.assertRegex(data, r'DOMAINS=hogehoge')
3374 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3375 self.assertRegex(data, r'LLMNR=no')
3376 self.assertRegex(data, r'MDNS=yes')
3377 self.assertRegex(data, r'DNSSEC=no')
3378
be68c2c9 3379class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 3380 links = [
c2990ec3 3381 'bond199',
c3a8853f 3382 'bond99',
cc3e488c
YW
3383 'dummy98',
3384 'test1']
c3a8853f
YW
3385
3386 units = [
cc3e488c
YW
3387 '11-dummy.netdev',
3388 '12-dummy.netdev',
c2990ec3
YW
3389 '23-active-slave.network',
3390 '23-bond199.network',
3391 '23-primary-slave.network',
c2990ec3 3392 '25-bond-active-backup-slave.netdev',
c3a8853f 3393 '25-bond.netdev',
c3a8853f 3394 'bond99.network',
cc3e488c 3395 'bond-slave.network']
c3a8853f
YW
3396
3397 def setUp(self):
ec38833c 3398 remove_links(self.links)
aaae5713 3399 stop_networkd(show_logs=False)
c3a8853f
YW
3400
3401 def tearDown(self):
ec38833c
ZJS
3402 remove_links(self.links)
3403 remove_unit_from_networkd_path(self.units)
aaae5713 3404 stop_networkd(show_logs=True)
c3a8853f 3405
c2990ec3 3406 def test_bond_active_slave(self):
ec38833c 3407 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3408 start_networkd()
e2aea43f 3409 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3410
371810d1 3411 output = check_output('ip -d link show bond199')
c2990ec3
YW
3412 print(output)
3413 self.assertRegex(output, 'active_slave dummy98')
3414
3415 def test_bond_primary_slave(self):
35a78c51 3416 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3417 start_networkd()
e2aea43f 3418 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3419
371810d1 3420 output = check_output('ip -d link show bond199')
c2990ec3 3421 print(output)
35a78c51 3422 self.assertRegex(output, 'primary dummy98')
c2990ec3 3423
cc3e488c 3424 def test_bond_operstate(self):
ec38833c
ZJS
3425 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
3426 'bond99.network','bond-slave.network')
2cf6fdff 3427 start_networkd()
e2aea43f 3428 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 3429
371810d1 3430 output = check_output('ip -d link show dummy98')
c3a8853f 3431 print(output)
cc3e488c 3432 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 3433
371810d1 3434 output = check_output('ip -d link show test1')
c3a8853f
YW
3435 print(output)
3436 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
3437
371810d1 3438 output = check_output('ip -d link show bond99')
c3a8853f
YW
3439 print(output)
3440 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
3441
19cf3143
DS
3442 self.wait_operstate('dummy98', 'enslaved')
3443 self.wait_operstate('test1', 'enslaved')
3444 self.wait_operstate('bond99', 'routable')
c3a8853f 3445
cefd6b3d 3446 check_output('ip link set dummy98 down')
c3a8853f 3447
19cf3143
DS
3448 self.wait_operstate('dummy98', 'off')
3449 self.wait_operstate('test1', 'enslaved')
3450 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 3451
cefd6b3d 3452 check_output('ip link set dummy98 up')
c3a8853f 3453
19cf3143
DS
3454 self.wait_operstate('dummy98', 'enslaved')
3455 self.wait_operstate('test1', 'enslaved')
3456 self.wait_operstate('bond99', 'routable')
c3a8853f 3457
cefd6b3d
ZJS
3458 check_output('ip link set dummy98 down')
3459 check_output('ip link set test1 down')
cc3e488c 3460
19cf3143
DS
3461 self.wait_operstate('dummy98', 'off')
3462 self.wait_operstate('test1', 'off')
2700d2c7 3463
a4632dc7 3464 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
3465 # Huh? Kernel does not recognize that all slave interfaces are down?
3466 # Let's confirm that networkd's operstate is consistent with ip's result.
3467 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 3468
be68c2c9 3469class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
3470 links = [
3471 'bridge99',
3472 'dummy98',
988b0660
YW
3473 'test1',
3474 'vlan99',
3475 ]
09ea6724
YW
3476
3477 units = [
3478 '11-dummy.netdev',
3479 '12-dummy.netdev',
988b0660
YW
3480 '21-vlan.netdev',
3481 '21-vlan.network',
09ea6724 3482 '26-bridge.netdev',
0fc0d85f 3483 '26-bridge-configure-without-carrier.network',
988b0660 3484 '26-bridge-issue-20373.netdev',
cc0276cc
YW
3485 '26-bridge-mdb-master.network',
3486 '26-bridge-mdb-slave.network',
09ea6724
YW
3487 '26-bridge-slave-interface-1.network',
3488 '26-bridge-slave-interface-2.network',
988b0660 3489 '26-bridge-vlan-master-issue-20373.network',
6f943798 3490 '26-bridge-vlan-master.network',
988b0660 3491 '26-bridge-vlan-slave-issue-20373.network',
6f943798 3492 '26-bridge-vlan-slave.network',
804b6cd2 3493 'bridge99-ignore-carrier-loss.network',
988b0660
YW
3494 'bridge99.network'
3495 ]
1f0e3109 3496
8d17c386
YW
3497 routing_policy_rule_tables = ['100']
3498
1f0e3109 3499 def setUp(self):
8d17c386 3500 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 3501 remove_links(self.links)
aaae5713 3502 stop_networkd(show_logs=False)
1f0e3109
SS
3503
3504 def tearDown(self):
8d17c386 3505 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
3506 remove_links(self.links)
3507 remove_unit_from_networkd_path(self.units)
aaae5713 3508 stop_networkd(show_logs=True)
1f0e3109 3509
6f943798
YW
3510 def test_bridge_vlan(self):
3511 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
3512 '26-bridge.netdev', '26-bridge-vlan-master.network')
3513 start_networkd()
e2aea43f 3514 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
3515
3516 output = check_output('bridge vlan show dev test1')
3517 print(output)
3518 self.assertNotRegex(output, '4063')
3519 for i in range(4064, 4095):
3520 self.assertRegex(output, f'{i}')
3521 self.assertNotRegex(output, '4095')
3522
3523 output = check_output('bridge vlan show dev bridge99')
3524 print(output)
3525 self.assertNotRegex(output, '4059')
3526 for i in range(4060, 4095):
3527 self.assertRegex(output, f'{i}')
3528 self.assertNotRegex(output, '4095')
3529
988b0660
YW
3530 def test_bridge_vlan_issue_20373(self):
3531 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network',
3532 '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network',
3533 '21-vlan.netdev', '21-vlan.network')
3534 start_networkd()
3535 self.wait_online(['test1:enslaved', 'bridge99:degraded', 'vlan99:routable'])
3536
3537 output = check_output('bridge vlan show dev test1')
3538 print(output)
3539 self.assertIn('100 PVID Egress Untagged', output)
3540 self.assertIn('560', output)
3541 self.assertIn('600', output)
3542
3543 output = check_output('bridge vlan show dev bridge99')
3544 print(output)
3545 self.assertIn('1 PVID Egress Untagged', output)
3546 self.assertIn('100', output)
3547 self.assertIn('600', output)
3548
cc0276cc
YW
3549 def test_bridge_mdb(self):
3550 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network',
3551 '26-bridge.netdev', '26-bridge-mdb-master.network')
3552 start_networkd()
3553 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
3554
3555 output = check_output('bridge mdb show dev bridge99')
3556 print(output)
3557 self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064')
3558 self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065')
3559
9f773037
YW
3560 # Old kernel may not support bridge MDB entries on bridge master
3561 if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0:
3562 self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
3563 self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
3564
1f0e3109 3565 def test_bridge_property(self):
ec38833c
ZJS
3566 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3567 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3568 'bridge99.network')
2cf6fdff 3569 start_networkd()
e2aea43f 3570 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 3571
371810d1 3572 output = check_output('ip -d link show test1')
1f0e3109
SS
3573 print(output)
3574 self.assertRegex(output, 'master')
3575 self.assertRegex(output, 'bridge')
3576
371810d1 3577 output = check_output('ip -d link show dummy98')
1f0e3109
SS
3578 print(output)
3579 self.assertRegex(output, 'master')
3580 self.assertRegex(output, 'bridge')
3581
371810d1 3582 output = check_output('ip addr show bridge99')
1f0e3109 3583 print(output)
2be6c5d2 3584 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 3585
371810d1 3586 output = check_output('bridge -d link show dummy98')
1f0e3109 3587 print(output)
ec38833c 3588 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
3589 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
3590 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
3591 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
3592 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
3593 # CONFIG_BRIDGE_IGMP_SNOOPING=y
3594 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
3595 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 3596 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
3597 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
3598 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
3599 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
3600 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
3601 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 3602
5424fd95
YW
3603 output = check_output('bridge -d link show test1')
3604 print(output)
3605 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 3606
371810d1 3607 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3608 time.sleep(1)
3609
371810d1 3610 output = check_output('ip addr show bridge99')
2be6c5d2
YW
3611 print(output)
3612 self.assertRegex(output, '192.168.0.16/24')
3613
e3cbaeab
YW
3614 # for issue #6088
3615 print('### ip -6 route list table all dev bridge99')
3616 output = check_output('ip -6 route list table all dev bridge99')
3617 print(output)
beb75dd3 3618 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3619
371810d1 3620 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 3621
19cf3143 3622 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 3623
cefd6b3d 3624 check_output('ip link del dummy98')
804b6cd2 3625
19cf3143 3626 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 3627
371810d1 3628 output = check_output('ip address show bridge99')
804b6cd2
YW
3629 print(output)
3630 self.assertRegex(output, 'NO-CARRIER')
3631 self.assertNotRegex(output, '192.168.0.15/24')
3632 self.assertNotRegex(output, '192.168.0.16/24')
3633
e3cbaeab
YW
3634 print('### ip -6 route list table all dev bridge99')
3635 output = check_output('ip -6 route list table all dev bridge99')
3636 print(output)
beb75dd3 3637 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3638
0fc0d85f
DS
3639 def test_bridge_configure_without_carrier(self):
3640 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
3641 '11-dummy.netdev')
3642 start_networkd()
3643
3644 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
3645 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
3646 with self.subTest(test=test):
3647 if test == 'no-slave':
3648 # bridge has no slaves; it's up but *might* not have carrier
001c07cf 3649 self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30)
0fc0d85f
DS
3650 # due to a bug in the kernel, newly-created bridges are brought up
3651 # *with* carrier, unless they have had any setting changed; e.g.
3652 # their mac set, priority set, etc. Then, they will lose carrier
3653 # as soon as a (down) slave interface is added, and regain carrier
3654 # again once the slave interface is brought up.
3655 #self.check_link_attr('bridge99', 'carrier', '0')
3656 elif test == 'add-slave':
3657 # add slave to bridge, but leave it down; bridge is definitely no-carrier
3658 self.check_link_attr('test1', 'operstate', 'down')
3659 check_output('ip link set dev test1 master bridge99')
001c07cf 3660 self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None)
0fc0d85f
DS
3661 self.check_link_attr('bridge99', 'carrier', '0')
3662 elif test == 'slave-up':
3663 # bring up slave, which will have carrier; bridge gains carrier
3664 check_output('ip link set dev test1 up')
3665 self.wait_online(['bridge99:routable'])
3666 self.check_link_attr('bridge99', 'carrier', '1')
3667 elif test == 'slave-no-carrier':
3668 # drop slave carrier; bridge loses carrier
3669 check_output('ip link set dev test1 carrier off')
3670 self.wait_online(['bridge99:no-carrier:no-carrier'])
3671 self.check_link_attr('bridge99', 'carrier', '0')
3672 elif test == 'slave-carrier':
3673 # restore slave carrier; bridge gains carrier
3674 check_output('ip link set dev test1 carrier on')
3675 self.wait_online(['bridge99:routable'])
3676 self.check_link_attr('bridge99', 'carrier', '1')
3677 elif test == 'slave-down':
3678 # bring down slave; bridge loses carrier
3679 check_output('ip link set dev test1 down')
3680 self.wait_online(['bridge99:no-carrier:no-carrier'])
3681 self.check_link_attr('bridge99', 'carrier', '0')
3682
3683 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
0fc0d85f
DS
3684 self.assertRegex(output, '10.1.2.3')
3685 self.assertRegex(output, '10.1.2.1')
3686
804b6cd2 3687 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
3688 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3689 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3690 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3691 start_networkd()
e2aea43f 3692 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 3693
371810d1 3694 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3695 time.sleep(1)
3696
371810d1
ZJS
3697 check_output('ip link del test1')
3698 check_output('ip link del dummy98')
804b6cd2
YW
3699 time.sleep(3)
3700
371810d1 3701 output = check_output('ip address show bridge99')
804b6cd2
YW
3702 print(output)
3703 self.assertRegex(output, 'NO-CARRIER')
3704 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3705 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
3706
6609924c 3707 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
3708 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
3709 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3710 start_networkd()
e2aea43f 3711 self.wait_online(['bridge99:no-carrier'])
6609924c 3712
90e3bcbd
YW
3713 for trial in range(4):
3714 check_output('ip link add dummy98 type dummy')
3715 check_output('ip link set dummy98 up')
3716 if trial < 3:
3717 check_output('ip link del dummy98')
6609924c 3718
e2aea43f 3719 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 3720
371810d1 3721 output = check_output('ip address show bridge99')
6609924c
YW
3722 print(output)
3723 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3724
371810d1 3725 output = check_output('ip rule list table 100')
6609924c 3726 print(output)
c4f7a347 3727 self.assertIn('from all to 8.8.8.8 lookup 100', output)
6609924c 3728
be68c2c9 3729class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
3730 links = ['veth99']
3731
09ea6724
YW
3732 units = [
3733 '23-emit-lldp.network',
3734 '24-lldp.network',
3735 '25-veth.netdev']
1f0e3109
SS
3736
3737 def setUp(self):
ec38833c 3738 remove_links(self.links)
aaae5713 3739 stop_networkd(show_logs=False)
1f0e3109
SS
3740
3741 def tearDown(self):
ec38833c
ZJS
3742 remove_links(self.links)
3743 remove_unit_from_networkd_path(self.units)
aaae5713 3744 stop_networkd(show_logs=True)
1f0e3109
SS
3745
3746 def test_lldp(self):
ec38833c 3747 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 3748 start_networkd()
e2aea43f 3749 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 3750
f0d87798
YW
3751 for trial in range(10):
3752 if trial > 0:
3753 time.sleep(1)
3754
3755 output = check_output(*networkctl_cmd, 'lldp', env=env)
3756 print(output)
3757 if re.search(r'veth99 .* veth-peer', output):
3758 break
3759 else:
3760 self.fail()
1f0e3109 3761
be68c2c9 3762class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
3763 links = ['veth99']
3764
09ea6724
YW
3765 units = [
3766 '25-veth.netdev',
3767 'ipv6-prefix.network',
87bbebea 3768 'ipv6-prefix-veth.network',
e2c4070e 3769 'ipv6-prefix-veth-token-static.network',
68248f43
YW
3770 'ipv6-prefix-veth-token-prefixstable.network',
3771 'ipv6-prefix-veth-token-prefixstable-without-address.network']
1f0e3109
SS
3772
3773 def setUp(self):
ec38833c 3774 remove_links(self.links)
aaae5713 3775 stop_networkd(show_logs=False)
1f0e3109
SS
3776
3777 def tearDown(self):
ec38833c
ZJS
3778 remove_links(self.links)
3779 remove_unit_from_networkd_path(self.units)
aaae5713 3780 stop_networkd(show_logs=True)
1f0e3109
SS
3781
3782 def test_ipv6_prefix_delegation(self):
ec38833c 3783 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 3784 start_networkd()
e2aea43f 3785 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 3786
41fd8fe7
YW
3787 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3788 print(output)
3789 self.assertRegex(output, 'fe80::')
3790 self.assertRegex(output, '2002:da8:1::1')
3791
80762ccc
YW
3792 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3793 print(output)
3794 self.assertIn('hogehoge.test', output)
3795
fc79e6ff 3796 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3797 print(output)
3798 self.assertRegex(output, '2002:da8:1:0')
3799
e2c4070e
YW
3800 def test_ipv6_token_static(self):
3801 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 3802 start_networkd()
b241fa00
KF
3803 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3804
3805 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3806 print(output)
3807 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
68248f43
YW
3808 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
3809 self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d')
3810 self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe')
b241fa00 3811
68248f43
YW
3812 def test_ipv6_token_prefixstable(self):
3813 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
c24c83dc
KF
3814 start_networkd()
3815 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3816
3817 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3818 print(output)
68248f43
YW
3819 self.assertRegex(output, '2002:da8:1:0')
3820 self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI
c24c83dc 3821
68248f43
YW
3822 def test_ipv6_token_prefixstable_without_address(self):
3823 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network')
87bbebea
YW
3824 start_networkd()
3825 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3826
3827 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3828 print(output)
3829 self.assertRegex(output, '2002:da8:1:0')
68248f43 3830 self.assertRegex(output, '2002:da8:2:0')
87bbebea 3831
be68c2c9 3832class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
4e0006cc
YW
3833 links = [
3834 'dummy98',
3835 'veth99',
3836 ]
09ea6724
YW
3837
3838 units = [
4e0006cc 3839 '12-dummy.netdev',
09ea6724
YW
3840 '25-veth.netdev',
3841 'dhcp-client.network',
ffaece68 3842 'dhcp-client-static-lease.network',
09ea6724
YW
3843 'dhcp-client-timezone-router.network',
3844 'dhcp-server.network',
ffaece68 3845 'dhcp-server-static-lease.network',
4e0006cc
YW
3846 'dhcp-server-timezone-router.network',
3847 'dhcp-server-uplink.network',
3848 ]
1f0e3109
SS
3849
3850 def setUp(self):
ec38833c 3851 remove_links(self.links)
aaae5713 3852 stop_networkd(show_logs=False)
1f0e3109
SS
3853
3854 def tearDown(self):
ec38833c
ZJS
3855 remove_links(self.links)
3856 remove_unit_from_networkd_path(self.units)
aaae5713 3857 stop_networkd(show_logs=True)
1f0e3109
SS
3858
3859 def test_dhcp_server(self):
4e0006cc
YW
3860 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network',
3861 '12-dummy.netdev', 'dhcp-server-uplink.network')
2cf6fdff 3862 start_networkd()
e2aea43f 3863 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3864
fc79e6ff 3865 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3866 print(output)
3867 self.assertRegex(output, '192.168.5.*')
3868 self.assertRegex(output, 'Gateway: 192.168.5.1')
3869 self.assertRegex(output, 'DNS: 192.168.5.1')
3870 self.assertRegex(output, 'NTP: 192.168.5.1')
3871
1f0e3109 3872 def test_emit_router_timezone(self):
ec38833c 3873 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 3874 start_networkd()
e2aea43f 3875 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3876
fc79e6ff 3877 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3878 print(output)
3879 self.assertRegex(output, 'Gateway: 192.168.5.*')
3880 self.assertRegex(output, '192.168.5.*')
3881 self.assertRegex(output, 'Europe/Berlin')
3882
ffaece68 3883 def test_dhcp_server_static_lease(self):
3884 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-static-lease.network', 'dhcp-server-static-lease.network')
3885 start_networkd()
3886 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3887
3888 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3889 print(output)
af0d4e6e 3890 self.assertIn('10.1.1.200 (DHCP4 via 10.1.1.1)', output)
ffaece68 3891
c95df587
YA
3892class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
3893 links = [
3894 'client',
3895 'server',
3896 'client-peer',
3897 'server-peer',
3898 ]
3899
3900 units = [
3901 'agent-veth-client.netdev',
3902 'agent-veth-server.netdev',
3903 'agent-client.network',
3904 'agent-server.network',
3905 'agent-client-peer.network',
3906 'agent-server-peer.network',
3907 ]
3908
3909 def setUp(self):
3910 remove_links(self.links)
3911 stop_networkd(show_logs=False)
3912
3913 def tearDown(self):
3914 remove_links(self.links)
3915 remove_unit_from_networkd_path(self.units)
3916 stop_networkd(show_logs=True)
3917
3918 def test_relay_agent(self):
3919 copy_unit_to_networkd_unit_path(*self.units)
3920 start_networkd()
3921
c95df587
YA
3922 self.wait_online(['client:routable'])
3923
3924 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env)
3925 print(output)
3926 self.assertRegex(output, 'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
3927
be68c2c9 3928class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 3929 links = [
18c613dc
YW
3930 'veth99',
3931 'vrf99']
09ea6724
YW
3932
3933 units = [
3934 '25-veth.netdev',
18c613dc
YW
3935 '25-vrf.netdev',
3936 '25-vrf.network',
ab47f960 3937 'dhcp-client-allow-list.network',
09ea6724 3938 'dhcp-client-anonymize.network',
0fd8b718 3939 'dhcp-client-decline.network',
214c5bae
YW
3940 'dhcp-client-gateway-ipv4.network',
3941 'dhcp-client-gateway-ipv6.network',
af3b1498 3942 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
3943 'dhcp-client-ipv4-dhcp-settings.network',
3944 'dhcp-client-ipv4-only-ipv6-disabled.network',
3945 'dhcp-client-ipv4-only.network',
7c0d36ff 3946 'dhcp-client-ipv4-use-routes-use-gateway.network',
09ea6724
YW
3947 'dhcp-client-ipv6-only.network',
3948 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
3949 'dhcp-client-keep-configuration-dhcp-on-stop.network',
3950 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 3951 'dhcp-client-listen-port.network',
c1b01a62
YW
3952 'dhcp-client-reassign-static-routes-ipv4.network',
3953 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
3954 'dhcp-client-route-metric.network',
3955 'dhcp-client-route-table.network',
e2d5aab3
YW
3956 'dhcp-client-use-dns-ipv4-and-ra.network',
3957 'dhcp-client-use-dns-ipv4.network',
3958 'dhcp-client-use-dns-no.network',
3959 'dhcp-client-use-dns-yes.network',
e0c1341d 3960 'dhcp-client-use-domains.network',
18c613dc 3961 'dhcp-client-vrf.network',
240e4137 3962 'dhcp-client-with-ipv4ll.network',
4c882c16 3963 'dhcp-client-with-static-address.network',
3e9d5552 3964 'dhcp-client.network',
0fd8b718 3965 'dhcp-server-decline.network',
09ea6724 3966 'dhcp-server-veth-peer.network',
30d3b54e
YW
3967 'dhcp-v4-server-veth-peer.network',
3968 'static.network']
1f0e3109
SS
3969
3970 def setUp(self):
ec38833c
ZJS
3971 stop_dnsmasq(dnsmasq_pid_file)
3972 remove_links(self.links)
aaae5713 3973 stop_networkd(show_logs=False)
1f0e3109
SS
3974
3975 def tearDown(self):
ec38833c
ZJS
3976 stop_dnsmasq(dnsmasq_pid_file)
3977 remove_lease_file()
3978 remove_log_file()
3979 remove_links(self.links)
3980 remove_unit_from_networkd_path(self.units)
aaae5713 3981 stop_networkd(show_logs=True)
1f0e3109
SS
3982
3983 def test_dhcp_client_ipv6_only(self):
ec38833c 3984 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 3985
2cf6fdff 3986 start_networkd()
e2aea43f 3987 self.wait_online(['veth-peer:carrier'])
ec38833c 3988 start_dnsmasq()
e2aea43f 3989 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3990
fc79e6ff 3991 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3992 print(output)
3993 self.assertRegex(output, '2600::')
3994 self.assertNotRegex(output, '192.168.5')
3995
c5fcd8a7
YW
3996 output = check_output('ip addr show dev veth99')
3997 print(output)
3998 self.assertRegex(output, '2600::')
3999 self.assertNotRegex(output, '192.168.5')
4000 self.assertNotRegex(output, 'tentative')
4001
3a956d38 4002 # Confirm that ipv6 token is not set in the kernel
371810d1 4003 output = check_output('ip token show dev veth99')
3a956d38
YW
4004 print(output)
4005 self.assertRegex(output, 'token :: dev veth99')
4006
1f0e3109 4007 def test_dhcp_client_ipv4_only(self):
ec38833c 4008 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 4009
2cf6fdff 4010 start_networkd()
e2aea43f 4011 self.wait_online(['veth-peer:carrier'])
195a18c1 4012 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 4013 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4014
fc79e6ff 4015 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4016 print(output)
4017 self.assertNotRegex(output, '2600::')
4018 self.assertRegex(output, '192.168.5')
195a18c1
YW
4019 self.assertRegex(output, '192.168.5.6')
4020 self.assertRegex(output, '192.168.5.7')
4021
4022 # checking routes to DNS servers
4023 output = check_output('ip route show dev veth99')
4024 print(output)
4025 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4026 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
4027 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4028
4029 stop_dnsmasq(dnsmasq_pid_file)
4030 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
4031
4032 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4033 print('Wait for the dynamic address to be renewed')
4034 time.sleep(125)
4035
4036 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4037
fc79e6ff 4038 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
4039 print(output)
4040 self.assertNotRegex(output, '2600::')
4041 self.assertRegex(output, '192.168.5')
4042 self.assertNotRegex(output, '192.168.5.6')
4043 self.assertRegex(output, '192.168.5.7')
4044 self.assertRegex(output, '192.168.5.8')
4045
4046 # checking routes to DNS servers
4047 output = check_output('ip route show dev veth99')
4048 print(output)
4049 self.assertNotRegex(output, r'192.168.5.6')
4050 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4051 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4052 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 4053
7c0d36ff 4054 def test_dhcp_client_ipv4_use_routes_gateway(self):
e1220a70 4055 for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
7c0d36ff 4056 self.setUp()
e1220a70
YW
4057 with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
4058 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
7c0d36ff
DS
4059 self.tearDown()
4060
e1220a70 4061 def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
7c0d36ff
DS
4062 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
4063 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
625772c9
YW
4064 testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf');
4065 testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf');
e1220a70 4066 testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf');
7c0d36ff 4067 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
4c2e1833
YW
4068
4069 start_networkd()
4070 self.wait_online(['veth-peer:carrier'])
e1220a70 4071 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
4072 if classless:
4073 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'
4074 start_dnsmasq(additional_options=additional_options, lease_time='2m')
4c2e1833
YW
4075 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4076
625772c9 4077 output = check_output('ip -4 route show dev veth99')
4c2e1833 4078 print(output)
4c2e1833 4079
7c0d36ff 4080 # Check UseRoutes=
625772c9
YW
4081 if use_routes:
4082 if classless:
4083 self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4084 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4085 self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4086 self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4087 else:
4088 self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4089 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4090 self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4091 else:
625772c9
YW
4092 self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4093 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4094 self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4095 self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4096 self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4097 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4098 self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
0d7bd445 4099
7c0d36ff 4100 # Check UseGateway=
625772c9
YW
4101 if use_gateway and (not classless or not use_routes):
4102 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4103 else:
625772c9 4104 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32
YW
4105
4106 # Check route to gateway
4107 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes):
4108 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4109 else:
625772c9 4110 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4111
e1220a70
YW
4112 # Check RoutesToDNS= and RoutesToNTP=
4113 if dns_and_ntp_routes:
625772c9 4114 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4115 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9
YW
4116 if classless and use_routes:
4117 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4118 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32 4119 else:
625772c9 4120 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4121 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4122 else:
625772c9 4123 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4124 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9 4125 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 4126 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 4127
1f0e3109 4128 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
4129 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
4130 'dhcp-client-ipv4-only.network')
2cf6fdff 4131 start_networkd()
e2aea43f 4132 self.wait_online(['veth-peer:carrier'])
ec38833c 4133 start_dnsmasq()
e2aea43f 4134 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4135
4136 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4137 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 4138 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 4139
fc79e6ff 4140 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4141 print(output)
4142 self.assertRegex(output, '2600::')
4143 self.assertRegex(output, '192.168.5')
4144
4145 def test_dhcp_client_settings(self):
ec38833c 4146 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 4147
2cf6fdff 4148 start_networkd()
e2aea43f 4149 self.wait_online(['veth-peer:carrier'])
ec38833c 4150 start_dnsmasq()
e2aea43f 4151 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4152
0ae7a66d 4153 print('## ip address show dev veth99')
371810d1 4154 output = check_output('ip address show dev veth99')
1f0e3109
SS
4155 print(output)
4156 self.assertRegex(output, '12:34:56:78:9a:bc')
4157 self.assertRegex(output, '192.168.5')
4158 self.assertRegex(output, '1492')
d419ef02 4159 self.assertRegex(output, 'test-label')
1f0e3109 4160
0ae7a66d 4161 print('## ip route show table main dev veth99')
371810d1 4162 output = check_output('ip route show table main dev veth99')
1f0e3109 4163 print(output)
156ddf8d 4164 # See issue #8726
dd9b10c8
YW
4165 main_table_is_empty = output == ''
4166 if not main_table_is_empty:
4167 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 4168
0ae7a66d 4169 print('## ip route show table 211 dev veth99')
371810d1 4170 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
4171 print(output)
4172 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
4173 if main_table_is_empty:
4174 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
4175 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
4176
4177 print('## dnsmasq log')
ec38833c
ZJS
4178 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
4179 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
4180 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
4181 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4182
4183 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 4184 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 4185 start_networkd()
e2aea43f 4186 self.wait_online(['veth-peer:carrier'])
ec38833c 4187 start_dnsmasq()
e2aea43f 4188 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4189
371810d1 4190 output = check_output('ip address show dev veth99')
1f0e3109
SS
4191 print(output)
4192 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4193 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4194
4195 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 4196 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 4197 start_networkd()
e2aea43f 4198 self.wait_online(['veth-peer:carrier'])
ec38833c 4199 start_dnsmasq()
e2aea43f 4200 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4201
371810d1 4202 output = check_output('ip address show dev veth99')
1f0e3109
SS
4203 print(output)
4204 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4205 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4206
4207 def test_dhcp_client_settings_anonymize(self):
ec38833c 4208 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 4209 start_networkd()
e2aea43f 4210 self.wait_online(['veth-peer:carrier'])
ec38833c 4211 start_dnsmasq()
e2aea43f 4212 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4213
ec38833c
ZJS
4214 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
4215 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
4216 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4217
4218 def test_dhcp_client_listen_port(self):
ec38833c 4219 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 4220 start_networkd()
e2aea43f 4221 self.wait_online(['veth-peer:carrier'])
ec38833c 4222 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 4223 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 4224
371810d1 4225 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
4226 print(output)
4227 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 4228
4c882c16
YW
4229 def test_dhcp_client_with_static_address(self):
4230 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
4231 'dhcp-client-with-static-address.network')
4232 start_networkd()
e2aea43f 4233 self.wait_online(['veth-peer:carrier'])
4c882c16 4234 start_dnsmasq()
e2aea43f 4235 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
4236
4237 output = check_output('ip address show dev veth99 scope global')
4238 print(output)
4239 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3e726c15 4240 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
4241
4242 output = check_output('ip route show dev veth99')
4243 print(output)
4244 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
4245 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
4c882c16
YW
4246 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4247
1f0e3109 4248 def test_dhcp_route_table_id(self):
ec38833c 4249 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 4250 start_networkd()
e2aea43f 4251 self.wait_online(['veth-peer:carrier'])
ec38833c 4252 start_dnsmasq()
e2aea43f 4253 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4254
371810d1 4255 output = check_output('ip route show table 12')
1f0e3109 4256 print(output)
1f0e3109
SS
4257 self.assertRegex(output, 'veth99 proto dhcp')
4258 self.assertRegex(output, '192.168.5.1')
4259
4260 def test_dhcp_route_metric(self):
ec38833c 4261 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 4262 start_networkd()
e2aea43f 4263 self.wait_online(['veth-peer:carrier'])
ec38833c 4264 start_dnsmasq()
e2aea43f 4265 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4266
371810d1 4267 output = check_output('ip route show dev veth99')
1f0e3109 4268 print(output)
3e726c15
YW
4269 self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output)
4270 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output)
4271 self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output)
1f0e3109 4272
c1b01a62 4273 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 4274 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 4275 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 4276 start_networkd()
e2aea43f 4277 self.wait_online(['veth-peer:carrier'])
c38d2d4d 4278 start_dnsmasq(lease_time='2m')
e2aea43f 4279 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
4280
4281 output = check_output('ip address show dev veth99 scope global')
4282 print(output)
3e726c15 4283 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
c38d2d4d
YW
4284
4285 output = check_output('ip route show dev veth99')
4286 print(output)
4287 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4288 self.assertRegex(output, r'192.168.5.0/24 proto static')
4289 self.assertRegex(output, r'192.168.6.0/24 proto static')
4290 self.assertRegex(output, r'192.168.7.0/24 proto static')
4291
c1b01a62
YW
4292 stop_dnsmasq(dnsmasq_pid_file)
4293 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
4294
c38d2d4d
YW
4295 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4296 print('Wait for the dynamic address to be renewed')
4297 time.sleep(125)
4298
e2aea43f 4299 self.wait_online(['veth99:routable'])
c38d2d4d
YW
4300
4301 output = check_output('ip route show dev veth99')
4302 print(output)
4303 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4304 self.assertRegex(output, r'192.168.5.0/24 proto static')
4305 self.assertRegex(output, r'192.168.6.0/24 proto static')
4306 self.assertRegex(output, r'192.168.7.0/24 proto static')
4307
c1b01a62
YW
4308 def test_dhcp_client_reassign_static_routes_ipv6(self):
4309 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4310 'dhcp-client-reassign-static-routes-ipv6.network')
4311 start_networkd()
e2aea43f 4312 self.wait_online(['veth-peer:carrier'])
c1b01a62 4313 start_dnsmasq(lease_time='2m')
e2aea43f 4314 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
4315
4316 output = check_output('ip address show dev veth99 scope global')
4317 print(output)
426654d7 4318 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
4319
4320 output = check_output('ip -6 route show dev veth99')
4321 print(output)
4322 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4323 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4324
4325 stop_dnsmasq(dnsmasq_pid_file)
4326 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
4327
4328 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4329 print('Wait for the dynamic address to be renewed')
4330 time.sleep(125)
4331
e2aea43f 4332 self.wait_online(['veth99:routable'])
c1b01a62
YW
4333
4334 output = check_output('ip -6 route show dev veth99')
4335 print(output)
4336 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4337 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4338
1e498853
YW
4339 def test_dhcp_keep_configuration_dhcp(self):
4340 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 4341 start_networkd()
e2aea43f 4342 self.wait_online(['veth-peer:carrier'])
1e498853 4343 start_dnsmasq(lease_time='2m')
e2aea43f 4344 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4345
1e498853
YW
4346 output = check_output('ip address show dev veth99 scope global')
4347 print(output)
4348 self.assertRegex(output, r'192.168.5.*')
4349
fc79e6ff 4350 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4351 print(output)
1e498853 4352 self.assertRegex(output, r'192.168.5.*')
e40a58b5 4353
5238e957 4354 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 4355 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
4356
4357 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 4358 print('Wait for the dynamic address to be expired')
1f0e3109
SS
4359 time.sleep(125)
4360
1e498853
YW
4361 print('The lease address should be kept after lease expired')
4362 output = check_output('ip address show dev veth99 scope global')
4363 print(output)
4364 self.assertRegex(output, r'192.168.5.*')
4365
fc79e6ff 4366 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4367 print(output)
1e498853
YW
4368 self.assertRegex(output, r'192.168.5.*')
4369
3aa645f0
MB
4370 check_output('systemctl stop systemd-networkd.socket')
4371 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4372
4373 print('The lease address should be kept after networkd stopped')
4374 output = check_output('ip address show dev veth99 scope global')
4375 print(output)
4376 self.assertRegex(output, r'192.168.5.*')
4377
fc79e6ff 4378 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4379 print(output)
4380 self.assertRegex(output, r'192.168.5.*')
4381
e2aea43f
YW
4382 start_networkd(3)
4383 self.wait_online(['veth-peer:routable'])
1e498853
YW
4384
4385 print('Still the lease address should be kept after networkd restarted')
4386 output = check_output('ip address show dev veth99 scope global')
4387 print(output)
4388 self.assertRegex(output, r'192.168.5.*')
4389
fc79e6ff 4390 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4391 print(output)
4392 self.assertRegex(output, r'192.168.5.*')
4393
4394 def test_dhcp_keep_configuration_dhcp_on_stop(self):
4395 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4396 start_networkd()
e2aea43f 4397 self.wait_online(['veth-peer:carrier'])
1e498853 4398 start_dnsmasq(lease_time='2m')
e2aea43f 4399 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4400
4401 output = check_output('ip address show dev veth99 scope global')
4402 print(output)
4403 self.assertRegex(output, r'192.168.5.*')
4404
4405 stop_dnsmasq(dnsmasq_pid_file)
3aa645f0
MB
4406 check_output('systemctl stop systemd-networkd.socket')
4407 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4408
4409 output = check_output('ip address show dev veth99 scope global')
4410 print(output)
4411 self.assertRegex(output, r'192.168.5.*')
4412
e2aea43f
YW
4413 restart_networkd(3)
4414 self.wait_online(['veth-peer:routable'])
1e498853
YW
4415
4416 output = check_output('ip address show dev veth99 scope global')
4417 print(output)
4418 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 4419
30d3b54e 4420 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 4421 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 4422 start_networkd()
e2aea43f 4423 self.wait_online(['veth-peer:carrier'])
ec38833c 4424 start_dnsmasq()
e2aea43f 4425 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4426
4427 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4428 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 4429 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4430
371810d1 4431 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
4432 print(output)
4433 self.assertRegex(output, '192.168.5')
4434 self.assertRegex(output, '2600::')
4435
2629df47
YW
4436 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
4437 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
4438 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
4439 print(static_network)
4440
ec38833c 4441 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
4442
4443 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
4444 f.write(static_network)
4445
2629df47
YW
4446 # When networkd started, the links are already configured, so let's wait for 5 seconds
4447 # the links to be re-configured.
aaae5713 4448 restart_networkd(5)
e2aea43f 4449 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 4450
371810d1 4451 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
4452 print(output)
4453 self.assertRegex(output, '192.168.5')
4454 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4455
371810d1 4456 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
4457 print(output)
4458 self.assertRegex(output, '2600::')
4459 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4460
18c613dc
YW
4461 @expectedFailureIfModuleIsNotAvailable('vrf')
4462 def test_dhcp_client_vrf(self):
ec38833c
ZJS
4463 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
4464 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4465 start_networkd()
e2aea43f 4466 self.wait_online(['veth-peer:carrier'])
ec38833c 4467 start_dnsmasq()
e2aea43f 4468 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4469
4470 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4471 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 4472 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4473
4474 print('## ip -d link show dev vrf99')
371810d1 4475 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4476 print(output)
4477 self.assertRegex(output, 'vrf table 42')
4478
4479 print('## ip address show vrf vrf99')
371810d1 4480 output = check_output('ip address show vrf vrf99')
d90f4f7d 4481 print(output)
3e726c15 4482 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4483 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4484 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4485
4486 print('## ip address show dev veth99')
371810d1 4487 output = check_output('ip address show dev veth99')
18c613dc 4488 print(output)
3e726c15 4489 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4490 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4491 self.assertRegex(output, 'inet6 .* scope link')
4492
4493 print('## ip route show vrf vrf99')
371810d1 4494 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4495 print(output)
4496 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc 4497 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
18c613dc
YW
4498 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4499
4500 print('## ip route show table main dev veth99')
371810d1 4501 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4502 print(output)
4503 self.assertEqual(output, '')
4504
214c5bae
YW
4505 def test_dhcp_client_gateway_ipv4(self):
4506 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4507 'dhcp-client-gateway-ipv4.network')
4508 start_networkd()
4509 self.wait_online(['veth-peer:carrier'])
4510 start_dnsmasq()
4511 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4512
4df8a8e8 4513 output = check_output('ip route list dev veth99')
214c5bae 4514 print(output)
4df8a8e8
YW
4515 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4516 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4517
4518 with open(os.path.join(network_unit_file_path, 'dhcp-client-gateway-ipv4.network'), mode='a') as f:
4519 f.write('[DHCPv4]\nUseGateway=no\n')
4520
4521 rc = call(*networkctl_cmd, 'reload', env=env)
4522 self.assertEqual(rc, 0)
4523
4524 time.sleep(2)
4525 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4526
4527 output = check_output('ip route list dev veth99')
4528 print(output)
4529 self.assertNotRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4530 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
214c5bae
YW
4531
4532 def test_dhcp_client_gateway_ipv6(self):
4533 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4534 'dhcp-client-gateway-ipv6.network')
4535 start_networkd()
4536 self.wait_online(['veth-peer:carrier'])
4537 start_dnsmasq()
4538 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4539
4540 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4541 print(output)
4542 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4543
af3b1498 4544 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
4545 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4546 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4547 start_networkd()
e2aea43f 4548 self.wait_online(['veth-peer:carrier'])
ec38833c 4549 start_dnsmasq()
e2aea43f 4550 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4551
fc79e6ff 4552 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4553 print(output)
4554 self.assertRegex(output, '192.168.5')
4555
371810d1 4556 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4557 print(output)
4558 self.assertRegex(output, 'onlink')
371810d1 4559 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4560 print(output)
4561 self.assertRegex(output, 'onlink')
4562
3ca1fab7 4563 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
ec38833c 4564 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4565 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4566 start_networkd()
e2aea43f 4567 self.wait_online(['veth-peer:carrier'])
ec38833c 4568 start_dnsmasq(lease_time='2m')
e2aea43f 4569 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 4570
371810d1 4571 output = check_output('ip address show dev veth99')
63c598ed
YW
4572 print(output)
4573
371810d1 4574 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4575 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4576 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4577 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4578 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4579 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4580 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4581 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed
YW
4582
4583 print('Wait for the dynamic address to be expired')
4584 time.sleep(130)
4585
371810d1 4586 output = check_output('ip address show dev veth99')
63c598ed
YW
4587 print(output)
4588
371810d1 4589 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4590 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4591 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4592 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4593 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4594 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4595 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4596 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed 4597
ec38833c 4598 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 4599
3ca1fab7 4600 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
ec38833c 4601 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4602 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4603 start_networkd()
b226c15c
DS
4604 # we need to increase timeout above default, as this will need to wait for
4605 # systemd-networkd to get the dhcpv4 transient failure event
4606 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
117a55c7 4607
371810d1 4608 output = check_output('ip address show dev veth99')
117a55c7
YW
4609 print(output)
4610
371810d1 4611 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4612 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4613 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4614 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4615 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4616 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4617 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4618 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
240e4137
YW
4619
4620 start_dnsmasq(lease_time='2m')
3e726c15
YW
4621 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4622 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 4623
b6efd661 4624 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
4625 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4626 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 4627 start_networkd()
e2aea43f 4628 self.wait_online(['veth-peer:carrier'])
ec38833c 4629 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 4630 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
4631
4632 # test for issue #12490
4633
371810d1 4634 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4635 print(output)
3e726c15 4636 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4637 address1=None
4638 for line in output.splitlines():
4639 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
4640 address1 = line.split()[1].split('/')[0]
4641 break
4642
371810d1 4643 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4644 print(output)
4645 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4646 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4647
ec38833c
ZJS
4648 stop_dnsmasq(dnsmasq_pid_file)
4649 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
4650
4651 print('Wait for the dynamic address to be expired')
4652 time.sleep(130)
4653
371810d1 4654 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4655 print(output)
3e726c15 4656 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4657 address2=None
4658 for line in output.splitlines():
3e726c15 4659 if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line:
b6efd661
YW
4660 address2 = line.split()[1].split('/')[0]
4661 break
4662
4663 self.assertNotEqual(address1, address2)
4664
371810d1 4665 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4666 print(output)
4667 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4668 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4669 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
4670 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
4671
e2d5aab3
YW
4672 def test_dhcp_client_use_dns_yes(self):
4673 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
4674
4675 start_networkd()
e2aea43f 4676 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4677 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4678 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4679
4680 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4681 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 4682 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4683
693283cd 4684 time.sleep(3)
e2d5aab3
YW
4685 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4686 print(output)
4687 self.assertRegex(output, '192.168.5.1')
4688 self.assertRegex(output, '2600::1')
4689
4690 def test_dhcp_client_use_dns_no(self):
4691 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
4692
4693 start_networkd()
e2aea43f 4694 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4695 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4696 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4697
4698 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4699 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 4700 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4701
693283cd 4702 time.sleep(3)
e2d5aab3
YW
4703 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4704 print(output)
4705 self.assertNotRegex(output, '192.168.5.1')
4706 self.assertNotRegex(output, '2600::1')
4707
4708 def test_dhcp_client_use_dns_ipv4(self):
4709 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
4710
4711 start_networkd()
e2aea43f 4712 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4713 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4714 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4715
4716 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4717 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 4718 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4719
693283cd 4720 time.sleep(3)
e2d5aab3
YW
4721 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4722 print(output)
4723 self.assertRegex(output, '192.168.5.1')
4724 self.assertNotRegex(output, '2600::1')
4725
4726 def test_dhcp_client_use_dns_ipv4_and_ra(self):
4727 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
4728
4729 start_networkd()
e2aea43f 4730 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4731 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4732 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4733
4734 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4735 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 4736 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4737
693283cd 4738 time.sleep(3)
e2d5aab3
YW
4739 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4740 print(output)
4741 self.assertRegex(output, '192.168.5.1')
4742 self.assertRegex(output, '2600::1')
4743
e0c1341d
YW
4744 def test_dhcp_client_use_domains(self):
4745 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
4746
4747 start_networkd()
e2aea43f 4748 self.wait_online(['veth-peer:carrier'])
e0c1341d 4749 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 4750 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 4751
fc79e6ff 4752 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
4753 print(output)
4754 self.assertRegex(output, 'Search Domains: example.com')
4755
4756 time.sleep(3)
4757 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
4758 print(output)
4759 self.assertRegex(output, 'example.com')
4760
0fd8b718
YW
4761 def test_dhcp_client_decline(self):
4762 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
4763
4764 start_networkd()
44924431
YW
4765 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4766
4767 output = check_output('ip -4 address show dev veth99 scope global dynamic')
4768 print(output)
4769 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
0fd8b718 4770
ab47f960
YW
4771 def test_dhcp_client_allow_list(self):
4772 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-allow-list.network')
4773
4774 start_networkd()
4775 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4776
4777 output = check_output('ip -4 address show dev veth99 scope global dynamic')
4778 print(output)
4779 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
4780
9633f977 4781class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
4a906586
YW
4782 links = [
4783 'dummy98',
4784 'veth99',
4785 ]
9633f977
SS
4786
4787 units = [
4a906586 4788 '12-dummy.netdev',
9633f977 4789 '25-veth.netdev',
635f2a66 4790 'ipv6ra-prefix-client-deny-list.network',
9633f977 4791 'ipv6ra-prefix-client.network',
4a906586
YW
4792 'ipv6ra-prefix.network',
4793 'ipv6ra-uplink.network',
4794 ]
9633f977
SS
4795
4796 def setUp(self):
4797 remove_links(self.links)
4798 stop_networkd(show_logs=False)
4799
4800 def tearDown(self):
4801 remove_log_file()
4802 remove_links(self.links)
4803 remove_unit_from_networkd_path(self.units)
4804 stop_networkd(show_logs=True)
4805
4806 def test_ipv6_route_prefix(self):
4a906586
YW
4807 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network',
4808 '12-dummy.netdev', 'ipv6ra-uplink.network')
9633f977
SS
4809
4810 start_networkd()
4a906586 4811 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
9633f977 4812
635f2a66
YW
4813 output = check_output('ip address show dev veth-peer')
4814 print(output)
4815 self.assertIn('inet6 2001:db8:0:1:', output)
4816 self.assertNotIn('inet6 2001:db8:0:2:', output)
ab47f960 4817 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 4818
3c874fd7 4819 output = check_output('ip -6 route show dev veth-peer')
9633f977 4820 print(output)
635f2a66
YW
4821 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4822 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
ab47f960 4823 self.assertNotIn('2001:db8:0:3::/64 proto ra', output)
635f2a66
YW
4824 self.assertIn('2001:db0:fff::/64 via ', output)
4825 self.assertNotIn('2001:db1:fff::/64 via ', output)
ab47f960 4826 self.assertNotIn('2001:db2:fff::/64 via ', output)
9633f977 4827
635f2a66
YW
4828 output = check_output('ip address show dev veth99')
4829 print(output)
4830 self.assertNotIn('inet6 2001:db8:0:1:', output)
4831 self.assertIn('inet6 2001:db8:0:2:', output)
ab47f960 4832 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 4833
4a906586
YW
4834 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
4835 print(output)
4836 self.assertRegex(output, '2001:db8:1:1::2')
4837
4838 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
4839 print(output)
4840 self.assertIn('example.com', output)
4841
635f2a66 4842 def test_ipv6_route_prefix_deny_list(self):
4a906586
YW
4843 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network',
4844 '12-dummy.netdev', 'ipv6ra-uplink.network')
635f2a66
YW
4845
4846 start_networkd()
4a906586 4847 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
635f2a66
YW
4848
4849 output = check_output('ip address show dev veth-peer')
4850 print(output)
4851 self.assertIn('inet6 2001:db8:0:1:', output)
4852 self.assertNotIn('inet6 2001:db8:0:2:', output)
4853
4854 output = check_output('ip -6 route show dev veth-peer')
4855 print(output)
4856 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4857 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4858 self.assertIn('2001:db0:fff::/64 via ', output)
4859 self.assertNotIn('2001:db1:fff::/64 via ', output)
4860
4861 output = check_output('ip address show dev veth99')
3c874fd7 4862 print(output)
635f2a66
YW
4863 self.assertNotIn('inet6 2001:db8:0:1:', output)
4864 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 4865
4a906586
YW
4866 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
4867 print(output)
4868 self.assertRegex(output, '2001:db8:1:1::2')
4869
4870 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
4871 print(output)
4872 self.assertIn('example.com', output)
4873
7db05447
DS
4874class NetworkdMTUTests(unittest.TestCase, Utilities):
4875 links = ['dummy98']
4876
4877 units = [
4878 '12-dummy.netdev',
4879 '12-dummy-mtu.netdev',
4880 '12-dummy-mtu.link',
4881 '12-dummy.network',
4882 ]
4883
4884 def setUp(self):
4885 remove_links(self.links)
4886 stop_networkd(show_logs=False)
4887
4888 def tearDown(self):
4889 remove_log_file()
4890 remove_links(self.links)
4891 remove_unit_from_networkd_path(self.units)
4892 stop_networkd(show_logs=True)
4893
4894 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
4895 if not ipv6_mtu:
4896 ipv6_mtu = mtu
4897
4898 # test normal start
4899 start_networkd()
4900 self.wait_online(['dummy98:routable'])
4901 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4902 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4903
4904 # test normal restart
4905 restart_networkd()
4906 self.wait_online(['dummy98:routable'])
4907 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4908 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4909
4910 if reset:
4911 self.reset_check_mtu(mtu, ipv6_mtu)
4912
4913 def reset_check_mtu(self, mtu, ipv6_mtu=None):
4914 ''' test setting mtu/ipv6_mtu with interface already up '''
4915 stop_networkd()
4916
4917 # note - changing the device mtu resets the ipv6 mtu
4918 run('ip link set up mtu 1501 dev dummy98')
4919 run('ip link set up mtu 1500 dev dummy98')
4920 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
4921 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
4922
4923 self.check_mtu(mtu, ipv6_mtu, reset=False)
4924
4925 def test_mtu_network(self):
4926 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
4927 self.check_mtu('1600')
4928
4929 def test_mtu_netdev(self):
4930 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
4931 # note - MTU set by .netdev happens ONLY at device creation!
4932 self.check_mtu('1600', reset=False)
4933
4934 def test_mtu_link(self):
4935 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
4936 # must reload udev because it only picks up new files after 3 second delay
4937 call('udevadm control --reload')
4938 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
4939 self.check_mtu('1600', reset=False)
4940
4941 def test_ipv6_mtu(self):
4942 ''' set ipv6 mtu without setting device mtu '''
4943 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
4944 self.check_mtu('1500', '1400')
4945
4946 def test_ipv6_mtu_toolarge(self):
4947 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
4948 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4949 self.check_mtu('1500', '1500')
4950
4951 def test_mtu_network_ipv6_mtu(self):
4952 ''' set ipv6 mtu and set device mtu via network file '''
4953 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
4954 self.check_mtu('1600', '1550')
4955
4956 def test_mtu_netdev_ipv6_mtu(self):
4957 ''' set ipv6 mtu and set device mtu via netdev file '''
4958 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4959 self.check_mtu('1600', '1550', reset=False)
4960
4961 def test_mtu_link_ipv6_mtu(self):
4962 ''' set ipv6 mtu and set device mtu via link file '''
4963 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
4964 # must reload udev because it only picks up new files after 3 second delay
4965 call('udevadm control --reload')
4966 self.check_mtu('1600', '1550', reset=False)
4967
4968
1f0e3109 4969if __name__ == '__main__':
9c1ae484
YW
4970 parser = argparse.ArgumentParser()
4971 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
4972 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 4973 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 4974 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
4975 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
4976 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
4977 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
4978 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
4979 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
4980 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 4981 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 4982 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 4983 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
4984 ns, args = parser.parse_known_args(namespace=unittest)
4985
4986 if ns.build_dir:
641aa412 4987 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 4988 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 4989 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 4990 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 4991 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
4992 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
4993 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
4994 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
4995 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
4996 else:
4997 if ns.networkd_bin:
4998 networkd_bin = ns.networkd_bin
b6d587d1
YW
4999 if ns.resolved_bin:
5000 resolved_bin = ns.resolved_bin
641aa412
YW
5001 if ns.udevd_bin:
5002 udevd_bin = ns.udevd_bin
9c1ae484
YW
5003 if ns.wait_online_bin:
5004 wait_online_bin = ns.wait_online_bin
5005 if ns.networkctl_bin:
5006 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
5007 if ns.resolvectl_bin:
5008 resolvectl_bin = ns.resolvectl_bin
5009 if ns.timedatectl_bin:
5010 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
5011
5012 use_valgrind = ns.use_valgrind
5013 enable_debug = ns.enable_debug
94c03122 5014 asan_options = ns.asan_options
fa4c6095 5015 lsan_options = ns.lsan_options
94c03122 5016 ubsan_options = ns.ubsan_options
9c1ae484
YW
5017
5018 if use_valgrind:
5019 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
5020 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
5021 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
5022 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
5023 else:
5024 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
5025 resolvectl_cmd = [resolvectl_bin]
5026 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
5027 wait_online_cmd = [wait_online_bin]
5028
5029 if enable_debug:
5030 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
5031 if asan_options:
5032 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
5033 if lsan_options:
5034 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
5035 if ubsan_options:
5036 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
5037
5038 sys.argv[1:] = args
1f0e3109
SS
5039 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
5040 verbosity=3))