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