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