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