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