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