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