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