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