]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: tc: support HTB class
[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',
40afe491 1592 'vrf99',
74761cf3 1593 ]
09ea6724
YW
1594
1595 units = [
1596 '11-dummy.netdev',
1597 '12-dummy.netdev',
1598 '23-active-slave.network',
1e498853 1599 '24-keep-configuration-static.network',
fdcd1ec5 1600 '24-search-domain.network',
dc7d3c5f
YW
1601 '25-address-dad-veth-peer.network',
1602 '25-address-dad-veth99.network',
09ea6724 1603 '25-address-link-section.network',
e4783b54 1604 '25-address-preferred-lifetime-zero.network',
b8102725 1605 '25-address-static.network',
cd65d067 1606 '25-bind-carrier.network',
09ea6724
YW
1607 '25-bond-active-backup-slave.netdev',
1608 '25-fibrule-invert.network',
1609 '25-fibrule-port-range.network',
6be8e78e 1610 '25-fibrule-uidrange.network',
74761cf3 1611 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1612 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1613 '25-ipv6-address-label-section.network',
ef3c8a92
YW
1614 '25-link-local-addressing-no.network',
1615 '25-link-local-addressing-yes.network',
1616 '25-link-section-unmanaged.network',
e4a71bf3 1617 '25-neighbor-section.network',
d1bdafd2 1618 '25-neighbor-next.network',
fb2ba330 1619 '25-neighbor-ipv6.network',
74761cf3
YW
1620 '25-neighbor-ip-dummy.network',
1621 '25-neighbor-ip.network',
086bcf5d 1622 '25-nexthop.network',
ab9dc1db 1623 '25-qdisc-clsact-root-compat.network',
a3d35654 1624 '25-qdisc-fq-codel.network',
ab9dc1db
YW
1625 '25-qdisc-ingress-netem-compat.network',
1626 '25-qdisc-ingress-root.network',
40821c2a 1627 '25-qdisc-netem-and-fqcodel.network',
0ab92791 1628 '25-qdisc-tbf-and-sfq.network',
931c8c82 1629 '25-qdisc-teql-and-htb.network',
20ca06a6 1630 '25-route-ipv6-src.network',
0ef830cf 1631 '25-route-static.network',
40afe491 1632 '25-route-vrf.network',
0b1cd3e2
WKI
1633 '25-gateway-static.network',
1634 '25-gateway-next-static.network',
4da33154 1635 '25-sysctl-disable-ipv6.network',
09ea6724 1636 '25-sysctl.network',
086bcf5d
YW
1637 '25-veth-peer.network',
1638 '25-veth.netdev',
40afe491 1639 '25-vrf.netdev',
7b3770a7 1640 '26-link-local-addressing-ipv6.network',
09ea6724 1641 'configure-without-carrier.network',
b677774d 1642 'routing-policy-rule-dummy98.network',
b8102725 1643 'routing-policy-rule-test1.network']
1f0e3109 1644
65c24cd0 1645 routing_policy_rule_tables = ['7', '8', '9']
5f68a6a4 1646 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1647
1f0e3109 1648 def setUp(self):
ec38833c
ZJS
1649 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1650 remove_routes(self.routes)
1651 remove_links(self.links)
aaae5713 1652 stop_networkd(show_logs=False)
1f0e3109
SS
1653
1654 def tearDown(self):
ec38833c
ZJS
1655 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1656 remove_routes(self.routes)
1657 remove_links(self.links)
1658 remove_unit_from_networkd_path(self.units)
aaae5713 1659 stop_networkd(show_logs=True)
1f0e3109 1660
b8102725 1661 def test_address_static(self):
ec38833c 1662 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 1663 start_networkd()
b8102725 1664
e2aea43f 1665 self.wait_online(['dummy98:routable'])
b8102725 1666
371810d1 1667 output = check_output('ip -4 address show dev dummy98')
b8102725
YW
1668 print(output)
1669 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1670 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1671 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1672
1673 # invalid sections
1674 self.assertNotRegex(output, '10.10.0.1/16')
1675 self.assertNotRegex(output, '10.10.0.2/16')
1676
371810d1 1677 output = check_output('ip -4 address show dev dummy98 label 32')
b8102725
YW
1678 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1679
371810d1 1680 output = check_output('ip -4 address show dev dummy98 label 33')
b8102725
YW
1681 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1682
371810d1 1683 output = check_output('ip -4 address show dev dummy98 label 34')
b8102725
YW
1684 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1685
371810d1 1686 output = check_output('ip -4 address show dev dummy98 label 35')
b8102725
YW
1687 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1688
371810d1 1689 output = check_output('ip -6 address show dev dummy98')
b8102725
YW
1690 print(output)
1691 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1692 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1693 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1694 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1695 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1696 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1697
1698 def test_address_preferred_lifetime_zero_ipv6(self):
e4783b54 1699 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
01943d43 1700 start_networkd(5)
1f0e3109 1701
e4783b54 1702 self.wait_online(['dummy98:routable'])
b8102725 1703
371810d1 1704 output = check_output('ip address show dummy98')
b8102725
YW
1705 print(output)
1706 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1707 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109 1708
e4783b54
YW
1709 output = check_output('ip route show dev dummy98')
1710 print(output)
1711 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1712
dc7d3c5f
YW
1713 def test_address_dad(self):
1714 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1715 '25-veth.netdev')
1716 start_networkd()
1717 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1718
1719 output = check_output('ip -4 address show dev veth99')
1720 print(output)
1721 self.assertRegex(output, '192.168.100.10/24')
1722
1723 output = check_output('ip -4 address show dev veth-peer')
1724 print(output)
1725 self.assertNotRegex(output, '192.168.100.10/24')
1726
1f0e3109 1727 def test_configure_without_carrier(self):
ec38833c 1728 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
2cf6fdff 1729 start_networkd()
e2aea43f 1730 self.wait_online(['test1:routable'])
e40a58b5 1731
fc79e6ff 1732 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1f0e3109
SS
1733 print(output)
1734 self.assertRegex(output, '192.168.0.15')
1735 self.assertRegex(output, '192.168.0.1')
1736 self.assertRegex(output, 'routable')
1737
1f0e3109 1738 def test_routing_policy_rule(self):
ec38833c 1739 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 1740 start_networkd()
e2aea43f 1741 self.wait_online(['test1:degraded'])
e40a58b5 1742
65c24cd0 1743 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 1744 print(output)
65c24cd0 1745 self.assertRegex(output, '111:')
1f0e3109 1746 self.assertRegex(output, 'from 192.168.100.18')
426654d7 1747 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
1748 self.assertRegex(output, 'iif test1')
1749 self.assertRegex(output, 'oif test1')
1750 self.assertRegex(output, 'lookup 7')
1751
65c24cd0
YW
1752 output = check_output('ip rule list iif test1 priority 101')
1753 print(output)
1754 self.assertRegex(output, '101:')
1755 self.assertRegex(output, 'from all')
1756 self.assertRegex(output, 'iif test1')
1757 self.assertRegex(output, 'lookup 9')
1758
1759 output = check_output('ip -6 rule list iif test1 priority 100')
1760 print(output)
1761 self.assertRegex(output, '100:')
1762 self.assertRegex(output, 'from all')
1763 self.assertRegex(output, 'iif test1')
1764 self.assertRegex(output, 'lookup 8')
1765
1766 output = check_output('ip -6 rule list iif test1 priority 101')
1767 print(output)
1768 self.assertRegex(output, '101:')
1769 self.assertRegex(output, 'from all')
1770 self.assertRegex(output, 'iif test1')
1771 self.assertRegex(output, 'lookup 9')
1772
b677774d 1773 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
1774 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1775 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 1776
b677774d
YW
1777 for trial in range(3):
1778 # Remove state files only first time
e2aea43f
YW
1779 start_networkd(3)
1780 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 1781 time.sleep(1)
b677774d 1782
371810d1 1783 output = check_output('ip rule list table 7')
b677774d 1784 print(output)
426654d7 1785 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 1786
371810d1 1787 output = check_output('ip rule list table 8')
b677774d 1788 print(output)
426654d7 1789 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 1790
aaae5713
YW
1791 stop_networkd(remove_state_files=False)
1792
d586a2c3 1793 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 1794 def test_routing_policy_rule_port_range(self):
ec38833c 1795 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 1796 start_networkd()
e2aea43f 1797 self.wait_online(['test1:degraded'])
e40a58b5 1798
371810d1 1799 output = check_output('ip rule')
926062f0
SS
1800 print(output)
1801 self.assertRegex(output, '111')
1802 self.assertRegex(output, 'from 192.168.100.18')
1803 self.assertRegex(output, '1123-1150')
1804 self.assertRegex(output, '3224-3290')
1805 self.assertRegex(output, 'tcp')
1806 self.assertRegex(output, 'lookup 7')
1f0e3109 1807
d586a2c3 1808 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 1809 def test_routing_policy_rule_invert(self):
ec38833c 1810 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 1811 start_networkd()
e2aea43f 1812 self.wait_online(['test1:degraded'])
e40a58b5 1813
371810d1 1814 output = check_output('ip rule')
efecf9cd 1815 print(output)
efecf9cd
SS
1816 self.assertRegex(output, '111')
1817 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1818 self.assertRegex(output, 'tcp')
1819 self.assertRegex(output, 'lookup 7')
1820
6be8e78e
YW
1821 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
1822 def test_routing_policy_rule_uidrange(self):
1823 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
1824 start_networkd()
1825 self.wait_online(['test1:degraded'])
1826
1827 output = check_output('ip rule')
1828 print(output)
1829 self.assertRegex(output, '111')
1830 self.assertRegex(output, 'from 192.168.100.18')
1831 self.assertRegex(output, 'lookup 7')
1832 self.assertRegex(output, 'uidrange 100-200')
1833
0ef830cf 1834 def test_route_static(self):
ec38833c 1835 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 1836 start_networkd()
e2aea43f
YW
1837 self.wait_online(['dummy98:routable'])
1838
fc79e6ff 1839 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 1840 print(output)
0d34228f 1841
6d60f9db 1842 print('### ip -6 route show dev dummy98')
371810d1 1843 output = check_output('ip -6 route show dev dummy98')
0d34228f 1844 print(output)
0ef830cf
YW
1845 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1846 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1847
6d60f9db 1848 print('### ip -6 route show dev dummy98 default')
371810d1 1849 output = check_output('ip -6 route show dev dummy98 default')
6d60f9db 1850 print(output)
0ef830cf 1851 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1852
6d60f9db 1853 print('### ip -4 route show dev dummy98')
371810d1 1854 output = check_output('ip -4 route show dev dummy98')
1f0e3109 1855 print(output)
0ef830cf
YW
1856 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1857 self.assertRegex(output, '149.10.124.64 proto static scope link')
2b00dff8 1858 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
0ef830cf
YW
1859 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1860 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
6d60f9db 1861 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1f0e3109 1862
6d60f9db 1863 print('### ip -4 route show dev dummy98 default')
371810d1 1864 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 1865 print(output)
0ef830cf
YW
1866 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1867 self.assertRegex(output, 'default via 149.10.124.64 proto static')
6543b7fd 1868 self.assertRegex(output, 'default proto static')
1f0e3109 1869
6d60f9db
YW
1870 print('### ip -4 route show table local dev dummy98')
1871 output = check_output('ip -4 route show table local dev dummy98')
1872 print(output)
1873 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1874 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1875 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1876
1877 print('### ip route show type blackhole')
371810d1 1878 output = check_output('ip route show type blackhole')
1f0e3109 1879 print(output)
0ef830cf 1880 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1881
6d60f9db 1882 print('### ip route show type unreachable')
371810d1 1883 output = check_output('ip route show type unreachable')
f5050e48 1884 print(output)
0ef830cf 1885 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1886
6d60f9db 1887 print('### ip route show type prohibit')
371810d1 1888 output = check_output('ip route show type prohibit')
f5050e48 1889 print(output)
0ef830cf 1890 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1891
a0ce990e
YW
1892 print('### ip route show 192.168.10.1')
1893 output = check_output('ip route show 192.168.10.1')
1894 print(output)
1895 self.assertRegex(output, '192.168.10.1 proto static')
1896 self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1897 self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1898
1899 print('### ip route show 192.168.10.2')
1900 output = check_output('ip route show 192.168.10.2')
1901 print(output)
1902 # old ip command does not show IPv6 gateways...
1903 self.assertRegex(output, '192.168.10.2 proto static')
1904 self.assertRegex(output, 'nexthop')
1905 self.assertRegex(output, 'dev dummy98 weight 10')
1906 self.assertRegex(output, 'dev dummy98 weight 5')
1907
1908 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1909 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1910 print(output)
1911 # old ip command does not show 'nexthop' keyword and weight...
1912 self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
1913 self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
1914 self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
1915
40afe491
YW
1916 @expectedFailureIfModuleIsNotAvailable('vrf')
1917 def test_route_vrf(self):
1918 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
1919 '25-vrf.netdev', '25-vrf.network')
1920 start_networkd()
1921 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
1922
1923 output = check_output('ip route show vrf vrf99')
1924 print(output)
1925 self.assertRegex(output, 'default via 192.168.100.1')
1926
1927 output = check_output('ip route show')
1928 print(output)
1929 self.assertNotRegex(output, 'default via 192.168.100.1')
1930
0b1cd3e2
WKI
1931 def test_gateway_reconfigure(self):
1932 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1933 start_networkd()
1934 self.wait_online(['dummy98:routable'])
1935 print('### ip -4 route show dev dummy98 default')
1936 output = check_output('ip -4 route show dev dummy98 default')
1937 print(output)
1938 self.assertRegex(output, 'default via 149.10.124.59 proto static')
1939 self.assertNotRegex(output, '149.10.124.60')
1940
1941 remove_unit_from_networkd_path(['25-gateway-static.network'])
1942 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1943 restart_networkd(3)
1944 self.wait_online(['dummy98:routable'])
1945 print('### ip -4 route show dev dummy98 default')
1946 output = check_output('ip -4 route show dev dummy98 default')
1947 print(output)
1948 self.assertNotRegex(output, '149.10.124.59')
1949 self.assertRegex(output, 'default via 149.10.124.60 proto static')
1950
20ca06a6
DA
1951 def test_ip_route_ipv6_src_route(self):
1952 # a dummy device does not make the addresses go through tentative state, so we
1953 # reuse a bond from an earlier test, which does make the addresses go through
1954 # tentative state, and do our test on that
ec38833c 1955 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 1956 start_networkd()
e2aea43f 1957 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 1958
371810d1 1959 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
1960 print(output)
1961 self.assertRegex(output, 'abcd::/16')
1962 self.assertRegex(output, 'src')
1963 self.assertRegex(output, '2001:1234:56:8f63::2')
1964
1f0e3109 1965 def test_ip_link_mac_address(self):
ec38833c 1966 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 1967 start_networkd()
e2aea43f 1968 self.wait_online(['dummy98:degraded'])
1f0e3109 1969
371810d1 1970 output = check_output('ip link show dummy98')
1f0e3109
SS
1971 print(output)
1972 self.assertRegex(output, '00:01:02:aa:bb:cc')
1973
1974 def test_ip_link_unmanaged(self):
ec38833c 1975 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 1976 start_networkd(5)
1f0e3109 1977
e39cc445 1978 self.check_link_exists('dummy98')
1f0e3109 1979
19cf3143 1980 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
1981
1982 def test_ipv6_address_label(self):
ec38833c 1983 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 1984 start_networkd()
e2aea43f 1985 self.wait_online(['dummy98:degraded'])
1f0e3109 1986
371810d1 1987 output = check_output('ip addrlabel list')
1f0e3109
SS
1988 print(output)
1989 self.assertRegex(output, '2004:da8:1::/64')
1990
d86f5c19 1991 def test_neighbor_section(self):
ec38833c 1992 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 1993 start_networkd()
e2aea43f 1994 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 1995
d1bdafd2 1996 print('### ip neigh list dev dummy98')
df7f9afa 1997 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
1998 print(output)
1999 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2000 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2001
d1bdafd2
WKI
2002 def test_neighbor_reconfigure(self):
2003 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2004 start_networkd()
2005 self.wait_online(['dummy98:degraded'], timeout='40s')
2006
2007 print('### ip neigh list dev dummy98')
2008 output = check_output('ip neigh list dev dummy98')
2009 print(output)
2010 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2011 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2012
2013 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2014 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2015 restart_networkd(3)
2016 self.wait_online(['dummy98:degraded'], timeout='40s')
2017 print('### ip neigh list dev dummy98')
2018 output = check_output('ip neigh list dev dummy98')
2019 print(output)
2020 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2021 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2022 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2023
74761cf3 2024 def test_neighbor_gre(self):
fb2ba330
YW
2025 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2026 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2027 start_networkd()
fb2ba330 2028 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2029
2030 output = check_output('ip neigh list dev gretun97')
2031 print(output)
2032 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2033
2034 output = check_output('ip neigh list dev ip6gretun97')
2035 print(output)
2036 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2037
05514ae1 2038 def test_link_local_addressing(self):
ec38833c
ZJS
2039 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2040 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2041 start_networkd()
e2aea43f 2042 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2043
371810d1 2044 output = check_output('ip address show dev test1')
05514ae1
YW
2045 print(output)
2046 self.assertRegex(output, 'inet .* scope link')
2047 self.assertRegex(output, 'inet6 .* scope link')
2048
371810d1 2049 output = check_output('ip address show dev dummy98')
05514ae1
YW
2050 print(output)
2051 self.assertNotRegex(output, 'inet6* .* scope link')
2052
05514ae1
YW
2053 '''
2054 Documentation/networking/ip-sysctl.txt
2055
2056 addr_gen_mode - INTEGER
2057 Defines how link-local and autoconf addresses are generated.
2058
2059 0: generate address based on EUI64 (default)
2060 1: do no generate a link-local address, use EUI64 for addresses generated
2061 from autoconf
2062 2: generate stable privacy addresses, using the secret from
2063 stable_secret (RFC7217)
2064 3: generate stable privacy addresses, using a random secret if unset
2065 '''
2066
2067 test1_addr_gen_mode = ''
2068 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2069 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2070 try:
2071 f.readline()
2072 except IOError:
2073 # if stable_secret is unset, then EIO is returned
2074 test1_addr_gen_mode = '0'
2075 else:
2076 test1_addr_gen_mode = '2'
2077 else:
2078 test1_addr_gen_mode = '0'
2079
2080 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 2081 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
2082
2083 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 2084 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2085
7b3770a7
YW
2086 def test_link_local_addressing_remove_ipv6ll(self):
2087 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2088 start_networkd()
2089 self.wait_online(['dummy98:degraded'])
2090
2091 output = check_output('ip address show dev dummy98')
2092 print(output)
2093 self.assertRegex(output, 'inet6 .* scope link')
2094
2095 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2096 restart_networkd(1)
2097 self.wait_online(['dummy98:carrier'])
2098
2099 output = check_output('ip address show dev dummy98')
2100 print(output)
2101 self.assertNotRegex(output, 'inet6* .* scope link')
2102
1f0e3109 2103 def test_sysctl(self):
ec38833c 2104 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2105 start_networkd()
e2aea43f 2106 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2107
2108 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2109 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2110 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2111 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2112 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2113 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2114 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1f0e3109 2115
4da33154 2116 def test_sysctl_disable_ipv6(self):
ec38833c 2117 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2118
2119 print('## Disable ipv6')
cefd6b3d
ZJS
2120 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2121 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2122
2cf6fdff 2123 start_networkd()
e2aea43f 2124 self.wait_online(['dummy98:routable'])
4da33154 2125
371810d1 2126 output = check_output('ip -4 address show dummy98')
4da33154
YW
2127 print(output)
2128 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2129 output = check_output('ip -6 address show dummy98')
4da33154 2130 print(output)
57ad7607
ZJS
2131 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2132 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2133 output = check_output('ip -4 route show dev dummy98')
2134 print(output)
2135 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2136 output = check_output('ip -6 route show dev dummy98')
2137 print(output)
57ad7607 2138 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2139
cefd6b3d 2140 check_output('ip link del dummy98')
4da33154
YW
2141
2142 print('## Enable ipv6')
cefd6b3d
ZJS
2143 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2144 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2145
e2aea43f
YW
2146 restart_networkd(3)
2147 self.wait_online(['dummy98:routable'])
4da33154 2148
371810d1 2149 output = check_output('ip -4 address show dummy98')
4da33154
YW
2150 print(output)
2151 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2152 output = check_output('ip -6 address show dummy98')
4da33154 2153 print(output)
4933b97d 2154 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2155 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2156 output = check_output('ip -4 route show dev dummy98')
2157 print(output)
2158 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2159 output = check_output('ip -6 route show dev dummy98')
2160 print(output)
2161 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2162
cd65d067 2163 def test_bind_carrier(self):
bc942f69
YW
2164 check_output('ip link add dummy98 type dummy')
2165 check_output('ip link set dummy98 up')
2166 time.sleep(2)
2167
ec38833c 2168 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2169 start_networkd()
e2aea43f 2170 self.wait_online(['test1:routable'])
cd65d067 2171
371810d1 2172 output = check_output('ip address show test1')
cd65d067
YW
2173 print(output)
2174 self.assertRegex(output, 'UP,LOWER_UP')
2175 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2176 self.wait_operstate('test1', 'routable')
cd65d067 2177
cefd6b3d
ZJS
2178 check_output('ip link add dummy99 type dummy')
2179 check_output('ip link set dummy99 up')
b117044c 2180 time.sleep(2)
371810d1 2181 output = check_output('ip address show test1')
cd65d067
YW
2182 print(output)
2183 self.assertRegex(output, 'UP,LOWER_UP')
2184 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2185 self.wait_operstate('test1', 'routable')
cd65d067 2186
cefd6b3d 2187 check_output('ip link del dummy98')
b117044c 2188 time.sleep(2)
371810d1 2189 output = check_output('ip address show test1')
cd65d067
YW
2190 print(output)
2191 self.assertRegex(output, 'UP,LOWER_UP')
2192 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2193 self.wait_operstate('test1', 'routable')
cd65d067 2194
bc942f69 2195 check_output('ip link set dummy99 down')
b117044c 2196 time.sleep(2)
371810d1 2197 output = check_output('ip address show test1')
cd65d067
YW
2198 print(output)
2199 self.assertNotRegex(output, 'UP,LOWER_UP')
2200 self.assertRegex(output, 'DOWN')
2201 self.assertNotRegex(output, '192.168.10')
19cf3143 2202 self.wait_operstate('test1', 'off')
cd65d067 2203
bc942f69 2204 check_output('ip link set dummy99 up')
b117044c 2205 time.sleep(2)
371810d1 2206 output = check_output('ip address show test1')
cd65d067
YW
2207 print(output)
2208 self.assertRegex(output, 'UP,LOWER_UP')
2209 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2210 self.wait_operstate('test1', 'routable')
cd65d067 2211
fdcd1ec5 2212 def test_domain(self):
ec38833c 2213 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2214 start_networkd()
e2aea43f 2215 self.wait_online(['dummy98:routable'])
fdcd1ec5 2216
fc79e6ff 2217 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2218 print(output)
2219 self.assertRegex(output, 'Address: 192.168.42.100')
2220 self.assertRegex(output, 'DNS: 192.168.42.1')
2221 self.assertRegex(output, 'Search Domains: one')
2222
1e498853
YW
2223 def test_keep_configuration_static(self):
2224 check_output('systemctl stop systemd-networkd')
2225
2226 check_output('ip link add name dummy98 type dummy')
2227 check_output('ip address add 10.1.2.3/16 dev dummy98')
2228 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2229 output = check_output('ip address show dummy98')
2230 print(output)
2231 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2232 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2233 output = check_output('ip route show dev dummy98')
2234 print(output)
2235
2236 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2237 start_networkd()
e2aea43f 2238 self.wait_online(['dummy98:routable'])
1e498853
YW
2239
2240 output = check_output('ip address show dummy98')
2241 print(output)
2242 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2243 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2244
086bcf5d
YW
2245 @expectedFailureIfNexthopIsNotAvailable()
2246 def test_nexthop(self):
2247 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2248 start_networkd()
2249 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2250
2251 output = check_output('ip nexthop list dev veth99')
2252 print(output)
2253 self.assertRegex(output, '192.168.5.1')
2254
ef3c8a92 2255 def test_qdisc(self):
40821c2a 2256 copy_unit_to_networkd_unit_path('25-qdisc-netem-and-fqcodel.network', '12-dummy.netdev',
0ab92791 2257 '25-qdisc-tbf-and-sfq.network', '11-dummy.netdev')
ef3c8a92
YW
2258 start_networkd()
2259
1b628c4f 2260 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92
YW
2261
2262 output = check_output('tc qdisc show dev dummy98')
2263 print(output)
38d1255a 2264 self.assertRegex(output, 'qdisc netem 1f:')
ef3c8a92 2265 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
40821c2a 2266 self.assertRegex(output, 'qdisc fq_codel')
9401e488 2267 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
2268 output = check_output('tc qdisc show dev test1')
2269 print(output)
38d1255a 2270 self.assertRegex(output, 'qdisc tbf 3f:')
886e07a9 2271 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70.0ms')
0ab92791
YW
2272 self.assertRegex(output, 'qdisc sfq')
2273 self.assertRegex(output, 'perturb 5sec')
ef3c8a92 2274
0baddbd5 2275 def test_qdisc2(self):
ab9dc1db
YW
2276 copy_unit_to_networkd_unit_path('25-qdisc-fq-codel.network', '12-dummy.netdev',
2277 '25-qdisc-ingress-root.network', '11-dummy.netdev')
0baddbd5
YW
2278 start_networkd()
2279
ab9dc1db 2280 self.wait_online(['dummy98:routable', 'test1:routable'])
0baddbd5
YW
2281
2282 output = check_output('tc qdisc show dev dummy98')
2283 print(output)
38d1255a 2284 self.assertRegex(output, 'qdisc fq 3:')
a05a6e8b
YW
2285 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2286 self.assertRegex(output, 'quantum 1500')
2287 self.assertRegex(output, 'initial_quantum 13000')
2288 self.assertRegex(output, 'maxrate 1Mbit')
a3d35654
YW
2289 self.assertRegex(output, 'qdisc codel')
2290 self.assertRegex(output, 'limit 2000p target 10.0ms ce_threshold 100.0ms interval 50.0ms ecn')
ab9dc1db
YW
2291 output = check_output('tc qdisc show dev test1')
2292 print(output)
2293 self.assertRegex(output, 'qdisc ingress')
2294
2295 def test_qdisc3(self):
2296 copy_unit_to_networkd_unit_path('25-qdisc-clsact-root-compat.network', '12-dummy.netdev',
2297 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2298 start_networkd()
2299
2300 self.wait_online(['dummy98:routable', 'test1:routable'])
2301
2302 output = check_output('tc qdisc show dev dummy98')
2303 print(output)
2304 self.assertRegex(output, 'qdisc clsact')
2305 output = check_output('tc qdisc show dev test1')
2306 print(output)
2307 self.assertRegex(output, 'qdisc netem')
2308 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2309 self.assertRegex(output, 'qdisc ingress')
0baddbd5 2310
3d55b5a9 2311 def test_qdisc4(self):
931c8c82 2312 copy_unit_to_networkd_unit_path('25-qdisc-teql-and-htb.network', '12-dummy.netdev')
3d55b5a9
YW
2313 check_output('modprobe sch_teql max_equalizers=2')
2314 start_networkd()
2315
2316 self.wait_online(['dummy98:routable'])
2317
2318 output = check_output('tc qdisc show dev dummy98')
2319 print(output)
931c8c82
YW
2320 self.assertRegex(output, 'qdisc teql1')
2321 self.assertRegex(output, 'qdisc htb 2:')
2322 self.assertRegex(output, r'default (0x30|30)')
3d55b5a9 2323
336d18f0
YW
2324class NetworkdStateFileTests(unittest.TestCase, Utilities):
2325 links = [
2326 'dummy98',
2327 ]
2328
2329 units = [
2330 '12-dummy.netdev',
2331 'state-file-tests.network',
2332 ]
2333
2334 def setUp(self):
2335 remove_links(self.links)
2336 stop_networkd(show_logs=False)
2337
2338 def tearDown(self):
2339 remove_links(self.links)
2340 remove_unit_from_networkd_path(self.units)
2341 stop_networkd(show_logs=True)
2342
2343 def test_state_file(self):
2344 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2345 start_networkd()
2346 self.wait_online(['dummy98:routable'])
2347
2348 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2349 print(output)
2350 ifindex = output.split()[0]
2351
2352 path = os.path.join('/run/systemd/netif/links/', ifindex)
2353 self.assertTrue(os.path.exists(path))
2354 time.sleep(2)
2355
2356 with open(path) as f:
2357 data = f.read()
2358 self.assertRegex(data, r'ADMIN_STATE=configured')
2359 self.assertRegex(data, r'OPER_STATE=routable')
2360 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2361 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2362 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2363 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2364 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2365 self.assertRegex(data, r'DOMAINS=hogehoge')
2366 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2367 self.assertRegex(data, r'LLMNR=no')
2368 self.assertRegex(data, r'MDNS=yes')
2369 self.assertRegex(data, r'DNSSEC=no')
426654d7 2370 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
336d18f0
YW
2371
2372 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2373 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2374 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2375 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2376 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2377 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2378 time.sleep(2)
2379
2380 with open(path) as f:
2381 data = f.read()
2382 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2383 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2384 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2385 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2386 self.assertRegex(data, r'LLMNR=yes')
2387 self.assertRegex(data, r'MDNS=no')
2388 self.assertRegex(data, r'DNSSEC=yes')
2389
2390 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2391 time.sleep(2)
2392
2393 with open(path) as f:
2394 data = f.read()
2395 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2396 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2397 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2398 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2399 self.assertRegex(data, r'LLMNR=yes')
2400 self.assertRegex(data, r'MDNS=no')
2401 self.assertRegex(data, r'DNSSEC=yes')
2402
2403 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2404 time.sleep(2)
2405
2406 with open(path) as f:
2407 data = f.read()
2408 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2409 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2410 self.assertRegex(data, r'DOMAINS=hogehoge')
2411 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2412 self.assertRegex(data, r'LLMNR=no')
2413 self.assertRegex(data, r'MDNS=yes')
2414 self.assertRegex(data, r'DNSSEC=no')
2415
be68c2c9 2416class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 2417 links = [
c2990ec3 2418 'bond199',
c3a8853f 2419 'bond99',
cc3e488c
YW
2420 'dummy98',
2421 'test1']
c3a8853f
YW
2422
2423 units = [
cc3e488c
YW
2424 '11-dummy.netdev',
2425 '12-dummy.netdev',
c2990ec3
YW
2426 '23-active-slave.network',
2427 '23-bond199.network',
2428 '23-primary-slave.network',
c2990ec3 2429 '25-bond-active-backup-slave.netdev',
c3a8853f 2430 '25-bond.netdev',
c3a8853f 2431 'bond99.network',
cc3e488c 2432 'bond-slave.network']
c3a8853f
YW
2433
2434 def setUp(self):
ec38833c 2435 remove_links(self.links)
aaae5713 2436 stop_networkd(show_logs=False)
c3a8853f
YW
2437
2438 def tearDown(self):
ec38833c
ZJS
2439 remove_links(self.links)
2440 remove_unit_from_networkd_path(self.units)
aaae5713 2441 stop_networkd(show_logs=True)
c3a8853f 2442
c2990ec3 2443 def test_bond_active_slave(self):
ec38833c 2444 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2445 start_networkd()
e2aea43f 2446 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2447
371810d1 2448 output = check_output('ip -d link show bond199')
c2990ec3
YW
2449 print(output)
2450 self.assertRegex(output, 'active_slave dummy98')
2451
2452 def test_bond_primary_slave(self):
35a78c51 2453 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2454 start_networkd()
e2aea43f 2455 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2456
371810d1 2457 output = check_output('ip -d link show bond199')
c2990ec3 2458 print(output)
35a78c51 2459 self.assertRegex(output, 'primary dummy98')
c2990ec3 2460
cc3e488c 2461 def test_bond_operstate(self):
ec38833c
ZJS
2462 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2463 'bond99.network','bond-slave.network')
2cf6fdff 2464 start_networkd()
e2aea43f 2465 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 2466
371810d1 2467 output = check_output('ip -d link show dummy98')
c3a8853f 2468 print(output)
cc3e488c 2469 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 2470
371810d1 2471 output = check_output('ip -d link show test1')
c3a8853f
YW
2472 print(output)
2473 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2474
371810d1 2475 output = check_output('ip -d link show bond99')
c3a8853f
YW
2476 print(output)
2477 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2478
19cf3143
DS
2479 self.wait_operstate('dummy98', 'enslaved')
2480 self.wait_operstate('test1', 'enslaved')
2481 self.wait_operstate('bond99', 'routable')
c3a8853f 2482
cefd6b3d 2483 check_output('ip link set dummy98 down')
c3a8853f 2484
19cf3143
DS
2485 self.wait_operstate('dummy98', 'off')
2486 self.wait_operstate('test1', 'enslaved')
2487 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 2488
cefd6b3d 2489 check_output('ip link set dummy98 up')
c3a8853f 2490
19cf3143
DS
2491 self.wait_operstate('dummy98', 'enslaved')
2492 self.wait_operstate('test1', 'enslaved')
2493 self.wait_operstate('bond99', 'routable')
c3a8853f 2494
cefd6b3d
ZJS
2495 check_output('ip link set dummy98 down')
2496 check_output('ip link set test1 down')
cc3e488c 2497
19cf3143
DS
2498 self.wait_operstate('dummy98', 'off')
2499 self.wait_operstate('test1', 'off')
2700d2c7 2500
a4632dc7 2501 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
2502 # Huh? Kernel does not recognize that all slave interfaces are down?
2503 # Let's confirm that networkd's operstate is consistent with ip's result.
2504 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 2505
be68c2c9 2506class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
2507 links = [
2508 'bridge99',
2509 'dummy98',
2510 'test1']
2511
2512 units = [
2513 '11-dummy.netdev',
2514 '12-dummy.netdev',
2515 '26-bridge.netdev',
2516 '26-bridge-slave-interface-1.network',
2517 '26-bridge-slave-interface-2.network',
6f943798
YW
2518 '26-bridge-vlan-master.network',
2519 '26-bridge-vlan-slave.network',
804b6cd2 2520 'bridge99-ignore-carrier-loss.network',
09ea6724 2521 'bridge99.network']
1f0e3109 2522
8d17c386
YW
2523 routing_policy_rule_tables = ['100']
2524
1f0e3109 2525 def setUp(self):
8d17c386 2526 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 2527 remove_links(self.links)
aaae5713 2528 stop_networkd(show_logs=False)
1f0e3109
SS
2529
2530 def tearDown(self):
8d17c386 2531 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
2532 remove_links(self.links)
2533 remove_unit_from_networkd_path(self.units)
aaae5713 2534 stop_networkd(show_logs=True)
1f0e3109 2535
6f943798
YW
2536 def test_bridge_vlan(self):
2537 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2538 '26-bridge.netdev', '26-bridge-vlan-master.network')
2539 start_networkd()
e2aea43f 2540 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
2541
2542 output = check_output('bridge vlan show dev test1')
2543 print(output)
2544 self.assertNotRegex(output, '4063')
2545 for i in range(4064, 4095):
2546 self.assertRegex(output, f'{i}')
2547 self.assertNotRegex(output, '4095')
2548
2549 output = check_output('bridge vlan show dev bridge99')
2550 print(output)
2551 self.assertNotRegex(output, '4059')
2552 for i in range(4060, 4095):
2553 self.assertRegex(output, f'{i}')
2554 self.assertNotRegex(output, '4095')
2555
1f0e3109 2556 def test_bridge_property(self):
ec38833c
ZJS
2557 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2558 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2559 'bridge99.network')
2cf6fdff 2560 start_networkd()
e2aea43f 2561 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 2562
371810d1 2563 output = check_output('ip -d link show test1')
1f0e3109
SS
2564 print(output)
2565 self.assertRegex(output, 'master')
2566 self.assertRegex(output, 'bridge')
2567
371810d1 2568 output = check_output('ip -d link show dummy98')
1f0e3109
SS
2569 print(output)
2570 self.assertRegex(output, 'master')
2571 self.assertRegex(output, 'bridge')
2572
371810d1 2573 output = check_output('ip addr show bridge99')
1f0e3109 2574 print(output)
2be6c5d2 2575 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 2576
371810d1 2577 output = check_output('bridge -d link show dummy98')
1f0e3109 2578 print(output)
ec38833c 2579 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
2580 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2581 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
2582 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2583 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
2584 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2585 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2586 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 2587 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
2588 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2589 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
2590 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2591 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2592 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 2593
5424fd95
YW
2594 output = check_output('bridge -d link show test1')
2595 print(output)
2596 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 2597
371810d1 2598 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2599 time.sleep(1)
2600
371810d1 2601 output = check_output('ip addr show bridge99')
2be6c5d2
YW
2602 print(output)
2603 self.assertRegex(output, '192.168.0.16/24')
2604
e3cbaeab
YW
2605 # for issue #6088
2606 print('### ip -6 route list table all dev bridge99')
2607 output = check_output('ip -6 route list table all dev bridge99')
2608 print(output)
2609 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2610
371810d1 2611 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 2612
19cf3143 2613 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 2614
cefd6b3d 2615 check_output('ip link del dummy98')
804b6cd2 2616
19cf3143 2617 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 2618
371810d1 2619 output = check_output('ip address show bridge99')
804b6cd2
YW
2620 print(output)
2621 self.assertRegex(output, 'NO-CARRIER')
2622 self.assertNotRegex(output, '192.168.0.15/24')
2623 self.assertNotRegex(output, '192.168.0.16/24')
2624
e3cbaeab
YW
2625 print('### ip -6 route list table all dev bridge99')
2626 output = check_output('ip -6 route list table all dev bridge99')
2627 print(output)
426654d7 2628 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
e3cbaeab 2629
804b6cd2 2630 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
2631 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2632 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2633 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2634 start_networkd()
e2aea43f 2635 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 2636
371810d1 2637 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2638 time.sleep(1)
2639
371810d1
ZJS
2640 check_output('ip link del test1')
2641 check_output('ip link del dummy98')
804b6cd2
YW
2642 time.sleep(3)
2643
371810d1 2644 output = check_output('ip address show bridge99')
804b6cd2
YW
2645 print(output)
2646 self.assertRegex(output, 'NO-CARRIER')
2647 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2648 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2649
6609924c 2650 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
2651 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2652 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2653 start_networkd()
e2aea43f 2654 self.wait_online(['bridge99:no-carrier'])
6609924c 2655
90e3bcbd
YW
2656 for trial in range(4):
2657 check_output('ip link add dummy98 type dummy')
2658 check_output('ip link set dummy98 up')
2659 if trial < 3:
2660 check_output('ip link del dummy98')
6609924c 2661
e2aea43f 2662 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 2663
371810d1 2664 output = check_output('ip address show bridge99')
6609924c
YW
2665 print(output)
2666 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2667
371810d1 2668 output = check_output('ip rule list table 100')
6609924c
YW
2669 print(output)
2670 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2671
be68c2c9 2672class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
2673 links = ['veth99']
2674
09ea6724
YW
2675 units = [
2676 '23-emit-lldp.network',
2677 '24-lldp.network',
2678 '25-veth.netdev']
1f0e3109
SS
2679
2680 def setUp(self):
ec38833c 2681 remove_links(self.links)
aaae5713 2682 stop_networkd(show_logs=False)
1f0e3109
SS
2683
2684 def tearDown(self):
ec38833c
ZJS
2685 remove_links(self.links)
2686 remove_unit_from_networkd_path(self.units)
aaae5713 2687 stop_networkd(show_logs=True)
1f0e3109
SS
2688
2689 def test_lldp(self):
ec38833c 2690 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 2691 start_networkd()
e2aea43f 2692 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 2693
371810d1 2694 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
2695 print(output)
2696 self.assertRegex(output, 'veth-peer')
2697 self.assertRegex(output, 'veth99')
2698
be68c2c9 2699class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
2700 links = ['veth99']
2701
09ea6724
YW
2702 units = [
2703 '25-veth.netdev',
2704 'ipv6-prefix.network',
87bbebea 2705 'ipv6-prefix-veth.network',
e2c4070e 2706 'ipv6-prefix-veth-token-static.network',
b241fa00 2707 'ipv6-prefix-veth-token-static-explicit.network',
c24c83dc 2708 'ipv6-prefix-veth-token-static-multiple.network',
87bbebea 2709 'ipv6-prefix-veth-token-prefixstable.network']
1f0e3109
SS
2710
2711 def setUp(self):
ec38833c 2712 remove_links(self.links)
aaae5713 2713 stop_networkd(show_logs=False)
1f0e3109
SS
2714
2715 def tearDown(self):
ec38833c
ZJS
2716 remove_links(self.links)
2717 remove_unit_from_networkd_path(self.units)
aaae5713 2718 stop_networkd(show_logs=True)
1f0e3109
SS
2719
2720 def test_ipv6_prefix_delegation(self):
ec38833c 2721 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 2722 start_networkd()
e2aea43f 2723 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 2724
41fd8fe7
YW
2725 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2726 print(output)
2727 self.assertRegex(output, 'fe80::')
2728 self.assertRegex(output, '2002:da8:1::1')
2729
fc79e6ff 2730 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2731 print(output)
2732 self.assertRegex(output, '2002:da8:1:0')
2733
e2c4070e
YW
2734 def test_ipv6_token_static(self):
2735 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 2736 start_networkd()
b241fa00
KF
2737 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2738
2739 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2740 print(output)
2741 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2742
2743 def test_ipv6_token_static_explicit(self):
2744 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2745 start_networkd()
87bbebea
YW
2746 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2747
2748 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2749 print(output)
2750 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2751
c24c83dc
KF
2752 def test_ipv6_token_static_multiple(self):
2753 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2754 start_networkd()
2755 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2756
2757 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2758 print(output)
2759 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2760 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
2761
87bbebea
YW
2762 def test_ipv6_token_prefixstable(self):
2763 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2764 start_networkd()
2765 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2766
2767 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2768 print(output)
2769 self.assertRegex(output, '2002:da8:1:0')
2770
be68c2c9 2771class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 2772 links = ['veth99']
09ea6724
YW
2773
2774 units = [
09ea6724
YW
2775 '25-veth.netdev',
2776 'dhcp-client.network',
2777 'dhcp-client-timezone-router.network',
2778 'dhcp-server.network',
2779 'dhcp-server-timezone-router.network']
1f0e3109
SS
2780
2781 def setUp(self):
ec38833c 2782 remove_links(self.links)
aaae5713 2783 stop_networkd(show_logs=False)
1f0e3109
SS
2784
2785 def tearDown(self):
ec38833c
ZJS
2786 remove_links(self.links)
2787 remove_unit_from_networkd_path(self.units)
aaae5713 2788 stop_networkd(show_logs=True)
1f0e3109
SS
2789
2790 def test_dhcp_server(self):
ec38833c 2791 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2cf6fdff 2792 start_networkd()
e2aea43f 2793 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2794
fc79e6ff 2795 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2796 print(output)
2797 self.assertRegex(output, '192.168.5.*')
2798 self.assertRegex(output, 'Gateway: 192.168.5.1')
2799 self.assertRegex(output, 'DNS: 192.168.5.1')
2800 self.assertRegex(output, 'NTP: 192.168.5.1')
2801
1f0e3109 2802 def test_emit_router_timezone(self):
ec38833c 2803 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 2804 start_networkd()
e2aea43f 2805 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2806
fc79e6ff 2807 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2808 print(output)
2809 self.assertRegex(output, 'Gateway: 192.168.5.*')
2810 self.assertRegex(output, '192.168.5.*')
2811 self.assertRegex(output, 'Europe/Berlin')
2812
be68c2c9 2813class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2814 links = [
18c613dc
YW
2815 'veth99',
2816 'vrf99']
09ea6724
YW
2817
2818 units = [
2819 '25-veth.netdev',
18c613dc
YW
2820 '25-vrf.netdev',
2821 '25-vrf.network',
09ea6724 2822 'dhcp-client-anonymize.network',
0fd8b718 2823 'dhcp-client-decline.network',
214c5bae
YW
2824 'dhcp-client-gateway-ipv4.network',
2825 'dhcp-client-gateway-ipv6.network',
af3b1498 2826 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2827 'dhcp-client-ipv4-dhcp-settings.network',
2828 'dhcp-client-ipv4-only-ipv6-disabled.network',
2829 'dhcp-client-ipv4-only.network',
4c2e1833 2830 'dhcp-client-ipv4-use-routes-no.network',
09ea6724
YW
2831 'dhcp-client-ipv6-only.network',
2832 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2833 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2834 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 2835 'dhcp-client-listen-port.network',
c1b01a62
YW
2836 'dhcp-client-reassign-static-routes-ipv4.network',
2837 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
2838 'dhcp-client-route-metric.network',
2839 'dhcp-client-route-table.network',
e2d5aab3
YW
2840 'dhcp-client-use-dns-ipv4-and-ra.network',
2841 'dhcp-client-use-dns-ipv4.network',
2842 'dhcp-client-use-dns-no.network',
2843 'dhcp-client-use-dns-yes.network',
e0c1341d 2844 'dhcp-client-use-domains.network',
c38d2d4d 2845 'dhcp-client-use-routes-no.network',
18c613dc 2846 'dhcp-client-vrf.network',
117a55c7
YW
2847 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2848 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
4c882c16 2849 'dhcp-client-with-static-address.network',
3e9d5552 2850 'dhcp-client.network',
0fd8b718 2851 'dhcp-server-decline.network',
09ea6724 2852 'dhcp-server-veth-peer.network',
30d3b54e 2853 'dhcp-v4-server-veth-peer.network',
e0c1341d 2854 'dhcp-client-use-domains.network',
30d3b54e 2855 'static.network']
1f0e3109
SS
2856
2857 def setUp(self):
ec38833c
ZJS
2858 stop_dnsmasq(dnsmasq_pid_file)
2859 remove_links(self.links)
aaae5713 2860 stop_networkd(show_logs=False)
1f0e3109
SS
2861
2862 def tearDown(self):
ec38833c
ZJS
2863 stop_dnsmasq(dnsmasq_pid_file)
2864 remove_lease_file()
2865 remove_log_file()
2866 remove_links(self.links)
2867 remove_unit_from_networkd_path(self.units)
aaae5713 2868 stop_networkd(show_logs=True)
1f0e3109
SS
2869
2870 def test_dhcp_client_ipv6_only(self):
ec38833c 2871 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2872
2cf6fdff 2873 start_networkd()
e2aea43f 2874 self.wait_online(['veth-peer:carrier'])
ec38833c 2875 start_dnsmasq()
e2aea43f 2876 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2877
fc79e6ff 2878 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2879 print(output)
2880 self.assertRegex(output, '2600::')
2881 self.assertNotRegex(output, '192.168.5')
2882
3a956d38 2883 # Confirm that ipv6 token is not set in the kernel
371810d1 2884 output = check_output('ip token show dev veth99')
3a956d38
YW
2885 print(output)
2886 self.assertRegex(output, 'token :: dev veth99')
2887
1f0e3109 2888 def test_dhcp_client_ipv4_only(self):
ec38833c 2889 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2890
2cf6fdff 2891 start_networkd()
e2aea43f 2892 self.wait_online(['veth-peer:carrier'])
195a18c1 2893 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 2894 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2895
fc79e6ff 2896 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2897 print(output)
2898 self.assertNotRegex(output, '2600::')
2899 self.assertRegex(output, '192.168.5')
195a18c1
YW
2900 self.assertRegex(output, '192.168.5.6')
2901 self.assertRegex(output, '192.168.5.7')
2902
2903 # checking routes to DNS servers
2904 output = check_output('ip route show dev veth99')
2905 print(output)
2906 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2907 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2908 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2909
2910 stop_dnsmasq(dnsmasq_pid_file)
2911 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2912
2913 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2914 print('Wait for the dynamic address to be renewed')
2915 time.sleep(125)
2916
2917 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2918
fc79e6ff 2919 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
2920 print(output)
2921 self.assertNotRegex(output, '2600::')
2922 self.assertRegex(output, '192.168.5')
2923 self.assertNotRegex(output, '192.168.5.6')
2924 self.assertRegex(output, '192.168.5.7')
2925 self.assertRegex(output, '192.168.5.8')
2926
2927 # checking routes to DNS servers
2928 output = check_output('ip route show dev veth99')
2929 print(output)
2930 self.assertNotRegex(output, r'192.168.5.6')
2931 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2932 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2933 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 2934
4c2e1833
YW
2935 def test_dhcp_client_ipv4_use_routes_no(self):
2936 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
2937
2938 start_networkd()
2939 self.wait_online(['veth-peer:carrier'])
2940 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
2941 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2942
2943 output = check_output('ip route show dev veth99')
2944 print(output)
2945 self.assertNotRegex(output, r'192.168.5.5')
2946 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
2947 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2948
1f0e3109 2949 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
2950 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2951 'dhcp-client-ipv4-only.network')
2cf6fdff 2952 start_networkd()
e2aea43f 2953 self.wait_online(['veth-peer:carrier'])
ec38833c 2954 start_dnsmasq()
e2aea43f 2955 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2956
2957 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 2958 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 2959 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2960
fc79e6ff 2961 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2962 print(output)
2963 self.assertRegex(output, '2600::')
2964 self.assertRegex(output, '192.168.5')
2965
2966 def test_dhcp_client_settings(self):
ec38833c 2967 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 2968
2cf6fdff 2969 start_networkd()
e2aea43f 2970 self.wait_online(['veth-peer:carrier'])
ec38833c 2971 start_dnsmasq()
e2aea43f 2972 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2973
0ae7a66d 2974 print('## ip address show dev veth99')
371810d1 2975 output = check_output('ip address show dev veth99')
1f0e3109
SS
2976 print(output)
2977 self.assertRegex(output, '12:34:56:78:9a:bc')
2978 self.assertRegex(output, '192.168.5')
2979 self.assertRegex(output, '1492')
2980
0ae7a66d 2981 print('## ip route show table main dev veth99')
371810d1 2982 output = check_output('ip route show table main dev veth99')
1f0e3109 2983 print(output)
156ddf8d 2984 # See issue #8726
dd9b10c8
YW
2985 main_table_is_empty = output == ''
2986 if not main_table_is_empty:
2987 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 2988
0ae7a66d 2989 print('## ip route show table 211 dev veth99')
371810d1 2990 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
2991 print(output)
2992 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
2993 if main_table_is_empty:
2994 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
2995 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2996 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2997
2998 print('## dnsmasq log')
ec38833c
ZJS
2999 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3000 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3001 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3002 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3003
3004 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 3005 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 3006 start_networkd()
e2aea43f 3007 self.wait_online(['veth-peer:carrier'])
ec38833c 3008 start_dnsmasq()
e2aea43f 3009 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3010
371810d1 3011 output = check_output('ip address show dev veth99')
1f0e3109
SS
3012 print(output)
3013 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3014 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3015
3016 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 3017 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 3018 start_networkd()
e2aea43f 3019 self.wait_online(['veth-peer:carrier'])
ec38833c 3020 start_dnsmasq()
e2aea43f 3021 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3022
371810d1 3023 output = check_output('ip address show dev veth99')
1f0e3109
SS
3024 print(output)
3025 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3026 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3027
3028 def test_dhcp_client_settings_anonymize(self):
ec38833c 3029 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 3030 start_networkd()
e2aea43f 3031 self.wait_online(['veth-peer:carrier'])
ec38833c 3032 start_dnsmasq()
e2aea43f 3033 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3034
ec38833c
ZJS
3035 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3036 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3037 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3038
3039 def test_dhcp_client_listen_port(self):
ec38833c 3040 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 3041 start_networkd()
e2aea43f 3042 self.wait_online(['veth-peer:carrier'])
ec38833c 3043 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 3044 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 3045
371810d1 3046 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
3047 print(output)
3048 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 3049
4c882c16
YW
3050 def test_dhcp_client_with_static_address(self):
3051 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3052 'dhcp-client-with-static-address.network')
3053 start_networkd()
e2aea43f 3054 self.wait_online(['veth-peer:carrier'])
4c882c16 3055 start_dnsmasq()
e2aea43f 3056 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
3057
3058 output = check_output('ip address show dev veth99 scope global')
3059 print(output)
3060 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3061 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3062
3063 output = check_output('ip route show dev veth99')
3064 print(output)
3065 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3066 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3067 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3068 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3069
1f0e3109 3070 def test_dhcp_route_table_id(self):
ec38833c 3071 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 3072 start_networkd()
e2aea43f 3073 self.wait_online(['veth-peer:carrier'])
ec38833c 3074 start_dnsmasq()
e2aea43f 3075 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3076
371810d1 3077 output = check_output('ip route show table 12')
1f0e3109 3078 print(output)
1f0e3109
SS
3079 self.assertRegex(output, 'veth99 proto dhcp')
3080 self.assertRegex(output, '192.168.5.1')
3081
3082 def test_dhcp_route_metric(self):
ec38833c 3083 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 3084 start_networkd()
e2aea43f 3085 self.wait_online(['veth-peer:carrier'])
ec38833c 3086 start_dnsmasq()
e2aea43f 3087 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3088
371810d1 3089 output = check_output('ip route show dev veth99')
1f0e3109 3090 print(output)
1f0e3109
SS
3091 self.assertRegex(output, 'metric 24')
3092
c1b01a62 3093 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 3094 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 3095 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 3096 start_networkd()
e2aea43f 3097 self.wait_online(['veth-peer:carrier'])
c38d2d4d 3098 start_dnsmasq(lease_time='2m')
e2aea43f 3099 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
3100
3101 output = check_output('ip address show dev veth99 scope global')
3102 print(output)
3103 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3104
3105 output = check_output('ip route show dev veth99')
3106 print(output)
3107 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3108 self.assertRegex(output, r'192.168.5.0/24 proto static')
3109 self.assertRegex(output, r'192.168.6.0/24 proto static')
3110 self.assertRegex(output, r'192.168.7.0/24 proto static')
3111
c1b01a62
YW
3112 stop_dnsmasq(dnsmasq_pid_file)
3113 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3114
c38d2d4d
YW
3115 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3116 print('Wait for the dynamic address to be renewed')
3117 time.sleep(125)
3118
e2aea43f 3119 self.wait_online(['veth99:routable'])
c38d2d4d
YW
3120
3121 output = check_output('ip route show dev veth99')
3122 print(output)
3123 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3124 self.assertRegex(output, r'192.168.5.0/24 proto static')
3125 self.assertRegex(output, r'192.168.6.0/24 proto static')
3126 self.assertRegex(output, r'192.168.7.0/24 proto static')
3127
c1b01a62
YW
3128 def test_dhcp_client_reassign_static_routes_ipv6(self):
3129 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3130 'dhcp-client-reassign-static-routes-ipv6.network')
3131 start_networkd()
e2aea43f 3132 self.wait_online(['veth-peer:carrier'])
c1b01a62 3133 start_dnsmasq(lease_time='2m')
e2aea43f 3134 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
3135
3136 output = check_output('ip address show dev veth99 scope global')
3137 print(output)
426654d7 3138 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
3139
3140 output = check_output('ip -6 route show dev veth99')
3141 print(output)
3142 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3143 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3144
3145 stop_dnsmasq(dnsmasq_pid_file)
3146 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3147
3148 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3149 print('Wait for the dynamic address to be renewed')
3150 time.sleep(125)
3151
e2aea43f 3152 self.wait_online(['veth99:routable'])
c1b01a62
YW
3153
3154 output = check_output('ip -6 route show dev veth99')
3155 print(output)
3156 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3157 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3158
1e498853
YW
3159 def test_dhcp_keep_configuration_dhcp(self):
3160 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 3161 start_networkd()
e2aea43f 3162 self.wait_online(['veth-peer:carrier'])
1e498853 3163 start_dnsmasq(lease_time='2m')
e2aea43f 3164 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3165
1e498853
YW
3166 output = check_output('ip address show dev veth99 scope global')
3167 print(output)
3168 self.assertRegex(output, r'192.168.5.*')
3169
fc79e6ff 3170 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3171 print(output)
1e498853 3172 self.assertRegex(output, r'192.168.5.*')
e40a58b5 3173
5238e957 3174 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 3175 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
3176
3177 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 3178 print('Wait for the dynamic address to be expired')
1f0e3109
SS
3179 time.sleep(125)
3180
1e498853
YW
3181 print('The lease address should be kept after lease expired')
3182 output = check_output('ip address show dev veth99 scope global')
3183 print(output)
3184 self.assertRegex(output, r'192.168.5.*')
3185
fc79e6ff 3186 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3187 print(output)
1e498853
YW
3188 self.assertRegex(output, r'192.168.5.*')
3189
3190 check_output('systemctl stop systemd-networkd')
3191
3192 print('The lease address should be kept after networkd stopped')
3193 output = check_output('ip address show dev veth99 scope global')
3194 print(output)
3195 self.assertRegex(output, r'192.168.5.*')
3196
fc79e6ff 3197 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3198 print(output)
3199 self.assertRegex(output, r'192.168.5.*')
3200
e2aea43f
YW
3201 start_networkd(3)
3202 self.wait_online(['veth-peer:routable'])
1e498853
YW
3203
3204 print('Still the lease address should be kept after networkd restarted')
3205 output = check_output('ip address show dev veth99 scope global')
3206 print(output)
3207 self.assertRegex(output, r'192.168.5.*')
3208
fc79e6ff 3209 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3210 print(output)
3211 self.assertRegex(output, r'192.168.5.*')
3212
3213 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3214 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 3215 start_networkd()
e2aea43f 3216 self.wait_online(['veth-peer:carrier'])
1e498853 3217 start_dnsmasq(lease_time='2m')
e2aea43f 3218 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
3219
3220 output = check_output('ip address show dev veth99 scope global')
3221 print(output)
3222 self.assertRegex(output, r'192.168.5.*')
3223
3224 stop_dnsmasq(dnsmasq_pid_file)
3225 check_output('systemctl stop systemd-networkd')
3226
3227 output = check_output('ip address show dev veth99 scope global')
3228 print(output)
3229 self.assertRegex(output, r'192.168.5.*')
3230
e2aea43f
YW
3231 restart_networkd(3)
3232 self.wait_online(['veth-peer:routable'])
1e498853
YW
3233
3234 output = check_output('ip address show dev veth99 scope global')
3235 print(output)
3236 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 3237
30d3b54e 3238 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 3239 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 3240 start_networkd()
e2aea43f 3241 self.wait_online(['veth-peer:carrier'])
ec38833c 3242 start_dnsmasq()
e2aea43f 3243 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3244
3245 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3246 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3247 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 3248
371810d1 3249 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
3250 print(output)
3251 self.assertRegex(output, '192.168.5')
3252 self.assertRegex(output, '2600::')
3253
2629df47
YW
3254 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3255 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
3256 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3257 print(static_network)
3258
ec38833c 3259 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
3260
3261 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3262 f.write(static_network)
3263
2629df47
YW
3264 # When networkd started, the links are already configured, so let's wait for 5 seconds
3265 # the links to be re-configured.
aaae5713 3266 restart_networkd(5)
e2aea43f 3267 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 3268
371810d1 3269 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
3270 print(output)
3271 self.assertRegex(output, '192.168.5')
3272 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3273
371810d1 3274 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
3275 print(output)
3276 self.assertRegex(output, '2600::')
3277 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3278
18c613dc
YW
3279 @expectedFailureIfModuleIsNotAvailable('vrf')
3280 def test_dhcp_client_vrf(self):
ec38833c
ZJS
3281 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3282 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 3283 start_networkd()
e2aea43f 3284 self.wait_online(['veth-peer:carrier'])
ec38833c 3285 start_dnsmasq()
e2aea43f 3286 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
3287
3288 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3289 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3290 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
3291
3292 print('## ip -d link show dev vrf99')
371810d1 3293 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
3294 print(output)
3295 self.assertRegex(output, 'vrf table 42')
3296
3297 print('## ip address show vrf vrf99')
371810d1 3298 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
3299 print(output)
3300 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3301 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3302 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 3303 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
3304
3305 print('## ip address show dev veth99')
371810d1 3306 output = check_output('ip address show dev veth99')
18c613dc 3307 print(output)
18c613dc
YW
3308 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3309 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3310 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
3311 self.assertRegex(output, 'inet6 .* scope link')
3312
3313 print('## ip route show vrf vrf99')
371810d1 3314 output = check_output('ip route show vrf vrf99')
18c613dc
YW
3315 print(output)
3316 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc
YW
3317 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3318 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3319 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3320 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3321
3322 print('## ip route show table main dev veth99')
371810d1 3323 output = check_output('ip route show table main dev veth99')
18c613dc
YW
3324 print(output)
3325 self.assertEqual(output, '')
3326
214c5bae
YW
3327 def test_dhcp_client_gateway_ipv4(self):
3328 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3329 'dhcp-client-gateway-ipv4.network')
3330 start_networkd()
3331 self.wait_online(['veth-peer:carrier'])
3332 start_dnsmasq()
3333 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3334
3335 output = check_output('ip route list dev veth99 10.0.0.0/8')
3336 print(output)
3337 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3338
3339 def test_dhcp_client_gateway_ipv6(self):
3340 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3341 'dhcp-client-gateway-ipv6.network')
3342 start_networkd()
3343 self.wait_online(['veth-peer:carrier'])
3344 start_dnsmasq()
3345 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3346
3347 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3348 print(output)
3349 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3350
af3b1498 3351 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
3352 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3353 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 3354 start_networkd()
e2aea43f 3355 self.wait_online(['veth-peer:carrier'])
ec38833c 3356 start_dnsmasq()
e2aea43f 3357 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 3358
fc79e6ff 3359 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
3360 print(output)
3361 self.assertRegex(output, '192.168.5')
3362
371810d1 3363 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
3364 print(output)
3365 self.assertRegex(output, 'onlink')
371810d1 3366 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
3367 print(output)
3368 self.assertRegex(output, 'onlink')
3369
117a55c7 3370 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
3371 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3372 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2cf6fdff 3373 start_networkd()
e2aea43f 3374 self.wait_online(['veth-peer:carrier'])
ec38833c 3375 start_dnsmasq(lease_time='2m')
e2aea43f 3376 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 3377
371810d1 3378 output = check_output('ip address show dev veth99')
63c598ed
YW
3379 print(output)
3380
371810d1 3381 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 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')
63c598ed 3384 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3385 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3386 self.assertRegex(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')
63c598ed
YW
3388 self.assertNotRegex(output, 'inet .* scope link')
3389
3390 print('Wait for the dynamic address to be expired')
3391 time.sleep(130)
3392
371810d1 3393 output = check_output('ip address show dev veth99')
63c598ed
YW
3394 print(output)
3395
371810d1 3396 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3397 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3398 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3399 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3400 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3401 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3402 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3403 self.assertNotRegex(output, 'inet .* scope link')
3404
ec38833c 3405 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 3406
117a55c7 3407 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
3408 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3409 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2cf6fdff 3410 start_networkd()
e2aea43f 3411 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 3412
371810d1 3413 output = check_output('ip address show dev veth99')
117a55c7
YW
3414 print(output)
3415
371810d1 3416 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 3417 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3418 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 3419 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3420 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 3421 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3422 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
3423 self.assertRegex(output, 'inet .* scope link')
3424
b6efd661 3425 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
3426 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3427 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 3428 start_networkd()
e2aea43f 3429 self.wait_online(['veth-peer:carrier'])
ec38833c 3430 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 3431 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
3432
3433 # test for issue #12490
3434
371810d1 3435 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3436 print(output)
3437 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3438 address1=None
3439 for line in output.splitlines():
3440 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3441 address1 = line.split()[1].split('/')[0]
3442 break
3443
371810d1 3444 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3445 print(output)
3446 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3447 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3448
ec38833c
ZJS
3449 stop_dnsmasq(dnsmasq_pid_file)
3450 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
3451
3452 print('Wait for the dynamic address to be expired')
3453 time.sleep(130)
3454
371810d1 3455 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3456 print(output)
3457 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3458 address2=None
3459 for line in output.splitlines():
3460 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3461 address2 = line.split()[1].split('/')[0]
3462 break
3463
3464 self.assertNotEqual(address1, address2)
3465
371810d1 3466 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3467 print(output)
3468 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3469 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3470 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3471 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3472
e2d5aab3
YW
3473 def test_dhcp_client_use_dns_yes(self):
3474 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3475
3476 start_networkd()
e2aea43f 3477 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3478 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3479 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3480
3481 # link become 'routable' when at least one protocol provide an valid address.
3482 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3483 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3484
693283cd 3485 time.sleep(3)
e2d5aab3
YW
3486 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3487 print(output)
3488 self.assertRegex(output, '192.168.5.1')
3489 self.assertRegex(output, '2600::1')
3490
3491 def test_dhcp_client_use_dns_no(self):
3492 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3493
3494 start_networkd()
e2aea43f 3495 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3496 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3497 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3498
3499 # link become 'routable' when at least one protocol provide an valid address.
3500 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3501 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3502
693283cd 3503 time.sleep(3)
e2d5aab3
YW
3504 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3505 print(output)
3506 self.assertNotRegex(output, '192.168.5.1')
3507 self.assertNotRegex(output, '2600::1')
3508
3509 def test_dhcp_client_use_dns_ipv4(self):
3510 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3511
3512 start_networkd()
e2aea43f 3513 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3514 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3515 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3516
3517 # link become 'routable' when at least one protocol provide an valid address.
3518 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3519 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3520
693283cd 3521 time.sleep(3)
e2d5aab3
YW
3522 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3523 print(output)
3524 self.assertRegex(output, '192.168.5.1')
3525 self.assertNotRegex(output, '2600::1')
3526
3527 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3528 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3529
3530 start_networkd()
e2aea43f 3531 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3532 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3533 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3534
3535 # link become 'routable' when at least one protocol provide an valid address.
3536 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3537 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3538
693283cd 3539 time.sleep(3)
e2d5aab3
YW
3540 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3541 print(output)
3542 self.assertRegex(output, '192.168.5.1')
3543 self.assertRegex(output, '2600::1')
3544
e0c1341d
YW
3545 def test_dhcp_client_use_domains(self):
3546 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3547
3548 start_networkd()
e2aea43f 3549 self.wait_online(['veth-peer:carrier'])
e0c1341d 3550 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 3551 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 3552
fc79e6ff 3553 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
3554 print(output)
3555 self.assertRegex(output, 'Search Domains: example.com')
3556
3557 time.sleep(3)
3558 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3559 print(output)
3560 self.assertRegex(output, 'example.com')
3561
0fd8b718
YW
3562 def test_dhcp_client_decline(self):
3563 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3564
3565 start_networkd()
3566 self.wait_online(['veth-peer:carrier'])
3567 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3568 self.assertTrue(rc == 1)
3569
9633f977
SS
3570class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3571 links = ['veth99']
3572
3573 units = [
3574 '25-veth.netdev',
3575 'ipv6ra-prefix-client.network',
3576 'ipv6ra-prefix.network'
3577 ]
3578
3579 def setUp(self):
3580 remove_links(self.links)
3581 stop_networkd(show_logs=False)
3582
3583 def tearDown(self):
3584 remove_log_file()
3585 remove_links(self.links)
3586 remove_unit_from_networkd_path(self.units)
3587 stop_networkd(show_logs=True)
3588
3589 def test_ipv6_route_prefix(self):
3590 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3591
3592 start_networkd()
9633f977
SS
3593 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3594
3595 output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3596 print(output)
3597 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3598
7db05447
DS
3599class NetworkdMTUTests(unittest.TestCase, Utilities):
3600 links = ['dummy98']
3601
3602 units = [
3603 '12-dummy.netdev',
3604 '12-dummy-mtu.netdev',
3605 '12-dummy-mtu.link',
3606 '12-dummy.network',
3607 ]
3608
3609 def setUp(self):
3610 remove_links(self.links)
3611 stop_networkd(show_logs=False)
3612
3613 def tearDown(self):
3614 remove_log_file()
3615 remove_links(self.links)
3616 remove_unit_from_networkd_path(self.units)
3617 stop_networkd(show_logs=True)
3618
3619 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3620 if not ipv6_mtu:
3621 ipv6_mtu = mtu
3622
3623 # test normal start
3624 start_networkd()
3625 self.wait_online(['dummy98:routable'])
3626 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3627 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3628
3629 # test normal restart
3630 restart_networkd()
3631 self.wait_online(['dummy98:routable'])
3632 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3633 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3634
3635 if reset:
3636 self.reset_check_mtu(mtu, ipv6_mtu)
3637
3638 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3639 ''' test setting mtu/ipv6_mtu with interface already up '''
3640 stop_networkd()
3641
3642 # note - changing the device mtu resets the ipv6 mtu
3643 run('ip link set up mtu 1501 dev dummy98')
3644 run('ip link set up mtu 1500 dev dummy98')
3645 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3646 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3647
3648 self.check_mtu(mtu, ipv6_mtu, reset=False)
3649
3650 def test_mtu_network(self):
3651 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3652 self.check_mtu('1600')
3653
3654 def test_mtu_netdev(self):
3655 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3656 # note - MTU set by .netdev happens ONLY at device creation!
3657 self.check_mtu('1600', reset=False)
3658
3659 def test_mtu_link(self):
3660 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3661 # must reload udev because it only picks up new files after 3 second delay
3662 call('udevadm control --reload')
3663 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3664 self.check_mtu('1600', reset=False)
3665
3666 def test_ipv6_mtu(self):
3667 ''' set ipv6 mtu without setting device mtu '''
3668 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3669 self.check_mtu('1500', '1400')
3670
3671 def test_ipv6_mtu_toolarge(self):
3672 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3673 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3674 self.check_mtu('1500', '1500')
3675
3676 def test_mtu_network_ipv6_mtu(self):
3677 ''' set ipv6 mtu and set device mtu via network file '''
3678 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3679 self.check_mtu('1600', '1550')
3680
3681 def test_mtu_netdev_ipv6_mtu(self):
3682 ''' set ipv6 mtu and set device mtu via netdev file '''
3683 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3684 self.check_mtu('1600', '1550', reset=False)
3685
3686 def test_mtu_link_ipv6_mtu(self):
3687 ''' set ipv6 mtu and set device mtu via link file '''
3688 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3689 # must reload udev because it only picks up new files after 3 second delay
3690 call('udevadm control --reload')
3691 self.check_mtu('1600', '1550', reset=False)
3692
3693
1f0e3109 3694if __name__ == '__main__':
9c1ae484
YW
3695 parser = argparse.ArgumentParser()
3696 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3697 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 3698 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 3699 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
3700 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3701 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
3702 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3703 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
3704 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3705 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 3706 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 3707 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 3708 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
3709 ns, args = parser.parse_known_args(namespace=unittest)
3710
3711 if ns.build_dir:
641aa412 3712 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 3713 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 3714 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 3715 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 3716 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
3717 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3718 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
3719 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3720 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
3721 else:
3722 if ns.networkd_bin:
3723 networkd_bin = ns.networkd_bin
b6d587d1
YW
3724 if ns.resolved_bin:
3725 resolved_bin = ns.resolved_bin
641aa412
YW
3726 if ns.udevd_bin:
3727 udevd_bin = ns.udevd_bin
9c1ae484
YW
3728 if ns.wait_online_bin:
3729 wait_online_bin = ns.wait_online_bin
3730 if ns.networkctl_bin:
3731 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
3732 if ns.resolvectl_bin:
3733 resolvectl_bin = ns.resolvectl_bin
3734 if ns.timedatectl_bin:
3735 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
3736
3737 use_valgrind = ns.use_valgrind
3738 enable_debug = ns.enable_debug
94c03122 3739 asan_options = ns.asan_options
fa4c6095 3740 lsan_options = ns.lsan_options
94c03122 3741 ubsan_options = ns.ubsan_options
9c1ae484
YW
3742
3743 if use_valgrind:
3744 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
3745 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3746 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
3747 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3748 else:
3749 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
3750 resolvectl_cmd = [resolvectl_bin]
3751 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
3752 wait_online_cmd = [wait_online_bin]
3753
3754 if enable_debug:
3755 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
3756 if asan_options:
3757 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
3758 if lsan_options:
3759 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
3760 if ubsan_options:
3761 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
3762
3763 sys.argv[1:] = args
1f0e3109
SS
3764 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3765 verbosity=3))