]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #14990 from keszybz/nss-homed-fix
[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 'vrf99',
1593 ]
1594
1595 units = [
1596 '11-dummy.netdev',
1597 '12-dummy.netdev',
1598 '23-active-slave.network',
1599 '24-keep-configuration-static.network',
1600 '24-search-domain.network',
1601 '25-address-dad-veth-peer.network',
1602 '25-address-dad-veth99.network',
1603 '25-address-link-section.network',
1604 '25-address-preferred-lifetime-zero.network',
1605 '25-address-static.network',
1606 '25-bind-carrier.network',
1607 '25-bond-active-backup-slave.netdev',
1608 '25-fibrule-invert.network',
1609 '25-fibrule-port-range.network',
1610 '25-fibrule-uidrange.network',
1611 '25-gre-tunnel-remote-any.netdev',
1612 '25-ip6gre-tunnel-remote-any.netdev',
1613 '25-ipv6-address-label-section.network',
1614 '25-link-local-addressing-no.network',
1615 '25-link-local-addressing-yes.network',
1616 '25-link-section-unmanaged.network',
1617 '25-neighbor-section.network',
1618 '25-neighbor-next.network',
1619 '25-neighbor-ipv6.network',
1620 '25-neighbor-ip-dummy.network',
1621 '25-neighbor-ip.network',
1622 '25-nexthop.network',
1623 '25-qdisc-clsact-root-compat.network',
1624 '25-qdisc-fq-codel.network',
1625 '25-qdisc-ingress-netem-compat.network',
1626 '25-qdisc-ingress-root.network',
1627 '25-qdisc-netem-and-fqcodel.network',
1628 '25-qdisc-tbf-and-sfq.network',
1629 '25-qdisc-teql.network',
1630 '25-route-ipv6-src.network',
1631 '25-route-static.network',
1632 '25-route-vrf.network',
1633 '25-gateway-static.network',
1634 '25-gateway-next-static.network',
1635 '25-sysctl-disable-ipv6.network',
1636 '25-sysctl.network',
1637 '25-veth-peer.network',
1638 '25-veth.netdev',
1639 '25-vrf.netdev',
1640 '26-link-local-addressing-ipv6.network',
1641 'configure-without-carrier.network',
1642 'routing-policy-rule-dummy98.network',
1643 'routing-policy-rule-test1.network']
1644
1645 routing_policy_rule_tables = ['7', '8', '9']
1646 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1647
1648 def setUp(self):
1649 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1650 remove_routes(self.routes)
1651 remove_links(self.links)
1652 stop_networkd(show_logs=False)
1653
1654 def tearDown(self):
1655 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1656 remove_routes(self.routes)
1657 remove_links(self.links)
1658 remove_unit_from_networkd_path(self.units)
1659 stop_networkd(show_logs=True)
1660
1661 def test_address_static(self):
1662 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1663 start_networkd()
1664
1665 self.wait_online(['dummy98:routable'])
1666
1667 output = check_output('ip -4 address show dev dummy98')
1668 print(output)
1669 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1670 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1671 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1672
1673 # invalid sections
1674 self.assertNotRegex(output, '10.10.0.1/16')
1675 self.assertNotRegex(output, '10.10.0.2/16')
1676
1677 output = check_output('ip -4 address show dev dummy98 label 32')
1678 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1679
1680 output = check_output('ip -4 address show dev dummy98 label 33')
1681 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1682
1683 output = check_output('ip -4 address show dev dummy98 label 34')
1684 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1685
1686 output = check_output('ip -4 address show dev dummy98 label 35')
1687 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1688
1689 output = check_output('ip -6 address show dev dummy98')
1690 print(output)
1691 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1692 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1693 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1694 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1695 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1696 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1697
1698 def test_address_preferred_lifetime_zero_ipv6(self):
1699 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1700 start_networkd(5)
1701
1702 self.wait_online(['dummy98:routable'])
1703
1704 output = check_output('ip address show dummy98')
1705 print(output)
1706 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1707 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1708
1709 output = check_output('ip route show dev dummy98')
1710 print(output)
1711 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1712
1713 def test_address_dad(self):
1714 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1715 '25-veth.netdev')
1716 start_networkd()
1717 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1718
1719 output = check_output('ip -4 address show dev veth99')
1720 print(output)
1721 self.assertRegex(output, '192.168.100.10/24')
1722
1723 output = check_output('ip -4 address show dev veth-peer')
1724 print(output)
1725 self.assertNotRegex(output, '192.168.100.10/24')
1726
1727 def test_configure_without_carrier(self):
1728 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1729 start_networkd()
1730 self.wait_online(['test1:routable'])
1731
1732 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1733 print(output)
1734 self.assertRegex(output, '192.168.0.15')
1735 self.assertRegex(output, '192.168.0.1')
1736 self.assertRegex(output, 'routable')
1737
1738 def test_routing_policy_rule(self):
1739 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1740 start_networkd()
1741 self.wait_online(['test1:degraded'])
1742
1743 output = check_output('ip rule list iif test1 priority 111')
1744 print(output)
1745 self.assertRegex(output, '111:')
1746 self.assertRegex(output, 'from 192.168.100.18')
1747 self.assertRegex(output, r'tos (0x08|throughput)\s')
1748 self.assertRegex(output, 'iif test1')
1749 self.assertRegex(output, 'oif test1')
1750 self.assertRegex(output, 'lookup 7')
1751
1752 output = check_output('ip rule list iif test1 priority 101')
1753 print(output)
1754 self.assertRegex(output, '101:')
1755 self.assertRegex(output, 'from all')
1756 self.assertRegex(output, 'iif test1')
1757 self.assertRegex(output, 'lookup 9')
1758
1759 output = check_output('ip -6 rule list iif test1 priority 100')
1760 print(output)
1761 self.assertRegex(output, '100:')
1762 self.assertRegex(output, 'from all')
1763 self.assertRegex(output, 'iif test1')
1764 self.assertRegex(output, 'lookup 8')
1765
1766 output = check_output('ip -6 rule list iif test1 priority 101')
1767 print(output)
1768 self.assertRegex(output, '101:')
1769 self.assertRegex(output, 'from all')
1770 self.assertRegex(output, 'iif test1')
1771 self.assertRegex(output, 'lookup 9')
1772
1773 def test_routing_policy_rule_issue_11280(self):
1774 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1775 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1776
1777 for trial in range(3):
1778 # Remove state files only first time
1779 start_networkd(3)
1780 self.wait_online(['test1:degraded', 'dummy98:degraded'])
1781 time.sleep(1)
1782
1783 output = check_output('ip rule list table 7')
1784 print(output)
1785 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1786
1787 output = check_output('ip rule list table 8')
1788 print(output)
1789 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1790
1791 stop_networkd(remove_state_files=False)
1792
1793 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1794 def test_routing_policy_rule_port_range(self):
1795 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1796 start_networkd()
1797 self.wait_online(['test1:degraded'])
1798
1799 output = check_output('ip rule')
1800 print(output)
1801 self.assertRegex(output, '111')
1802 self.assertRegex(output, 'from 192.168.100.18')
1803 self.assertRegex(output, '1123-1150')
1804 self.assertRegex(output, '3224-3290')
1805 self.assertRegex(output, 'tcp')
1806 self.assertRegex(output, 'lookup 7')
1807
1808 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1809 def test_routing_policy_rule_invert(self):
1810 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1811 start_networkd()
1812 self.wait_online(['test1:degraded'])
1813
1814 output = check_output('ip rule')
1815 print(output)
1816 self.assertRegex(output, '111')
1817 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1818 self.assertRegex(output, 'tcp')
1819 self.assertRegex(output, 'lookup 7')
1820
1821 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
1822 def test_routing_policy_rule_uidrange(self):
1823 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
1824 start_networkd()
1825 self.wait_online(['test1:degraded'])
1826
1827 output = check_output('ip rule')
1828 print(output)
1829 self.assertRegex(output, '111')
1830 self.assertRegex(output, 'from 192.168.100.18')
1831 self.assertRegex(output, 'lookup 7')
1832 self.assertRegex(output, 'uidrange 100-200')
1833
1834 def test_route_static(self):
1835 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1836 start_networkd()
1837 self.wait_online(['dummy98:routable'])
1838
1839 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
1840 print(output)
1841
1842 print('### ip -6 route show dev dummy98')
1843 output = check_output('ip -6 route show dev dummy98')
1844 print(output)
1845 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1846 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1847
1848 print('### ip -6 route show dev dummy98 default')
1849 output = check_output('ip -6 route show dev dummy98 default')
1850 print(output)
1851 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1852
1853 print('### ip -4 route show dev dummy98')
1854 output = check_output('ip -4 route show dev dummy98')
1855 print(output)
1856 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1857 self.assertRegex(output, '149.10.124.64 proto static scope link')
1858 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1859 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1860 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1861 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1862
1863 print('### ip -4 route show dev dummy98 default')
1864 output = check_output('ip -4 route show dev dummy98 default')
1865 print(output)
1866 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1867 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1868 self.assertRegex(output, 'default proto static')
1869
1870 print('### ip -4 route show table local dev dummy98')
1871 output = check_output('ip -4 route show table local dev dummy98')
1872 print(output)
1873 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1874 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1875 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1876
1877 print('### ip route show type blackhole')
1878 output = check_output('ip route show type blackhole')
1879 print(output)
1880 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1881
1882 print('### ip route show type unreachable')
1883 output = check_output('ip route show type unreachable')
1884 print(output)
1885 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1886
1887 print('### ip route show type prohibit')
1888 output = check_output('ip route show type prohibit')
1889 print(output)
1890 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1891
1892 print('### ip route show 192.168.10.1')
1893 output = check_output('ip route show 192.168.10.1')
1894 print(output)
1895 self.assertRegex(output, '192.168.10.1 proto static')
1896 self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1897 self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1898
1899 print('### ip route show 192.168.10.2')
1900 output = check_output('ip route show 192.168.10.2')
1901 print(output)
1902 # old ip command does not show IPv6 gateways...
1903 self.assertRegex(output, '192.168.10.2 proto static')
1904 self.assertRegex(output, 'nexthop')
1905 self.assertRegex(output, 'dev dummy98 weight 10')
1906 self.assertRegex(output, 'dev dummy98 weight 5')
1907
1908 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1909 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1910 print(output)
1911 # old ip command does not show 'nexthop' keyword and weight...
1912 self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
1913 self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
1914 self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
1915
1916 @expectedFailureIfModuleIsNotAvailable('vrf')
1917 def test_route_vrf(self):
1918 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
1919 '25-vrf.netdev', '25-vrf.network')
1920 start_networkd()
1921 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
1922
1923 output = check_output('ip route show vrf vrf99')
1924 print(output)
1925 self.assertRegex(output, 'default via 192.168.100.1')
1926
1927 output = check_output('ip route show')
1928 print(output)
1929 self.assertNotRegex(output, 'default via 192.168.100.1')
1930
1931 def test_gateway_reconfigure(self):
1932 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1933 start_networkd()
1934 self.wait_online(['dummy98:routable'])
1935 print('### ip -4 route show dev dummy98 default')
1936 output = check_output('ip -4 route show dev dummy98 default')
1937 print(output)
1938 self.assertRegex(output, 'default via 149.10.124.59 proto static')
1939 self.assertNotRegex(output, '149.10.124.60')
1940
1941 remove_unit_from_networkd_path(['25-gateway-static.network'])
1942 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1943 restart_networkd(3)
1944 self.wait_online(['dummy98:routable'])
1945 print('### ip -4 route show dev dummy98 default')
1946 output = check_output('ip -4 route show dev dummy98 default')
1947 print(output)
1948 self.assertNotRegex(output, '149.10.124.59')
1949 self.assertRegex(output, 'default via 149.10.124.60 proto static')
1950
1951 def test_ip_route_ipv6_src_route(self):
1952 # a dummy device does not make the addresses go through tentative state, so we
1953 # reuse a bond from an earlier test, which does make the addresses go through
1954 # tentative state, and do our test on that
1955 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1956 start_networkd()
1957 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
1958
1959 output = check_output('ip -6 route list dev bond199')
1960 print(output)
1961 self.assertRegex(output, 'abcd::/16')
1962 self.assertRegex(output, 'src')
1963 self.assertRegex(output, '2001:1234:56:8f63::2')
1964
1965 def test_ip_link_mac_address(self):
1966 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1967 start_networkd()
1968 self.wait_online(['dummy98:degraded'])
1969
1970 output = check_output('ip link show dummy98')
1971 print(output)
1972 self.assertRegex(output, '00:01:02:aa:bb:cc')
1973
1974 def test_ip_link_unmanaged(self):
1975 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1976 start_networkd(5)
1977
1978 self.check_link_exists('dummy98')
1979
1980 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1981
1982 def test_ipv6_address_label(self):
1983 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1984 start_networkd()
1985 self.wait_online(['dummy98:degraded'])
1986
1987 output = check_output('ip addrlabel list')
1988 print(output)
1989 self.assertRegex(output, '2004:da8:1::/64')
1990
1991 def test_neighbor_section(self):
1992 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1993 start_networkd()
1994 self.wait_online(['dummy98:degraded'], timeout='40s')
1995
1996 print('### ip neigh list dev dummy98')
1997 output = check_output('ip neigh list dev dummy98')
1998 print(output)
1999 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2000 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2001
2002 def test_neighbor_reconfigure(self):
2003 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2004 start_networkd()
2005 self.wait_online(['dummy98:degraded'], timeout='40s')
2006
2007 print('### ip neigh list dev dummy98')
2008 output = check_output('ip neigh list dev dummy98')
2009 print(output)
2010 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2011 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2012
2013 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2014 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2015 restart_networkd(3)
2016 self.wait_online(['dummy98:degraded'], timeout='40s')
2017 print('### ip neigh list dev dummy98')
2018 output = check_output('ip neigh list dev dummy98')
2019 print(output)
2020 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2021 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2022 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2023
2024 def test_neighbor_gre(self):
2025 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2026 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
2027 start_networkd()
2028 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
2029
2030 output = check_output('ip neigh list dev gretun97')
2031 print(output)
2032 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
2033
2034 output = check_output('ip neigh list dev ip6gretun97')
2035 print(output)
2036 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
2037
2038 def test_link_local_addressing(self):
2039 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2040 '25-link-local-addressing-no.network', '12-dummy.netdev')
2041 start_networkd()
2042 self.wait_online(['test1:degraded', 'dummy98:carrier'])
2043
2044 output = check_output('ip address show dev test1')
2045 print(output)
2046 self.assertRegex(output, 'inet .* scope link')
2047 self.assertRegex(output, 'inet6 .* scope link')
2048
2049 output = check_output('ip address show dev dummy98')
2050 print(output)
2051 self.assertNotRegex(output, 'inet6* .* scope link')
2052
2053 '''
2054 Documentation/networking/ip-sysctl.txt
2055
2056 addr_gen_mode - INTEGER
2057 Defines how link-local and autoconf addresses are generated.
2058
2059 0: generate address based on EUI64 (default)
2060 1: do no generate a link-local address, use EUI64 for addresses generated
2061 from autoconf
2062 2: generate stable privacy addresses, using the secret from
2063 stable_secret (RFC7217)
2064 3: generate stable privacy addresses, using a random secret if unset
2065 '''
2066
2067 test1_addr_gen_mode = ''
2068 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2069 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2070 try:
2071 f.readline()
2072 except IOError:
2073 # if stable_secret is unset, then EIO is returned
2074 test1_addr_gen_mode = '0'
2075 else:
2076 test1_addr_gen_mode = '2'
2077 else:
2078 test1_addr_gen_mode = '0'
2079
2080 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
2081 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
2082
2083 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
2084 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
2085
2086 def test_link_local_addressing_remove_ipv6ll(self):
2087 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2088 start_networkd()
2089 self.wait_online(['dummy98:degraded'])
2090
2091 output = check_output('ip address show dev dummy98')
2092 print(output)
2093 self.assertRegex(output, 'inet6 .* scope link')
2094
2095 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2096 restart_networkd(1)
2097 self.wait_online(['dummy98:carrier'])
2098
2099 output = check_output('ip address show dev dummy98')
2100 print(output)
2101 self.assertNotRegex(output, 'inet6* .* scope link')
2102
2103 def test_sysctl(self):
2104 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2105 start_networkd()
2106 self.wait_online(['dummy98:degraded'])
2107
2108 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2109 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2110 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2111 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2112 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2113 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2114 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
2115
2116 def test_sysctl_disable_ipv6(self):
2117 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
2118
2119 print('## Disable ipv6')
2120 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2121 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
2122
2123 start_networkd()
2124 self.wait_online(['dummy98:routable'])
2125
2126 output = check_output('ip -4 address show dummy98')
2127 print(output)
2128 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2129 output = check_output('ip -6 address show dummy98')
2130 print(output)
2131 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2132 self.assertRegex(output, 'inet6 .* scope link')
2133 output = check_output('ip -4 route show dev dummy98')
2134 print(output)
2135 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2136 output = check_output('ip -6 route show dev dummy98')
2137 print(output)
2138 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2139
2140 check_output('ip link del dummy98')
2141
2142 print('## Enable ipv6')
2143 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2144 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
2145
2146 restart_networkd(3)
2147 self.wait_online(['dummy98:routable'])
2148
2149 output = check_output('ip -4 address show dummy98')
2150 print(output)
2151 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
2152 output = check_output('ip -6 address show dummy98')
2153 print(output)
2154 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2155 self.assertRegex(output, 'inet6 .* scope link')
2156 output = check_output('ip -4 route show dev dummy98')
2157 print(output)
2158 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2159 output = check_output('ip -6 route show dev dummy98')
2160 print(output)
2161 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
2162
2163 def test_bind_carrier(self):
2164 check_output('ip link add dummy98 type dummy')
2165 check_output('ip link set dummy98 up')
2166 time.sleep(2)
2167
2168 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2169 start_networkd()
2170 self.wait_online(['test1:routable'])
2171
2172 output = check_output('ip address show test1')
2173 print(output)
2174 self.assertRegex(output, 'UP,LOWER_UP')
2175 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2176 self.wait_operstate('test1', 'routable')
2177
2178 check_output('ip link add dummy99 type dummy')
2179 check_output('ip link set dummy99 up')
2180 time.sleep(2)
2181 output = check_output('ip address show test1')
2182 print(output)
2183 self.assertRegex(output, 'UP,LOWER_UP')
2184 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2185 self.wait_operstate('test1', 'routable')
2186
2187 check_output('ip link del dummy98')
2188 time.sleep(2)
2189 output = check_output('ip address show test1')
2190 print(output)
2191 self.assertRegex(output, 'UP,LOWER_UP')
2192 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2193 self.wait_operstate('test1', 'routable')
2194
2195 check_output('ip link set dummy99 down')
2196 time.sleep(2)
2197 output = check_output('ip address show test1')
2198 print(output)
2199 self.assertNotRegex(output, 'UP,LOWER_UP')
2200 self.assertRegex(output, 'DOWN')
2201 self.assertNotRegex(output, '192.168.10')
2202 self.wait_operstate('test1', 'off')
2203
2204 check_output('ip link set dummy99 up')
2205 time.sleep(2)
2206 output = check_output('ip address show test1')
2207 print(output)
2208 self.assertRegex(output, 'UP,LOWER_UP')
2209 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2210 self.wait_operstate('test1', 'routable')
2211
2212 def test_domain(self):
2213 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2214 start_networkd()
2215 self.wait_online(['dummy98:routable'])
2216
2217 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2218 print(output)
2219 self.assertRegex(output, 'Address: 192.168.42.100')
2220 self.assertRegex(output, 'DNS: 192.168.42.1')
2221 self.assertRegex(output, 'Search Domains: one')
2222
2223 def test_keep_configuration_static(self):
2224 check_output('systemctl stop systemd-networkd')
2225
2226 check_output('ip link add name dummy98 type dummy')
2227 check_output('ip address add 10.1.2.3/16 dev dummy98')
2228 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2229 output = check_output('ip address show dummy98')
2230 print(output)
2231 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2232 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2233 output = check_output('ip route show dev dummy98')
2234 print(output)
2235
2236 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2237 start_networkd()
2238 self.wait_online(['dummy98:routable'])
2239
2240 output = check_output('ip address show dummy98')
2241 print(output)
2242 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2243 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2244
2245 @expectedFailureIfNexthopIsNotAvailable()
2246 def test_nexthop(self):
2247 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2248 start_networkd()
2249 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2250
2251 output = check_output('ip nexthop list dev veth99')
2252 print(output)
2253 self.assertRegex(output, '192.168.5.1')
2254
2255 def test_qdisc(self):
2256 copy_unit_to_networkd_unit_path('25-qdisc-netem-and-fqcodel.network', '12-dummy.netdev',
2257 '25-qdisc-tbf-and-sfq.network', '11-dummy.netdev')
2258 start_networkd()
2259
2260 self.wait_online(['dummy98:routable', 'test1:routable'])
2261
2262 output = check_output('tc qdisc show dev dummy98')
2263 print(output)
2264 self.assertRegex(output, 'qdisc netem 1f:')
2265 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2266 self.assertRegex(output, 'qdisc fq_codel')
2267 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
2268 output = check_output('tc qdisc show dev test1')
2269 print(output)
2270 self.assertRegex(output, 'qdisc tbf 3f:')
2271 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70.0ms')
2272 self.assertRegex(output, 'qdisc sfq')
2273 self.assertRegex(output, 'perturb 5sec')
2274
2275 def test_qdisc2(self):
2276 copy_unit_to_networkd_unit_path('25-qdisc-fq-codel.network', '12-dummy.netdev',
2277 '25-qdisc-ingress-root.network', '11-dummy.netdev')
2278 start_networkd()
2279
2280 self.wait_online(['dummy98:routable', 'test1:routable'])
2281
2282 output = check_output('tc qdisc show dev dummy98')
2283 print(output)
2284 self.assertRegex(output, 'qdisc fq 3:')
2285 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2286 self.assertRegex(output, 'quantum 1500')
2287 self.assertRegex(output, 'initial_quantum 13000')
2288 self.assertRegex(output, 'maxrate 1Mbit')
2289 self.assertRegex(output, 'qdisc codel')
2290 self.assertRegex(output, 'limit 2000p target 10.0ms ce_threshold 100.0ms interval 50.0ms ecn')
2291 output = check_output('tc qdisc show dev test1')
2292 print(output)
2293 self.assertRegex(output, 'qdisc ingress')
2294
2295 def test_qdisc3(self):
2296 copy_unit_to_networkd_unit_path('25-qdisc-clsact-root-compat.network', '12-dummy.netdev',
2297 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2298 start_networkd()
2299
2300 self.wait_online(['dummy98:routable', 'test1:routable'])
2301
2302 output = check_output('tc qdisc show dev dummy98')
2303 print(output)
2304 self.assertRegex(output, 'qdisc clsact')
2305 output = check_output('tc qdisc show dev test1')
2306 print(output)
2307 self.assertRegex(output, 'qdisc netem')
2308 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2309 self.assertRegex(output, 'qdisc ingress')
2310
2311 def test_qdisc4(self):
2312 copy_unit_to_networkd_unit_path('25-qdisc-teql.network', '12-dummy.netdev')
2313 check_output('modprobe sch_teql max_equalizers=2')
2314 start_networkd()
2315
2316 self.wait_online(['dummy98:routable'])
2317
2318 output = check_output('tc qdisc show dev dummy98')
2319 print(output)
2320 self.assertRegex(output, 'qdisc teql1 2:')
2321
2322 class NetworkdStateFileTests(unittest.TestCase, Utilities):
2323 links = [
2324 'dummy98',
2325 ]
2326
2327 units = [
2328 '12-dummy.netdev',
2329 'state-file-tests.network',
2330 ]
2331
2332 def setUp(self):
2333 remove_links(self.links)
2334 stop_networkd(show_logs=False)
2335
2336 def tearDown(self):
2337 remove_links(self.links)
2338 remove_unit_from_networkd_path(self.units)
2339 stop_networkd(show_logs=True)
2340
2341 def test_state_file(self):
2342 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2343 start_networkd()
2344 self.wait_online(['dummy98:routable'])
2345
2346 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2347 print(output)
2348 ifindex = output.split()[0]
2349
2350 path = os.path.join('/run/systemd/netif/links/', ifindex)
2351 self.assertTrue(os.path.exists(path))
2352 time.sleep(2)
2353
2354 with open(path) as f:
2355 data = f.read()
2356 self.assertRegex(data, r'ADMIN_STATE=configured')
2357 self.assertRegex(data, r'OPER_STATE=routable')
2358 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2359 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2360 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2361 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2362 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2363 self.assertRegex(data, r'DOMAINS=hogehoge')
2364 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2365 self.assertRegex(data, r'LLMNR=no')
2366 self.assertRegex(data, r'MDNS=yes')
2367 self.assertRegex(data, r'DNSSEC=no')
2368 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2369
2370 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2371 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2372 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2373 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2374 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2375 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2376 time.sleep(2)
2377
2378 with open(path) as f:
2379 data = f.read()
2380 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2381 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2382 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2383 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2384 self.assertRegex(data, r'LLMNR=yes')
2385 self.assertRegex(data, r'MDNS=no')
2386 self.assertRegex(data, r'DNSSEC=yes')
2387
2388 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2389 time.sleep(2)
2390
2391 with open(path) as f:
2392 data = f.read()
2393 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2394 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2395 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2396 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2397 self.assertRegex(data, r'LLMNR=yes')
2398 self.assertRegex(data, r'MDNS=no')
2399 self.assertRegex(data, r'DNSSEC=yes')
2400
2401 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2402 time.sleep(2)
2403
2404 with open(path) as f:
2405 data = f.read()
2406 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2407 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2408 self.assertRegex(data, r'DOMAINS=hogehoge')
2409 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2410 self.assertRegex(data, r'LLMNR=no')
2411 self.assertRegex(data, r'MDNS=yes')
2412 self.assertRegex(data, r'DNSSEC=no')
2413
2414 class NetworkdBondTests(unittest.TestCase, Utilities):
2415 links = [
2416 'bond199',
2417 'bond99',
2418 'dummy98',
2419 'test1']
2420
2421 units = [
2422 '11-dummy.netdev',
2423 '12-dummy.netdev',
2424 '23-active-slave.network',
2425 '23-bond199.network',
2426 '23-primary-slave.network',
2427 '25-bond-active-backup-slave.netdev',
2428 '25-bond.netdev',
2429 'bond99.network',
2430 'bond-slave.network']
2431
2432 def setUp(self):
2433 remove_links(self.links)
2434 stop_networkd(show_logs=False)
2435
2436 def tearDown(self):
2437 remove_links(self.links)
2438 remove_unit_from_networkd_path(self.units)
2439 stop_networkd(show_logs=True)
2440
2441 def test_bond_active_slave(self):
2442 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2443 start_networkd()
2444 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2445
2446 output = check_output('ip -d link show bond199')
2447 print(output)
2448 self.assertRegex(output, 'active_slave dummy98')
2449
2450 def test_bond_primary_slave(self):
2451 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2452 start_networkd()
2453 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2454
2455 output = check_output('ip -d link show bond199')
2456 print(output)
2457 self.assertRegex(output, 'primary dummy98')
2458
2459 def test_bond_operstate(self):
2460 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2461 'bond99.network','bond-slave.network')
2462 start_networkd()
2463 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2464
2465 output = check_output('ip -d link show dummy98')
2466 print(output)
2467 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2468
2469 output = check_output('ip -d link show test1')
2470 print(output)
2471 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2472
2473 output = check_output('ip -d link show bond99')
2474 print(output)
2475 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2476
2477 self.wait_operstate('dummy98', 'enslaved')
2478 self.wait_operstate('test1', 'enslaved')
2479 self.wait_operstate('bond99', 'routable')
2480
2481 check_output('ip link set dummy98 down')
2482
2483 self.wait_operstate('dummy98', 'off')
2484 self.wait_operstate('test1', 'enslaved')
2485 self.wait_operstate('bond99', 'degraded-carrier')
2486
2487 check_output('ip link set dummy98 up')
2488
2489 self.wait_operstate('dummy98', 'enslaved')
2490 self.wait_operstate('test1', 'enslaved')
2491 self.wait_operstate('bond99', 'routable')
2492
2493 check_output('ip link set dummy98 down')
2494 check_output('ip link set test1 down')
2495
2496 self.wait_operstate('dummy98', 'off')
2497 self.wait_operstate('test1', 'off')
2498
2499 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2500 # Huh? Kernel does not recognize that all slave interfaces are down?
2501 # Let's confirm that networkd's operstate is consistent with ip's result.
2502 self.assertNotRegex(output, 'NO-CARRIER')
2503
2504 class NetworkdBridgeTests(unittest.TestCase, Utilities):
2505 links = [
2506 'bridge99',
2507 'dummy98',
2508 'test1']
2509
2510 units = [
2511 '11-dummy.netdev',
2512 '12-dummy.netdev',
2513 '26-bridge.netdev',
2514 '26-bridge-slave-interface-1.network',
2515 '26-bridge-slave-interface-2.network',
2516 '26-bridge-vlan-master.network',
2517 '26-bridge-vlan-slave.network',
2518 'bridge99-ignore-carrier-loss.network',
2519 'bridge99.network']
2520
2521 routing_policy_rule_tables = ['100']
2522
2523 def setUp(self):
2524 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2525 remove_links(self.links)
2526 stop_networkd(show_logs=False)
2527
2528 def tearDown(self):
2529 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2530 remove_links(self.links)
2531 remove_unit_from_networkd_path(self.units)
2532 stop_networkd(show_logs=True)
2533
2534 def test_bridge_vlan(self):
2535 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2536 '26-bridge.netdev', '26-bridge-vlan-master.network')
2537 start_networkd()
2538 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
2539
2540 output = check_output('bridge vlan show dev test1')
2541 print(output)
2542 self.assertNotRegex(output, '4063')
2543 for i in range(4064, 4095):
2544 self.assertRegex(output, f'{i}')
2545 self.assertNotRegex(output, '4095')
2546
2547 output = check_output('bridge vlan show dev bridge99')
2548 print(output)
2549 self.assertNotRegex(output, '4059')
2550 for i in range(4060, 4095):
2551 self.assertRegex(output, f'{i}')
2552 self.assertNotRegex(output, '4095')
2553
2554 def test_bridge_property(self):
2555 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2556 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2557 'bridge99.network')
2558 start_networkd()
2559 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2560
2561 output = check_output('ip -d link show test1')
2562 print(output)
2563 self.assertRegex(output, 'master')
2564 self.assertRegex(output, 'bridge')
2565
2566 output = check_output('ip -d link show dummy98')
2567 print(output)
2568 self.assertRegex(output, 'master')
2569 self.assertRegex(output, 'bridge')
2570
2571 output = check_output('ip addr show bridge99')
2572 print(output)
2573 self.assertRegex(output, '192.168.0.15/24')
2574
2575 output = check_output('bridge -d link show dummy98')
2576 print(output)
2577 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2578 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2579 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2580 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2581 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2582 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2583 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2584 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2585 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2586 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2587 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2588 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2589 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2590 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2591
2592 output = check_output('bridge -d link show test1')
2593 print(output)
2594 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2595
2596 check_output('ip address add 192.168.0.16/24 dev bridge99')
2597 time.sleep(1)
2598
2599 output = check_output('ip addr show bridge99')
2600 print(output)
2601 self.assertRegex(output, '192.168.0.16/24')
2602
2603 # for issue #6088
2604 print('### ip -6 route list table all dev bridge99')
2605 output = check_output('ip -6 route list table all dev bridge99')
2606 print(output)
2607 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2608
2609 self.assertEqual(call('ip link del test1'), 0)
2610
2611 self.wait_operstate('bridge99', 'degraded-carrier')
2612
2613 check_output('ip link del dummy98')
2614
2615 self.wait_operstate('bridge99', 'no-carrier')
2616
2617 output = check_output('ip address show bridge99')
2618 print(output)
2619 self.assertRegex(output, 'NO-CARRIER')
2620 self.assertNotRegex(output, '192.168.0.15/24')
2621 self.assertNotRegex(output, '192.168.0.16/24')
2622
2623 print('### ip -6 route list table all dev bridge99')
2624 output = check_output('ip -6 route list table all dev bridge99')
2625 print(output)
2626 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2627
2628 def test_bridge_ignore_carrier_loss(self):
2629 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2630 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2631 'bridge99-ignore-carrier-loss.network')
2632 start_networkd()
2633 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2634
2635 check_output('ip address add 192.168.0.16/24 dev bridge99')
2636 time.sleep(1)
2637
2638 check_output('ip link del test1')
2639 check_output('ip link del dummy98')
2640 time.sleep(3)
2641
2642 output = check_output('ip address show bridge99')
2643 print(output)
2644 self.assertRegex(output, 'NO-CARRIER')
2645 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2646 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2647
2648 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2649 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2650 'bridge99-ignore-carrier-loss.network')
2651 start_networkd()
2652 self.wait_online(['bridge99:no-carrier'])
2653
2654 for trial in range(4):
2655 check_output('ip link add dummy98 type dummy')
2656 check_output('ip link set dummy98 up')
2657 if trial < 3:
2658 check_output('ip link del dummy98')
2659
2660 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2661
2662 output = check_output('ip address show bridge99')
2663 print(output)
2664 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2665
2666 output = check_output('ip rule list table 100')
2667 print(output)
2668 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2669
2670 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2671 links = ['veth99']
2672
2673 units = [
2674 '23-emit-lldp.network',
2675 '24-lldp.network',
2676 '25-veth.netdev']
2677
2678 def setUp(self):
2679 remove_links(self.links)
2680 stop_networkd(show_logs=False)
2681
2682 def tearDown(self):
2683 remove_links(self.links)
2684 remove_unit_from_networkd_path(self.units)
2685 stop_networkd(show_logs=True)
2686
2687 def test_lldp(self):
2688 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2689 start_networkd()
2690 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2691
2692 output = check_output(*networkctl_cmd, 'lldp', env=env)
2693 print(output)
2694 self.assertRegex(output, 'veth-peer')
2695 self.assertRegex(output, 'veth99')
2696
2697 class NetworkdRATests(unittest.TestCase, Utilities):
2698 links = ['veth99']
2699
2700 units = [
2701 '25-veth.netdev',
2702 'ipv6-prefix.network',
2703 'ipv6-prefix-veth.network',
2704 'ipv6-prefix-veth-token-static.network',
2705 'ipv6-prefix-veth-token-static-explicit.network',
2706 'ipv6-prefix-veth-token-static-multiple.network',
2707 'ipv6-prefix-veth-token-prefixstable.network']
2708
2709 def setUp(self):
2710 remove_links(self.links)
2711 stop_networkd(show_logs=False)
2712
2713 def tearDown(self):
2714 remove_links(self.links)
2715 remove_unit_from_networkd_path(self.units)
2716 stop_networkd(show_logs=True)
2717
2718 def test_ipv6_prefix_delegation(self):
2719 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2720 start_networkd()
2721 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2722
2723 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2724 print(output)
2725 self.assertRegex(output, 'fe80::')
2726 self.assertRegex(output, '2002:da8:1::1')
2727
2728 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2729 print(output)
2730 self.assertRegex(output, '2002:da8:1:0')
2731
2732 def test_ipv6_token_static(self):
2733 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
2734 start_networkd()
2735 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2736
2737 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2738 print(output)
2739 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2740
2741 def test_ipv6_token_static_explicit(self):
2742 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2743 start_networkd()
2744 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2745
2746 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2747 print(output)
2748 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2749
2750 def test_ipv6_token_static_multiple(self):
2751 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2752 start_networkd()
2753 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2754
2755 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2756 print(output)
2757 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2758 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
2759
2760 def test_ipv6_token_prefixstable(self):
2761 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2762 start_networkd()
2763 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2764
2765 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2766 print(output)
2767 self.assertRegex(output, '2002:da8:1:0')
2768
2769 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
2770 links = ['veth99']
2771
2772 units = [
2773 '25-veth.netdev',
2774 'dhcp-client.network',
2775 'dhcp-client-timezone-router.network',
2776 'dhcp-server.network',
2777 'dhcp-server-timezone-router.network']
2778
2779 def setUp(self):
2780 remove_links(self.links)
2781 stop_networkd(show_logs=False)
2782
2783 def tearDown(self):
2784 remove_links(self.links)
2785 remove_unit_from_networkd_path(self.units)
2786 stop_networkd(show_logs=True)
2787
2788 def test_dhcp_server(self):
2789 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2790 start_networkd()
2791 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2792
2793 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2794 print(output)
2795 self.assertRegex(output, '192.168.5.*')
2796 self.assertRegex(output, 'Gateway: 192.168.5.1')
2797 self.assertRegex(output, 'DNS: 192.168.5.1')
2798 self.assertRegex(output, 'NTP: 192.168.5.1')
2799
2800 def test_emit_router_timezone(self):
2801 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2802 start_networkd()
2803 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2804
2805 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2806 print(output)
2807 self.assertRegex(output, 'Gateway: 192.168.5.*')
2808 self.assertRegex(output, '192.168.5.*')
2809 self.assertRegex(output, 'Europe/Berlin')
2810
2811 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
2812 links = [
2813 'veth99',
2814 'vrf99']
2815
2816 units = [
2817 '25-veth.netdev',
2818 '25-vrf.netdev',
2819 '25-vrf.network',
2820 'dhcp-client-anonymize.network',
2821 'dhcp-client-decline.network',
2822 'dhcp-client-gateway-ipv4.network',
2823 'dhcp-client-gateway-ipv6.network',
2824 'dhcp-client-gateway-onlink-implicit.network',
2825 'dhcp-client-ipv4-dhcp-settings.network',
2826 'dhcp-client-ipv4-only-ipv6-disabled.network',
2827 'dhcp-client-ipv4-only.network',
2828 'dhcp-client-ipv4-use-routes-no.network',
2829 'dhcp-client-ipv6-only.network',
2830 'dhcp-client-ipv6-rapid-commit.network',
2831 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2832 'dhcp-client-keep-configuration-dhcp.network',
2833 'dhcp-client-listen-port.network',
2834 'dhcp-client-reassign-static-routes-ipv4.network',
2835 'dhcp-client-reassign-static-routes-ipv6.network',
2836 'dhcp-client-route-metric.network',
2837 'dhcp-client-route-table.network',
2838 'dhcp-client-use-dns-ipv4-and-ra.network',
2839 'dhcp-client-use-dns-ipv4.network',
2840 'dhcp-client-use-dns-no.network',
2841 'dhcp-client-use-dns-yes.network',
2842 'dhcp-client-use-domains.network',
2843 'dhcp-client-use-routes-no.network',
2844 'dhcp-client-vrf.network',
2845 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2846 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2847 'dhcp-client-with-static-address.network',
2848 'dhcp-client.network',
2849 'dhcp-server-decline.network',
2850 'dhcp-server-veth-peer.network',
2851 'dhcp-v4-server-veth-peer.network',
2852 'dhcp-client-use-domains.network',
2853 'static.network']
2854
2855 def setUp(self):
2856 stop_dnsmasq(dnsmasq_pid_file)
2857 remove_links(self.links)
2858 stop_networkd(show_logs=False)
2859
2860 def tearDown(self):
2861 stop_dnsmasq(dnsmasq_pid_file)
2862 remove_lease_file()
2863 remove_log_file()
2864 remove_links(self.links)
2865 remove_unit_from_networkd_path(self.units)
2866 stop_networkd(show_logs=True)
2867
2868 def test_dhcp_client_ipv6_only(self):
2869 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2870
2871 start_networkd()
2872 self.wait_online(['veth-peer:carrier'])
2873 start_dnsmasq()
2874 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2875
2876 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2877 print(output)
2878 self.assertRegex(output, '2600::')
2879 self.assertNotRegex(output, '192.168.5')
2880
2881 # Confirm that ipv6 token is not set in the kernel
2882 output = check_output('ip token show dev veth99')
2883 print(output)
2884 self.assertRegex(output, 'token :: dev veth99')
2885
2886 def test_dhcp_client_ipv4_only(self):
2887 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2888
2889 start_networkd()
2890 self.wait_online(['veth-peer:carrier'])
2891 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
2892 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2893
2894 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2895 print(output)
2896 self.assertNotRegex(output, '2600::')
2897 self.assertRegex(output, '192.168.5')
2898 self.assertRegex(output, '192.168.5.6')
2899 self.assertRegex(output, '192.168.5.7')
2900
2901 # checking routes to DNS servers
2902 output = check_output('ip route show dev veth99')
2903 print(output)
2904 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2905 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2906 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2907
2908 stop_dnsmasq(dnsmasq_pid_file)
2909 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2910
2911 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2912 print('Wait for the dynamic address to be renewed')
2913 time.sleep(125)
2914
2915 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2916
2917 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2918 print(output)
2919 self.assertNotRegex(output, '2600::')
2920 self.assertRegex(output, '192.168.5')
2921 self.assertNotRegex(output, '192.168.5.6')
2922 self.assertRegex(output, '192.168.5.7')
2923 self.assertRegex(output, '192.168.5.8')
2924
2925 # checking routes to DNS servers
2926 output = check_output('ip route show dev veth99')
2927 print(output)
2928 self.assertNotRegex(output, r'192.168.5.6')
2929 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2930 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2931 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2932
2933 def test_dhcp_client_ipv4_use_routes_no(self):
2934 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
2935
2936 start_networkd()
2937 self.wait_online(['veth-peer:carrier'])
2938 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
2939 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2940
2941 output = check_output('ip route show dev veth99')
2942 print(output)
2943 self.assertNotRegex(output, r'192.168.5.5')
2944 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
2945 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2946
2947 def test_dhcp_client_ipv4_ipv6(self):
2948 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2949 'dhcp-client-ipv4-only.network')
2950 start_networkd()
2951 self.wait_online(['veth-peer:carrier'])
2952 start_dnsmasq()
2953 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2954
2955 # link become 'routable' when at least one protocol provide an valid address.
2956 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2957 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2958
2959 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2960 print(output)
2961 self.assertRegex(output, '2600::')
2962 self.assertRegex(output, '192.168.5')
2963
2964 def test_dhcp_client_settings(self):
2965 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2966
2967 start_networkd()
2968 self.wait_online(['veth-peer:carrier'])
2969 start_dnsmasq()
2970 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2971
2972 print('## ip address show dev veth99')
2973 output = check_output('ip address show dev veth99')
2974 print(output)
2975 self.assertRegex(output, '12:34:56:78:9a:bc')
2976 self.assertRegex(output, '192.168.5')
2977 self.assertRegex(output, '1492')
2978
2979 print('## ip route show table main dev veth99')
2980 output = check_output('ip route show table main dev veth99')
2981 print(output)
2982 # See issue #8726
2983 main_table_is_empty = output == ''
2984 if not main_table_is_empty:
2985 self.assertNotRegex(output, 'proto dhcp')
2986
2987 print('## ip route show table 211 dev veth99')
2988 output = check_output('ip route show table 211 dev veth99')
2989 print(output)
2990 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2991 if main_table_is_empty:
2992 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
2993 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2994 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2995
2996 print('## dnsmasq log')
2997 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2998 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2999 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3000 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
3001
3002 def test_dhcp6_client_settings_rapidcommit_true(self):
3003 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3004 start_networkd()
3005 self.wait_online(['veth-peer:carrier'])
3006 start_dnsmasq()
3007 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3008
3009 output = check_output('ip address show dev veth99')
3010 print(output)
3011 self.assertRegex(output, '12:34:56:78:9a:bc')
3012 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
3013
3014 def test_dhcp6_client_settings_rapidcommit_false(self):
3015 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
3016 start_networkd()
3017 self.wait_online(['veth-peer:carrier'])
3018 start_dnsmasq()
3019 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3020
3021 output = check_output('ip address show dev veth99')
3022 print(output)
3023 self.assertRegex(output, '12:34:56:78:9a:bc')
3024 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
3025
3026 def test_dhcp_client_settings_anonymize(self):
3027 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
3028 start_networkd()
3029 self.wait_online(['veth-peer:carrier'])
3030 start_dnsmasq()
3031 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3032
3033 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3034 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3035 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
3036
3037 def test_dhcp_client_listen_port(self):
3038 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
3039 start_networkd()
3040 self.wait_online(['veth-peer:carrier'])
3041 start_dnsmasq('--dhcp-alternate-port=67,5555')
3042 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3043
3044 output = check_output('ip -4 address show dev veth99')
3045 print(output)
3046 self.assertRegex(output, '192.168.5.* dynamic')
3047
3048 def test_dhcp_client_with_static_address(self):
3049 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3050 'dhcp-client-with-static-address.network')
3051 start_networkd()
3052 self.wait_online(['veth-peer:carrier'])
3053 start_dnsmasq()
3054 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3055
3056 output = check_output('ip address show dev veth99 scope global')
3057 print(output)
3058 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3059 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3060
3061 output = check_output('ip route show dev veth99')
3062 print(output)
3063 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3064 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3065 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3066 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3067
3068 def test_dhcp_route_table_id(self):
3069 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
3070 start_networkd()
3071 self.wait_online(['veth-peer:carrier'])
3072 start_dnsmasq()
3073 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3074
3075 output = check_output('ip route show table 12')
3076 print(output)
3077 self.assertRegex(output, 'veth99 proto dhcp')
3078 self.assertRegex(output, '192.168.5.1')
3079
3080 def test_dhcp_route_metric(self):
3081 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
3082 start_networkd()
3083 self.wait_online(['veth-peer:carrier'])
3084 start_dnsmasq()
3085 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3086
3087 output = check_output('ip route show dev veth99')
3088 print(output)
3089 self.assertRegex(output, 'metric 24')
3090
3091 def test_dhcp_client_reassign_static_routes_ipv4(self):
3092 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3093 'dhcp-client-reassign-static-routes-ipv4.network')
3094 start_networkd()
3095 self.wait_online(['veth-peer:carrier'])
3096 start_dnsmasq(lease_time='2m')
3097 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3098
3099 output = check_output('ip address show dev veth99 scope global')
3100 print(output)
3101 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3102
3103 output = check_output('ip route show dev veth99')
3104 print(output)
3105 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3106 self.assertRegex(output, r'192.168.5.0/24 proto static')
3107 self.assertRegex(output, r'192.168.6.0/24 proto static')
3108 self.assertRegex(output, r'192.168.7.0/24 proto static')
3109
3110 stop_dnsmasq(dnsmasq_pid_file)
3111 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3112
3113 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3114 print('Wait for the dynamic address to be renewed')
3115 time.sleep(125)
3116
3117 self.wait_online(['veth99:routable'])
3118
3119 output = check_output('ip route show dev veth99')
3120 print(output)
3121 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3122 self.assertRegex(output, r'192.168.5.0/24 proto static')
3123 self.assertRegex(output, r'192.168.6.0/24 proto static')
3124 self.assertRegex(output, r'192.168.7.0/24 proto static')
3125
3126 def test_dhcp_client_reassign_static_routes_ipv6(self):
3127 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3128 'dhcp-client-reassign-static-routes-ipv6.network')
3129 start_networkd()
3130 self.wait_online(['veth-peer:carrier'])
3131 start_dnsmasq(lease_time='2m')
3132 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3133
3134 output = check_output('ip address show dev veth99 scope global')
3135 print(output)
3136 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
3137
3138 output = check_output('ip -6 route show dev veth99')
3139 print(output)
3140 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3141 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3142
3143 stop_dnsmasq(dnsmasq_pid_file)
3144 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3145
3146 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3147 print('Wait for the dynamic address to be renewed')
3148 time.sleep(125)
3149
3150 self.wait_online(['veth99:routable'])
3151
3152 output = check_output('ip -6 route show dev veth99')
3153 print(output)
3154 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3155 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3156
3157 def test_dhcp_keep_configuration_dhcp(self):
3158 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
3159 start_networkd()
3160 self.wait_online(['veth-peer:carrier'])
3161 start_dnsmasq(lease_time='2m')
3162 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3163
3164 output = check_output('ip address show dev veth99 scope global')
3165 print(output)
3166 self.assertRegex(output, r'192.168.5.*')
3167
3168 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3169 print(output)
3170 self.assertRegex(output, r'192.168.5.*')
3171
3172 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
3173 stop_dnsmasq(dnsmasq_pid_file)
3174
3175 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3176 print('Wait for the dynamic address to be expired')
3177 time.sleep(125)
3178
3179 print('The lease address should be kept after lease expired')
3180 output = check_output('ip address show dev veth99 scope global')
3181 print(output)
3182 self.assertRegex(output, r'192.168.5.*')
3183
3184 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3185 print(output)
3186 self.assertRegex(output, r'192.168.5.*')
3187
3188 check_output('systemctl stop systemd-networkd')
3189
3190 print('The lease address should be kept after networkd stopped')
3191 output = check_output('ip address show dev veth99 scope global')
3192 print(output)
3193 self.assertRegex(output, r'192.168.5.*')
3194
3195 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3196 print(output)
3197 self.assertRegex(output, r'192.168.5.*')
3198
3199 start_networkd(3)
3200 self.wait_online(['veth-peer:routable'])
3201
3202 print('Still the lease address should be kept after networkd restarted')
3203 output = check_output('ip address show dev veth99 scope global')
3204 print(output)
3205 self.assertRegex(output, r'192.168.5.*')
3206
3207 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3208 print(output)
3209 self.assertRegex(output, r'192.168.5.*')
3210
3211 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3212 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
3213 start_networkd()
3214 self.wait_online(['veth-peer:carrier'])
3215 start_dnsmasq(lease_time='2m')
3216 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3217
3218 output = check_output('ip address show dev veth99 scope global')
3219 print(output)
3220 self.assertRegex(output, r'192.168.5.*')
3221
3222 stop_dnsmasq(dnsmasq_pid_file)
3223 check_output('systemctl stop systemd-networkd')
3224
3225 output = check_output('ip address show dev veth99 scope global')
3226 print(output)
3227 self.assertRegex(output, r'192.168.5.*')
3228
3229 restart_networkd(3)
3230 self.wait_online(['veth-peer:routable'])
3231
3232 output = check_output('ip address show dev veth99 scope global')
3233 print(output)
3234 self.assertNotRegex(output, r'192.168.5.*')
3235
3236 def test_dhcp_client_reuse_address_as_static(self):
3237 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
3238 start_networkd()
3239 self.wait_online(['veth-peer:carrier'])
3240 start_dnsmasq()
3241 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3242
3243 # link become 'routable' when at least one protocol provide an valid address.
3244 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3245 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3246
3247 output = check_output('ip address show dev veth99 scope global')
3248 print(output)
3249 self.assertRegex(output, '192.168.5')
3250 self.assertRegex(output, '2600::')
3251
3252 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3253 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
3254 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3255 print(static_network)
3256
3257 remove_unit_from_networkd_path(['dhcp-client.network'])
3258
3259 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3260 f.write(static_network)
3261
3262 # When networkd started, the links are already configured, so let's wait for 5 seconds
3263 # the links to be re-configured.
3264 restart_networkd(5)
3265 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3266
3267 output = check_output('ip -4 address show dev veth99 scope global')
3268 print(output)
3269 self.assertRegex(output, '192.168.5')
3270 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3271
3272 output = check_output('ip -6 address show dev veth99 scope global')
3273 print(output)
3274 self.assertRegex(output, '2600::')
3275 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3276
3277 @expectedFailureIfModuleIsNotAvailable('vrf')
3278 def test_dhcp_client_vrf(self):
3279 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3280 '25-vrf.netdev', '25-vrf.network')
3281 start_networkd()
3282 self.wait_online(['veth-peer:carrier'])
3283 start_dnsmasq()
3284 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
3285
3286 # link become 'routable' when at least one protocol provide an valid address.
3287 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3288 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3289
3290 print('## ip -d link show dev vrf99')
3291 output = check_output('ip -d link show dev vrf99')
3292 print(output)
3293 self.assertRegex(output, 'vrf table 42')
3294
3295 print('## ip address show vrf vrf99')
3296 output = check_output('ip address show vrf vrf99')
3297 print(output)
3298 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3299 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3300 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3301 self.assertRegex(output, 'inet6 .* scope link')
3302
3303 print('## ip address show dev veth99')
3304 output = check_output('ip address show dev veth99')
3305 print(output)
3306 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3307 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3308 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3309 self.assertRegex(output, 'inet6 .* scope link')
3310
3311 print('## ip route show vrf vrf99')
3312 output = check_output('ip route show vrf vrf99')
3313 print(output)
3314 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3315 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3316 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3317 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3318 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3319
3320 print('## ip route show table main dev veth99')
3321 output = check_output('ip route show table main dev veth99')
3322 print(output)
3323 self.assertEqual(output, '')
3324
3325 def test_dhcp_client_gateway_ipv4(self):
3326 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3327 'dhcp-client-gateway-ipv4.network')
3328 start_networkd()
3329 self.wait_online(['veth-peer:carrier'])
3330 start_dnsmasq()
3331 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3332
3333 output = check_output('ip route list dev veth99 10.0.0.0/8')
3334 print(output)
3335 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3336
3337 def test_dhcp_client_gateway_ipv6(self):
3338 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3339 'dhcp-client-gateway-ipv6.network')
3340 start_networkd()
3341 self.wait_online(['veth-peer:carrier'])
3342 start_dnsmasq()
3343 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3344
3345 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3346 print(output)
3347 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3348
3349 def test_dhcp_client_gateway_onlink_implicit(self):
3350 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3351 'dhcp-client-gateway-onlink-implicit.network')
3352 start_networkd()
3353 self.wait_online(['veth-peer:carrier'])
3354 start_dnsmasq()
3355 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3356
3357 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3358 print(output)
3359 self.assertRegex(output, '192.168.5')
3360
3361 output = check_output('ip route list dev veth99 10.0.0.0/8')
3362 print(output)
3363 self.assertRegex(output, 'onlink')
3364 output = check_output('ip route list dev veth99 192.168.100.0/24')
3365 print(output)
3366 self.assertRegex(output, 'onlink')
3367
3368 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
3369 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3370 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3371 start_networkd()
3372 self.wait_online(['veth-peer:carrier'])
3373 start_dnsmasq(lease_time='2m')
3374 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3375
3376 output = check_output('ip address show dev veth99')
3377 print(output)
3378
3379 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3380 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3381 output = check_output('ip -6 address show dev veth99 scope link')
3382 self.assertRegex(output, 'inet6 .* scope link')
3383 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3384 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3385 output = check_output('ip -4 address show dev veth99 scope link')
3386 self.assertNotRegex(output, 'inet .* scope link')
3387
3388 print('Wait for the dynamic address to be expired')
3389 time.sleep(130)
3390
3391 output = check_output('ip address show dev veth99')
3392 print(output)
3393
3394 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3395 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3396 output = check_output('ip -6 address show dev veth99 scope link')
3397 self.assertRegex(output, 'inet6 .* scope link')
3398 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3399 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3400 output = check_output('ip -4 address show dev veth99 scope link')
3401 self.assertNotRegex(output, 'inet .* scope link')
3402
3403 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
3404
3405 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
3406 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3407 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3408 start_networkd()
3409 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
3410
3411 output = check_output('ip address show dev veth99')
3412 print(output)
3413
3414 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3415 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3416 output = check_output('ip -6 address show dev veth99 scope link')
3417 self.assertRegex(output, 'inet6 .* scope link')
3418 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3419 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3420 output = check_output('ip -4 address show dev veth99 scope link')
3421 self.assertRegex(output, 'inet .* scope link')
3422
3423 def test_dhcp_client_route_remove_on_renew(self):
3424 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3425 'dhcp-client-ipv4-only-ipv6-disabled.network')
3426 start_networkd()
3427 self.wait_online(['veth-peer:carrier'])
3428 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
3429 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3430
3431 # test for issue #12490
3432
3433 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3434 print(output)
3435 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3436 address1=None
3437 for line in output.splitlines():
3438 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3439 address1 = line.split()[1].split('/')[0]
3440 break
3441
3442 output = check_output('ip -4 route show dev veth99')
3443 print(output)
3444 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3445 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3446
3447 stop_dnsmasq(dnsmasq_pid_file)
3448 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
3449
3450 print('Wait for the dynamic address to be expired')
3451 time.sleep(130)
3452
3453 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3454 print(output)
3455 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3456 address2=None
3457 for line in output.splitlines():
3458 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3459 address2 = line.split()[1].split('/')[0]
3460 break
3461
3462 self.assertNotEqual(address1, address2)
3463
3464 output = check_output('ip -4 route show dev veth99')
3465 print(output)
3466 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3467 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3468 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3469 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3470
3471 def test_dhcp_client_use_dns_yes(self):
3472 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3473
3474 start_networkd()
3475 self.wait_online(['veth-peer:carrier'])
3476 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3477 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3478
3479 # link become 'routable' when at least one protocol provide an valid address.
3480 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3481 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3482
3483 time.sleep(3)
3484 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3485 print(output)
3486 self.assertRegex(output, '192.168.5.1')
3487 self.assertRegex(output, '2600::1')
3488
3489 def test_dhcp_client_use_dns_no(self):
3490 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3491
3492 start_networkd()
3493 self.wait_online(['veth-peer:carrier'])
3494 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3495 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3496
3497 # link become 'routable' when at least one protocol provide an valid address.
3498 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3499 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3500
3501 time.sleep(3)
3502 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3503 print(output)
3504 self.assertNotRegex(output, '192.168.5.1')
3505 self.assertNotRegex(output, '2600::1')
3506
3507 def test_dhcp_client_use_dns_ipv4(self):
3508 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3509
3510 start_networkd()
3511 self.wait_online(['veth-peer:carrier'])
3512 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3513 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3514
3515 # link become 'routable' when at least one protocol provide an valid address.
3516 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3517 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3518
3519 time.sleep(3)
3520 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3521 print(output)
3522 self.assertRegex(output, '192.168.5.1')
3523 self.assertNotRegex(output, '2600::1')
3524
3525 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3526 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3527
3528 start_networkd()
3529 self.wait_online(['veth-peer:carrier'])
3530 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3531 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3532
3533 # link become 'routable' when at least one protocol provide an valid address.
3534 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3535 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3536
3537 time.sleep(3)
3538 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3539 print(output)
3540 self.assertRegex(output, '192.168.5.1')
3541 self.assertRegex(output, '2600::1')
3542
3543 def test_dhcp_client_use_domains(self):
3544 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3545
3546 start_networkd()
3547 self.wait_online(['veth-peer:carrier'])
3548 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3549 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3550
3551 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3552 print(output)
3553 self.assertRegex(output, 'Search Domains: example.com')
3554
3555 time.sleep(3)
3556 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3557 print(output)
3558 self.assertRegex(output, 'example.com')
3559
3560 def test_dhcp_client_decline(self):
3561 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3562
3563 start_networkd()
3564 self.wait_online(['veth-peer:carrier'])
3565 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3566 self.assertTrue(rc == 1)
3567
3568 class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3569 links = ['veth99']
3570
3571 units = [
3572 '25-veth.netdev',
3573 'ipv6ra-prefix-client.network',
3574 'ipv6ra-prefix.network'
3575 ]
3576
3577 def setUp(self):
3578 remove_links(self.links)
3579 stop_networkd(show_logs=False)
3580
3581 def tearDown(self):
3582 remove_log_file()
3583 remove_links(self.links)
3584 remove_unit_from_networkd_path(self.units)
3585 stop_networkd(show_logs=True)
3586
3587 def test_ipv6_route_prefix(self):
3588 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3589
3590 start_networkd()
3591 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3592
3593 output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3594 print(output)
3595 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3596
3597 class NetworkdMTUTests(unittest.TestCase, Utilities):
3598 links = ['dummy98']
3599
3600 units = [
3601 '12-dummy.netdev',
3602 '12-dummy-mtu.netdev',
3603 '12-dummy-mtu.link',
3604 '12-dummy.network',
3605 ]
3606
3607 def setUp(self):
3608 remove_links(self.links)
3609 stop_networkd(show_logs=False)
3610
3611 def tearDown(self):
3612 remove_log_file()
3613 remove_links(self.links)
3614 remove_unit_from_networkd_path(self.units)
3615 stop_networkd(show_logs=True)
3616
3617 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3618 if not ipv6_mtu:
3619 ipv6_mtu = mtu
3620
3621 # test normal start
3622 start_networkd()
3623 self.wait_online(['dummy98:routable'])
3624 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3625 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3626
3627 # test normal restart
3628 restart_networkd()
3629 self.wait_online(['dummy98:routable'])
3630 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3631 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3632
3633 if reset:
3634 self.reset_check_mtu(mtu, ipv6_mtu)
3635
3636 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3637 ''' test setting mtu/ipv6_mtu with interface already up '''
3638 stop_networkd()
3639
3640 # note - changing the device mtu resets the ipv6 mtu
3641 run('ip link set up mtu 1501 dev dummy98')
3642 run('ip link set up mtu 1500 dev dummy98')
3643 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3644 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3645
3646 self.check_mtu(mtu, ipv6_mtu, reset=False)
3647
3648 def test_mtu_network(self):
3649 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3650 self.check_mtu('1600')
3651
3652 def test_mtu_netdev(self):
3653 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3654 # note - MTU set by .netdev happens ONLY at device creation!
3655 self.check_mtu('1600', reset=False)
3656
3657 def test_mtu_link(self):
3658 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3659 # must reload udev because it only picks up new files after 3 second delay
3660 call('udevadm control --reload')
3661 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3662 self.check_mtu('1600', reset=False)
3663
3664 def test_ipv6_mtu(self):
3665 ''' set ipv6 mtu without setting device mtu '''
3666 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3667 self.check_mtu('1500', '1400')
3668
3669 def test_ipv6_mtu_toolarge(self):
3670 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3671 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3672 self.check_mtu('1500', '1500')
3673
3674 def test_mtu_network_ipv6_mtu(self):
3675 ''' set ipv6 mtu and set device mtu via network file '''
3676 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3677 self.check_mtu('1600', '1550')
3678
3679 def test_mtu_netdev_ipv6_mtu(self):
3680 ''' set ipv6 mtu and set device mtu via netdev file '''
3681 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3682 self.check_mtu('1600', '1550', reset=False)
3683
3684 def test_mtu_link_ipv6_mtu(self):
3685 ''' set ipv6 mtu and set device mtu via link file '''
3686 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3687 # must reload udev because it only picks up new files after 3 second delay
3688 call('udevadm control --reload')
3689 self.check_mtu('1600', '1550', reset=False)
3690
3691
3692 if __name__ == '__main__':
3693 parser = argparse.ArgumentParser()
3694 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3695 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
3696 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
3697 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
3698 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3699 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
3700 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3701 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
3702 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3703 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
3704 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
3705 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
3706 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
3707 ns, args = parser.parse_known_args(namespace=unittest)
3708
3709 if ns.build_dir:
3710 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:
3711 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3712 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
3713 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
3714 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
3715 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3716 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
3717 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3718 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
3719 else:
3720 if ns.networkd_bin:
3721 networkd_bin = ns.networkd_bin
3722 if ns.resolved_bin:
3723 resolved_bin = ns.resolved_bin
3724 if ns.udevd_bin:
3725 udevd_bin = ns.udevd_bin
3726 if ns.wait_online_bin:
3727 wait_online_bin = ns.wait_online_bin
3728 if ns.networkctl_bin:
3729 networkctl_bin = ns.networkctl_bin
3730 if ns.resolvectl_bin:
3731 resolvectl_bin = ns.resolvectl_bin
3732 if ns.timedatectl_bin:
3733 timedatectl_bin = ns.timedatectl_bin
3734
3735 use_valgrind = ns.use_valgrind
3736 enable_debug = ns.enable_debug
3737 asan_options = ns.asan_options
3738 lsan_options = ns.lsan_options
3739 ubsan_options = ns.ubsan_options
3740
3741 if use_valgrind:
3742 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
3743 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3744 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
3745 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3746 else:
3747 networkctl_cmd = [networkctl_bin]
3748 resolvectl_cmd = [resolvectl_bin]
3749 timedatectl_cmd = [timedatectl_bin]
3750 wait_online_cmd = [wait_online_bin]
3751
3752 if enable_debug:
3753 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3754 if asan_options:
3755 env.update({ 'ASAN_OPTIONS' : asan_options })
3756 if lsan_options:
3757 env.update({ 'LSAN_OPTIONS' : lsan_options })
3758 if ubsan_options:
3759 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
3760
3761 sys.argv[1:] = args
3762 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3763 verbosity=3))