]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
sd-netlink: always append new bridge FDB entries
[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')
7c0d36ff 4020 else:
625772c9 4021 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32
YW
4022
4023 # Check route to gateway
4024 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes):
4025 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4026 else:
625772c9 4027 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4028
e1220a70
YW
4029 # Check RoutesToDNS= and RoutesToNTP=
4030 if dns_and_ntp_routes:
625772c9 4031 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4032 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9
YW
4033 if classless and use_routes:
4034 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4035 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32 4036 else:
625772c9 4037 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4038 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4039 else:
625772c9 4040 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4041 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9 4042 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 4043 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 4044
1f0e3109 4045 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
4046 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
4047 'dhcp-client-ipv4-only.network')
2cf6fdff 4048 start_networkd()
e2aea43f 4049 self.wait_online(['veth-peer:carrier'])
ec38833c 4050 start_dnsmasq()
e2aea43f 4051 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4052
4053 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4054 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 4055 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 4056
fc79e6ff 4057 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4058 print(output)
4059 self.assertRegex(output, '2600::')
4060 self.assertRegex(output, '192.168.5')
4061
4062 def test_dhcp_client_settings(self):
ec38833c 4063 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 4064
2cf6fdff 4065 start_networkd()
e2aea43f 4066 self.wait_online(['veth-peer:carrier'])
ec38833c 4067 start_dnsmasq()
e2aea43f 4068 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4069
0ae7a66d 4070 print('## ip address show dev veth99')
371810d1 4071 output = check_output('ip address show dev veth99')
1f0e3109
SS
4072 print(output)
4073 self.assertRegex(output, '12:34:56:78:9a:bc')
4074 self.assertRegex(output, '192.168.5')
4075 self.assertRegex(output, '1492')
4076
0ae7a66d 4077 print('## ip route show table main dev veth99')
371810d1 4078 output = check_output('ip route show table main dev veth99')
1f0e3109 4079 print(output)
156ddf8d 4080 # See issue #8726
dd9b10c8
YW
4081 main_table_is_empty = output == ''
4082 if not main_table_is_empty:
4083 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 4084
0ae7a66d 4085 print('## ip route show table 211 dev veth99')
371810d1 4086 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
4087 print(output)
4088 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
4089 if main_table_is_empty:
4090 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
4091 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
4092
4093 print('## dnsmasq log')
ec38833c
ZJS
4094 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
4095 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
4096 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
4097 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4098
4099 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 4100 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 4101 start_networkd()
e2aea43f 4102 self.wait_online(['veth-peer:carrier'])
ec38833c 4103 start_dnsmasq()
e2aea43f 4104 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4105
371810d1 4106 output = check_output('ip address show dev veth99')
1f0e3109
SS
4107 print(output)
4108 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4109 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4110
4111 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 4112 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 4113 start_networkd()
e2aea43f 4114 self.wait_online(['veth-peer:carrier'])
ec38833c 4115 start_dnsmasq()
e2aea43f 4116 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4117
371810d1 4118 output = check_output('ip address show dev veth99')
1f0e3109
SS
4119 print(output)
4120 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 4121 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
4122
4123 def test_dhcp_client_settings_anonymize(self):
ec38833c 4124 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 4125 start_networkd()
e2aea43f 4126 self.wait_online(['veth-peer:carrier'])
ec38833c 4127 start_dnsmasq()
e2aea43f 4128 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4129
ec38833c
ZJS
4130 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
4131 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
4132 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4133
4134 def test_dhcp_client_listen_port(self):
ec38833c 4135 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 4136 start_networkd()
e2aea43f 4137 self.wait_online(['veth-peer:carrier'])
ec38833c 4138 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 4139 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 4140
371810d1 4141 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
4142 print(output)
4143 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 4144
4c882c16
YW
4145 def test_dhcp_client_with_static_address(self):
4146 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
4147 'dhcp-client-with-static-address.network')
4148 start_networkd()
e2aea43f 4149 self.wait_online(['veth-peer:carrier'])
4c882c16 4150 start_dnsmasq()
e2aea43f 4151 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
4152
4153 output = check_output('ip address show dev veth99 scope global')
4154 print(output)
4155 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3e726c15 4156 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
4157
4158 output = check_output('ip route show dev veth99')
4159 print(output)
4160 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
4161 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
4c882c16
YW
4162 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4163
1f0e3109 4164 def test_dhcp_route_table_id(self):
ec38833c 4165 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 4166 start_networkd()
e2aea43f 4167 self.wait_online(['veth-peer:carrier'])
ec38833c 4168 start_dnsmasq()
e2aea43f 4169 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4170
371810d1 4171 output = check_output('ip route show table 12')
1f0e3109 4172 print(output)
1f0e3109
SS
4173 self.assertRegex(output, 'veth99 proto dhcp')
4174 self.assertRegex(output, '192.168.5.1')
4175
4176 def test_dhcp_route_metric(self):
ec38833c 4177 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 4178 start_networkd()
e2aea43f 4179 self.wait_online(['veth-peer:carrier'])
ec38833c 4180 start_dnsmasq()
e2aea43f 4181 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4182
371810d1 4183 output = check_output('ip route show dev veth99')
1f0e3109 4184 print(output)
3e726c15
YW
4185 self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output)
4186 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output)
4187 self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output)
1f0e3109 4188
c1b01a62 4189 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 4190 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 4191 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 4192 start_networkd()
e2aea43f 4193 self.wait_online(['veth-peer:carrier'])
c38d2d4d 4194 start_dnsmasq(lease_time='2m')
e2aea43f 4195 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
4196
4197 output = check_output('ip address show dev veth99 scope global')
4198 print(output)
3e726c15 4199 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
c38d2d4d
YW
4200
4201 output = check_output('ip route show dev veth99')
4202 print(output)
4203 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4204 self.assertRegex(output, r'192.168.5.0/24 proto static')
4205 self.assertRegex(output, r'192.168.6.0/24 proto static')
4206 self.assertRegex(output, r'192.168.7.0/24 proto static')
4207
c1b01a62
YW
4208 stop_dnsmasq(dnsmasq_pid_file)
4209 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
4210
c38d2d4d
YW
4211 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4212 print('Wait for the dynamic address to be renewed')
4213 time.sleep(125)
4214
e2aea43f 4215 self.wait_online(['veth99:routable'])
c38d2d4d
YW
4216
4217 output = check_output('ip route show dev veth99')
4218 print(output)
4219 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4220 self.assertRegex(output, r'192.168.5.0/24 proto static')
4221 self.assertRegex(output, r'192.168.6.0/24 proto static')
4222 self.assertRegex(output, r'192.168.7.0/24 proto static')
4223
c1b01a62
YW
4224 def test_dhcp_client_reassign_static_routes_ipv6(self):
4225 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4226 'dhcp-client-reassign-static-routes-ipv6.network')
4227 start_networkd()
e2aea43f 4228 self.wait_online(['veth-peer:carrier'])
c1b01a62 4229 start_dnsmasq(lease_time='2m')
e2aea43f 4230 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
4231
4232 output = check_output('ip address show dev veth99 scope global')
4233 print(output)
426654d7 4234 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
4235
4236 output = check_output('ip -6 route show dev veth99')
4237 print(output)
4238 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4239 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4240
4241 stop_dnsmasq(dnsmasq_pid_file)
4242 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
4243
4244 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4245 print('Wait for the dynamic address to be renewed')
4246 time.sleep(125)
4247
e2aea43f 4248 self.wait_online(['veth99:routable'])
c1b01a62
YW
4249
4250 output = check_output('ip -6 route show dev veth99')
4251 print(output)
4252 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4253 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4254
1e498853
YW
4255 def test_dhcp_keep_configuration_dhcp(self):
4256 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 4257 start_networkd()
e2aea43f 4258 self.wait_online(['veth-peer:carrier'])
1e498853 4259 start_dnsmasq(lease_time='2m')
e2aea43f 4260 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4261
1e498853
YW
4262 output = check_output('ip address show dev veth99 scope global')
4263 print(output)
4264 self.assertRegex(output, r'192.168.5.*')
4265
fc79e6ff 4266 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4267 print(output)
1e498853 4268 self.assertRegex(output, r'192.168.5.*')
e40a58b5 4269
5238e957 4270 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 4271 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
4272
4273 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 4274 print('Wait for the dynamic address to be expired')
1f0e3109
SS
4275 time.sleep(125)
4276
1e498853
YW
4277 print('The lease address should be kept after lease expired')
4278 output = check_output('ip address show dev veth99 scope global')
4279 print(output)
4280 self.assertRegex(output, r'192.168.5.*')
4281
fc79e6ff 4282 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4283 print(output)
1e498853
YW
4284 self.assertRegex(output, r'192.168.5.*')
4285
3aa645f0
MB
4286 check_output('systemctl stop systemd-networkd.socket')
4287 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4288
4289 print('The lease address should be kept after networkd stopped')
4290 output = check_output('ip address show dev veth99 scope global')
4291 print(output)
4292 self.assertRegex(output, r'192.168.5.*')
4293
fc79e6ff 4294 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4295 print(output)
4296 self.assertRegex(output, r'192.168.5.*')
4297
e2aea43f
YW
4298 start_networkd(3)
4299 self.wait_online(['veth-peer:routable'])
1e498853
YW
4300
4301 print('Still the lease address should be kept after networkd restarted')
4302 output = check_output('ip address show dev veth99 scope global')
4303 print(output)
4304 self.assertRegex(output, r'192.168.5.*')
4305
fc79e6ff 4306 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4307 print(output)
4308 self.assertRegex(output, r'192.168.5.*')
4309
4310 def test_dhcp_keep_configuration_dhcp_on_stop(self):
4311 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4312 start_networkd()
e2aea43f 4313 self.wait_online(['veth-peer:carrier'])
1e498853 4314 start_dnsmasq(lease_time='2m')
e2aea43f 4315 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4316
4317 output = check_output('ip address show dev veth99 scope global')
4318 print(output)
4319 self.assertRegex(output, r'192.168.5.*')
4320
4321 stop_dnsmasq(dnsmasq_pid_file)
3aa645f0
MB
4322 check_output('systemctl stop systemd-networkd.socket')
4323 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4324
4325 output = check_output('ip address show dev veth99 scope global')
4326 print(output)
4327 self.assertRegex(output, r'192.168.5.*')
4328
e2aea43f
YW
4329 restart_networkd(3)
4330 self.wait_online(['veth-peer:routable'])
1e498853
YW
4331
4332 output = check_output('ip address show dev veth99 scope global')
4333 print(output)
4334 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 4335
30d3b54e 4336 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 4337 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 4338 start_networkd()
e2aea43f 4339 self.wait_online(['veth-peer:carrier'])
ec38833c 4340 start_dnsmasq()
e2aea43f 4341 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4342
4343 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4344 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 4345 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4346
371810d1 4347 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
4348 print(output)
4349 self.assertRegex(output, '192.168.5')
4350 self.assertRegex(output, '2600::')
4351
2629df47
YW
4352 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
4353 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
4354 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
4355 print(static_network)
4356
ec38833c 4357 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
4358
4359 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
4360 f.write(static_network)
4361
2629df47
YW
4362 # When networkd started, the links are already configured, so let's wait for 5 seconds
4363 # the links to be re-configured.
aaae5713 4364 restart_networkd(5)
e2aea43f 4365 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 4366
371810d1 4367 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
4368 print(output)
4369 self.assertRegex(output, '192.168.5')
4370 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4371
371810d1 4372 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
4373 print(output)
4374 self.assertRegex(output, '2600::')
4375 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4376
18c613dc
YW
4377 @expectedFailureIfModuleIsNotAvailable('vrf')
4378 def test_dhcp_client_vrf(self):
ec38833c
ZJS
4379 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
4380 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4381 start_networkd()
e2aea43f 4382 self.wait_online(['veth-peer:carrier'])
ec38833c 4383 start_dnsmasq()
e2aea43f 4384 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4385
4386 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4387 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 4388 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4389
4390 print('## ip -d link show dev vrf99')
371810d1 4391 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4392 print(output)
4393 self.assertRegex(output, 'vrf table 42')
4394
4395 print('## ip address show vrf vrf99')
371810d1 4396 output = check_output('ip address show vrf vrf99')
d90f4f7d 4397 print(output)
3e726c15 4398 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4399 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4400 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4401
4402 print('## ip address show dev veth99')
371810d1 4403 output = check_output('ip address show dev veth99')
18c613dc 4404 print(output)
3e726c15 4405 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4406 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4407 self.assertRegex(output, 'inet6 .* scope link')
4408
4409 print('## ip route show vrf vrf99')
371810d1 4410 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4411 print(output)
4412 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc 4413 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
18c613dc
YW
4414 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4415
4416 print('## ip route show table main dev veth99')
371810d1 4417 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4418 print(output)
4419 self.assertEqual(output, '')
4420
214c5bae
YW
4421 def test_dhcp_client_gateway_ipv4(self):
4422 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4423 'dhcp-client-gateway-ipv4.network')
4424 start_networkd()
4425 self.wait_online(['veth-peer:carrier'])
4426 start_dnsmasq()
4427 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4428
4df8a8e8 4429 output = check_output('ip route list dev veth99')
214c5bae 4430 print(output)
4df8a8e8
YW
4431 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4432 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4433
4434 with open(os.path.join(network_unit_file_path, 'dhcp-client-gateway-ipv4.network'), mode='a') as f:
4435 f.write('[DHCPv4]\nUseGateway=no\n')
4436
4437 rc = call(*networkctl_cmd, 'reload', env=env)
4438 self.assertEqual(rc, 0)
4439
4440 time.sleep(2)
4441 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4442
4443 output = check_output('ip route list dev veth99')
4444 print(output)
4445 self.assertNotRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4446 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
214c5bae
YW
4447
4448 def test_dhcp_client_gateway_ipv6(self):
4449 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4450 'dhcp-client-gateway-ipv6.network')
4451 start_networkd()
4452 self.wait_online(['veth-peer:carrier'])
4453 start_dnsmasq()
4454 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4455
4456 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4457 print(output)
4458 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4459
af3b1498 4460 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
4461 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4462 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4463 start_networkd()
e2aea43f 4464 self.wait_online(['veth-peer:carrier'])
ec38833c 4465 start_dnsmasq()
e2aea43f 4466 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4467
fc79e6ff 4468 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4469 print(output)
4470 self.assertRegex(output, '192.168.5')
4471
371810d1 4472 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4473 print(output)
4474 self.assertRegex(output, 'onlink')
371810d1 4475 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4476 print(output)
4477 self.assertRegex(output, 'onlink')
4478
3ca1fab7 4479 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
ec38833c 4480 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4481 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4482 start_networkd()
e2aea43f 4483 self.wait_online(['veth-peer:carrier'])
ec38833c 4484 start_dnsmasq(lease_time='2m')
e2aea43f 4485 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 4486
371810d1 4487 output = check_output('ip address show dev veth99')
63c598ed
YW
4488 print(output)
4489
371810d1 4490 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4491 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4492 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4493 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4494 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4495 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4496 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4497 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed
YW
4498
4499 print('Wait for the dynamic address to be expired')
4500 time.sleep(130)
4501
371810d1 4502 output = check_output('ip address show dev veth99')
63c598ed
YW
4503 print(output)
4504
371810d1 4505 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4506 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4507 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4508 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4509 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4510 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4511 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4512 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed 4513
ec38833c 4514 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 4515
3ca1fab7 4516 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
ec38833c 4517 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4518 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4519 start_networkd()
b226c15c
DS
4520 # we need to increase timeout above default, as this will need to wait for
4521 # systemd-networkd to get the dhcpv4 transient failure event
4522 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
117a55c7 4523
371810d1 4524 output = check_output('ip address show dev veth99')
117a55c7
YW
4525 print(output)
4526
371810d1 4527 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4528 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4529 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4530 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4531 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4532 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4533 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4534 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
240e4137
YW
4535
4536 start_dnsmasq(lease_time='2m')
3e726c15
YW
4537 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4538 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 4539
b6efd661 4540 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
4541 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4542 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 4543 start_networkd()
e2aea43f 4544 self.wait_online(['veth-peer:carrier'])
ec38833c 4545 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 4546 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
4547
4548 # test for issue #12490
4549
371810d1 4550 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4551 print(output)
3e726c15 4552 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4553 address1=None
4554 for line in output.splitlines():
4555 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
4556 address1 = line.split()[1].split('/')[0]
4557 break
4558
371810d1 4559 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4560 print(output)
4561 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4562 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4563
ec38833c
ZJS
4564 stop_dnsmasq(dnsmasq_pid_file)
4565 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
4566
4567 print('Wait for the dynamic address to be expired')
4568 time.sleep(130)
4569
371810d1 4570 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 4571 print(output)
3e726c15 4572 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
4573 address2=None
4574 for line in output.splitlines():
3e726c15 4575 if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line:
b6efd661
YW
4576 address2 = line.split()[1].split('/')[0]
4577 break
4578
4579 self.assertNotEqual(address1, address2)
4580
371810d1 4581 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4582 print(output)
4583 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4584 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4585 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
4586 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
4587
e2d5aab3
YW
4588 def test_dhcp_client_use_dns_yes(self):
4589 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
4590
4591 start_networkd()
e2aea43f 4592 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4593 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4594 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4595
4596 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4597 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 4598 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4599
693283cd 4600 time.sleep(3)
e2d5aab3
YW
4601 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4602 print(output)
4603 self.assertRegex(output, '192.168.5.1')
4604 self.assertRegex(output, '2600::1')
4605
4606 def test_dhcp_client_use_dns_no(self):
4607 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
4608
4609 start_networkd()
e2aea43f 4610 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4611 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4612 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4613
4614 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4615 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 4616 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4617
693283cd 4618 time.sleep(3)
e2d5aab3
YW
4619 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4620 print(output)
4621 self.assertNotRegex(output, '192.168.5.1')
4622 self.assertNotRegex(output, '2600::1')
4623
4624 def test_dhcp_client_use_dns_ipv4(self):
4625 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
4626
4627 start_networkd()
e2aea43f 4628 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4629 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4630 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4631
4632 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4633 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 4634 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4635
693283cd 4636 time.sleep(3)
e2d5aab3
YW
4637 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4638 print(output)
4639 self.assertRegex(output, '192.168.5.1')
4640 self.assertNotRegex(output, '2600::1')
4641
4642 def test_dhcp_client_use_dns_ipv4_and_ra(self):
4643 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
4644
4645 start_networkd()
e2aea43f 4646 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4647 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4648 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4649
4650 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4651 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 4652 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4653
693283cd 4654 time.sleep(3)
e2d5aab3
YW
4655 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4656 print(output)
4657 self.assertRegex(output, '192.168.5.1')
4658 self.assertRegex(output, '2600::1')
4659
e0c1341d
YW
4660 def test_dhcp_client_use_domains(self):
4661 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
4662
4663 start_networkd()
e2aea43f 4664 self.wait_online(['veth-peer:carrier'])
e0c1341d 4665 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 4666 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 4667
fc79e6ff 4668 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
4669 print(output)
4670 self.assertRegex(output, 'Search Domains: example.com')
4671
4672 time.sleep(3)
4673 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
4674 print(output)
4675 self.assertRegex(output, 'example.com')
4676
0fd8b718
YW
4677 def test_dhcp_client_decline(self):
4678 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
4679
4680 start_networkd()
44924431
YW
4681 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4682
4683 output = check_output('ip -4 address show dev veth99 scope global dynamic')
4684 print(output)
4685 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
0fd8b718 4686
9633f977
SS
4687class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
4688 links = ['veth99']
4689
4690 units = [
4691 '25-veth.netdev',
635f2a66 4692 'ipv6ra-prefix-client-deny-list.network',
9633f977
SS
4693 'ipv6ra-prefix-client.network',
4694 'ipv6ra-prefix.network'
4695 ]
4696
4697 def setUp(self):
4698 remove_links(self.links)
4699 stop_networkd(show_logs=False)
4700
4701 def tearDown(self):
4702 remove_log_file()
4703 remove_links(self.links)
4704 remove_unit_from_networkd_path(self.units)
4705 stop_networkd(show_logs=True)
4706
4707 def test_ipv6_route_prefix(self):
4708 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
4709
4710 start_networkd()
9633f977
SS
4711 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4712
635f2a66
YW
4713 output = check_output('ip address show dev veth-peer')
4714 print(output)
4715 self.assertIn('inet6 2001:db8:0:1:', output)
4716 self.assertNotIn('inet6 2001:db8:0:2:', output)
4717
3c874fd7 4718 output = check_output('ip -6 route show dev veth-peer')
9633f977 4719 print(output)
635f2a66
YW
4720 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4721 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4722 self.assertIn('2001:db0:fff::/64 via ', output)
4723 self.assertNotIn('2001:db1:fff::/64 via ', output)
9633f977 4724
635f2a66
YW
4725 output = check_output('ip address show dev veth99')
4726 print(output)
4727 self.assertNotIn('inet6 2001:db8:0:1:', output)
4728 self.assertIn('inet6 2001:db8:0:2:', output)
4729
4730 def test_ipv6_route_prefix_deny_list(self):
4731 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network')
4732
4733 start_networkd()
4734 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4735
4736 output = check_output('ip address show dev veth-peer')
4737 print(output)
4738 self.assertIn('inet6 2001:db8:0:1:', output)
4739 self.assertNotIn('inet6 2001:db8:0:2:', output)
4740
4741 output = check_output('ip -6 route show dev veth-peer')
4742 print(output)
4743 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4744 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4745 self.assertIn('2001:db0:fff::/64 via ', output)
4746 self.assertNotIn('2001:db1:fff::/64 via ', output)
4747
4748 output = check_output('ip address show dev veth99')
3c874fd7 4749 print(output)
635f2a66
YW
4750 self.assertNotIn('inet6 2001:db8:0:1:', output)
4751 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 4752
7db05447
DS
4753class NetworkdMTUTests(unittest.TestCase, Utilities):
4754 links = ['dummy98']
4755
4756 units = [
4757 '12-dummy.netdev',
4758 '12-dummy-mtu.netdev',
4759 '12-dummy-mtu.link',
4760 '12-dummy.network',
4761 ]
4762
4763 def setUp(self):
4764 remove_links(self.links)
4765 stop_networkd(show_logs=False)
4766
4767 def tearDown(self):
4768 remove_log_file()
4769 remove_links(self.links)
4770 remove_unit_from_networkd_path(self.units)
4771 stop_networkd(show_logs=True)
4772
4773 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
4774 if not ipv6_mtu:
4775 ipv6_mtu = mtu
4776
4777 # test normal start
4778 start_networkd()
4779 self.wait_online(['dummy98:routable'])
4780 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4781 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4782
4783 # test normal restart
4784 restart_networkd()
4785 self.wait_online(['dummy98:routable'])
4786 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4787 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4788
4789 if reset:
4790 self.reset_check_mtu(mtu, ipv6_mtu)
4791
4792 def reset_check_mtu(self, mtu, ipv6_mtu=None):
4793 ''' test setting mtu/ipv6_mtu with interface already up '''
4794 stop_networkd()
4795
4796 # note - changing the device mtu resets the ipv6 mtu
4797 run('ip link set up mtu 1501 dev dummy98')
4798 run('ip link set up mtu 1500 dev dummy98')
4799 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
4800 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
4801
4802 self.check_mtu(mtu, ipv6_mtu, reset=False)
4803
4804 def test_mtu_network(self):
4805 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
4806 self.check_mtu('1600')
4807
4808 def test_mtu_netdev(self):
4809 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
4810 # note - MTU set by .netdev happens ONLY at device creation!
4811 self.check_mtu('1600', reset=False)
4812
4813 def test_mtu_link(self):
4814 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
4815 # must reload udev because it only picks up new files after 3 second delay
4816 call('udevadm control --reload')
4817 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
4818 self.check_mtu('1600', reset=False)
4819
4820 def test_ipv6_mtu(self):
4821 ''' set ipv6 mtu without setting device mtu '''
4822 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
4823 self.check_mtu('1500', '1400')
4824
4825 def test_ipv6_mtu_toolarge(self):
4826 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
4827 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4828 self.check_mtu('1500', '1500')
4829
4830 def test_mtu_network_ipv6_mtu(self):
4831 ''' set ipv6 mtu and set device mtu via network file '''
4832 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
4833 self.check_mtu('1600', '1550')
4834
4835 def test_mtu_netdev_ipv6_mtu(self):
4836 ''' set ipv6 mtu and set device mtu via netdev file '''
4837 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4838 self.check_mtu('1600', '1550', reset=False)
4839
4840 def test_mtu_link_ipv6_mtu(self):
4841 ''' set ipv6 mtu and set device mtu via link file '''
4842 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
4843 # must reload udev because it only picks up new files after 3 second delay
4844 call('udevadm control --reload')
4845 self.check_mtu('1600', '1550', reset=False)
4846
4847
1f0e3109 4848if __name__ == '__main__':
9c1ae484
YW
4849 parser = argparse.ArgumentParser()
4850 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
4851 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 4852 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 4853 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
4854 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
4855 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
4856 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
4857 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
4858 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
4859 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 4860 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 4861 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 4862 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
4863 ns, args = parser.parse_known_args(namespace=unittest)
4864
4865 if ns.build_dir:
641aa412 4866 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 4867 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 4868 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 4869 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 4870 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
4871 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
4872 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
4873 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
4874 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
4875 else:
4876 if ns.networkd_bin:
4877 networkd_bin = ns.networkd_bin
b6d587d1
YW
4878 if ns.resolved_bin:
4879 resolved_bin = ns.resolved_bin
641aa412
YW
4880 if ns.udevd_bin:
4881 udevd_bin = ns.udevd_bin
9c1ae484
YW
4882 if ns.wait_online_bin:
4883 wait_online_bin = ns.wait_online_bin
4884 if ns.networkctl_bin:
4885 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
4886 if ns.resolvectl_bin:
4887 resolvectl_bin = ns.resolvectl_bin
4888 if ns.timedatectl_bin:
4889 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
4890
4891 use_valgrind = ns.use_valgrind
4892 enable_debug = ns.enable_debug
94c03122 4893 asan_options = ns.asan_options
fa4c6095 4894 lsan_options = ns.lsan_options
94c03122 4895 ubsan_options = ns.ubsan_options
9c1ae484
YW
4896
4897 if use_valgrind:
4898 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
4899 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
4900 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
4901 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
4902 else:
4903 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
4904 resolvectl_cmd = [resolvectl_bin]
4905 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
4906 wait_online_cmd = [wait_online_bin]
4907
4908 if enable_debug:
4909 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
4910 if asan_options:
4911 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
4912 if lsan_options:
4913 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
4914 if ubsan_options:
4915 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
4916
4917 sys.argv[1:] = args
1f0e3109
SS
4918 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
4919 verbosity=3))