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