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