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