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