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