]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: rename check_operstate() to wait_operstate()
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109
SS
1#!/usr/bin/env python3
2# SPDX-License-Identifier: LGPL-2.1+
3# systemd-networkd tests
4
9c1ae484 5import argparse
1f0e3109 6import os
201bf07f 7import re
1f0e3109
SS
8import shutil
9import signal
a9bc5e37
YW
10import subprocess
11import sys
a9bc5e37
YW
12import time
13import unittest
1f0e3109
SS
14from shutil import copytree
15
d486a2d0 16network_unit_file_path='/run/systemd/network'
bad4969b 17networkd_runtime_directory='/run/systemd/netif'
d486a2d0 18networkd_ci_path='/run/networkd-ci'
1f0e3109
SS
19network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
d486a2d0
YW
22dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
23dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
1f0e3109 24
7471bcb0
DS
25systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
26which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
27
28networkd_bin=shutil.which('systemd-networkd', path=which_paths)
29resolved_bin=shutil.which('systemd-resolved', path=which_paths)
30wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
31networkctl_bin=shutil.which('networkctl', path=which_paths)
32resolvectl_bin=shutil.which('resolvectl', path=which_paths)
33timedatectl_bin=shutil.which('timedatectl', path=which_paths)
34
9c1ae484 35use_valgrind=False
aaae5713 36enable_debug=True
9c1ae484 37env = {}
94c03122 38asan_options=None
fa4c6095 39lsan_options=None
94c03122 40ubsan_options=None
5aa58329 41
2225e7fd
YW
42running_units = []
43
371810d1
ZJS
44def check_output(*command, **kwargs):
45 # This replaces both check_output and check_call (output can be ignored)
46 command = command[0].split() + list(command[1:])
47 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
48
49def call(*command, **kwargs):
50 command = command[0].split() + list(command[1:])
51 return subprocess.call(command, universal_newlines=True, **kwargs)
52
53def run(*command, **kwargs):
54 command = command[0].split() + list(command[1:])
55 return subprocess.run(command, universal_newlines=True, **kwargs)
56
7a0a37b2 57def is_module_available(module_name):
371810d1
ZJS
58 lsmod_output = check_output('lsmod')
59 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
856423f1 60 return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
7a0a37b2
EV
61
62def expectedFailureIfModuleIsNotAvailable(module_name):
63 def f(func):
64 if not is_module_available(module_name):
65 return unittest.expectedFailure(func)
66 return func
67
68 return f
69
7bea7f9b
SS
70def expectedFailureIfERSPANModuleIsNotAvailable():
71 def f(func):
856423f1 72 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 73 if rc == 0:
371810d1 74 call('ip link del erspan99')
7bea7f9b
SS
75 return func
76 else:
77 return unittest.expectedFailure(func)
78
79 return f
80
d586a2c3
YW
81def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
82 def f(func):
856423f1 83 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
d586a2c3 84 if rc == 0:
371810d1 85 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3
YW
86 return func
87 else:
88 return unittest.expectedFailure(func)
89
90 return f
91
92def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
93 def f(func):
856423f1 94 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
d586a2c3 95 if rc == 0:
371810d1 96 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
d586a2c3
YW
97 return func
98 else:
99 return unittest.expectedFailure(func)
100
101 return f
102
e28fd95f
YW
103def expectedFailureIfLinkFileFieldIsNotSet():
104 def f(func):
105 support = False
856423f1 106 rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
e28fd95f
YW
107 if rc == 0:
108 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
109 if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
110 support = True
111 call('ip link del dummy99')
112
113 if support:
114 return func
115 else:
116 return unittest.expectedFailure(func)
117
118 return f
119
086bcf5d
YW
120def expectedFailureIfNexthopIsNotAvailable():
121 def f(func):
856423f1 122 rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
086bcf5d
YW
123 if rc == 0:
124 return func
125 else:
126 return unittest.expectedFailure(func)
127
128 return f
129
6934ace0
YW
130def expectedFailureIfAlternativeNameIsNotAvailable():
131 def f(func):
132 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
133 rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
134 if rc == 0:
135 return func
136 else:
137 return unittest.expectedFailure(func)
138
139 return f
140
1f0e3109 141def setUpModule():
2225e7fd
YW
142 global running_units
143
1f0e3109
SS
144 os.makedirs(network_unit_file_path, exist_ok=True)
145 os.makedirs(networkd_ci_path, exist_ok=True)
146
147 shutil.rmtree(networkd_ci_path)
6aea9276 148 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 149
2225e7fd
YW
150 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']:
151 if call(f'systemctl is-active --quiet {u}') == 0:
152 check_output(f'systemctl stop {u}')
153 running_units.append(u)
c0bf6733 154
9c1ae484 155 drop_in = [
3e821525
DS
156 '[Unit]',
157 'StartLimitIntervalSec=0',
9c1ae484
YW
158 '[Service]',
159 'Restart=no',
160 'ExecStart=',
161 ]
162 if use_valgrind:
163 drop_in += [
164 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
94c03122 165 'PrivateTmp=yes'
9c1ae484
YW
166 ]
167 else:
168 drop_in += ['ExecStart=!!' + networkd_bin]
169 if enable_debug:
170 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
94c03122
YW
171 if asan_options:
172 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
fa4c6095
YW
173 if lsan_options:
174 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
94c03122
YW
175 if ubsan_options:
176 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
78690bb5
YW
177 if asan_options or lsan_options or ubsan_options:
178 drop_in += ['SystemCallFilter=']
fa4c6095 179 if use_valgrind or asan_options or lsan_options or ubsan_options:
94c03122 180 drop_in += ['MemoryDenyWriteExecute=no']
9c1ae484 181
9c1ae484
YW
182 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
183 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
72917fcc 184 f.write('\n'.join(drop_in))
9c1ae484 185
b6d587d1
YW
186 drop_in = [
187 '[Service]',
188 'Restart=no',
189 'ExecStart=',
190 ]
191 if use_valgrind:
192 drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin]
193 else:
194 drop_in += ['ExecStart=!!' + resolved_bin]
195 if enable_debug:
196 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
197 if asan_options:
198 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
199 if lsan_options:
200 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
201 if ubsan_options:
202 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
203 if asan_options or lsan_options or ubsan_options:
204 drop_in += ['SystemCallFilter=']
205 if use_valgrind or asan_options or lsan_options or ubsan_options:
206 drop_in += ['MemoryDenyWriteExecute=no']
207
208 os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True)
209 with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f:
210 f.write('\n'.join(drop_in))
211
371810d1
ZJS
212 check_output('systemctl daemon-reload')
213 print(check_output('systemctl cat systemd-networkd.service'))
b6d587d1
YW
214 print(check_output('systemctl cat systemd-resolved.service'))
215 check_output('systemctl restart systemd-resolved')
9c1ae484 216
1f0e3109 217def tearDownModule():
2225e7fd
YW
218 global running_units
219
1f0e3109 220 shutil.rmtree(networkd_ci_path)
d4fda2a5 221
2225e7fd
YW
222 for u in ['systemd-networkd.service', 'systemd-resolved.service']:
223 check_output(f'systemctl stop {u}')
d4fda2a5 224
9c1ae484 225 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
b6d587d1 226 shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
371810d1 227 check_output('systemctl daemon-reload')
1f0e3109 228
2225e7fd
YW
229 for u in running_units:
230 check_output(f'systemctl start {u}')
c0bf6733 231
befd4b8b
DS
232def read_link_attr(*args):
233 with open(os.path.join('/sys/class/net/', *args)) as f:
ec38833c
ZJS
234 return f.readline().strip()
235
236def read_bridge_port_attr(bridge, link, attribute):
237 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
238 path_port = 'lower_' + link + '/brport'
239 path = os.path.join(path_bridge, path_port)
240
241 with open(os.path.join(path, attribute)) as f:
242 return f.readline().strip()
243
244def link_exists(link):
245 return os.path.exists(os.path.join('/sys/class/net', link))
246
247def remove_links(links):
248 for link in links:
249 if link_exists(link):
250 call('ip link del dev', link)
251 time.sleep(1)
252
253def remove_fou_ports(ports):
254 for port in ports:
5239d7b3 255 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
256
257def remove_routing_policy_rule_tables(tables):
258 for table in tables:
4ef39b49
YW
259 rc = 0
260 while rc == 0:
261 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
262
263def remove_routes(routes):
264 for route_type, addr in routes:
5239d7b3 265 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c 266
ad78d7b0 267def remove_l2tp_tunnels(tunnel_ids):
ec38833c
ZJS
268 output = check_output('ip l2tp show tunnel')
269 for tid in tunnel_ids:
270 words='Tunnel ' + tid + ', encap'
271 if words in output:
272 call('ip l2tp del tunnel tid', tid)
273 time.sleep(1)
274
275def read_ipv6_sysctl_attr(link, attribute):
276 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
277 return f.readline().strip()
278
279def read_ipv4_sysctl_attr(link, attribute):
280 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
281 return f.readline().strip()
282
9dfc1a93
DS
283def copy_unit_to_networkd_unit_path(*units, dropins=True):
284 """Copy networkd unit files into the testbed.
285
286 Any networkd unit file type can be specified, as well as drop-in files.
287
288 By default, all drop-ins for a specified unit file are copied in;
289 to avoid that specify dropins=False.
290
291 When a drop-in file is specified, its unit file is also copied in automatically.
292 """
ec38833c
ZJS
293 print()
294 for unit in units:
9dfc1a93 295 if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')):
ec38833c 296 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
9dfc1a93
DS
297 if unit.endswith('.conf'):
298 dropin = unit
299 dropindir = os.path.join(network_unit_file_path, os.path.dirname(dropin))
300 os.makedirs(dropindir, exist_ok=True)
301 shutil.copy(os.path.join(networkd_ci_path, dropin), dropindir)
302 unit = os.path.dirname(dropin).rstrip('.d')
303 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
ec38833c
ZJS
304
305def remove_unit_from_networkd_path(units):
9dfc1a93
DS
306 """Remove previously copied unit files from the testbed.
307
308 Drop-ins will be removed automatically.
309 """
ec38833c
ZJS
310 for unit in units:
311 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
312 os.remove(os.path.join(network_unit_file_path, unit))
313 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
314 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
315
ec38833c 316def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
ec38833c
ZJS
317 dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
318 check_output(dnsmasq_command)
319
320def stop_dnsmasq(pid_file):
321 if os.path.exists(pid_file):
322 with open(pid_file, 'r') as f:
323 pid = f.read().rstrip(' \t\r\n\0')
324 os.kill(int(pid), signal.SIGTERM)
325
326 os.remove(pid_file)
327
328def search_words_in_dnsmasq_log(words, show_all=False):
329 if os.path.exists(dnsmasq_log_file):
330 with open (dnsmasq_log_file) as in_file:
331 contents = in_file.read()
332 if show_all:
333 print(contents)
334 for line in contents.splitlines():
335 if words in line:
336 in_file.close()
337 print("%s, %s" % (words, line))
338 return True
339 return False
340
341def remove_lease_file():
342 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
343 os.remove(os.path.join(networkd_ci_path, 'lease'))
344
345def remove_log_file():
346 if os.path.exists(dnsmasq_log_file):
347 os.remove(dnsmasq_log_file)
348
aaae5713
YW
349def remove_networkd_state_files():
350 if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
ec38833c 351 os.remove(os.path.join(networkd_runtime_directory, 'state'))
aaae5713
YW
352
353def stop_networkd(show_logs=True, remove_state_files=True):
354 if show_logs:
355 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
356 check_output('systemctl stop systemd-networkd')
357 if show_logs:
358 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
359 if remove_state_files:
360 remove_networkd_state_files()
361
362def start_networkd(sleep_sec=0):
363 check_output('systemctl start systemd-networkd')
ec38833c
ZJS
364 if sleep_sec > 0:
365 time.sleep(sleep_sec)
366
aaae5713
YW
367def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
368 stop_networkd(show_logs, remove_state_files)
369 start_networkd(sleep_sec)
370
ec38833c 371def get_operstate(link, show_status=True, setup_state='configured'):
fc79e6ff 372 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env)
ec38833c
ZJS
373 if show_status:
374 print(output)
375 for line in output.splitlines():
376 if 'State:' in line and (not setup_state or setup_state in line):
377 return line.split()[1]
378 return None
1f0e3109 379
ec38833c 380class Utilities():
e39cc445 381 def check_link_exists(self, link):
ec38833c 382 self.assertTrue(link_exists(link))
2be0b6fc 383
19cf3143 384 def wait_operstate(self, link, expected, show_status=True, setup_state='configured'):
ec38833c 385 self.assertRegex(get_operstate(link, show_status, setup_state), expected)
2be0b6fc 386
fd372b1a 387 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured', setup_timeout=5):
e2aea43f
YW
388 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
389 if bool_any:
390 args += ['--any']
391 try:
392 check_output(*args, env=env)
393 except subprocess.CalledProcessError:
394 for link in links_with_operstate:
fc79e6ff 395 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env)
e2aea43f
YW
396 print(output)
397 raise
fd372b1a
DS
398 if not bool_any and setup_state:
399 # check at least once now, then once per sec for setup_timeout secs
400 for secs in range(setup_timeout + 1):
401 for link in links_with_operstate:
fc79e6ff 402 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0])
fd372b1a
DS
403 print(output)
404 if not re.search(rf'(?m)^\s*State:.*({setup_state}).*$', output):
405 # this link isn't in the right state; break into the sleep below
406 break
407 else:
408 # all the links were in the right state; break to exit the timer loop
409 break
410 # don't bother sleeping if time is up
411 if secs < setup_timeout:
412 time.sleep(1)
413 else:
414 self.fail(f'link {link} state does not match {setup_state}')
e2aea43f 415
53c32c2b 416 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
417 for i in range(timeout_sec):
418 if i > 0:
419 time.sleep(1)
371810d1 420 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
2629df47
YW
421 if re.search(address_regex, output):
422 break
423 else:
424 self.assertRegex(output, address_regex)
425
1ca44d7d
YW
426class NetworkctlTests(unittest.TestCase, Utilities):
427
428 links = [
dcd9f07c 429 'dummy98',
1ca44d7d
YW
430 'test1',
431 'veth99',
432 ]
433
434 units = [
435 '11-dummy.netdev',
6d5b4efe 436 '11-dummy-mtu.netdev',
1ca44d7d 437 '11-dummy.network',
dcd9f07c 438 '12-dummy.netdev',
6934ace0 439 '12-dummy.link',
dcd9f07c 440 '25-address-static.network',
1ca44d7d
YW
441 '25-veth.netdev',
442 'netdev-link-local-addressing-yes.network',
443 ]
444
445 def setUp(self):
ec38833c 446 remove_links(self.links)
aaae5713 447 stop_networkd(show_logs=False)
1ca44d7d
YW
448
449 def tearDown(self):
ec38833c
ZJS
450 remove_links(self.links)
451 remove_unit_from_networkd_path(self.units)
aaae5713 452 stop_networkd(show_logs=True)
1ca44d7d 453
6934ace0
YW
454 @expectedFailureIfAlternativeNameIsNotAvailable()
455 def test_altname(self):
456 copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
457 check_output('udevadm control --reload')
458 start_networkd()
459 self.wait_online(['dummy98:degraded'])
460
fc79e6ff 461 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6934ace0
YW
462 self.assertRegex(output, 'hogehogehogehogehogehoge')
463
dcd9f07c
YW
464 def test_reconfigure(self):
465 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
466 start_networkd()
467 self.wait_online(['dummy98:routable'])
468
469 output = check_output('ip -4 address show dev dummy98')
470 print(output)
471 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
472 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
473 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
474
475 check_output('ip address del 10.1.2.3/16 dev dummy98')
476 check_output('ip address del 10.1.2.4/16 dev dummy98')
477 check_output('ip address del 10.2.2.4/16 dev dummy98')
478
479 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
480 self.wait_online(['dummy98:routable'])
481
482 output = check_output('ip -4 address show dev dummy98')
483 print(output)
484 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
485 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
486 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
487
66de8671
YW
488 def test_reload(self):
489 start_networkd(3)
490
491 copy_unit_to_networkd_unit_path('11-dummy.netdev')
492 check_output(*networkctl_cmd, 'reload', env=env)
493 time.sleep(3)
494 self.check_link_exists('test1')
19cf3143 495 self.wait_operstate('test1', 'off', setup_state='unmanaged')
66de8671
YW
496
497 copy_unit_to_networkd_unit_path('11-dummy.network')
498 check_output(*networkctl_cmd, 'reload', env=env)
499 self.wait_online(['test1:degraded'])
500
501 remove_unit_from_networkd_path(['11-dummy.network'])
502 check_output(*networkctl_cmd, 'reload', env=env)
503 time.sleep(1)
19cf3143 504 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
505
506 remove_unit_from_networkd_path(['11-dummy.netdev'])
507 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 508 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
509
510 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
511 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 512 self.wait_operstate('test1', 'degraded')
66de8671 513
1ca44d7d 514 def test_glob(self):
ec38833c 515 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
2cf6fdff 516 start_networkd()
1ca44d7d 517
e2aea43f 518 self.wait_online(['test1:degraded'])
1ca44d7d 519
371810d1 520 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
521 self.assertRegex(output, '1 lo ')
522 self.assertRegex(output, 'test1')
523
371810d1 524 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
525 self.assertNotRegex(output, '1 lo ')
526 self.assertRegex(output, 'test1')
527
371810d1 528 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
529 self.assertNotRegex(output, '1 lo ')
530 self.assertRegex(output, 'test1')
531
fc79e6ff 532 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
1ca44d7d
YW
533 self.assertNotRegex(output, '1: lo ')
534 self.assertRegex(output, 'test1')
535
fc79e6ff 536 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
537 self.assertNotRegex(output, '1: lo ')
538 self.assertRegex(output, 'test1')
539
6d5b4efe 540 def test_mtu(self):
ec38833c 541 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
2cf6fdff 542 start_networkd()
6d5b4efe 543
e2aea43f 544 self.wait_online(['test1:degraded'])
6d5b4efe 545
fc79e6ff 546 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
6d5b4efe
YW
547 self.assertRegex(output, 'MTU: 1600')
548
e28fd95f
YW
549 def test_type(self):
550 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
551 start_networkd()
e2aea43f 552 self.wait_online(['test1:degraded'])
e28fd95f 553
fc79e6ff 554 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f
YW
555 print(output)
556 self.assertRegex(output, 'Type: ether')
557
fc79e6ff 558 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f
YW
559 print(output)
560 self.assertRegex(output, 'Type: loopback')
561
562 @expectedFailureIfLinkFileFieldIsNotSet()
563 def test_udev_link_file(self):
564 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
565 start_networkd()
e2aea43f 566 self.wait_online(['test1:degraded'])
e28fd95f 567
fc79e6ff 568 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f 569 print(output)
426654d7 570 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
571 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
572
fc79e6ff 573 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f 574 print(output)
426654d7 575 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
576 self.assertRegex(output, r'Network File: n/a')
577
bee692fd 578 def test_delete_links(self):
ec38833c
ZJS
579 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
580 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 581 start_networkd()
bee692fd 582
e2aea43f 583 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 584
7a2f6fb6 585 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
ec38833c
ZJS
586 self.assertFalse(link_exists('test1'))
587 self.assertFalse(link_exists('veth99'))
588 self.assertFalse(link_exists('veth-peer'))
bee692fd 589
1f0e3109
SS
590class NetworkdNetDevTests(unittest.TestCase, Utilities):
591
e64dc406
YW
592 links_remove_earlier = [
593 'xfrm99',
594 ]
595
596 links = [
09ea6724
YW
597 '6rdtun99',
598 'bond99',
599 'bridge99',
600 'dropin-test',
601 'dummy98',
6a97a864
YW
602 'erspan98',
603 'erspan99',
09ea6724 604 'geneve99',
4b6a6d1e 605 'gretap96',
6a97a864 606 'gretap98',
09ea6724 607 'gretap99',
4b6a6d1e 608 'gretun96',
6a97a864
YW
609 'gretun97',
610 'gretun98',
09ea6724 611 'gretun99',
b076d5d7 612 'ifb99',
6a97a864 613 'ip6gretap98',
09ea6724 614 'ip6gretap99',
42a29fcb 615 'ip6gretun96',
6a97a864
YW
616 'ip6gretun97',
617 'ip6gretun98',
618 'ip6gretun99',
619 'ip6tnl97',
620 'ip6tnl98',
09ea6724 621 'ip6tnl99',
4b6a6d1e 622 'ipiptun96',
6a97a864
YW
623 'ipiptun97',
624 'ipiptun98',
09ea6724
YW
625 'ipiptun99',
626 'ipvlan99',
956c8fec 627 'ipvtap99',
09ea6724
YW
628 'isataptun99',
629 'macvlan99',
630 'macvtap99',
811f33d0 631 'nlmon99',
4b6a6d1e 632 'sittun96',
6a97a864
YW
633 'sittun97',
634 'sittun98',
09ea6724
YW
635 'sittun99',
636 'tap99',
637 'test1',
638 'tun99',
639 'vcan99',
640 'veth99',
641 'vlan99',
642 'vrf99',
6a97a864
YW
643 'vti6tun97',
644 'vti6tun98',
09ea6724 645 'vti6tun99',
42a29fcb 646 'vtitun96',
6a97a864
YW
647 'vtitun97',
648 'vtitun98',
09ea6724 649 'vtitun99',
f63b14d3 650 'vxcan99',
09ea6724 651 'vxlan99',
da44fb8a 652 'wg98',
e64dc406
YW
653 'wg99',
654 ]
09ea6724
YW
655
656 units = [
657 '10-dropin-test.netdev',
658 '11-dummy.netdev',
03db80b2 659 '11-dummy.network',
09ea6724 660 '12-dummy.netdev',
6b9518a0
YW
661 '13-not-match-udev-property.network',
662 '14-match-udev-property.network',
753e0a24 663 '15-name-conflict-test.netdev',
09ea6724
YW
664 '21-macvlan.netdev',
665 '21-macvtap.netdev',
7f45d738 666 '21-vlan-test1.network',
09ea6724
YW
667 '21-vlan.netdev',
668 '21-vlan.network',
669 '25-6rd-tunnel.netdev',
670 '25-bond.netdev',
fde60a42 671 '25-bond-balanced-tlb.netdev',
09ea6724 672 '25-bridge.netdev',
1285edf3 673 '25-bridge-configure-without-carrier.network',
03db80b2 674 '25-bridge.network',
6a97a864 675 '25-erspan-tunnel-local-any.netdev',
09ea6724 676 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
677 '25-fou-gretap.netdev',
678 '25-fou-gre.netdev',
679 '25-fou-ipip.netdev',
680 '25-fou-ipproto-gre.netdev',
681 '25-fou-ipproto-ipip.netdev',
682 '25-fou-sit.netdev',
09ea6724 683 '25-geneve.netdev',
6a97a864 684 '25-gretap-tunnel-local-any.netdev',
09ea6724 685 '25-gretap-tunnel.netdev',
42a29fcb 686 '25-gre-tunnel-any-any.netdev',
6a97a864
YW
687 '25-gre-tunnel-local-any.netdev',
688 '25-gre-tunnel-remote-any.netdev',
09ea6724 689 '25-gre-tunnel.netdev',
b076d5d7 690 '25-ifb.netdev',
6a97a864
YW
691 '25-ip6gretap-tunnel-local-any.netdev',
692 '25-ip6gretap-tunnel.netdev',
42a29fcb 693 '25-ip6gre-tunnel-any-any.netdev',
6a97a864
YW
694 '25-ip6gre-tunnel-local-any.netdev',
695 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 696 '25-ip6gre-tunnel.netdev',
42a29fcb 697 '25-ip6tnl-tunnel-any-any.netdev',
6a97a864 698 '25-ip6tnl-tunnel-local-any.netdev',
42a29fcb 699 '25-ip6tnl-tunnel-remote-any.netdev',
09ea6724 700 '25-ip6tnl-tunnel.netdev',
42a29fcb 701 '25-ipip-tunnel-any-any.netdev',
09ea6724 702 '25-ipip-tunnel-independent.netdev',
95082dbe 703 '25-ipip-tunnel-independent-loopback.netdev',
6a97a864
YW
704 '25-ipip-tunnel-local-any.netdev',
705 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
706 '25-ipip-tunnel.netdev',
707 '25-ipvlan.netdev',
956c8fec 708 '25-ipvtap.netdev',
09ea6724 709 '25-isatap-tunnel.netdev',
02849d8b
YW
710 '25-macsec.key',
711 '25-macsec.netdev',
712 '25-macsec.network',
811f33d0 713 '25-nlmon.netdev',
42a29fcb 714 '25-sit-tunnel-any-any.netdev',
6a97a864
YW
715 '25-sit-tunnel-local-any.netdev',
716 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
717 '25-sit-tunnel.netdev',
718 '25-tap.netdev',
719 '25-tun.netdev',
11309591
YW
720 '25-tunnel-local-any.network',
721 '25-tunnel-remote-any.network',
722 '25-tunnel.network',
09ea6724
YW
723 '25-vcan.netdev',
724 '25-veth.netdev',
725 '25-vrf.netdev',
42a29fcb 726 '25-vti6-tunnel-any-any.netdev',
6a97a864
YW
727 '25-vti6-tunnel-local-any.netdev',
728 '25-vti6-tunnel-remote-any.netdev',
09ea6724 729 '25-vti6-tunnel.netdev',
42a29fcb 730 '25-vti-tunnel-any-any.netdev',
6a97a864
YW
731 '25-vti-tunnel-local-any.netdev',
732 '25-vti-tunnel-remote-any.netdev',
09ea6724 733 '25-vti-tunnel.netdev',
f63b14d3 734 '25-vxcan.netdev',
09ea6724 735 '25-vxlan.netdev',
da44fb8a
YW
736 '25-wireguard-23-peers.netdev',
737 '25-wireguard-23-peers.network',
9e5d79e7 738 '25-wireguard-preshared-key.txt',
39bcff3b 739 '25-wireguard-private-key.txt',
09ea6724 740 '25-wireguard.netdev',
5a0bd90b 741 '25-wireguard.network',
e64dc406
YW
742 '25-xfrm.netdev',
743 '25-xfrm-independent.netdev',
09ea6724 744 '6rd.network',
6730a1f3 745 'erspan.network',
09ea6724
YW
746 'gre.network',
747 'gretap.network',
748 'gretun.network',
749 'ip6gretap.network',
6a97a864 750 'ip6gretun.network',
09ea6724
YW
751 'ip6tnl.network',
752 'ipip.network',
753 'ipvlan.network',
956c8fec 754 'ipvtap.network',
09ea6724 755 'isatap.network',
02849d8b 756 'macsec.network',
09ea6724
YW
757 'macvlan.network',
758 'macvtap.network',
077f9abc 759 'netdev-link-local-addressing-yes.network',
09ea6724
YW
760 'sit.network',
761 'vti6.network',
762 'vti.network',
1c862fe0 763 'vxlan-test1.network',
e64dc406
YW
764 'vxlan.network',
765 'xfrm.network',
766 ]
1f0e3109 767
def9fc0d
YW
768 fou_ports = [
769 '55555',
770 '55556']
771
1f0e3109 772 def setUp(self):
ec38833c 773 remove_fou_ports(self.fou_ports)
e64dc406 774 remove_links(self.links_remove_earlier)
ec38833c 775 remove_links(self.links)
aaae5713 776 stop_networkd(show_logs=False)
1f0e3109
SS
777
778 def tearDown(self):
ec38833c 779 remove_fou_ports(self.fou_ports)
e64dc406 780 remove_links(self.links_remove_earlier)
ec38833c
ZJS
781 remove_links(self.links)
782 remove_unit_from_networkd_path(self.units)
aaae5713 783 stop_networkd(show_logs=True)
1f0e3109 784
1ca44d7d 785 def test_dropin_and_name_conflict(self):
ec38833c 786 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
2cf6fdff 787 start_networkd()
d80734f7 788
e2aea43f 789 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
d80734f7 790
371810d1 791 output = check_output('ip link show dropin-test')
d80734f7
YW
792 print(output)
793 self.assertRegex(output, '00:50:56:c0:00:28')
794
6b9518a0
YW
795 def test_match_udev_property(self):
796 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
797 start_networkd()
e2aea43f 798 self.wait_online(['dummy98:routable'])
6b9518a0 799
fc79e6ff 800 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6b9518a0
YW
801 print(output)
802 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
803
03db80b2 804 def test_wait_online_any(self):
ec38833c 805 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
2cf6fdff 806 start_networkd()
03db80b2 807
e2aea43f 808 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 809
19cf3143
DS
810 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
811 self.wait_operstate('test1', 'degraded')
03db80b2 812
1f0e3109 813 def test_bridge(self):
1285edf3 814 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
2cf6fdff 815 start_networkd()
1f0e3109 816
e2aea43f 817 self.wait_online(['bridge99:no-carrier'])
1f0e3109 818
3d165124 819 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
820 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
821 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
c9047092
YW
822 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick))
823 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick))
824 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
825 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
826 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
827 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
828 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
1f0e3109 829
fc79e6ff 830 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
36bc2ffb
YW
831 print(output)
832 self.assertRegex(output, 'Priority: 9')
833 self.assertRegex(output, 'STP: yes')
834 self.assertRegex(output, 'Multicast IGMP Version: 3')
835
1f0e3109 836 def test_bond(self):
ec38833c 837 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
2cf6fdff 838 start_networkd()
ec38833c 839
e2aea43f 840 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
ec38833c
ZJS
841
842 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
843 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
844 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
845 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
846 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
847 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
848 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
849 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
850 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
851 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
852 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
853
854 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
855 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
fde60a42 856
1f0e3109 857 def test_vlan(self):
ec38833c
ZJS
858 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
859 '21-vlan.network', '21-vlan-test1.network')
2cf6fdff 860 start_networkd()
1f0e3109 861
e2aea43f 862 self.wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 863
371810d1 864 output = check_output('ip -d link show test1')
72b7f1b9 865 print(output)
7d7be1b9 866 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 867
371810d1 868 output = check_output('ip -d link show vlan99')
14ecd604 869 print(output)
06895a1d
YW
870 self.assertRegex(output, ' mtu 2000 ')
871 self.assertRegex(output, 'REORDER_HDR')
872 self.assertRegex(output, 'LOOSE_BINDING')
873 self.assertRegex(output, 'GVRP')
874 self.assertRegex(output, 'MVRP')
875 self.assertRegex(output, ' id 99 ')
1f0e3109 876
371810d1 877 output = check_output('ip -4 address show dev test1')
7f45d738
YW
878 print(output)
879 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
880 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
881
371810d1 882 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
883 print(output)
884 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
885
1f0e3109 886 def test_macvtap(self):
460feb61
YW
887 for mode in ['private', 'vepa', 'bridge', 'passthru']:
888 with self.subTest(mode=mode):
889 if mode != 'private':
890 self.tearDown()
ec38833c
ZJS
891 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
892 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
893 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
894 f.write('[MACVTAP]\nMode=' + mode)
2cf6fdff 895 start_networkd()
1f0e3109 896
e2aea43f 897 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
460feb61 898
371810d1 899 output = check_output('ip -d link show macvtap99')
460feb61
YW
900 print(output)
901 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
902
903 def test_macvlan(self):
dff9792b
YW
904 for mode in ['private', 'vepa', 'bridge', 'passthru']:
905 with self.subTest(mode=mode):
906 if mode != 'private':
907 self.tearDown()
ec38833c
ZJS
908 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
909 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
910 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
911 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 912 start_networkd()
dff9792b 913
e2aea43f 914 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
dff9792b 915
371810d1 916 output = check_output('ip -d link show test1')
dff9792b
YW
917 print(output)
918 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 919
371810d1 920 output = check_output('ip -d link show macvlan99')
dff9792b
YW
921 print(output)
922 self.assertRegex(output, ' mtu 2000 ')
923 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 924
7a0a37b2 925 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 926 def test_ipvlan(self):
bc6dff6e
YW
927 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
928 with self.subTest(mode=mode, flag=flag):
929 if mode != 'L2':
930 self.tearDown()
ec38833c
ZJS
931 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
932 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
933 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
934 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 935
2cf6fdff 936 start_networkd()
e2aea43f 937 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 938
371810d1 939 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
940 print(output)
941 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 942
956c8fec
YW
943 @expectedFailureIfModuleIsNotAvailable('ipvtap')
944 def test_ipvtap(self):
40921f08
YW
945 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
946 with self.subTest(mode=mode, flag=flag):
947 if mode != 'L2':
948 self.tearDown()
ec38833c
ZJS
949 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
950 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
951 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
952 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
953
2cf6fdff 954 start_networkd()
e2aea43f 955 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 956
371810d1 957 output = check_output('ip -d link show ipvtap99')
40921f08
YW
958 print(output)
959 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 960
1f0e3109 961 def test_veth(self):
ec38833c 962 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 963 start_networkd()
1f0e3109 964
e2aea43f 965 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 966
371810d1 967 output = check_output('ip -d link show veth99')
671dacdf
YW
968 print(output)
969 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 970 output = check_output('ip -d link show veth-peer')
671dacdf
YW
971 print(output)
972 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 973
1f0e3109 974 def test_tun(self):
ec38833c 975 copy_unit_to_networkd_unit_path('25-tun.netdev')
2cf6fdff 976 start_networkd()
1f0e3109 977
e2aea43f 978 self.wait_online(['tun99:off'], setup_state='unmanaged')
1f0e3109 979
371810d1 980 output = check_output('ip -d link show tun99')
2746d307
YW
981 print(output)
982 # Old ip command does not support IFF_ flags
426654d7 983 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 984
1f0e3109 985 def test_tap(self):
ec38833c 986 copy_unit_to_networkd_unit_path('25-tap.netdev')
2cf6fdff 987 start_networkd()
1f0e3109 988
e2aea43f 989 self.wait_online(['tap99:off'], setup_state='unmanaged')
1f0e3109 990
371810d1 991 output = check_output('ip -d link show tap99')
2746d307
YW
992 print(output)
993 # Old ip command does not support IFF_ flags
426654d7 994 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 995
7a0a37b2 996 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 997 def test_vrf(self):
ec38833c 998 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 999 start_networkd()
1f0e3109 1000
e2aea43f 1001 self.wait_online(['vrf99:carrier'])
1f0e3109 1002
7a0a37b2 1003 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1004 def test_vcan(self):
ec38833c 1005 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1006 start_networkd()
1f0e3109 1007
e2aea43f 1008 self.wait_online(['vcan99:carrier'])
1f0e3109 1009
f63b14d3
YW
1010 @expectedFailureIfModuleIsNotAvailable('vxcan')
1011 def test_vxcan(self):
ec38833c 1012 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1013 start_networkd()
f63b14d3 1014
e2aea43f 1015 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1016
7a3bc5a8
EV
1017 @expectedFailureIfModuleIsNotAvailable('wireguard')
1018 def test_wireguard(self):
ec38833c
ZJS
1019 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1020 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
1021 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
2cf6fdff 1022 start_networkd()
e2aea43f 1023 self.wait_online(['wg99:carrier', 'wg98:routable'])
5a0bd90b 1024
7a3bc5a8 1025 if shutil.which('wg'):
371810d1 1026 call('wg')
5a0bd90b 1027
371810d1 1028 output = check_output('wg show wg99 listen-port')
06895a1d 1029 self.assertRegex(output, '51820')
371810d1 1030 output = check_output('wg show wg99 fwmark')
06895a1d 1031 self.assertRegex(output, '0x4d2')
371810d1 1032 output = check_output('wg show wg99 allowed-ips')
88aaf89e
ZJS
1033 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
1034 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
371810d1 1035 output = check_output('wg show wg99 persistent-keepalive')
88aaf89e 1036 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
371810d1 1037 output = check_output('wg show wg99 endpoints')
88aaf89e 1038 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
371810d1 1039 output = check_output('wg show wg99 private-key')
88aaf89e 1040 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
371810d1 1041 output = check_output('wg show wg99 preshared-keys')
88aaf89e
ZJS
1042 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
1043 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
7a3bc5a8 1044
371810d1 1045 output = check_output('wg show wg98 private-key')
88aaf89e 1046 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
da44fb8a 1047
1f0e3109 1048 def test_geneve(self):
ec38833c 1049 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1050 start_networkd()
1f0e3109 1051
e2aea43f 1052 self.wait_online(['geneve99:degraded'])
1f0e3109 1053
371810d1 1054 output = check_output('ip -d link show geneve99')
14ecd604 1055 print(output)
06895a1d
YW
1056 self.assertRegex(output, '192.168.22.1')
1057 self.assertRegex(output, '6082')
1058 self.assertRegex(output, 'udpcsum')
1059 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1060
1061 def test_ipip_tunnel(self):
ec38833c
ZJS
1062 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1063 '25-ipip-tunnel.netdev', '25-tunnel.network',
1064 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1065 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1066 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1067 start_networkd()
e2aea43f 1068 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1069
371810d1 1070 output = check_output('ip -d link show ipiptun99')
6a97a864 1071 print(output)
426654d7 1072 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1073 output = check_output('ip -d link show ipiptun98')
6a97a864 1074 print(output)
426654d7 1075 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1076 output = check_output('ip -d link show ipiptun97')
6a97a864 1077 print(output)
426654d7 1078 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1079 output = check_output('ip -d link show ipiptun96')
1080 print(output)
426654d7 1081 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1082
1083 def test_gre_tunnel(self):
ec38833c
ZJS
1084 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1085 '25-gre-tunnel.netdev', '25-tunnel.network',
1086 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1087 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1088 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1089 start_networkd()
e2aea43f 1090 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1091
371810d1 1092 output = check_output('ip -d link show gretun99')
6a97a864
YW
1093 print(output)
1094 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1095 self.assertRegex(output, 'ikey 1.2.3.103')
1096 self.assertRegex(output, 'okey 1.2.4.103')
1097 self.assertRegex(output, 'iseq')
1098 self.assertRegex(output, 'oseq')
371810d1 1099 output = check_output('ip -d link show gretun98')
6a97a864
YW
1100 print(output)
1101 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1102 self.assertRegex(output, 'ikey 0.0.0.104')
1103 self.assertRegex(output, 'okey 0.0.0.104')
1104 self.assertNotRegex(output, 'iseq')
1105 self.assertNotRegex(output, 'oseq')
371810d1 1106 output = check_output('ip -d link show gretun97')
6a97a864
YW
1107 print(output)
1108 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
1109 self.assertRegex(output, 'ikey 0.0.0.105')
1110 self.assertRegex(output, 'okey 0.0.0.105')
1111 self.assertNotRegex(output, 'iseq')
1112 self.assertNotRegex(output, 'oseq')
42a29fcb
YW
1113 output = check_output('ip -d link show gretun96')
1114 print(output)
1115 self.assertRegex(output, 'gre remote any local any dev dummy98')
1116 self.assertRegex(output, 'ikey 0.0.0.106')
1117 self.assertRegex(output, 'okey 0.0.0.106')
1118 self.assertNotRegex(output, 'iseq')
1119 self.assertNotRegex(output, 'oseq')
6a97a864
YW
1120
1121 def test_ip6gre_tunnel(self):
ec38833c
ZJS
1122 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1123 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1124 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1125 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1126 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
01943d43 1127 start_networkd(5)
6a97a864 1128
17bcf0a0
YW
1129 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1130
e39cc445
YW
1131 self.check_link_exists('dummy98')
1132 self.check_link_exists('ip6gretun99')
1133 self.check_link_exists('ip6gretun98')
1134 self.check_link_exists('ip6gretun97')
42a29fcb 1135 self.check_link_exists('ip6gretun96')
6a97a864 1136
371810d1 1137 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1138 print(output)
1139 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1140 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1141 print(output)
1142 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1143 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1144 print(output)
1145 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1146 output = check_output('ip -d link show ip6gretun96')
1147 print(output)
1148 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1149
11309591 1150 def test_gretap_tunnel(self):
ec38833c
ZJS
1151 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1152 '25-gretap-tunnel.netdev', '25-tunnel.network',
1153 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1154 start_networkd()
e2aea43f 1155 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1156
371810d1 1157 output = check_output('ip -d link show gretap99')
6a97a864
YW
1158 print(output)
1159 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1160 self.assertRegex(output, 'ikey 0.0.0.106')
1161 self.assertRegex(output, 'okey 0.0.0.106')
1162 self.assertRegex(output, 'iseq')
1163 self.assertRegex(output, 'oseq')
371810d1 1164 output = check_output('ip -d link show gretap98')
6a97a864
YW
1165 print(output)
1166 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1167 self.assertRegex(output, 'ikey 0.0.0.107')
1168 self.assertRegex(output, 'okey 0.0.0.107')
1169 self.assertRegex(output, 'iseq')
1170 self.assertRegex(output, 'oseq')
1f0e3109
SS
1171
1172 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
1173 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1174 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1175 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1176 start_networkd()
e2aea43f 1177 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1178
371810d1 1179 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1180 print(output)
1181 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1182 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1183 print(output)
1184 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1185
1186 def test_vti_tunnel(self):
ec38833c
ZJS
1187 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1188 '25-vti-tunnel.netdev', '25-tunnel.network',
1189 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1190 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1191 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1192 start_networkd()
e2aea43f 1193 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1194
371810d1 1195 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1196 print(output)
1197 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1198 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1199 print(output)
1200 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1201 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1202 print(output)
1203 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1204 output = check_output('ip -d link show vtitun96')
1205 print(output)
1206 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1207
1208 def test_vti6_tunnel(self):
ec38833c
ZJS
1209 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1210 '25-vti6-tunnel.netdev', '25-tunnel.network',
1211 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1212 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1213 start_networkd()
e2aea43f 1214 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1215
371810d1 1216 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1217 print(output)
1218 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1219 output = check_output('ip -d link show vti6tun98')
6a97a864 1220 print(output)
426654d7 1221 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1222 output = check_output('ip -d link show vti6tun97')
6a97a864 1223 print(output)
426654d7 1224 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1225
1226 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
1227 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1228 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1229 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1230 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1231 start_networkd()
e2aea43f 1232 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 1233
371810d1 1234 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
1235 print(output)
1236 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1237 output = check_output('ip -d link show ip6tnl98')
6a97a864 1238 print(output)
426654d7 1239 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1240 output = check_output('ip -d link show ip6tnl97')
6a97a864 1241 print(output)
426654d7 1242 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1243
1244 def test_sit_tunnel(self):
ec38833c
ZJS
1245 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1246 '25-sit-tunnel.netdev', '25-tunnel.network',
1247 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1248 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1249 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1250 start_networkd()
e2aea43f 1251 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1252
371810d1 1253 output = check_output('ip -d link show sittun99')
6a97a864 1254 print(output)
426654d7 1255 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1256 output = check_output('ip -d link show sittun98')
6a97a864 1257 print(output)
426654d7 1258 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1259 output = check_output('ip -d link show sittun97')
6a97a864 1260 print(output)
426654d7 1261 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1262 output = check_output('ip -d link show sittun96')
1263 print(output)
426654d7 1264 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1265
d0e728b6 1266 def test_isatap_tunnel(self):
ec38833c
ZJS
1267 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1268 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1269 start_networkd()
e2aea43f 1270 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1271
371810d1 1272 output = check_output('ip -d link show isataptun99')
14ecd604 1273 print(output)
d0e728b6
SS
1274 self.assertRegex(output, "isatap ")
1275
d29dc4f1 1276 def test_6rd_tunnel(self):
ec38833c
ZJS
1277 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1278 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1279 start_networkd()
e2aea43f 1280 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1281
371810d1 1282 output = check_output('ip -d link show sittun99')
6a97a864
YW
1283 print(output)
1284 self.assertRegex(output, '6rd-prefix 2602::/24')
1285
7bea7f9b 1286 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1287 def test_erspan_tunnel(self):
ec38833c
ZJS
1288 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1289 '25-erspan-tunnel.netdev', '25-tunnel.network',
1290 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1291 start_networkd()
e2aea43f 1292 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1293
371810d1 1294 output = check_output('ip -d link show erspan99')
6a97a864
YW
1295 print(output)
1296 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1297 self.assertRegex(output, 'ikey 0.0.0.101')
1298 self.assertRegex(output, 'okey 0.0.0.101')
1299 self.assertRegex(output, 'iseq')
1300 self.assertRegex(output, 'oseq')
371810d1 1301 output = check_output('ip -d link show erspan98')
2266864b 1302 print(output)
6a97a864
YW
1303 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1304 self.assertRegex(output, '102')
38f4bb44
YW
1305 self.assertRegex(output, 'ikey 0.0.0.102')
1306 self.assertRegex(output, 'okey 0.0.0.102')
1307 self.assertRegex(output, 'iseq')
1308 self.assertRegex(output, 'oseq')
2266864b 1309
1f0e3109 1310 def test_tunnel_independent(self):
ec38833c 1311 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1312 start_networkd()
e40a58b5 1313
e2aea43f 1314 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1315
95082dbe
YW
1316 def test_tunnel_independent_loopback(self):
1317 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1318 start_networkd()
1319
e2aea43f 1320 self.wait_online(['ipiptun99:carrier'])
95082dbe 1321
e64dc406
YW
1322 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1323 def test_xfrm(self):
1324 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1325 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1326 start_networkd()
1327
e2aea43f 1328 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
e64dc406
YW
1329
1330 output = check_output('ip link show dev xfrm99')
1331 print(output)
1332
1333 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1334 def test_xfrm_independent(self):
1335 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1336 start_networkd()
1337
e2aea43f 1338 self.wait_online(['xfrm99:degraded'])
e64dc406 1339
4b6a6d1e
YW
1340 @expectedFailureIfModuleIsNotAvailable('fou')
1341 def test_fou(self):
1342 # The following redundant check is necessary for CentOS CI.
1343 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1344 self.assertTrue(is_module_available('fou'))
1345
ec38833c
ZJS
1346 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1347 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1348 '25-fou-gre.netdev', '25-fou-gretap.netdev')
2cf6fdff 1349 start_networkd()
4b6a6d1e 1350
e2aea43f 1351 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1352
371810d1 1353 output = check_output('ip fou show')
4b6a6d1e
YW
1354 print(output)
1355 self.assertRegex(output, 'port 55555 ipproto 4')
1356 self.assertRegex(output, 'port 55556 ipproto 47')
1357
371810d1 1358 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1359 print(output)
1360 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1361 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1362 print(output)
1363 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1364 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1365 print(output)
1366 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1367 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1368 print(output)
1369 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1370
1f0e3109 1371 def test_vxlan(self):
ec38833c
ZJS
1372 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1373 '11-dummy.netdev', 'vxlan-test1.network')
2cf6fdff 1374 start_networkd()
1f0e3109 1375
e2aea43f 1376 self.wait_online(['test1:degraded', 'vxlan99:degraded'])
1f0e3109 1377
371810d1 1378 output = check_output('ip -d link show vxlan99')
14ecd604 1379 print(output)
1c862fe0 1380 self.assertRegex(output, '999')
1f0e3109
SS
1381 self.assertRegex(output, '5555')
1382 self.assertRegex(output, 'l2miss')
1383 self.assertRegex(output, 'l3miss')
1384 self.assertRegex(output, 'udpcsum')
1385 self.assertRegex(output, 'udp6zerocsumtx')
1386 self.assertRegex(output, 'udp6zerocsumrx')
1387 self.assertRegex(output, 'remcsumtx')
1388 self.assertRegex(output, 'remcsumrx')
1389 self.assertRegex(output, 'gbp')
1390
371810d1 1391 output = check_output('bridge fdb show dev vxlan99')
1c862fe0
YW
1392 print(output)
1393 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1394 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1395 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1396
fc79e6ff 1397 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb
YW
1398 print(output)
1399 self.assertRegex(output, 'VNI: 999')
1400 self.assertRegex(output, 'Destination Port: 5555')
1401 self.assertRegex(output, 'Underlying Device: test1')
1402
02849d8b 1403 def test_macsec(self):
ec38833c
ZJS
1404 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1405 'macsec.network', '12-dummy.netdev')
2cf6fdff 1406 start_networkd()
02849d8b 1407
e2aea43f 1408 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1409
371810d1 1410 output = check_output('ip -d link show macsec99')
02849d8b
YW
1411 print(output)
1412 self.assertRegex(output, 'macsec99@dummy98')
1413 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1414 self.assertRegex(output, 'encrypt on')
1415
371810d1 1416 output = check_output('ip macsec show macsec99')
02849d8b
YW
1417 print(output)
1418 self.assertRegex(output, 'encrypt on')
1419 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1420 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1421 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1422 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1423 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1424 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1425 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1426 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1427 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1428 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1429 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1430
811f33d0 1431 def test_nlmon(self):
ec38833c 1432 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1433 start_networkd()
811f33d0 1434
e2aea43f 1435 self.wait_online(['nlmon99:carrier'])
02849d8b 1436
b076d5d7
YW
1437 @expectedFailureIfModuleIsNotAvailable('ifb')
1438 def test_ifb(self):
1439 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1440 start_networkd()
1441
1442 self.wait_online(['ifb99:degraded'])
1443
cff83db9
YW
1444class NetworkdL2TPTests(unittest.TestCase, Utilities):
1445
1446 links =[
1447 'l2tp-ses1',
1448 'l2tp-ses2',
1449 'l2tp-ses3',
1450 'l2tp-ses4',
1451 'test1']
1452
1453 units = [
1454 '11-dummy.netdev',
1455 '25-l2tp-dummy.network',
e2aea43f 1456 '25-l2tp.network',
cff83db9
YW
1457 '25-l2tp-ip.netdev',
1458 '25-l2tp-udp.netdev']
1459
1460 l2tp_tunnel_ids = [ '10' ]
1461
1462 def setUp(self):
ad78d7b0 1463 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1464 remove_links(self.links)
aaae5713 1465 stop_networkd(show_logs=False)
cff83db9
YW
1466
1467 def tearDown(self):
ad78d7b0 1468 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1469 remove_links(self.links)
1470 remove_unit_from_networkd_path(self.units)
aaae5713 1471 stop_networkd(show_logs=True)
cff83db9
YW
1472
1473 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1474 def test_l2tp_udp(self):
e2aea43f
YW
1475 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1476 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 1477 start_networkd()
cff83db9 1478
e2aea43f 1479 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 1480
371810d1 1481 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1482 print(output)
1483 self.assertRegex(output, "Tunnel 10, encap UDP")
1484 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1485 self.assertRegex(output, "Peer tunnel 11")
1486 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1487 self.assertRegex(output, "UDP checksum: enabled")
1488
371810d1 1489 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1490 print(output)
1491 self.assertRegex(output, "Session 15 in tunnel 10")
1492 self.assertRegex(output, "Peer session 16, tunnel 11")
1493 self.assertRegex(output, "interface name: l2tp-ses1")
1494
371810d1 1495 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1496 print(output)
1497 self.assertRegex(output, "Session 17 in tunnel 10")
1498 self.assertRegex(output, "Peer session 18, tunnel 11")
1499 self.assertRegex(output, "interface name: l2tp-ses2")
1500
1501 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1502 def test_l2tp_ip(self):
e2aea43f
YW
1503 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1504 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 1505 start_networkd()
cff83db9 1506
e2aea43f 1507 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 1508
371810d1 1509 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1510 print(output)
1511 self.assertRegex(output, "Tunnel 10, encap IP")
1512 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1513 self.assertRegex(output, "Peer tunnel 12")
1514
371810d1 1515 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
1516 print(output)
1517 self.assertRegex(output, "Session 25 in tunnel 10")
1518 self.assertRegex(output, "Peer session 26, tunnel 12")
1519 self.assertRegex(output, "interface name: l2tp-ses3")
1520
371810d1 1521 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
1522 print(output)
1523 self.assertRegex(output, "Session 27 in tunnel 10")
1524 self.assertRegex(output, "Peer session 28, tunnel 12")
1525 self.assertRegex(output, "interface name: l2tp-ses4")
1526
be68c2c9 1527class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1528 links = [
1529 'bond199',
1530 'dummy98',
cd65d067 1531 'dummy99',
74761cf3 1532 'gretun97',
fb2ba330 1533 'ip6gretun97',
086bcf5d
YW
1534 'test1',
1535 'veth99',
74761cf3 1536 ]
09ea6724
YW
1537
1538 units = [
1539 '11-dummy.netdev',
1540 '12-dummy.netdev',
1541 '23-active-slave.network',
1e498853 1542 '24-keep-configuration-static.network',
fdcd1ec5 1543 '24-search-domain.network',
dc7d3c5f
YW
1544 '25-address-dad-veth-peer.network',
1545 '25-address-dad-veth99.network',
09ea6724 1546 '25-address-link-section.network',
e4783b54 1547 '25-address-preferred-lifetime-zero.network',
b8102725 1548 '25-address-static.network',
cd65d067 1549 '25-bind-carrier.network',
09ea6724
YW
1550 '25-bond-active-backup-slave.netdev',
1551 '25-fibrule-invert.network',
1552 '25-fibrule-port-range.network',
74761cf3 1553 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1554 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1555 '25-ipv6-address-label-section.network',
ef3c8a92
YW
1556 '25-link-local-addressing-no.network',
1557 '25-link-local-addressing-yes.network',
1558 '25-link-section-unmanaged.network',
e4a71bf3 1559 '25-neighbor-section.network',
d1bdafd2 1560 '25-neighbor-next.network',
fb2ba330 1561 '25-neighbor-ipv6.network',
74761cf3
YW
1562 '25-neighbor-ip-dummy.network',
1563 '25-neighbor-ip.network',
086bcf5d 1564 '25-nexthop.network',
a3d35654 1565 '25-qdisc-fq-codel.network',
40821c2a 1566 '25-qdisc-netem-and-fqcodel.network',
0ab92791 1567 '25-qdisc-tbf-and-sfq.network',
20ca06a6 1568 '25-route-ipv6-src.network',
0ef830cf 1569 '25-route-static.network',
0b1cd3e2
WKI
1570 '25-gateway-static.network',
1571 '25-gateway-next-static.network',
4da33154 1572 '25-sysctl-disable-ipv6.network',
09ea6724 1573 '25-sysctl.network',
086bcf5d
YW
1574 '25-veth-peer.network',
1575 '25-veth.netdev',
7b3770a7 1576 '26-link-local-addressing-ipv6.network',
09ea6724 1577 'configure-without-carrier.network',
b677774d 1578 'routing-policy-rule-dummy98.network',
b8102725 1579 'routing-policy-rule-test1.network']
1f0e3109 1580
65c24cd0 1581 routing_policy_rule_tables = ['7', '8', '9']
5f68a6a4 1582 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1583
1f0e3109 1584 def setUp(self):
ec38833c
ZJS
1585 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1586 remove_routes(self.routes)
1587 remove_links(self.links)
aaae5713 1588 stop_networkd(show_logs=False)
1f0e3109
SS
1589
1590 def tearDown(self):
ec38833c
ZJS
1591 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1592 remove_routes(self.routes)
1593 remove_links(self.links)
1594 remove_unit_from_networkd_path(self.units)
aaae5713 1595 stop_networkd(show_logs=True)
1f0e3109 1596
b8102725 1597 def test_address_static(self):
ec38833c 1598 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 1599 start_networkd()
b8102725 1600
e2aea43f 1601 self.wait_online(['dummy98:routable'])
b8102725 1602
371810d1 1603 output = check_output('ip -4 address show dev dummy98')
b8102725
YW
1604 print(output)
1605 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1606 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1607 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1608
1609 # invalid sections
1610 self.assertNotRegex(output, '10.10.0.1/16')
1611 self.assertNotRegex(output, '10.10.0.2/16')
1612
371810d1 1613 output = check_output('ip -4 address show dev dummy98 label 32')
b8102725
YW
1614 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1615
371810d1 1616 output = check_output('ip -4 address show dev dummy98 label 33')
b8102725
YW
1617 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1618
371810d1 1619 output = check_output('ip -4 address show dev dummy98 label 34')
b8102725
YW
1620 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1621
371810d1 1622 output = check_output('ip -4 address show dev dummy98 label 35')
b8102725
YW
1623 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1624
371810d1 1625 output = check_output('ip -6 address show dev dummy98')
b8102725
YW
1626 print(output)
1627 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1628 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1629 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1630 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1631 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1632 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1633
1634 def test_address_preferred_lifetime_zero_ipv6(self):
e4783b54 1635 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
01943d43 1636 start_networkd(5)
1f0e3109 1637
e4783b54 1638 self.wait_online(['dummy98:routable'])
b8102725 1639
371810d1 1640 output = check_output('ip address show dummy98')
b8102725
YW
1641 print(output)
1642 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1643 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109 1644
e4783b54
YW
1645 output = check_output('ip route show dev dummy98')
1646 print(output)
1647 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1648
dc7d3c5f
YW
1649 def test_address_dad(self):
1650 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1651 '25-veth.netdev')
1652 start_networkd()
1653 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1654
1655 output = check_output('ip -4 address show dev veth99')
1656 print(output)
1657 self.assertRegex(output, '192.168.100.10/24')
1658
1659 output = check_output('ip -4 address show dev veth-peer')
1660 print(output)
1661 self.assertNotRegex(output, '192.168.100.10/24')
1662
1f0e3109 1663 def test_configure_without_carrier(self):
ec38833c 1664 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
2cf6fdff 1665 start_networkd()
e2aea43f 1666 self.wait_online(['test1:routable'])
e40a58b5 1667
fc79e6ff 1668 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1f0e3109
SS
1669 print(output)
1670 self.assertRegex(output, '192.168.0.15')
1671 self.assertRegex(output, '192.168.0.1')
1672 self.assertRegex(output, 'routable')
1673
1f0e3109 1674 def test_routing_policy_rule(self):
ec38833c 1675 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 1676 start_networkd()
e2aea43f 1677 self.wait_online(['test1:degraded'])
e40a58b5 1678
65c24cd0 1679 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 1680 print(output)
65c24cd0 1681 self.assertRegex(output, '111:')
1f0e3109 1682 self.assertRegex(output, 'from 192.168.100.18')
426654d7 1683 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
1684 self.assertRegex(output, 'iif test1')
1685 self.assertRegex(output, 'oif test1')
1686 self.assertRegex(output, 'lookup 7')
1687
65c24cd0
YW
1688 output = check_output('ip rule list iif test1 priority 101')
1689 print(output)
1690 self.assertRegex(output, '101:')
1691 self.assertRegex(output, 'from all')
1692 self.assertRegex(output, 'iif test1')
1693 self.assertRegex(output, 'lookup 9')
1694
1695 output = check_output('ip -6 rule list iif test1 priority 100')
1696 print(output)
1697 self.assertRegex(output, '100:')
1698 self.assertRegex(output, 'from all')
1699 self.assertRegex(output, 'iif test1')
1700 self.assertRegex(output, 'lookup 8')
1701
1702 output = check_output('ip -6 rule list iif test1 priority 101')
1703 print(output)
1704 self.assertRegex(output, '101:')
1705 self.assertRegex(output, 'from all')
1706 self.assertRegex(output, 'iif test1')
1707 self.assertRegex(output, 'lookup 9')
1708
b677774d 1709 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
1710 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1711 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 1712
b677774d
YW
1713 for trial in range(3):
1714 # Remove state files only first time
e2aea43f
YW
1715 start_networkd(3)
1716 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 1717 time.sleep(1)
b677774d 1718
371810d1 1719 output = check_output('ip rule list table 7')
b677774d 1720 print(output)
426654d7 1721 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 1722
371810d1 1723 output = check_output('ip rule list table 8')
b677774d 1724 print(output)
426654d7 1725 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 1726
aaae5713
YW
1727 stop_networkd(remove_state_files=False)
1728
d586a2c3 1729 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 1730 def test_routing_policy_rule_port_range(self):
ec38833c 1731 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 1732 start_networkd()
e2aea43f 1733 self.wait_online(['test1:degraded'])
e40a58b5 1734
371810d1 1735 output = check_output('ip rule')
926062f0
SS
1736 print(output)
1737 self.assertRegex(output, '111')
1738 self.assertRegex(output, 'from 192.168.100.18')
1739 self.assertRegex(output, '1123-1150')
1740 self.assertRegex(output, '3224-3290')
1741 self.assertRegex(output, 'tcp')
1742 self.assertRegex(output, 'lookup 7')
1f0e3109 1743
d586a2c3 1744 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 1745 def test_routing_policy_rule_invert(self):
ec38833c 1746 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 1747 start_networkd()
e2aea43f 1748 self.wait_online(['test1:degraded'])
e40a58b5 1749
371810d1 1750 output = check_output('ip rule')
efecf9cd 1751 print(output)
efecf9cd
SS
1752 self.assertRegex(output, '111')
1753 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1754 self.assertRegex(output, 'tcp')
1755 self.assertRegex(output, 'lookup 7')
1756
0ef830cf 1757 def test_route_static(self):
ec38833c 1758 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 1759 start_networkd()
e2aea43f
YW
1760 self.wait_online(['dummy98:routable'])
1761
fc79e6ff 1762 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 1763 print(output)
0d34228f 1764
6d60f9db 1765 print('### ip -6 route show dev dummy98')
371810d1 1766 output = check_output('ip -6 route show dev dummy98')
0d34228f 1767 print(output)
0ef830cf
YW
1768 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1769 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1770
6d60f9db 1771 print('### ip -6 route show dev dummy98 default')
371810d1 1772 output = check_output('ip -6 route show dev dummy98 default')
6d60f9db 1773 print(output)
0ef830cf 1774 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1775
6d60f9db 1776 print('### ip -4 route show dev dummy98')
371810d1 1777 output = check_output('ip -4 route show dev dummy98')
1f0e3109 1778 print(output)
0ef830cf
YW
1779 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1780 self.assertRegex(output, '149.10.124.64 proto static scope link')
2b00dff8 1781 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
0ef830cf
YW
1782 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1783 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
6d60f9db 1784 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1f0e3109 1785
6d60f9db 1786 print('### ip -4 route show dev dummy98 default')
371810d1 1787 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 1788 print(output)
0ef830cf
YW
1789 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1790 self.assertRegex(output, 'default via 149.10.124.64 proto static')
6543b7fd 1791 self.assertRegex(output, 'default proto static')
1f0e3109 1792
6d60f9db
YW
1793 print('### ip -4 route show table local dev dummy98')
1794 output = check_output('ip -4 route show table local dev dummy98')
1795 print(output)
1796 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1797 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1798 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1799
1800 print('### ip route show type blackhole')
371810d1 1801 output = check_output('ip route show type blackhole')
1f0e3109 1802 print(output)
0ef830cf 1803 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1804
6d60f9db 1805 print('### ip route show type unreachable')
371810d1 1806 output = check_output('ip route show type unreachable')
f5050e48 1807 print(output)
0ef830cf 1808 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1809
6d60f9db 1810 print('### ip route show type prohibit')
371810d1 1811 output = check_output('ip route show type prohibit')
f5050e48 1812 print(output)
0ef830cf 1813 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1814
a0ce990e
YW
1815 print('### ip route show 192.168.10.1')
1816 output = check_output('ip route show 192.168.10.1')
1817 print(output)
1818 self.assertRegex(output, '192.168.10.1 proto static')
1819 self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1820 self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1821
1822 print('### ip route show 192.168.10.2')
1823 output = check_output('ip route show 192.168.10.2')
1824 print(output)
1825 # old ip command does not show IPv6 gateways...
1826 self.assertRegex(output, '192.168.10.2 proto static')
1827 self.assertRegex(output, 'nexthop')
1828 self.assertRegex(output, 'dev dummy98 weight 10')
1829 self.assertRegex(output, 'dev dummy98 weight 5')
1830
1831 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1832 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1833 print(output)
1834 # old ip command does not show 'nexthop' keyword and weight...
1835 self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
1836 self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
1837 self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
1838
0b1cd3e2
WKI
1839 def test_gateway_reconfigure(self):
1840 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1841 start_networkd()
1842 self.wait_online(['dummy98:routable'])
1843 print('### ip -4 route show dev dummy98 default')
1844 output = check_output('ip -4 route show dev dummy98 default')
1845 print(output)
1846 self.assertRegex(output, 'default via 149.10.124.59 proto static')
1847 self.assertNotRegex(output, '149.10.124.60')
1848
1849 remove_unit_from_networkd_path(['25-gateway-static.network'])
1850 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1851 restart_networkd(3)
1852 self.wait_online(['dummy98:routable'])
1853 print('### ip -4 route show dev dummy98 default')
1854 output = check_output('ip -4 route show dev dummy98 default')
1855 print(output)
1856 self.assertNotRegex(output, '149.10.124.59')
1857 self.assertRegex(output, 'default via 149.10.124.60 proto static')
1858
20ca06a6
DA
1859 def test_ip_route_ipv6_src_route(self):
1860 # a dummy device does not make the addresses go through tentative state, so we
1861 # reuse a bond from an earlier test, which does make the addresses go through
1862 # tentative state, and do our test on that
ec38833c 1863 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 1864 start_networkd()
e2aea43f 1865 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 1866
371810d1 1867 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
1868 print(output)
1869 self.assertRegex(output, 'abcd::/16')
1870 self.assertRegex(output, 'src')
1871 self.assertRegex(output, '2001:1234:56:8f63::2')
1872
1f0e3109 1873 def test_ip_link_mac_address(self):
ec38833c 1874 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 1875 start_networkd()
e2aea43f 1876 self.wait_online(['dummy98:degraded'])
1f0e3109 1877
371810d1 1878 output = check_output('ip link show dummy98')
1f0e3109
SS
1879 print(output)
1880 self.assertRegex(output, '00:01:02:aa:bb:cc')
1881
1882 def test_ip_link_unmanaged(self):
ec38833c 1883 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 1884 start_networkd(5)
1f0e3109 1885
e39cc445 1886 self.check_link_exists('dummy98')
1f0e3109 1887
19cf3143 1888 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
1889
1890 def test_ipv6_address_label(self):
ec38833c 1891 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 1892 start_networkd()
e2aea43f 1893 self.wait_online(['dummy98:degraded'])
1f0e3109 1894
371810d1 1895 output = check_output('ip addrlabel list')
1f0e3109
SS
1896 print(output)
1897 self.assertRegex(output, '2004:da8:1::/64')
1898
d86f5c19 1899 def test_neighbor_section(self):
ec38833c 1900 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 1901 start_networkd()
e2aea43f 1902 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 1903
d1bdafd2 1904 print('### ip neigh list dev dummy98')
df7f9afa 1905 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
1906 print(output)
1907 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 1908 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 1909
d1bdafd2
WKI
1910 def test_neighbor_reconfigure(self):
1911 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1912 start_networkd()
1913 self.wait_online(['dummy98:degraded'], timeout='40s')
1914
1915 print('### ip neigh list dev dummy98')
1916 output = check_output('ip neigh list dev dummy98')
1917 print(output)
1918 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1919 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1920
1921 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1922 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1923 restart_networkd(3)
1924 self.wait_online(['dummy98:degraded'], timeout='40s')
1925 print('### ip neigh list dev dummy98')
1926 output = check_output('ip neigh list dev dummy98')
1927 print(output)
1928 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1929 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1930 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
1931
74761cf3 1932 def test_neighbor_gre(self):
fb2ba330
YW
1933 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1934 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 1935 start_networkd()
fb2ba330 1936 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
1937
1938 output = check_output('ip neigh list dev gretun97')
1939 print(output)
1940 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
1941
1942 output = check_output('ip neigh list dev ip6gretun97')
1943 print(output)
1944 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 1945
05514ae1 1946 def test_link_local_addressing(self):
ec38833c
ZJS
1947 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1948 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 1949 start_networkd()
e2aea43f 1950 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 1951
371810d1 1952 output = check_output('ip address show dev test1')
05514ae1
YW
1953 print(output)
1954 self.assertRegex(output, 'inet .* scope link')
1955 self.assertRegex(output, 'inet6 .* scope link')
1956
371810d1 1957 output = check_output('ip address show dev dummy98')
05514ae1
YW
1958 print(output)
1959 self.assertNotRegex(output, 'inet6* .* scope link')
1960
05514ae1
YW
1961 '''
1962 Documentation/networking/ip-sysctl.txt
1963
1964 addr_gen_mode - INTEGER
1965 Defines how link-local and autoconf addresses are generated.
1966
1967 0: generate address based on EUI64 (default)
1968 1: do no generate a link-local address, use EUI64 for addresses generated
1969 from autoconf
1970 2: generate stable privacy addresses, using the secret from
1971 stable_secret (RFC7217)
1972 3: generate stable privacy addresses, using a random secret if unset
1973 '''
1974
1975 test1_addr_gen_mode = ''
1976 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1977 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1978 try:
1979 f.readline()
1980 except IOError:
1981 # if stable_secret is unset, then EIO is returned
1982 test1_addr_gen_mode = '0'
1983 else:
1984 test1_addr_gen_mode = '2'
1985 else:
1986 test1_addr_gen_mode = '0'
1987
1988 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 1989 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
1990
1991 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 1992 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 1993
7b3770a7
YW
1994 def test_link_local_addressing_remove_ipv6ll(self):
1995 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1996 start_networkd()
1997 self.wait_online(['dummy98:degraded'])
1998
1999 output = check_output('ip address show dev dummy98')
2000 print(output)
2001 self.assertRegex(output, 'inet6 .* scope link')
2002
2003 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2004 restart_networkd(1)
2005 self.wait_online(['dummy98:carrier'])
2006
2007 output = check_output('ip address show dev dummy98')
2008 print(output)
2009 self.assertNotRegex(output, 'inet6* .* scope link')
2010
1f0e3109 2011 def test_sysctl(self):
ec38833c 2012 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2013 start_networkd()
e2aea43f 2014 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2015
2016 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2017 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2018 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2019 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2020 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2021 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2022 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1f0e3109 2023
4da33154 2024 def test_sysctl_disable_ipv6(self):
ec38833c 2025 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2026
2027 print('## Disable ipv6')
cefd6b3d
ZJS
2028 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2029 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2030
2cf6fdff 2031 start_networkd()
e2aea43f 2032 self.wait_online(['dummy98:routable'])
4da33154 2033
371810d1 2034 output = check_output('ip -4 address show dummy98')
4da33154
YW
2035 print(output)
2036 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2037 output = check_output('ip -6 address show dummy98')
4da33154 2038 print(output)
57ad7607
ZJS
2039 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2040 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2041 output = check_output('ip -4 route show dev dummy98')
2042 print(output)
2043 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2044 output = check_output('ip -6 route show dev dummy98')
2045 print(output)
57ad7607 2046 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2047
cefd6b3d 2048 check_output('ip link del dummy98')
4da33154
YW
2049
2050 print('## Enable ipv6')
cefd6b3d
ZJS
2051 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2052 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2053
e2aea43f
YW
2054 restart_networkd(3)
2055 self.wait_online(['dummy98:routable'])
4da33154 2056
371810d1 2057 output = check_output('ip -4 address show dummy98')
4da33154
YW
2058 print(output)
2059 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2060 output = check_output('ip -6 address show dummy98')
4da33154 2061 print(output)
4933b97d 2062 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2063 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2064 output = check_output('ip -4 route show dev dummy98')
2065 print(output)
2066 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2067 output = check_output('ip -6 route show dev dummy98')
2068 print(output)
2069 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2070
cd65d067 2071 def test_bind_carrier(self):
bc942f69
YW
2072 check_output('ip link add dummy98 type dummy')
2073 check_output('ip link set dummy98 up')
2074 time.sleep(2)
2075
ec38833c 2076 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2077 start_networkd()
e2aea43f 2078 self.wait_online(['test1:routable'])
cd65d067 2079
371810d1 2080 output = check_output('ip address show test1')
cd65d067
YW
2081 print(output)
2082 self.assertRegex(output, 'UP,LOWER_UP')
2083 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2084 self.wait_operstate('test1', 'routable')
cd65d067 2085
cefd6b3d
ZJS
2086 check_output('ip link add dummy99 type dummy')
2087 check_output('ip link set dummy99 up')
b117044c 2088 time.sleep(2)
371810d1 2089 output = check_output('ip address show test1')
cd65d067
YW
2090 print(output)
2091 self.assertRegex(output, 'UP,LOWER_UP')
2092 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2093 self.wait_operstate('test1', 'routable')
cd65d067 2094
cefd6b3d 2095 check_output('ip link del dummy98')
b117044c 2096 time.sleep(2)
371810d1 2097 output = check_output('ip address show test1')
cd65d067
YW
2098 print(output)
2099 self.assertRegex(output, 'UP,LOWER_UP')
2100 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2101 self.wait_operstate('test1', 'routable')
cd65d067 2102
bc942f69 2103 check_output('ip link set dummy99 down')
b117044c 2104 time.sleep(2)
371810d1 2105 output = check_output('ip address show test1')
cd65d067
YW
2106 print(output)
2107 self.assertNotRegex(output, 'UP,LOWER_UP')
2108 self.assertRegex(output, 'DOWN')
2109 self.assertNotRegex(output, '192.168.10')
19cf3143 2110 self.wait_operstate('test1', 'off')
cd65d067 2111
bc942f69 2112 check_output('ip link set dummy99 up')
b117044c 2113 time.sleep(2)
371810d1 2114 output = check_output('ip address show test1')
cd65d067
YW
2115 print(output)
2116 self.assertRegex(output, 'UP,LOWER_UP')
2117 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2118 self.wait_operstate('test1', 'routable')
cd65d067 2119
fdcd1ec5 2120 def test_domain(self):
ec38833c 2121 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2122 start_networkd()
e2aea43f 2123 self.wait_online(['dummy98:routable'])
fdcd1ec5 2124
fc79e6ff 2125 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2126 print(output)
2127 self.assertRegex(output, 'Address: 192.168.42.100')
2128 self.assertRegex(output, 'DNS: 192.168.42.1')
2129 self.assertRegex(output, 'Search Domains: one')
2130
1e498853
YW
2131 def test_keep_configuration_static(self):
2132 check_output('systemctl stop systemd-networkd')
2133
2134 check_output('ip link add name dummy98 type dummy')
2135 check_output('ip address add 10.1.2.3/16 dev dummy98')
2136 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2137 output = check_output('ip address show dummy98')
2138 print(output)
2139 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2140 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2141 output = check_output('ip route show dev dummy98')
2142 print(output)
2143
2144 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2145 start_networkd()
e2aea43f 2146 self.wait_online(['dummy98:routable'])
1e498853
YW
2147
2148 output = check_output('ip address show dummy98')
2149 print(output)
2150 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2151 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2152
086bcf5d
YW
2153 @expectedFailureIfNexthopIsNotAvailable()
2154 def test_nexthop(self):
2155 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2156 start_networkd()
2157 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2158
2159 output = check_output('ip nexthop list dev veth99')
2160 print(output)
2161 self.assertRegex(output, '192.168.5.1')
2162
ef3c8a92 2163 def test_qdisc(self):
40821c2a 2164 copy_unit_to_networkd_unit_path('25-qdisc-netem-and-fqcodel.network', '12-dummy.netdev',
0ab92791 2165 '25-qdisc-tbf-and-sfq.network', '11-dummy.netdev')
ef3c8a92
YW
2166 start_networkd()
2167
1b628c4f 2168 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92
YW
2169
2170 output = check_output('tc qdisc show dev dummy98')
2171 print(output)
0ab92791 2172 self.assertRegex(output, 'qdisc netem')
ef3c8a92 2173 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
40821c2a 2174 self.assertRegex(output, 'qdisc fq_codel')
9401e488 2175 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
1b628c4f
YW
2176 output = check_output('tc qdisc show dev test1')
2177 print(output)
0ab92791 2178 self.assertRegex(output, 'qdisc tbf')
886e07a9 2179 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70.0ms')
0ab92791
YW
2180 self.assertRegex(output, 'qdisc sfq')
2181 self.assertRegex(output, 'perturb 5sec')
ef3c8a92 2182
0baddbd5 2183 def test_qdisc2(self):
a3d35654 2184 copy_unit_to_networkd_unit_path('25-qdisc-fq-codel.network', '12-dummy.netdev')
0baddbd5
YW
2185 start_networkd()
2186
2187 self.wait_online(['dummy98:routable'])
2188
2189 output = check_output('tc qdisc show dev dummy98')
2190 print(output)
2191 self.assertRegex(output, 'qdisc fq')
4ef28925 2192 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511 quantum 1500 initial_quantum 13000 maxrate 1Mbit')
a3d35654
YW
2193 self.assertRegex(output, 'qdisc codel')
2194 self.assertRegex(output, 'limit 2000p target 10.0ms ce_threshold 100.0ms interval 50.0ms ecn')
0baddbd5 2195
336d18f0
YW
2196class NetworkdStateFileTests(unittest.TestCase, Utilities):
2197 links = [
2198 'dummy98',
2199 ]
2200
2201 units = [
2202 '12-dummy.netdev',
2203 'state-file-tests.network',
2204 ]
2205
2206 def setUp(self):
2207 remove_links(self.links)
2208 stop_networkd(show_logs=False)
2209
2210 def tearDown(self):
2211 remove_links(self.links)
2212 remove_unit_from_networkd_path(self.units)
2213 stop_networkd(show_logs=True)
2214
2215 def test_state_file(self):
2216 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2217 start_networkd()
2218 self.wait_online(['dummy98:routable'])
2219
2220 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2221 print(output)
2222 ifindex = output.split()[0]
2223
2224 path = os.path.join('/run/systemd/netif/links/', ifindex)
2225 self.assertTrue(os.path.exists(path))
2226 time.sleep(2)
2227
2228 with open(path) as f:
2229 data = f.read()
2230 self.assertRegex(data, r'ADMIN_STATE=configured')
2231 self.assertRegex(data, r'OPER_STATE=routable')
2232 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2233 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2234 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2235 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2236 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2237 self.assertRegex(data, r'DOMAINS=hogehoge')
2238 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2239 self.assertRegex(data, r'LLMNR=no')
2240 self.assertRegex(data, r'MDNS=yes')
2241 self.assertRegex(data, r'DNSSEC=no')
426654d7 2242 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
336d18f0
YW
2243
2244 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2245 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2246 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2247 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2248 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2249 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2250 time.sleep(2)
2251
2252 with open(path) as f:
2253 data = f.read()
2254 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2255 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2256 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2257 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2258 self.assertRegex(data, r'LLMNR=yes')
2259 self.assertRegex(data, r'MDNS=no')
2260 self.assertRegex(data, r'DNSSEC=yes')
2261
2262 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2263 time.sleep(2)
2264
2265 with open(path) as f:
2266 data = f.read()
2267 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2268 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2269 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2270 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2271 self.assertRegex(data, r'LLMNR=yes')
2272 self.assertRegex(data, r'MDNS=no')
2273 self.assertRegex(data, r'DNSSEC=yes')
2274
2275 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2276 time.sleep(2)
2277
2278 with open(path) as f:
2279 data = f.read()
2280 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2281 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2282 self.assertRegex(data, r'DOMAINS=hogehoge')
2283 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2284 self.assertRegex(data, r'LLMNR=no')
2285 self.assertRegex(data, r'MDNS=yes')
2286 self.assertRegex(data, r'DNSSEC=no')
2287
be68c2c9 2288class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 2289 links = [
c2990ec3 2290 'bond199',
c3a8853f 2291 'bond99',
cc3e488c
YW
2292 'dummy98',
2293 'test1']
c3a8853f
YW
2294
2295 units = [
cc3e488c
YW
2296 '11-dummy.netdev',
2297 '12-dummy.netdev',
c2990ec3
YW
2298 '23-active-slave.network',
2299 '23-bond199.network',
2300 '23-primary-slave.network',
c2990ec3 2301 '25-bond-active-backup-slave.netdev',
c3a8853f 2302 '25-bond.netdev',
c3a8853f 2303 'bond99.network',
cc3e488c 2304 'bond-slave.network']
c3a8853f
YW
2305
2306 def setUp(self):
ec38833c 2307 remove_links(self.links)
aaae5713 2308 stop_networkd(show_logs=False)
c3a8853f
YW
2309
2310 def tearDown(self):
ec38833c
ZJS
2311 remove_links(self.links)
2312 remove_unit_from_networkd_path(self.units)
aaae5713 2313 stop_networkd(show_logs=True)
c3a8853f 2314
c2990ec3 2315 def test_bond_active_slave(self):
ec38833c 2316 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2317 start_networkd()
e2aea43f 2318 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2319
371810d1 2320 output = check_output('ip -d link show bond199')
c2990ec3
YW
2321 print(output)
2322 self.assertRegex(output, 'active_slave dummy98')
2323
2324 def test_bond_primary_slave(self):
35a78c51 2325 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2326 start_networkd()
e2aea43f 2327 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2328
371810d1 2329 output = check_output('ip -d link show bond199')
c2990ec3 2330 print(output)
35a78c51 2331 self.assertRegex(output, 'primary dummy98')
c2990ec3 2332
cc3e488c 2333 def test_bond_operstate(self):
ec38833c
ZJS
2334 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2335 'bond99.network','bond-slave.network')
2cf6fdff 2336 start_networkd()
e2aea43f 2337 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 2338
371810d1 2339 output = check_output('ip -d link show dummy98')
c3a8853f 2340 print(output)
cc3e488c 2341 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 2342
371810d1 2343 output = check_output('ip -d link show test1')
c3a8853f
YW
2344 print(output)
2345 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2346
371810d1 2347 output = check_output('ip -d link show bond99')
c3a8853f
YW
2348 print(output)
2349 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2350
19cf3143
DS
2351 self.wait_operstate('dummy98', 'enslaved')
2352 self.wait_operstate('test1', 'enslaved')
2353 self.wait_operstate('bond99', 'routable')
c3a8853f 2354
cefd6b3d 2355 check_output('ip link set dummy98 down')
c3a8853f
YW
2356 time.sleep(2)
2357
19cf3143
DS
2358 self.wait_operstate('dummy98', 'off')
2359 self.wait_operstate('test1', 'enslaved')
2360 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 2361
cefd6b3d 2362 check_output('ip link set dummy98 up')
c3a8853f
YW
2363 time.sleep(2)
2364
19cf3143
DS
2365 self.wait_operstate('dummy98', 'enslaved')
2366 self.wait_operstate('test1', 'enslaved')
2367 self.wait_operstate('bond99', 'routable')
c3a8853f 2368
cefd6b3d
ZJS
2369 check_output('ip link set dummy98 down')
2370 check_output('ip link set test1 down')
2700d2c7 2371 time.sleep(2)
cc3e488c 2372
19cf3143
DS
2373 self.wait_operstate('dummy98', 'off')
2374 self.wait_operstate('test1', 'off')
2700d2c7 2375
2700d2c7
YW
2376 for trial in range(30):
2377 if trial > 0:
2378 time.sleep(1)
371810d1 2379 output = check_output('ip address show bond99')
2700d2c7 2380 print(output)
ec38833c 2381 if get_operstate('bond99') == 'no-carrier':
2700d2c7
YW
2382 break
2383 else:
2384 # Huh? Kernel does not recognize that all slave interfaces are down?
2385 # Let's confirm that networkd's operstate is consistent with ip's result.
2386 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 2387
be68c2c9 2388class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
2389 links = [
2390 'bridge99',
2391 'dummy98',
2392 'test1']
2393
2394 units = [
2395 '11-dummy.netdev',
2396 '12-dummy.netdev',
2397 '26-bridge.netdev',
2398 '26-bridge-slave-interface-1.network',
2399 '26-bridge-slave-interface-2.network',
6f943798
YW
2400 '26-bridge-vlan-master.network',
2401 '26-bridge-vlan-slave.network',
804b6cd2 2402 'bridge99-ignore-carrier-loss.network',
09ea6724 2403 'bridge99.network']
1f0e3109 2404
8d17c386
YW
2405 routing_policy_rule_tables = ['100']
2406
1f0e3109 2407 def setUp(self):
8d17c386 2408 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 2409 remove_links(self.links)
aaae5713 2410 stop_networkd(show_logs=False)
1f0e3109
SS
2411
2412 def tearDown(self):
8d17c386 2413 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
2414 remove_links(self.links)
2415 remove_unit_from_networkd_path(self.units)
aaae5713 2416 stop_networkd(show_logs=True)
1f0e3109 2417
6f943798
YW
2418 def test_bridge_vlan(self):
2419 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2420 '26-bridge.netdev', '26-bridge-vlan-master.network')
2421 start_networkd()
e2aea43f 2422 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
2423
2424 output = check_output('bridge vlan show dev test1')
2425 print(output)
2426 self.assertNotRegex(output, '4063')
2427 for i in range(4064, 4095):
2428 self.assertRegex(output, f'{i}')
2429 self.assertNotRegex(output, '4095')
2430
2431 output = check_output('bridge vlan show dev bridge99')
2432 print(output)
2433 self.assertNotRegex(output, '4059')
2434 for i in range(4060, 4095):
2435 self.assertRegex(output, f'{i}')
2436 self.assertNotRegex(output, '4095')
2437
1f0e3109 2438 def test_bridge_property(self):
ec38833c
ZJS
2439 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2440 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2441 'bridge99.network')
2cf6fdff 2442 start_networkd()
e2aea43f 2443 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 2444
371810d1 2445 output = check_output('ip -d link show test1')
1f0e3109
SS
2446 print(output)
2447 self.assertRegex(output, 'master')
2448 self.assertRegex(output, 'bridge')
2449
371810d1 2450 output = check_output('ip -d link show dummy98')
1f0e3109
SS
2451 print(output)
2452 self.assertRegex(output, 'master')
2453 self.assertRegex(output, 'bridge')
2454
371810d1 2455 output = check_output('ip addr show bridge99')
1f0e3109 2456 print(output)
2be6c5d2 2457 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 2458
371810d1 2459 output = check_output('bridge -d link show dummy98')
1f0e3109 2460 print(output)
ec38833c 2461 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
2462 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2463 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
2464 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2465 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
2466 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2467 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2468 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 2469 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
2470 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2471 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
2472 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2473 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2474 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 2475
5424fd95
YW
2476 output = check_output('bridge -d link show test1')
2477 print(output)
2478 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 2479
371810d1 2480 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2481 time.sleep(1)
2482
371810d1 2483 output = check_output('ip addr show bridge99')
2be6c5d2
YW
2484 print(output)
2485 self.assertRegex(output, '192.168.0.16/24')
2486
e3cbaeab
YW
2487 # for issue #6088
2488 print('### ip -6 route list table all dev bridge99')
2489 output = check_output('ip -6 route list table all dev bridge99')
2490 print(output)
2491 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2492
371810d1 2493 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2
YW
2494 time.sleep(3)
2495
19cf3143 2496 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 2497
cefd6b3d 2498 check_output('ip link del dummy98')
804b6cd2
YW
2499 time.sleep(3)
2500
19cf3143 2501 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 2502
371810d1 2503 output = check_output('ip address show bridge99')
804b6cd2
YW
2504 print(output)
2505 self.assertRegex(output, 'NO-CARRIER')
2506 self.assertNotRegex(output, '192.168.0.15/24')
2507 self.assertNotRegex(output, '192.168.0.16/24')
2508
e3cbaeab
YW
2509 print('### ip -6 route list table all dev bridge99')
2510 output = check_output('ip -6 route list table all dev bridge99')
2511 print(output)
426654d7 2512 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
e3cbaeab 2513
804b6cd2 2514 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
2515 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2516 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2517 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2518 start_networkd()
e2aea43f 2519 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 2520
371810d1 2521 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2522 time.sleep(1)
2523
371810d1
ZJS
2524 check_output('ip link del test1')
2525 check_output('ip link del dummy98')
804b6cd2
YW
2526 time.sleep(3)
2527
371810d1 2528 output = check_output('ip address show bridge99')
804b6cd2
YW
2529 print(output)
2530 self.assertRegex(output, 'NO-CARRIER')
2531 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2532 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2533
6609924c 2534 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
2535 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2536 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2537 start_networkd()
e2aea43f 2538 self.wait_online(['bridge99:no-carrier'])
6609924c 2539
90e3bcbd
YW
2540 for trial in range(4):
2541 check_output('ip link add dummy98 type dummy')
2542 check_output('ip link set dummy98 up')
2543 if trial < 3:
2544 check_output('ip link del dummy98')
6609924c 2545
e2aea43f 2546 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 2547
371810d1 2548 output = check_output('ip address show bridge99')
6609924c
YW
2549 print(output)
2550 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2551
371810d1 2552 output = check_output('ip rule list table 100')
6609924c
YW
2553 print(output)
2554 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2555
be68c2c9 2556class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
2557 links = ['veth99']
2558
09ea6724
YW
2559 units = [
2560 '23-emit-lldp.network',
2561 '24-lldp.network',
2562 '25-veth.netdev']
1f0e3109
SS
2563
2564 def setUp(self):
ec38833c 2565 remove_links(self.links)
aaae5713 2566 stop_networkd(show_logs=False)
1f0e3109
SS
2567
2568 def tearDown(self):
ec38833c
ZJS
2569 remove_links(self.links)
2570 remove_unit_from_networkd_path(self.units)
aaae5713 2571 stop_networkd(show_logs=True)
1f0e3109
SS
2572
2573 def test_lldp(self):
ec38833c 2574 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 2575 start_networkd()
e2aea43f 2576 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 2577
371810d1 2578 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
2579 print(output)
2580 self.assertRegex(output, 'veth-peer')
2581 self.assertRegex(output, 'veth99')
2582
be68c2c9 2583class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
2584 links = ['veth99']
2585
09ea6724
YW
2586 units = [
2587 '25-veth.netdev',
2588 'ipv6-prefix.network',
2589 'ipv6-prefix-veth.network']
1f0e3109
SS
2590
2591 def setUp(self):
ec38833c 2592 remove_links(self.links)
aaae5713 2593 stop_networkd(show_logs=False)
1f0e3109
SS
2594
2595 def tearDown(self):
ec38833c
ZJS
2596 remove_links(self.links)
2597 remove_unit_from_networkd_path(self.units)
aaae5713 2598 stop_networkd(show_logs=True)
1f0e3109
SS
2599
2600 def test_ipv6_prefix_delegation(self):
ec38833c 2601 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 2602 start_networkd()
e2aea43f 2603 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 2604
fc79e6ff 2605 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2606 print(output)
2607 self.assertRegex(output, '2002:da8:1:0')
2608
be68c2c9 2609class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 2610 links = ['veth99']
09ea6724
YW
2611
2612 units = [
09ea6724
YW
2613 '25-veth.netdev',
2614 'dhcp-client.network',
2615 'dhcp-client-timezone-router.network',
2616 'dhcp-server.network',
2617 'dhcp-server-timezone-router.network']
1f0e3109
SS
2618
2619 def setUp(self):
ec38833c 2620 remove_links(self.links)
aaae5713 2621 stop_networkd(show_logs=False)
1f0e3109
SS
2622
2623 def tearDown(self):
ec38833c
ZJS
2624 remove_links(self.links)
2625 remove_unit_from_networkd_path(self.units)
aaae5713 2626 stop_networkd(show_logs=True)
1f0e3109
SS
2627
2628 def test_dhcp_server(self):
ec38833c 2629 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2cf6fdff 2630 start_networkd()
e2aea43f 2631 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2632
fc79e6ff 2633 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2634 print(output)
2635 self.assertRegex(output, '192.168.5.*')
2636 self.assertRegex(output, 'Gateway: 192.168.5.1')
2637 self.assertRegex(output, 'DNS: 192.168.5.1')
2638 self.assertRegex(output, 'NTP: 192.168.5.1')
2639
1f0e3109 2640 def test_emit_router_timezone(self):
ec38833c 2641 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 2642 start_networkd()
e2aea43f 2643 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2644
fc79e6ff 2645 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2646 print(output)
2647 self.assertRegex(output, 'Gateway: 192.168.5.*')
2648 self.assertRegex(output, '192.168.5.*')
2649 self.assertRegex(output, 'Europe/Berlin')
2650
be68c2c9 2651class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2652 links = [
18c613dc
YW
2653 'veth99',
2654 'vrf99']
09ea6724
YW
2655
2656 units = [
2657 '25-veth.netdev',
18c613dc
YW
2658 '25-vrf.netdev',
2659 '25-vrf.network',
09ea6724 2660 'dhcp-client-anonymize.network',
0fd8b718 2661 'dhcp-client-decline.network',
214c5bae
YW
2662 'dhcp-client-gateway-ipv4.network',
2663 'dhcp-client-gateway-ipv6.network',
af3b1498 2664 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2665 'dhcp-client-ipv4-dhcp-settings.network',
2666 'dhcp-client-ipv4-only-ipv6-disabled.network',
2667 'dhcp-client-ipv4-only.network',
2668 'dhcp-client-ipv6-only.network',
2669 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2670 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2671 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 2672 'dhcp-client-listen-port.network',
c1b01a62
YW
2673 'dhcp-client-reassign-static-routes-ipv4.network',
2674 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
2675 'dhcp-client-route-metric.network',
2676 'dhcp-client-route-table.network',
e2d5aab3
YW
2677 'dhcp-client-use-dns-ipv4-and-ra.network',
2678 'dhcp-client-use-dns-ipv4.network',
2679 'dhcp-client-use-dns-no.network',
2680 'dhcp-client-use-dns-yes.network',
e0c1341d 2681 'dhcp-client-use-domains.network',
c38d2d4d 2682 'dhcp-client-use-routes-no.network',
18c613dc 2683 'dhcp-client-vrf.network',
117a55c7
YW
2684 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2685 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
4c882c16 2686 'dhcp-client-with-static-address.network',
3e9d5552 2687 'dhcp-client.network',
0fd8b718 2688 'dhcp-server-decline.network',
09ea6724 2689 'dhcp-server-veth-peer.network',
30d3b54e 2690 'dhcp-v4-server-veth-peer.network',
e0c1341d 2691 'dhcp-client-use-domains.network',
30d3b54e 2692 'static.network']
1f0e3109
SS
2693
2694 def setUp(self):
ec38833c
ZJS
2695 stop_dnsmasq(dnsmasq_pid_file)
2696 remove_links(self.links)
aaae5713 2697 stop_networkd(show_logs=False)
1f0e3109
SS
2698
2699 def tearDown(self):
ec38833c
ZJS
2700 stop_dnsmasq(dnsmasq_pid_file)
2701 remove_lease_file()
2702 remove_log_file()
2703 remove_links(self.links)
2704 remove_unit_from_networkd_path(self.units)
aaae5713 2705 stop_networkd(show_logs=True)
1f0e3109
SS
2706
2707 def test_dhcp_client_ipv6_only(self):
ec38833c 2708 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2709
2cf6fdff 2710 start_networkd()
e2aea43f 2711 self.wait_online(['veth-peer:carrier'])
ec38833c 2712 start_dnsmasq()
e2aea43f 2713 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2714
fc79e6ff 2715 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2716 print(output)
2717 self.assertRegex(output, '2600::')
2718 self.assertNotRegex(output, '192.168.5')
2719
3a956d38 2720 # Confirm that ipv6 token is not set in the kernel
371810d1 2721 output = check_output('ip token show dev veth99')
3a956d38
YW
2722 print(output)
2723 self.assertRegex(output, 'token :: dev veth99')
2724
1f0e3109 2725 def test_dhcp_client_ipv4_only(self):
ec38833c 2726 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2727
2cf6fdff 2728 start_networkd()
e2aea43f 2729 self.wait_online(['veth-peer:carrier'])
195a18c1 2730 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 2731 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2732
fc79e6ff 2733 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2734 print(output)
2735 self.assertNotRegex(output, '2600::')
2736 self.assertRegex(output, '192.168.5')
195a18c1
YW
2737 self.assertRegex(output, '192.168.5.6')
2738 self.assertRegex(output, '192.168.5.7')
2739
2740 # checking routes to DNS servers
2741 output = check_output('ip route show dev veth99')
2742 print(output)
2743 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2744 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2745 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2746
2747 stop_dnsmasq(dnsmasq_pid_file)
2748 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2749
2750 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2751 print('Wait for the dynamic address to be renewed')
2752 time.sleep(125)
2753
2754 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2755
fc79e6ff 2756 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
2757 print(output)
2758 self.assertNotRegex(output, '2600::')
2759 self.assertRegex(output, '192.168.5')
2760 self.assertNotRegex(output, '192.168.5.6')
2761 self.assertRegex(output, '192.168.5.7')
2762 self.assertRegex(output, '192.168.5.8')
2763
2764 # checking routes to DNS servers
2765 output = check_output('ip route show dev veth99')
2766 print(output)
2767 self.assertNotRegex(output, r'192.168.5.6')
2768 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2769 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2770 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109
SS
2771
2772 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
2773 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2774 'dhcp-client-ipv4-only.network')
2cf6fdff 2775 start_networkd()
e2aea43f 2776 self.wait_online(['veth-peer:carrier'])
ec38833c 2777 start_dnsmasq()
e2aea43f 2778 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2779
2780 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 2781 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 2782 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2783
fc79e6ff 2784 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2785 print(output)
2786 self.assertRegex(output, '2600::')
2787 self.assertRegex(output, '192.168.5')
2788
2789 def test_dhcp_client_settings(self):
ec38833c 2790 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 2791
2cf6fdff 2792 start_networkd()
e2aea43f 2793 self.wait_online(['veth-peer:carrier'])
ec38833c 2794 start_dnsmasq()
e2aea43f 2795 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2796
0ae7a66d 2797 print('## ip address show dev veth99')
371810d1 2798 output = check_output('ip address show dev veth99')
1f0e3109
SS
2799 print(output)
2800 self.assertRegex(output, '12:34:56:78:9a:bc')
2801 self.assertRegex(output, '192.168.5')
2802 self.assertRegex(output, '1492')
2803
0ae7a66d 2804 print('## ip route show table main dev veth99')
371810d1 2805 output = check_output('ip route show table main dev veth99')
1f0e3109 2806 print(output)
156ddf8d 2807 # See issue #8726
dd9b10c8
YW
2808 main_table_is_empty = output == ''
2809 if not main_table_is_empty:
2810 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 2811
0ae7a66d 2812 print('## ip route show table 211 dev veth99')
371810d1 2813 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
2814 print(output)
2815 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
2816 if main_table_is_empty:
2817 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
2818 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2819 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2820
2821 print('## dnsmasq log')
ec38833c
ZJS
2822 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2823 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2824 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2825 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2826
2827 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 2828 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 2829 start_networkd()
e2aea43f 2830 self.wait_online(['veth-peer:carrier'])
ec38833c 2831 start_dnsmasq()
e2aea43f 2832 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2833
371810d1 2834 output = check_output('ip address show dev veth99')
1f0e3109
SS
2835 print(output)
2836 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2837 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2838
2839 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 2840 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 2841 start_networkd()
e2aea43f 2842 self.wait_online(['veth-peer:carrier'])
ec38833c 2843 start_dnsmasq()
e2aea43f 2844 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2845
371810d1 2846 output = check_output('ip address show dev veth99')
1f0e3109
SS
2847 print(output)
2848 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2849 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2850
2851 def test_dhcp_client_settings_anonymize(self):
ec38833c 2852 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 2853 start_networkd()
e2aea43f 2854 self.wait_online(['veth-peer:carrier'])
ec38833c 2855 start_dnsmasq()
e2aea43f 2856 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2857
ec38833c
ZJS
2858 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2859 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2860 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2861
2862 def test_dhcp_client_listen_port(self):
ec38833c 2863 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 2864 start_networkd()
e2aea43f 2865 self.wait_online(['veth-peer:carrier'])
ec38833c 2866 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 2867 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 2868
371810d1 2869 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
2870 print(output)
2871 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 2872
4c882c16
YW
2873 def test_dhcp_client_with_static_address(self):
2874 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2875 'dhcp-client-with-static-address.network')
2876 start_networkd()
e2aea43f 2877 self.wait_online(['veth-peer:carrier'])
4c882c16 2878 start_dnsmasq()
e2aea43f 2879 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
2880
2881 output = check_output('ip address show dev veth99 scope global')
2882 print(output)
2883 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2884 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2885
2886 output = check_output('ip route show dev veth99')
2887 print(output)
2888 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2889 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2890 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2891 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2892
1f0e3109 2893 def test_dhcp_route_table_id(self):
ec38833c 2894 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 2895 start_networkd()
e2aea43f 2896 self.wait_online(['veth-peer:carrier'])
ec38833c 2897 start_dnsmasq()
e2aea43f 2898 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2899
371810d1 2900 output = check_output('ip route show table 12')
1f0e3109 2901 print(output)
1f0e3109
SS
2902 self.assertRegex(output, 'veth99 proto dhcp')
2903 self.assertRegex(output, '192.168.5.1')
2904
2905 def test_dhcp_route_metric(self):
ec38833c 2906 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 2907 start_networkd()
e2aea43f 2908 self.wait_online(['veth-peer:carrier'])
ec38833c 2909 start_dnsmasq()
e2aea43f 2910 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2911
371810d1 2912 output = check_output('ip route show dev veth99')
1f0e3109 2913 print(output)
1f0e3109
SS
2914 self.assertRegex(output, 'metric 24')
2915
c1b01a62 2916 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 2917 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 2918 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 2919 start_networkd()
e2aea43f 2920 self.wait_online(['veth-peer:carrier'])
c38d2d4d 2921 start_dnsmasq(lease_time='2m')
e2aea43f 2922 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
2923
2924 output = check_output('ip address show dev veth99 scope global')
2925 print(output)
2926 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2927
2928 output = check_output('ip route show dev veth99')
2929 print(output)
2930 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2931 self.assertRegex(output, r'192.168.5.0/24 proto static')
2932 self.assertRegex(output, r'192.168.6.0/24 proto static')
2933 self.assertRegex(output, r'192.168.7.0/24 proto static')
2934
c1b01a62
YW
2935 stop_dnsmasq(dnsmasq_pid_file)
2936 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
2937
c38d2d4d
YW
2938 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2939 print('Wait for the dynamic address to be renewed')
2940 time.sleep(125)
2941
e2aea43f 2942 self.wait_online(['veth99:routable'])
c38d2d4d
YW
2943
2944 output = check_output('ip route show dev veth99')
2945 print(output)
2946 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2947 self.assertRegex(output, r'192.168.5.0/24 proto static')
2948 self.assertRegex(output, r'192.168.6.0/24 proto static')
2949 self.assertRegex(output, r'192.168.7.0/24 proto static')
2950
c1b01a62
YW
2951 def test_dhcp_client_reassign_static_routes_ipv6(self):
2952 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2953 'dhcp-client-reassign-static-routes-ipv6.network')
2954 start_networkd()
e2aea43f 2955 self.wait_online(['veth-peer:carrier'])
c1b01a62 2956 start_dnsmasq(lease_time='2m')
e2aea43f 2957 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
2958
2959 output = check_output('ip address show dev veth99 scope global')
2960 print(output)
426654d7 2961 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
2962
2963 output = check_output('ip -6 route show dev veth99')
2964 print(output)
2965 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2966 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2967
2968 stop_dnsmasq(dnsmasq_pid_file)
2969 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
2970
2971 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2972 print('Wait for the dynamic address to be renewed')
2973 time.sleep(125)
2974
e2aea43f 2975 self.wait_online(['veth99:routable'])
c1b01a62
YW
2976
2977 output = check_output('ip -6 route show dev veth99')
2978 print(output)
2979 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2980 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2981
1e498853
YW
2982 def test_dhcp_keep_configuration_dhcp(self):
2983 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 2984 start_networkd()
e2aea43f 2985 self.wait_online(['veth-peer:carrier'])
1e498853 2986 start_dnsmasq(lease_time='2m')
e2aea43f 2987 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2988
1e498853
YW
2989 output = check_output('ip address show dev veth99 scope global')
2990 print(output)
2991 self.assertRegex(output, r'192.168.5.*')
2992
fc79e6ff 2993 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 2994 print(output)
1e498853 2995 self.assertRegex(output, r'192.168.5.*')
e40a58b5 2996
5238e957 2997 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 2998 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
2999
3000 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 3001 print('Wait for the dynamic address to be expired')
1f0e3109
SS
3002 time.sleep(125)
3003
1e498853
YW
3004 print('The lease address should be kept after lease expired')
3005 output = check_output('ip address show dev veth99 scope global')
3006 print(output)
3007 self.assertRegex(output, r'192.168.5.*')
3008
fc79e6ff 3009 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3010 print(output)
1e498853
YW
3011 self.assertRegex(output, r'192.168.5.*')
3012
3013 check_output('systemctl stop systemd-networkd')
3014
3015 print('The lease address should be kept after networkd stopped')
3016 output = check_output('ip address show dev veth99 scope global')
3017 print(output)
3018 self.assertRegex(output, r'192.168.5.*')
3019
fc79e6ff 3020 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3021 print(output)
3022 self.assertRegex(output, r'192.168.5.*')
3023
e2aea43f
YW
3024 start_networkd(3)
3025 self.wait_online(['veth-peer:routable'])
1e498853
YW
3026
3027 print('Still the lease address should be kept after networkd restarted')
3028 output = check_output('ip address show dev veth99 scope global')
3029 print(output)
3030 self.assertRegex(output, r'192.168.5.*')
3031
fc79e6ff 3032 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3033 print(output)
3034 self.assertRegex(output, r'192.168.5.*')
3035
3036 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3037 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 3038 start_networkd()
e2aea43f 3039 self.wait_online(['veth-peer:carrier'])
1e498853 3040 start_dnsmasq(lease_time='2m')
e2aea43f 3041 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
3042
3043 output = check_output('ip address show dev veth99 scope global')
3044 print(output)
3045 self.assertRegex(output, r'192.168.5.*')
3046
3047 stop_dnsmasq(dnsmasq_pid_file)
3048 check_output('systemctl stop systemd-networkd')
3049
3050 output = check_output('ip address show dev veth99 scope global')
3051 print(output)
3052 self.assertRegex(output, r'192.168.5.*')
3053
e2aea43f
YW
3054 restart_networkd(3)
3055 self.wait_online(['veth-peer:routable'])
1e498853
YW
3056
3057 output = check_output('ip address show dev veth99 scope global')
3058 print(output)
3059 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 3060
30d3b54e 3061 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 3062 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 3063 start_networkd()
e2aea43f 3064 self.wait_online(['veth-peer:carrier'])
ec38833c 3065 start_dnsmasq()
e2aea43f 3066 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3067
3068 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3069 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3070 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 3071
371810d1 3072 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
3073 print(output)
3074 self.assertRegex(output, '192.168.5')
3075 self.assertRegex(output, '2600::')
3076
2629df47
YW
3077 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3078 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
3079 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3080 print(static_network)
3081
ec38833c 3082 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
3083
3084 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3085 f.write(static_network)
3086
2629df47
YW
3087 # When networkd started, the links are already configured, so let's wait for 5 seconds
3088 # the links to be re-configured.
aaae5713 3089 restart_networkd(5)
e2aea43f 3090 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 3091
371810d1 3092 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
3093 print(output)
3094 self.assertRegex(output, '192.168.5')
3095 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3096
371810d1 3097 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
3098 print(output)
3099 self.assertRegex(output, '2600::')
3100 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3101
18c613dc
YW
3102 @expectedFailureIfModuleIsNotAvailable('vrf')
3103 def test_dhcp_client_vrf(self):
ec38833c
ZJS
3104 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3105 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 3106 start_networkd()
e2aea43f 3107 self.wait_online(['veth-peer:carrier'])
ec38833c 3108 start_dnsmasq()
e2aea43f 3109 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
3110
3111 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3112 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3113 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
3114
3115 print('## ip -d link show dev vrf99')
371810d1 3116 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
3117 print(output)
3118 self.assertRegex(output, 'vrf table 42')
3119
3120 print('## ip address show vrf vrf99')
371810d1 3121 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
3122 print(output)
3123 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3124 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3125 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 3126 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
3127
3128 print('## ip address show dev veth99')
371810d1 3129 output = check_output('ip address show dev veth99')
18c613dc 3130 print(output)
18c613dc
YW
3131 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3132 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3133 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
3134 self.assertRegex(output, 'inet6 .* scope link')
3135
3136 print('## ip route show vrf vrf99')
371810d1 3137 output = check_output('ip route show vrf vrf99')
18c613dc
YW
3138 print(output)
3139 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc
YW
3140 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3141 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3142 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3143 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3144
3145 print('## ip route show table main dev veth99')
371810d1 3146 output = check_output('ip route show table main dev veth99')
18c613dc
YW
3147 print(output)
3148 self.assertEqual(output, '')
3149
214c5bae
YW
3150 def test_dhcp_client_gateway_ipv4(self):
3151 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3152 'dhcp-client-gateway-ipv4.network')
3153 start_networkd()
3154 self.wait_online(['veth-peer:carrier'])
3155 start_dnsmasq()
3156 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3157
3158 output = check_output('ip route list dev veth99 10.0.0.0/8')
3159 print(output)
3160 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3161
3162 def test_dhcp_client_gateway_ipv6(self):
3163 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3164 'dhcp-client-gateway-ipv6.network')
3165 start_networkd()
3166 self.wait_online(['veth-peer:carrier'])
3167 start_dnsmasq()
3168 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3169
3170 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3171 print(output)
3172 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3173
af3b1498 3174 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
3175 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3176 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 3177 start_networkd()
e2aea43f 3178 self.wait_online(['veth-peer:carrier'])
ec38833c 3179 start_dnsmasq()
e2aea43f 3180 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 3181
fc79e6ff 3182 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
3183 print(output)
3184 self.assertRegex(output, '192.168.5')
3185
371810d1 3186 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
3187 print(output)
3188 self.assertRegex(output, 'onlink')
371810d1 3189 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
3190 print(output)
3191 self.assertRegex(output, 'onlink')
3192
117a55c7 3193 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
3194 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3195 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2cf6fdff 3196 start_networkd()
e2aea43f 3197 self.wait_online(['veth-peer:carrier'])
ec38833c 3198 start_dnsmasq(lease_time='2m')
e2aea43f 3199 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 3200
371810d1 3201 output = check_output('ip address show dev veth99')
63c598ed
YW
3202 print(output)
3203
371810d1 3204 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3205 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3206 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3207 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3208 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3209 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3210 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3211 self.assertNotRegex(output, 'inet .* scope link')
3212
3213 print('Wait for the dynamic address to be expired')
3214 time.sleep(130)
3215
371810d1 3216 output = check_output('ip address show dev veth99')
63c598ed
YW
3217 print(output)
3218
371810d1 3219 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3220 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3221 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3222 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3223 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3224 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3225 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3226 self.assertNotRegex(output, 'inet .* scope link')
3227
ec38833c 3228 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 3229
117a55c7 3230 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
3231 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3232 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2cf6fdff 3233 start_networkd()
e2aea43f 3234 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 3235
371810d1 3236 output = check_output('ip address show dev veth99')
117a55c7
YW
3237 print(output)
3238
371810d1 3239 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 3240 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3241 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 3242 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3243 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 3244 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3245 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
3246 self.assertRegex(output, 'inet .* scope link')
3247
b6efd661 3248 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
3249 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3250 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 3251 start_networkd()
e2aea43f 3252 self.wait_online(['veth-peer:carrier'])
ec38833c 3253 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 3254 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
3255
3256 # test for issue #12490
3257
371810d1 3258 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3259 print(output)
3260 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3261 address1=None
3262 for line in output.splitlines():
3263 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3264 address1 = line.split()[1].split('/')[0]
3265 break
3266
371810d1 3267 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3268 print(output)
3269 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3270 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3271
ec38833c
ZJS
3272 stop_dnsmasq(dnsmasq_pid_file)
3273 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
3274
3275 print('Wait for the dynamic address to be expired')
3276 time.sleep(130)
3277
371810d1 3278 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3279 print(output)
3280 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3281 address2=None
3282 for line in output.splitlines():
3283 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3284 address2 = line.split()[1].split('/')[0]
3285 break
3286
3287 self.assertNotEqual(address1, address2)
3288
371810d1 3289 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3290 print(output)
3291 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3292 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3293 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3294 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3295
e2d5aab3
YW
3296 def test_dhcp_client_use_dns_yes(self):
3297 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3298
3299 start_networkd()
e2aea43f 3300 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3301 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3302 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3303
3304 # link become 'routable' when at least one protocol provide an valid address.
3305 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3306 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3307
693283cd 3308 time.sleep(3)
e2d5aab3
YW
3309 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3310 print(output)
3311 self.assertRegex(output, '192.168.5.1')
3312 self.assertRegex(output, '2600::1')
3313
3314 def test_dhcp_client_use_dns_no(self):
3315 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3316
3317 start_networkd()
e2aea43f 3318 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3319 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3320 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3321
3322 # link become 'routable' when at least one protocol provide an valid address.
3323 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3324 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3325
693283cd 3326 time.sleep(3)
e2d5aab3
YW
3327 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3328 print(output)
3329 self.assertNotRegex(output, '192.168.5.1')
3330 self.assertNotRegex(output, '2600::1')
3331
3332 def test_dhcp_client_use_dns_ipv4(self):
3333 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3334
3335 start_networkd()
e2aea43f 3336 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3337 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3338 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3339
3340 # link become 'routable' when at least one protocol provide an valid address.
3341 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3342 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3343
693283cd 3344 time.sleep(3)
e2d5aab3
YW
3345 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3346 print(output)
3347 self.assertRegex(output, '192.168.5.1')
3348 self.assertNotRegex(output, '2600::1')
3349
3350 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3351 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3352
3353 start_networkd()
e2aea43f 3354 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3355 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3356 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3357
3358 # link become 'routable' when at least one protocol provide an valid address.
3359 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3360 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3361
693283cd 3362 time.sleep(3)
e2d5aab3
YW
3363 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3364 print(output)
3365 self.assertRegex(output, '192.168.5.1')
3366 self.assertRegex(output, '2600::1')
3367
e0c1341d
YW
3368 def test_dhcp_client_use_domains(self):
3369 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3370
3371 start_networkd()
e2aea43f 3372 self.wait_online(['veth-peer:carrier'])
e0c1341d 3373 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 3374 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 3375
fc79e6ff 3376 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
3377 print(output)
3378 self.assertRegex(output, 'Search Domains: example.com')
3379
3380 time.sleep(3)
3381 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3382 print(output)
3383 self.assertRegex(output, 'example.com')
3384
0fd8b718
YW
3385 def test_dhcp_client_decline(self):
3386 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3387
3388 start_networkd()
3389 self.wait_online(['veth-peer:carrier'])
3390 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3391 self.assertTrue(rc == 1)
3392
9633f977
SS
3393class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3394 links = ['veth99']
3395
3396 units = [
3397 '25-veth.netdev',
3398 'ipv6ra-prefix-client.network',
3399 'ipv6ra-prefix.network'
3400 ]
3401
3402 def setUp(self):
3403 remove_links(self.links)
3404 stop_networkd(show_logs=False)
3405
3406 def tearDown(self):
3407 remove_log_file()
3408 remove_links(self.links)
3409 remove_unit_from_networkd_path(self.units)
3410 stop_networkd(show_logs=True)
3411
3412 def test_ipv6_route_prefix(self):
3413 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3414
3415 start_networkd()
9633f977
SS
3416 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3417
3418 output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3419 print(output)
3420 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3421
7db05447
DS
3422class NetworkdMTUTests(unittest.TestCase, Utilities):
3423 links = ['dummy98']
3424
3425 units = [
3426 '12-dummy.netdev',
3427 '12-dummy-mtu.netdev',
3428 '12-dummy-mtu.link',
3429 '12-dummy.network',
3430 ]
3431
3432 def setUp(self):
3433 remove_links(self.links)
3434 stop_networkd(show_logs=False)
3435
3436 def tearDown(self):
3437 remove_log_file()
3438 remove_links(self.links)
3439 remove_unit_from_networkd_path(self.units)
3440 stop_networkd(show_logs=True)
3441
3442 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3443 if not ipv6_mtu:
3444 ipv6_mtu = mtu
3445
3446 # test normal start
3447 start_networkd()
3448 self.wait_online(['dummy98:routable'])
3449 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3450 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3451
3452 # test normal restart
3453 restart_networkd()
3454 self.wait_online(['dummy98:routable'])
3455 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3456 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3457
3458 if reset:
3459 self.reset_check_mtu(mtu, ipv6_mtu)
3460
3461 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3462 ''' test setting mtu/ipv6_mtu with interface already up '''
3463 stop_networkd()
3464
3465 # note - changing the device mtu resets the ipv6 mtu
3466 run('ip link set up mtu 1501 dev dummy98')
3467 run('ip link set up mtu 1500 dev dummy98')
3468 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3469 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3470
3471 self.check_mtu(mtu, ipv6_mtu, reset=False)
3472
3473 def test_mtu_network(self):
3474 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3475 self.check_mtu('1600')
3476
3477 def test_mtu_netdev(self):
3478 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3479 # note - MTU set by .netdev happens ONLY at device creation!
3480 self.check_mtu('1600', reset=False)
3481
3482 def test_mtu_link(self):
3483 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3484 # must reload udev because it only picks up new files after 3 second delay
3485 call('udevadm control --reload')
3486 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3487 self.check_mtu('1600', reset=False)
3488
3489 def test_ipv6_mtu(self):
3490 ''' set ipv6 mtu without setting device mtu '''
3491 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3492 self.check_mtu('1500', '1400')
3493
3494 def test_ipv6_mtu_toolarge(self):
3495 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3496 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3497 self.check_mtu('1500', '1500')
3498
3499 def test_mtu_network_ipv6_mtu(self):
3500 ''' set ipv6 mtu and set device mtu via network file '''
3501 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3502 self.check_mtu('1600', '1550')
3503
3504 def test_mtu_netdev_ipv6_mtu(self):
3505 ''' set ipv6 mtu and set device mtu via netdev file '''
3506 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3507 self.check_mtu('1600', '1550', reset=False)
3508
3509 def test_mtu_link_ipv6_mtu(self):
3510 ''' set ipv6 mtu and set device mtu via link file '''
3511 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3512 # must reload udev because it only picks up new files after 3 second delay
3513 call('udevadm control --reload')
3514 self.check_mtu('1600', '1550', reset=False)
3515
3516
1f0e3109 3517if __name__ == '__main__':
9c1ae484
YW
3518 parser = argparse.ArgumentParser()
3519 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3520 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 3521 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
9c1ae484
YW
3522 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3523 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
3524 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3525 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
3526 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3527 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 3528 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 3529 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 3530 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
3531 ns, args = parser.parse_known_args(namespace=unittest)
3532
3533 if ns.build_dir:
b6d587d1
YW
3534 if ns.networkd_bin or ns.resolved_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin:
3535 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 3536 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 3537 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
9c1ae484
YW
3538 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3539 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
3540 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3541 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
3542 else:
3543 if ns.networkd_bin:
3544 networkd_bin = ns.networkd_bin
b6d587d1
YW
3545 if ns.resolved_bin:
3546 resolved_bin = ns.resolved_bin
9c1ae484
YW
3547 if ns.wait_online_bin:
3548 wait_online_bin = ns.wait_online_bin
3549 if ns.networkctl_bin:
3550 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
3551 if ns.resolvectl_bin:
3552 resolvectl_bin = ns.resolvectl_bin
3553 if ns.timedatectl_bin:
3554 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
3555
3556 use_valgrind = ns.use_valgrind
3557 enable_debug = ns.enable_debug
94c03122 3558 asan_options = ns.asan_options
fa4c6095 3559 lsan_options = ns.lsan_options
94c03122 3560 ubsan_options = ns.ubsan_options
9c1ae484
YW
3561
3562 if use_valgrind:
3563 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
3564 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3565 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
3566 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3567 else:
3568 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
3569 resolvectl_cmd = [resolvectl_bin]
3570 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
3571 wait_online_cmd = [wait_online_bin]
3572
3573 if enable_debug:
3574 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
3575 if asan_options:
3576 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
3577 if lsan_options:
3578 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
3579 if ubsan_options:
3580 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
3581
3582 sys.argv[1:] = args
1f0e3109
SS
3583 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3584 verbosity=3))