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