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