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