1#!/usr/bin/env python3 2# SPDX-License-Identifier: LGPL-2.1-or-later 3# pylint: disable=line-too-long,too-many-lines,too-many-branches,too-many-statements,too-many-arguments 4# pylint: disable=too-many-public-methods,too-many-boolean-expressions,invalid-name 5# pylint: disable=missing-function-docstring,missing-class-docstring,missing-module-docstring 6# systemd-networkd tests 7 8# These tests can be executed in the systemd mkosi image when booted in QEMU. After booting the QEMU VM, 9# simply run this file which can be found in the VM at /root/src/test/test-network/systemd-networkd-tests.py. 10 11import argparse 12import errno 13import itertools 14import os 15import re 16import shutil 17import signal 18import subprocess 19import sys 20import time 21import unittest 22from shutil import copytree 23from pathlib import Path 24 25network_unit_file_path='/run/systemd/network' 26networkd_runtime_directory='/run/systemd/netif' 27networkd_conf_dropin_path='/run/systemd/networkd.conf.d' 28networkd_ci_path='/run/networkd-ci' 29network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf' 30network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf' 31 32udev_rules_dir='/run/udev/rules.d' 33 34dnsmasq_pid_file='/run/networkd-ci/test-dnsmasq.pid' 35dnsmasq_log_file='/run/networkd-ci/test-dnsmasq.log' 36dnsmasq_lease_file='/run/networkd-ci/test-dnsmasq.lease' 37 38isc_dhcpd_pid_file='/run/networkd-ci/test-isc-dhcpd.pid' 39isc_dhcpd_lease_file='/run/networkd-ci/test-isc-dhcpd.lease' 40 41systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd'] 42which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':')) 43 44networkd_bin=shutil.which('systemd-networkd', path=which_paths) 45resolved_bin=shutil.which('systemd-resolved', path=which_paths) 46udevd_bin=shutil.which('systemd-udevd', path=which_paths) 47wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths) 48networkctl_bin=shutil.which('networkctl', path=which_paths) 49resolvectl_bin=shutil.which('resolvectl', path=which_paths) 50timedatectl_bin=shutil.which('timedatectl', path=which_paths) 51 52use_valgrind=False 53enable_debug=True 54env = {} 55asan_options=None 56lsan_options=None 57ubsan_options=None 58with_coverage=False 59 60running_units = [] 61 62def check_output(*command, **kwargs): 63 # This replaces both check_output and check_call (output can be ignored) 64 command = command[0].split() + list(command[1:]) 65 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip() 66 67def call(*command, **kwargs): 68 command = command[0].split() + list(command[1:]) 69 return subprocess.call(command, universal_newlines=True, **kwargs) 70 71def run(*command, **kwargs): 72 command = command[0].split() + list(command[1:]) 73 return subprocess.run(command, universal_newlines=True, check=False, **kwargs) 74 75def is_module_available(module_name): 76 lsmod_output = check_output('lsmod') 77 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE) 78 return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL) 79 80def expectedFailureIfModuleIsNotAvailable(module_name): 81 def f(func): 82 if not is_module_available(module_name): 83 return unittest.expectedFailure(func) 84 return func 85 86 return f 87 88def expectedFailureIfERSPANModuleIsNotAvailable(): 89 def f(func): 90 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) 91 if rc == 0: 92 call('ip link del erspan99') 93 return func 94 95 return unittest.expectedFailure(func) 96 97 return f 98 99def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable(): 100 def f(func): 101 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL) 102 if rc == 0: 103 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7') 104 return func 105 106 return unittest.expectedFailure(func) 107 108 return f 109 110def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable(): 111 def f(func): 112 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL) 113 if rc == 0: 114 call('ip rule del not from 192.168.100.19 ipproto tcp table 7') 115 return func 116 117 return unittest.expectedFailure(func) 118 119 return f 120 121def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable(): 122 def f(func): 123 support = False 124 rc = call('ip rule add from 192.168.100.19 table 7 uidrange 200-300', stderr=subprocess.DEVNULL) 125 if rc == 0: 126 ret = run('ip rule list from 192.168.100.19 table 7', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 127 if ret.returncode == 0 and 'uidrange 200-300' in ret.stdout.rstrip(): 128 support = True 129 call('ip rule del from 192.168.100.19 table 7 uidrange 200-300') 130 131 if support: 132 return func 133 134 return unittest.expectedFailure(func) 135 136 return f 137 138def expectedFailureIfLinkFileFieldIsNotSet(): 139 def f(func): 140 support = False 141 rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL) 142 if rc == 0: 143 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 144 if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip(): 145 support = True 146 call('ip link del dummy99') 147 148 if support: 149 return func 150 151 return unittest.expectedFailure(func) 152 153 return f 154 155def expectedFailureIfNexthopIsNotAvailable(): 156 def f(func): 157 rc = call('ip nexthop list', stderr=subprocess.DEVNULL) 158 if rc == 0: 159 return func 160 161 return unittest.expectedFailure(func) 162 163 return f 164 165def expectedFailureIfRTA_VIAIsNotSupported(): 166 def f(func): 167 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 168 call('ip link set up dev dummy98', stderr=subprocess.DEVNULL) 169 call('ip route add 2001:1234:5:8fff:ff:ff:ff:fe/128 dev dummy98', stderr=subprocess.DEVNULL) 170 rc = call('ip route add 10.10.10.10 via inet6 2001:1234:5:8fff:ff:ff:ff:fe dev dummy98', stderr=subprocess.DEVNULL) 171 call('ip link del dummy98', stderr=subprocess.DEVNULL) 172 if rc == 0: 173 return func 174 175 return unittest.expectedFailure(func) 176 177 return f 178 179def expectedFailureIfAlternativeNameIsNotAvailable(): 180 def f(func): 181 supported = False 182 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 183 rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL) 184 if rc == 0: 185 rc = call('ip link show dev hogehogehogehogehoge', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 186 if rc == 0: 187 supported = True 188 189 call('ip link del dummy98', stderr=subprocess.DEVNULL) 190 if supported: 191 return func 192 193 return unittest.expectedFailure(func) 194 195 return f 196 197def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable(): 198 def f(func): 199 call('rmmod netdevsim', stderr=subprocess.DEVNULL) 200 rc = call('modprobe netdevsim', stderr=subprocess.DEVNULL) 201 if rc != 0: 202 return unittest.expectedFailure(func) 203 204 try: 205 with open('/sys/bus/netdevsim/new_device', mode='w') as f: 206 f.write('99 1') 207 except OSError: 208 return unittest.expectedFailure(func) 209 210 call('udevadm settle') 211 call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL) 212 try: 213 with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f: 214 f.write('3') 215 except OSError: 216 call('rmmod netdevsim', stderr=subprocess.DEVNULL) 217 return unittest.expectedFailure(func) 218 219 call('rmmod netdevsim', stderr=subprocess.DEVNULL) 220 return func 221 222 return f 223 224def expectedFailureIfCAKEIsNotAvailable(): 225 def f(func): 226 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 227 rc = call('tc qdisc add dev dummy98 parent root cake', stderr=subprocess.DEVNULL) 228 call('ip link del dummy98', stderr=subprocess.DEVNULL) 229 if rc == 0: 230 return func 231 232 return unittest.expectedFailure(func) 233 234 return f 235 236def expectedFailureIfPIEIsNotAvailable(): 237 def f(func): 238 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 239 rc = call('tc qdisc add dev dummy98 parent root pie', stderr=subprocess.DEVNULL) 240 call('ip link del dummy98', stderr=subprocess.DEVNULL) 241 if rc == 0: 242 return func 243 244 return unittest.expectedFailure(func) 245 246 return f 247 248def expectedFailureIfHHFIsNotAvailable(): 249 def f(func): 250 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 251 rc = call('tc qdisc add dev dummy98 parent root hhf', stderr=subprocess.DEVNULL) 252 call('ip link del dummy98', stderr=subprocess.DEVNULL) 253 if rc == 0: 254 return func 255 256 return unittest.expectedFailure(func) 257 258 return f 259 260def expectedFailureIfETSIsNotAvailable(): 261 def f(func): 262 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 263 rc = call('tc qdisc add dev dummy98 parent root ets bands 10', stderr=subprocess.DEVNULL) 264 call('ip link del dummy98', stderr=subprocess.DEVNULL) 265 if rc == 0: 266 return func 267 268 return unittest.expectedFailure(func) 269 270 return f 271 272def expectedFailureIfFQPIEIsNotAvailable(): 273 def f(func): 274 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) 275 rc = call('tc qdisc add dev dummy98 parent root fq_pie', stderr=subprocess.DEVNULL) 276 call('ip link del dummy98', stderr=subprocess.DEVNULL) 277 if rc == 0: 278 return func 279 280 return unittest.expectedFailure(func) 281 282 return f 283 284def setUpModule(): 285 # pylint: disable=global-statement 286 global running_units 287 288 os.makedirs(network_unit_file_path, exist_ok=True) 289 os.makedirs(networkd_conf_dropin_path, exist_ok=True) 290 os.makedirs(networkd_ci_path, exist_ok=True) 291 os.makedirs(udev_rules_dir, exist_ok=True) 292 293 shutil.rmtree(networkd_ci_path) 294 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path) 295 296 shutil.copy(os.path.join(networkd_ci_path, '00-debug-net.rules'), udev_rules_dir) 297 298 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 299 'systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service', 300 'firewalld.service']: 301 if call(f'systemctl is-active --quiet {u}') == 0: 302 check_output(f'systemctl stop {u}') 303 running_units.append(u) 304 305 drop_in = [ 306 '[Unit]', 307 'StartLimitIntervalSec=0', 308 '[Service]', 309 'Restart=no', 310 'ExecStart=', 311 ] 312 if use_valgrind: 313 drop_in += [ 314 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin, 315 'PrivateTmp=yes' 316 ] 317 else: 318 drop_in += ['ExecStart=!!' + networkd_bin] 319 if enable_debug: 320 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] 321 if asan_options: 322 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] 323 if lsan_options: 324 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] 325 if ubsan_options: 326 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] 327 if asan_options or lsan_options or ubsan_options: 328 drop_in += ['SystemCallFilter='] 329 if use_valgrind or asan_options or lsan_options or ubsan_options: 330 drop_in += ['MemoryDenyWriteExecute=no'] 331 if with_coverage: 332 drop_in += [ 333 'ProtectSystem=no', 334 'ProtectHome=no', 335 ] 336 337 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True) 338 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f: 339 f.write('\n'.join(drop_in)) 340 341 drop_in = [ 342 '[Service]', 343 'Restart=no', 344 'ExecStart=', 345 ] 346 if use_valgrind: 347 drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin] 348 else: 349 drop_in += ['ExecStart=!!' + resolved_bin] 350 if enable_debug: 351 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] 352 if asan_options: 353 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] 354 if lsan_options: 355 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] 356 if ubsan_options: 357 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] 358 if asan_options or lsan_options or ubsan_options: 359 drop_in += ['SystemCallFilter='] 360 if use_valgrind or asan_options or lsan_options or ubsan_options: 361 drop_in += ['MemoryDenyWriteExecute=no'] 362 if with_coverage: 363 drop_in += [ 364 'ProtectSystem=no', 365 'ProtectHome=no', 366 ] 367 368 os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True) 369 with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f: 370 f.write('\n'.join(drop_in)) 371 372 drop_in = [ 373 '[Service]', 374 'ExecStart=', 375 'ExecStart=!!' + udevd_bin, 376 ] 377 378 os.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok=True) 379 with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w') as f: 380 f.write('\n'.join(drop_in)) 381 382 check_output('systemctl daemon-reload') 383 print(check_output('systemctl cat systemd-networkd.service')) 384 print(check_output('systemctl cat systemd-resolved.service')) 385 print(check_output('systemctl cat systemd-udevd.service')) 386 check_output('systemctl restart systemd-resolved') 387 check_output('systemctl restart systemd-udevd') 388 389def tearDownModule(): 390 # pylint: disable=global-statement 391 global running_units 392 393 shutil.rmtree(networkd_ci_path) 394 os.remove(os.path.join(udev_rules_dir, '00-debug-net.rules')) 395 396 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service']: 397 check_output(f'systemctl stop {u}') 398 399 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d') 400 shutil.rmtree('/run/systemd/system/systemd-resolved.service.d') 401 shutil.rmtree('/run/systemd/system/systemd-udevd.service.d') 402 check_output('systemctl daemon-reload') 403 check_output('systemctl restart systemd-udevd.service') 404 405 for u in running_units: 406 check_output(f'systemctl start {u}') 407 408def read_link_attr(*args): 409 with open(os.path.join('/sys/class/net/', *args)) as f: 410 return f.readline().strip() 411 412def read_bridge_port_attr(bridge, link, attribute): 413 path_bridge = os.path.join('/sys/devices/virtual/net', bridge) 414 path_port = 'lower_' + link + '/brport' 415 path = os.path.join(path_bridge, path_port) 416 417 with open(os.path.join(path, attribute)) as f: 418 return f.readline().strip() 419 420def link_exists(link): 421 return os.path.exists(os.path.join('/sys/class/net', link)) 422 423def remove_links(links): 424 for link in links: 425 if link_exists(link): 426 call('ip link del dev', link) 427 time.sleep(1) 428 429def remove_fou_ports(ports): 430 for port in ports: 431 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 432 433def remove_routing_policy_rule_tables(tables): 434 for table in tables: 435 rc = 0 436 while rc == 0: 437 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 438 rc = 0 439 while rc == 0: 440 rc = call('ip -6 rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 441 442def remove_routes(routes): 443 for route_type, addr in routes: 444 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 445 446def remove_blackhole_nexthops(): 447 ret = run('ip nexthop show dev lo', stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) 448 if ret.returncode == 0: 449 for line in ret.stdout.rstrip().splitlines(): 450 dev_id = line.split()[1] 451 call(f'ip nexthop del id {dev_id}') 452 453def remove_l2tp_tunnels(tunnel_ids): 454 output = check_output('ip l2tp show tunnel') 455 for tid in tunnel_ids: 456 words='Tunnel ' + tid + ', encap' 457 if words in output: 458 call('ip l2tp del tunnel tid', tid) 459 time.sleep(1) 460 461def read_ipv6_sysctl_attr(link, attribute): 462 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f: 463 return f.readline().strip() 464 465def read_ipv4_sysctl_attr(link, attribute): 466 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f: 467 return f.readline().strip() 468 469def copy_unit_to_networkd_unit_path(*units, dropins=True): 470 """Copy networkd unit files into the testbed. 471 472 Any networkd unit file type can be specified, as well as drop-in files. 473 474 By default, all drop-ins for a specified unit file are copied in; 475 to avoid that specify dropins=False. 476 477 When a drop-in file is specified, its unit file is also copied in automatically. 478 """ 479 print() 480 for unit in units: 481 if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')): 482 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d')) 483 if unit.endswith('.conf'): 484 dropin = unit 485 dropindir = os.path.join(network_unit_file_path, os.path.dirname(dropin)) 486 os.makedirs(dropindir, exist_ok=True) 487 shutil.copy(os.path.join(networkd_ci_path, dropin), dropindir) 488 unit = os.path.dirname(dropin).rstrip('.d') 489 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path) 490 491def remove_unit_from_networkd_path(units): 492 """Remove previously copied unit files from the testbed. 493 494 Drop-ins will be removed automatically. 495 """ 496 for unit in units: 497 if os.path.exists(os.path.join(network_unit_file_path, unit)): 498 os.remove(os.path.join(network_unit_file_path, unit)) 499 if os.path.exists(os.path.join(network_unit_file_path, unit + '.d')): 500 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d')) 501 502def copy_networkd_conf_dropin(*dropins): 503 """Copy networkd.conf dropin files into the testbed.""" 504 for dropin in dropins: 505 shutil.copy(os.path.join(networkd_ci_path, dropin), networkd_conf_dropin_path) 506 507def remove_networkd_conf_dropin(dropins): 508 """Remove previously copied networkd.conf dropin files from the testbed.""" 509 for dropin in dropins: 510 if os.path.exists(os.path.join(networkd_conf_dropin_path, dropin)): 511 os.remove(os.path.join(networkd_conf_dropin_path, dropin)) 512 513def start_dnsmasq(additional_options='', interface='veth-peer', ipv4_range='192.168.5.10,192.168.5.200', ipv4_router='192.168.5.1', ipv6_range='2600::10,2600::20', lease_time='1h'): 514 dnsmasq_command = f'dnsmasq -8 {dnsmasq_log_file} --log-queries=extra --log-dhcp --pid-file={dnsmasq_pid_file} --conf-file=/dev/null --bind-interfaces --interface={interface} --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile={dnsmasq_lease_file} --dhcp-option=26,1492 --dhcp-option=option:router,{ipv4_router} --port=0 ' + additional_options 515 check_output(dnsmasq_command) 516 517def stop_by_pid_file(pid_file): 518 if os.path.exists(pid_file): 519 with open(pid_file, 'r') as f: 520 pid = f.read().rstrip(' \t\r\n\0') 521 os.kill(int(pid), signal.SIGTERM) 522 for _ in range(25): 523 try: 524 os.kill(int(pid), 0) 525 print(f"PID {pid} is still alive, waiting...") 526 time.sleep(.2) 527 except OSError as e: 528 if e.errno == errno.ESRCH: 529 break 530 print(f"Unexpected exception when waiting for {pid} to die: {e.errno}") 531 532 os.remove(pid_file) 533 534def stop_dnsmasq(): 535 stop_by_pid_file(dnsmasq_pid_file) 536 537def dump_dnsmasq_log_file(): 538 if os.path.exists(dnsmasq_log_file): 539 with open (dnsmasq_log_file) as in_file: 540 print(in_file.read()) 541 542def search_words_in_dnsmasq_log(words, show_all=False): 543 if os.path.exists(dnsmasq_log_file): 544 with open (dnsmasq_log_file) as in_file: 545 contents = in_file.read() 546 if show_all: 547 print(contents) 548 for line in contents.splitlines(): 549 if words in line: 550 in_file.close() 551 print("%s, %s" % (words, line)) 552 return True 553 return False 554 555def remove_dnsmasq_lease_file(): 556 if os.path.exists(dnsmasq_lease_file): 557 os.remove(dnsmasq_lease_file) 558 559def remove_dnsmasq_log_file(): 560 if os.path.exists(dnsmasq_log_file): 561 os.remove(dnsmasq_log_file) 562 563def start_isc_dhcpd(interface, conf_file, ip): 564 conf_file_path = os.path.join(networkd_ci_path, conf_file) 565 isc_dhcpd_command = f'dhcpd {ip} -cf {conf_file_path} -lf {isc_dhcpd_lease_file} -pf {isc_dhcpd_pid_file} {interface}' 566 Path(isc_dhcpd_lease_file).touch() 567 check_output(isc_dhcpd_command) 568 569def stop_isc_dhcpd(): 570 stop_by_pid_file(isc_dhcpd_pid_file) 571 if os.path.exists(isc_dhcpd_lease_file): 572 os.remove(isc_dhcpd_lease_file) 573 574def remove_networkd_state_files(): 575 if os.path.exists(os.path.join(networkd_runtime_directory, 'state')): 576 os.remove(os.path.join(networkd_runtime_directory, 'state')) 577 578def stop_networkd(show_logs=True, remove_state_files=True): 579 if show_logs: 580 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value') 581 check_output('systemctl stop systemd-networkd.socket') 582 check_output('systemctl stop systemd-networkd.service') 583 if show_logs: 584 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)) 585 if remove_state_files: 586 remove_networkd_state_files() 587 588def start_networkd(sleep_sec=0): 589 check_output('systemctl start systemd-networkd') 590 if sleep_sec > 0: 591 time.sleep(sleep_sec) 592 593def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True): 594 stop_networkd(show_logs, remove_state_files) 595 start_networkd(sleep_sec) 596 597class Utilities(): 598 # pylint: disable=no-member 599 600 def check_link_exists(self, link): 601 self.assertTrue(link_exists(link)) 602 603 def check_link_attr(self, *args): 604 self.assertEqual(read_link_attr(*args[:-1]), args[-1]) 605 606 def wait_activated(self, link, state='down', timeout=20, fail_assert=True): 607 # wait for the interface is activated. 608 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value') 609 needle = f'{link}: Bringing link {state}' 610 flag = state.upper() 611 for iteration in range(timeout+1): 612 if iteration != 0: 613 time.sleep(1) 614 if not link_exists(link): 615 continue 616 output = check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id) 617 if needle in output and flag in check_output(f'ip link show {link}'): 618 return True 619 if fail_assert: 620 self.fail(f'Timed out waiting for {link} activated.') 621 return False 622 623 def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True): 624 """Wait for the link to reach the specified operstate and/or setup state. 625 626 Specify None or '' for either operstate or setup_state to ignore that state. 627 This will recheck until the state conditions are met or the timeout expires. 628 629 If the link successfully matches the requested state, this returns True. 630 If this times out waiting for the link to match, the behavior depends on the 631 'fail_assert' parameter; if True, this causes a test assertion failure, 632 otherwise this returns False. The default is to cause assertion failure. 633 634 Note that this function matches on *exactly* the given operstate and setup_state. 635 To wait for a link to reach *or exceed* a given operstate, use wait_online(). 636 """ 637 if not operstate: 638 operstate = r'\S+' 639 if not setup_state: 640 setup_state = r'\S+' 641 642 for secs in range(setup_timeout + 1): 643 if secs != 0: 644 time.sleep(1) 645 if not link_exists(link): 646 continue 647 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env) 648 print(output) 649 if re.search(rf'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output): 650 return True 651 if fail_assert: 652 self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}') 653 return False 654 655 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5): 656 """Wait for the link(s) to reach the specified operstate and/or setup state. 657 658 This is similar to wait_operstate() but can be used for multiple links, 659 and it also calls systemd-networkd-wait-online to wait for the given operstate. 660 The operstate should be specified in the link name, like 'eth0:degraded'. 661 If just a link name is provided, wait-online's default operstate to wait for is degraded. 662 663 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the 664 'setup_timeout' controls the per-link timeout waiting for the setup_state. 665 666 Set 'bool_any' to True to wait for any (instead of all) of the given links. 667 If this is set, no setup_state checks are done. 668 669 Set 'ipv4' or 'ipv6' to True to wait for IPv4 address or IPv6 address, respectively, of each of the given links. 670 This is applied only for the operational state 'degraded' or above. 671 672 Note that this function waits for the link(s) to reach *or exceed* the given operstate. 673 However, the setup_state, if specified, must be matched *exactly*. 674 675 This returns if the link(s) reached the requested operstate/setup_state; otherwise it 676 raises CalledProcessError or fails test assertion. 677 """ 678 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate] 679 if bool_any: 680 args += ['--any'] 681 if ipv4: 682 args += ['--ipv4'] 683 if ipv6: 684 args += ['--ipv6'] 685 try: 686 check_output(*args, env=env) 687 except subprocess.CalledProcessError: 688 for link in links_with_operstate: 689 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env) 690 print(output) 691 raise 692 if not bool_any and setup_state: 693 for link in links_with_operstate: 694 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout) 695 696 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100): 697 for i in range(timeout_sec): 698 if i > 0: 699 time.sleep(1) 700 output = check_output(f'ip {ipv} address show dev {link} scope {scope}') 701 if re.search(address_regex, output) and 'tentative' not in output: 702 break 703 704 self.assertRegex(output, address_regex) 705 706 def wait_address_dropped(self, link, address_regex, scope='global', ipv='', timeout_sec=100): 707 for i in range(timeout_sec): 708 if i > 0: 709 time.sleep(1) 710 output = check_output(f'ip {ipv} address show dev {link} scope {scope}') 711 if not re.search(address_regex, output): 712 break 713 714 self.assertNotRegex(output, address_regex) 715 716class NetworkctlTests(unittest.TestCase, Utilities): 717 718 links = [ 719 'dummy98', 720 'test1', 721 'veth99', 722 ] 723 724 units = [ 725 '11-dummy.netdev', 726 '11-dummy-mtu.netdev', 727 '11-dummy.network', 728 '12-dummy.netdev', 729 '12-dummy.link', 730 '25-address-static.network', 731 '25-veth.netdev', 732 '26-netdev-link-local-addressing-yes.network', 733 ] 734 735 def setUp(self): 736 remove_links(self.links) 737 stop_networkd(show_logs=False) 738 739 def tearDown(self): 740 remove_links(self.links) 741 remove_unit_from_networkd_path(self.units) 742 stop_networkd(show_logs=True) 743 744 @expectedFailureIfAlternativeNameIsNotAvailable() 745 def test_altname(self): 746 copy_unit_to_networkd_unit_path('26-netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link') 747 check_output('udevadm control --reload') 748 start_networkd() 749 self.wait_online(['dummy98:degraded']) 750 751 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) 752 self.assertRegex(output, 'hogehogehogehogehogehoge') 753 754 def test_reconfigure(self): 755 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev') 756 start_networkd() 757 self.wait_online(['dummy98:routable']) 758 759 output = check_output('ip -4 address show dev dummy98') 760 print(output) 761 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) 762 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) 763 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) 764 765 check_output('ip address del 10.1.2.3/16 dev dummy98') 766 check_output('ip address del 10.1.2.4/16 dev dummy98') 767 check_output('ip address del 10.2.2.4/16 dev dummy98') 768 769 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env) 770 self.wait_online(['dummy98:routable']) 771 772 output = check_output('ip -4 address show dev dummy98') 773 print(output) 774 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) 775 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) 776 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) 777 778 remove_unit_from_networkd_path(['25-address-static.network']) 779 780 check_output(*networkctl_cmd, 'reload', env=env) 781 self.wait_operstate('dummy98', 'degraded', setup_state='unmanaged') 782 783 output = check_output('ip -4 address show dev dummy98') 784 print(output) 785 self.assertNotIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) 786 self.assertNotIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) 787 self.assertNotIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) 788 789 copy_unit_to_networkd_unit_path('25-address-static.network') 790 check_output(*networkctl_cmd, 'reload', env=env) 791 self.wait_online(['dummy98:routable']) 792 793 output = check_output('ip -4 address show dev dummy98') 794 print(output) 795 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) 796 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) 797 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) 798 799 def test_reload(self): 800 start_networkd(3) 801 802 copy_unit_to_networkd_unit_path('11-dummy.netdev') 803 check_output(*networkctl_cmd, 'reload', env=env) 804 self.wait_operstate('test1', 'off', setup_state='unmanaged') 805 806 copy_unit_to_networkd_unit_path('11-dummy.network') 807 check_output(*networkctl_cmd, 'reload', env=env) 808 self.wait_online(['test1:degraded']) 809 810 remove_unit_from_networkd_path(['11-dummy.network']) 811 check_output(*networkctl_cmd, 'reload', env=env) 812 self.wait_operstate('test1', 'degraded', setup_state='unmanaged') 813 814 remove_unit_from_networkd_path(['11-dummy.netdev']) 815 check_output(*networkctl_cmd, 'reload', env=env) 816 self.wait_operstate('test1', 'degraded', setup_state='unmanaged') 817 818 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') 819 check_output(*networkctl_cmd, 'reload', env=env) 820 self.wait_operstate('test1', 'degraded') 821 822 def test_glob(self): 823 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') 824 start_networkd() 825 826 self.wait_online(['test1:degraded']) 827 828 output = check_output(*networkctl_cmd, 'list', env=env) 829 self.assertRegex(output, '1 lo ') 830 self.assertRegex(output, 'test1') 831 832 output = check_output(*networkctl_cmd, 'list', 'test1', env=env) 833 self.assertNotRegex(output, '1 lo ') 834 self.assertRegex(output, 'test1') 835 836 output = check_output(*networkctl_cmd, 'list', 'te*', env=env) 837 self.assertNotRegex(output, '1 lo ') 838 self.assertRegex(output, 'test1') 839 840 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env) 841 self.assertNotRegex(output, '1: lo ') 842 self.assertRegex(output, 'test1') 843 844 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env) 845 self.assertNotRegex(output, '1: lo ') 846 self.assertRegex(output, 'test1') 847 848 def test_mtu(self): 849 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network') 850 start_networkd() 851 852 self.wait_online(['test1:degraded']) 853 854 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 855 self.assertRegex(output, 'MTU: 1600') 856 857 def test_type(self): 858 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') 859 start_networkd() 860 self.wait_online(['test1:degraded']) 861 862 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 863 print(output) 864 self.assertRegex(output, 'Type: ether') 865 866 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env) 867 print(output) 868 self.assertRegex(output, 'Type: loopback') 869 870 @expectedFailureIfLinkFileFieldIsNotSet() 871 def test_udev_link_file(self): 872 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') 873 start_networkd() 874 self.wait_online(['test1:degraded']) 875 876 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 877 print(output) 878 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link') 879 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network') 880 881 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env) 882 print(output) 883 self.assertRegex(output, r'Link File: n/a') 884 self.assertRegex(output, r'Network File: n/a') 885 886 def test_delete_links(self): 887 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network', 888 '25-veth.netdev', '26-netdev-link-local-addressing-yes.network') 889 start_networkd() 890 891 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded']) 892 893 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env) 894 self.assertFalse(link_exists('test1')) 895 self.assertFalse(link_exists('veth99')) 896 self.assertFalse(link_exists('veth-peer')) 897 898class NetworkdNetDevTests(unittest.TestCase, Utilities): 899 900 links_remove_earlier = [ 901 'xfrm98', 902 'xfrm99', 903 ] 904 905 links = [ 906 '6rdtun99', 907 'bareudp99', 908 'batadv99', 909 'bond98', 910 'bond99', 911 'bridge99', 912 'dropin-test', 913 'dummy98', 914 'erspan98', 915 'erspan99', 916 'geneve99', 917 'gretap96', 918 'gretap98', 919 'gretap99', 920 'gretun96', 921 'gretun97', 922 'gretun98', 923 'gretun99', 924 'ifb99', 925 'ip6gretap98', 926 'ip6gretap99', 927 'ip6gretun96', 928 'ip6gretun97', 929 'ip6gretun98', 930 'ip6gretun99', 931 'ip6tnl-external', 932 'ip6tnl-slaac', 933 'ip6tnl97', 934 'ip6tnl98', 935 'ip6tnl99', 936 'ipiptun96', 937 'ipiptun97', 938 'ipiptun98', 939 'ipiptun99', 940 'ipvlan99', 941 'ipvtap99', 942 'isataptun99', 943 'macvlan99', 944 'macvtap99', 945 'nlmon99', 946 'sittun96', 947 'sittun97', 948 'sittun98', 949 'sittun99', 950 'tap99', 951 'test1', 952 'tun99', 953 'vcan99', 954 'veth-mtu', 955 'veth99', 956 'vlan99', 957 'vrf99', 958 'vti6tun97', 959 'vti6tun98', 960 'vti6tun99', 961 'vtitun96', 962 'vtitun97', 963 'vtitun98', 964 'vtitun99', 965 'vxcan99', 966 'vxlan-slaac', 967 'vxlan97', 968 'vxlan98', 969 'vxlan99', 970 'wg97', 971 'wg98', 972 'wg99', 973 ] 974 975 units = [ 976 '10-dropin-test.netdev', 977 '11-dummy.netdev', 978 '11-dummy.network', 979 '12-dummy.netdev', 980 '13-not-match-udev-property.network', 981 '14-match-udev-property.network', 982 '15-name-conflict-test.netdev', 983 '21-macvlan.netdev', 984 '21-macvtap.netdev', 985 '21-vlan-test1.network', 986 '21-vlan.netdev', 987 '21-vlan.network', 988 '25-6rd-tunnel.netdev', 989 '25-bareudp.netdev', 990 '25-batadv.netdev', 991 '25-bond.netdev', 992 '25-bond-balanced-tlb.netdev', 993 '25-bridge.netdev', 994 '25-bridge-configure-without-carrier.network', 995 '25-bridge.network', 996 '25-erspan-tunnel-local-any.netdev', 997 '25-erspan-tunnel.netdev', 998 '25-fou-gretap.netdev', 999 '25-fou-gre.netdev', 1000 '25-fou-ipip.netdev', 1001 '25-fou-ipproto-gre.netdev', 1002 '25-fou-ipproto-ipip.netdev', 1003 '25-fou-sit.netdev', 1004 '25-geneve.netdev', 1005 '25-gretap-tunnel-local-any.netdev', 1006 '25-gretap-tunnel.netdev', 1007 '25-gre-tunnel-any-any.netdev', 1008 '25-gre-tunnel-local-any.netdev', 1009 '25-gre-tunnel-remote-any.netdev', 1010 '25-gre-tunnel.netdev', 1011 '25-ifb.netdev', 1012 '25-ip6gretap-tunnel-local-any.netdev', 1013 '25-ip6gretap-tunnel.netdev', 1014 '25-ip6gre-tunnel-any-any.netdev', 1015 '25-ip6gre-tunnel-local-any.netdev', 1016 '25-ip6gre-tunnel-remote-any.netdev', 1017 '25-ip6gre-tunnel.netdev', 1018 '25-ip6tnl-tunnel-external.netdev', 1019 '25-ip6tnl-tunnel-local-any.netdev', 1020 '25-ip6tnl-tunnel-local-slaac.netdev', 1021 '25-ip6tnl-tunnel-local-slaac.network', 1022 '25-ip6tnl-tunnel-remote-any.netdev', 1023 '25-ip6tnl-tunnel.netdev', 1024 '25-ipip-tunnel-any-any.netdev', 1025 '25-ipip-tunnel-independent.netdev', 1026 '25-ipip-tunnel-independent-loopback.netdev', 1027 '25-ipip-tunnel-local-any.netdev', 1028 '25-ipip-tunnel-remote-any.netdev', 1029 '25-ipip-tunnel.netdev', 1030 '25-ipvlan.netdev', 1031 '25-ipvtap.netdev', 1032 '25-isatap-tunnel.netdev', 1033 '25-macsec.key', 1034 '25-macsec.netdev', 1035 '25-macsec.network', 1036 '25-nlmon.netdev', 1037 '25-sit-tunnel-any-any.netdev', 1038 '25-sit-tunnel-local-any.netdev', 1039 '25-sit-tunnel-remote-any.netdev', 1040 '25-sit-tunnel.netdev', 1041 '25-tap.netdev', 1042 '25-tun.netdev', 1043 '25-tunnel-any-any.network', 1044 '25-tunnel-local-any.network', 1045 '25-tunnel-remote-any.network', 1046 '25-tunnel.network', 1047 '25-vcan.netdev', 1048 '25-veth-mtu.netdev', 1049 '25-veth.netdev', 1050 '25-vrf.netdev', 1051 '25-vti6-tunnel-any-any.netdev', 1052 '25-vti6-tunnel-local-any.netdev', 1053 '25-vti6-tunnel-remote-any.netdev', 1054 '25-vti6-tunnel.netdev', 1055 '25-vti-tunnel-any-any.netdev', 1056 '25-vti-tunnel-local-any.netdev', 1057 '25-vti-tunnel-remote-any.netdev', 1058 '25-vti-tunnel.netdev', 1059 '25-vxcan.netdev', 1060 '25-vxlan-independent.netdev', 1061 '25-vxlan-ipv6.netdev', 1062 '25-vxlan-local-slaac.netdev', 1063 '25-vxlan-local-slaac.network', 1064 '25-vxlan-veth99.network', 1065 '25-vxlan.netdev', 1066 '25-wireguard-23-peers.netdev', 1067 '25-wireguard-23-peers.network', 1068 '25-wireguard-no-peer.netdev', 1069 '25-wireguard-no-peer.network', 1070 '25-wireguard-preshared-key.txt', 1071 '25-wireguard-private-key.txt', 1072 '25-wireguard.netdev', 1073 '25-wireguard.network', 1074 '25-xfrm.netdev', 1075 '25-xfrm-independent.netdev', 1076 '25-6rd.network', 1077 '25-erspan.network', 1078 '25-gre.network', 1079 '25-gretap.network', 1080 '25-gretun.network', 1081 '25-ip6gretap.network', 1082 '25-ip6gretun.network', 1083 '25-ip6tnl-slaac.network', 1084 '25-ip6tnl.network', 1085 '25-ipip.network', 1086 '25-ipv6-prefix.network', 1087 '25-ipvlan.network', 1088 '25-ipvtap.network', 1089 '25-isatap.network', 1090 '26-macsec.network', 1091 '25-macvlan.network', 1092 '25-macvtap.network', 1093 '26-netdev-link-local-addressing-yes.network', 1094 '25-sit.network', 1095 '25-vti6.network', 1096 '25-vti.network', 1097 '25-vxlan-ipv6.network', 1098 '25-vxlan-test1.network', 1099 '25-vxlan.network', 1100 '25-xfrm.network', 1101 ] 1102 1103 fou_ports = [ 1104 '55555', 1105 '55556'] 1106 1107 def setUp(self): 1108 remove_fou_ports(self.fou_ports) 1109 remove_links(self.links_remove_earlier) 1110 remove_links(self.links) 1111 stop_networkd(show_logs=False) 1112 1113 def tearDown(self): 1114 remove_fou_ports(self.fou_ports) 1115 remove_links(self.links_remove_earlier) 1116 remove_links(self.links) 1117 remove_unit_from_networkd_path(self.units) 1118 stop_networkd(show_logs=True) 1119 1120 def test_dropin_and_name_conflict(self): 1121 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev') 1122 start_networkd() 1123 1124 self.wait_online(['dropin-test:off'], setup_state='unmanaged') 1125 1126 output = check_output('ip link show dropin-test') 1127 print(output) 1128 self.assertRegex(output, '00:50:56:c0:00:28') 1129 1130 def test_match_udev_property(self): 1131 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network') 1132 start_networkd() 1133 self.wait_online(['dummy98:routable']) 1134 1135 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) 1136 print(output) 1137 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property') 1138 1139 def test_wait_online_any(self): 1140 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network') 1141 start_networkd() 1142 1143 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True) 1144 1145 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring') 1146 self.wait_operstate('test1', 'degraded') 1147 1148 @expectedFailureIfModuleIsNotAvailable('bareudp') 1149 def test_bareudp(self): 1150 copy_unit_to_networkd_unit_path('25-bareudp.netdev', '26-netdev-link-local-addressing-yes.network') 1151 start_networkd() 1152 1153 self.wait_online(['bareudp99:degraded']) 1154 1155 output = check_output('ip -d link show bareudp99') 1156 print(output) 1157 self.assertRegex(output, 'dstport 1000 ') 1158 self.assertRegex(output, 'ethertype ip ') 1159 1160 @expectedFailureIfModuleIsNotAvailable('batman-adv') 1161 def test_batadv(self): 1162 copy_unit_to_networkd_unit_path('25-batadv.netdev', '26-netdev-link-local-addressing-yes.network') 1163 start_networkd() 1164 1165 self.wait_online(['batadv99:degraded']) 1166 1167 output = check_output('ip -d link show batadv99') 1168 print(output) 1169 self.assertRegex(output, 'batadv') 1170 1171 def test_bridge(self): 1172 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network') 1173 start_networkd() 1174 1175 self.wait_online(['bridge99:no-carrier']) 1176 1177 tick = os.sysconf('SC_CLK_TCK') 1178 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick)) 1179 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick)) 1180 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick)) 1181 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick)) 1182 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority'))) 1183 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier'))) 1184 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping'))) 1185 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state'))) 1186 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version'))) 1187 1188 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env) 1189 print(output) 1190 self.assertRegex(output, 'Priority: 9') 1191 self.assertRegex(output, 'STP: yes') 1192 self.assertRegex(output, 'Multicast IGMP Version: 3') 1193 1194 output = check_output('ip -d link show bridge99') 1195 print(output) 1196 self.assertIn('vlan_filtering 1 ', output) 1197 self.assertIn('vlan_protocol 802.1ad ', output) 1198 self.assertIn('vlan_default_pvid 9 ', output) 1199 1200 def test_bond(self): 1201 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev') 1202 start_networkd() 1203 1204 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged') 1205 1206 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode')) 1207 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy')) 1208 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon')) 1209 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate')) 1210 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay')) 1211 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay')) 1212 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp')) 1213 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links')) 1214 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio')) 1215 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key')) 1216 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system')) 1217 1218 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode')) 1219 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb')) 1220 1221 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bond99', env=env) 1222 print(output) 1223 self.assertIn('Mode: 802.3ad', output) 1224 self.assertIn('Miimon: 1s', output) 1225 self.assertIn('Updelay: 2s', output) 1226 self.assertIn('Downdelay: 2s', output) 1227 1228 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bond98', env=env) 1229 print(output) 1230 self.assertIn('Mode: balance-tlb', output) 1231 1232 def test_vlan(self): 1233 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', 1234 '21-vlan.network', '21-vlan-test1.network') 1235 start_networkd() 1236 1237 self.wait_online(['test1:degraded', 'vlan99:routable']) 1238 1239 output = check_output('ip -d link show test1') 1240 print(output) 1241 self.assertRegex(output, ' mtu 2000 ') 1242 1243 output = check_output('ip -d link show vlan99') 1244 print(output) 1245 self.assertRegex(output, ' mtu 2000 ') 1246 self.assertRegex(output, 'REORDER_HDR') 1247 self.assertRegex(output, 'LOOSE_BINDING') 1248 self.assertRegex(output, 'GVRP') 1249 self.assertRegex(output, 'MVRP') 1250 self.assertRegex(output, ' id 99 ') 1251 1252 output = check_output('ip -4 address show dev test1') 1253 print(output) 1254 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1') 1255 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1') 1256 1257 output = check_output('ip -4 address show dev vlan99') 1258 print(output) 1259 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99') 1260 1261 def test_macvtap(self): 1262 for mode in ['private', 'vepa', 'bridge', 'passthru']: 1263 with self.subTest(mode=mode): 1264 if mode != 'private': 1265 self.tearDown() 1266 copy_unit_to_networkd_unit_path('21-macvtap.netdev', '26-netdev-link-local-addressing-yes.network', 1267 '11-dummy.netdev', '25-macvtap.network') 1268 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f: 1269 f.write('[MACVTAP]\nMode=' + mode) 1270 start_networkd() 1271 1272 self.wait_online(['macvtap99:degraded', 1273 'test1:carrier' if mode == 'passthru' else 'test1:degraded']) 1274 1275 output = check_output('ip -d link show macvtap99') 1276 print(output) 1277 self.assertRegex(output, 'macvtap mode ' + mode + ' ') 1278 1279 def test_macvlan(self): 1280 for mode in ['private', 'vepa', 'bridge', 'passthru']: 1281 with self.subTest(mode=mode): 1282 if mode != 'private': 1283 self.tearDown() 1284 copy_unit_to_networkd_unit_path('21-macvlan.netdev', '26-netdev-link-local-addressing-yes.network', 1285 '11-dummy.netdev', '25-macvlan.network') 1286 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f: 1287 f.write('[MACVLAN]\nMode=' + mode) 1288 start_networkd() 1289 1290 self.wait_online(['macvlan99:degraded', 1291 'test1:carrier' if mode == 'passthru' else 'test1:degraded']) 1292 1293 output = check_output('ip -d link show test1') 1294 print(output) 1295 self.assertRegex(output, ' mtu 2000 ') 1296 1297 output = check_output('ip -d link show macvlan99') 1298 print(output) 1299 self.assertRegex(output, ' mtu 2000 ') 1300 self.assertRegex(output, 'macvlan mode ' + mode + ' ') 1301 1302 rc = call("ip link del test1") 1303 self.assertEqual(rc, 0) 1304 time.sleep(1) 1305 1306 rc = call("ip link add test1 type dummy") 1307 self.assertEqual(rc, 0) 1308 time.sleep(1) 1309 1310 self.wait_online(['macvlan99:degraded', 1311 'test1:carrier' if mode == 'passthru' else 'test1:degraded']) 1312 1313 output = check_output('ip -d link show test1') 1314 print(output) 1315 self.assertRegex(output, ' mtu 2000 ') 1316 1317 output = check_output('ip -d link show macvlan99') 1318 print(output) 1319 self.assertRegex(output, ' mtu 2000 ') 1320 self.assertRegex(output, 'macvlan mode ' + mode + ' ') 1321 1322 @expectedFailureIfModuleIsNotAvailable('ipvlan') 1323 def test_ipvlan(self): 1324 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: 1325 with self.subTest(mode=mode, flag=flag): 1326 if mode != 'L2': 1327 self.tearDown() 1328 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '26-netdev-link-local-addressing-yes.network', 1329 '11-dummy.netdev', '25-ipvlan.network') 1330 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f: 1331 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag) 1332 1333 start_networkd() 1334 self.wait_online(['ipvlan99:degraded', 'test1:degraded']) 1335 1336 output = check_output('ip -d link show ipvlan99') 1337 print(output) 1338 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag) 1339 1340 @expectedFailureIfModuleIsNotAvailable('ipvtap') 1341 def test_ipvtap(self): 1342 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: 1343 with self.subTest(mode=mode, flag=flag): 1344 if mode != 'L2': 1345 self.tearDown() 1346 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', '26-netdev-link-local-addressing-yes.network', 1347 '11-dummy.netdev', '25-ipvtap.network') 1348 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f: 1349 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag) 1350 1351 start_networkd() 1352 self.wait_online(['ipvtap99:degraded', 'test1:degraded']) 1353 1354 output = check_output('ip -d link show ipvtap99') 1355 print(output) 1356 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag) 1357 1358 def test_veth(self): 1359 copy_unit_to_networkd_unit_path('25-veth.netdev', '26-netdev-link-local-addressing-yes.network', 1360 '25-veth-mtu.netdev') 1361 start_networkd() 1362 1363 self.wait_online(['veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded']) 1364 1365 output = check_output('ip -d link show veth99') 1366 print(output) 1367 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc') 1368 output = check_output('ip -d link show veth-peer') 1369 print(output) 1370 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd') 1371 1372 output = check_output('ip -d link show veth-mtu') 1373 print(output) 1374 self.assertRegex(output, 'link/ether 12:34:56:78:9a:be') 1375 self.assertRegex(output, 'mtu 1800') 1376 output = check_output('ip -d link show veth-mtu-peer') 1377 print(output) 1378 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bf') 1379 self.assertRegex(output, 'mtu 1800') 1380 1381 def test_tun(self): 1382 copy_unit_to_networkd_unit_path('25-tun.netdev') 1383 start_networkd() 1384 1385 self.wait_online(['tun99:off'], setup_state='unmanaged') 1386 1387 output = check_output('ip -d link show tun99') 1388 print(output) 1389 # Old ip command does not support IFF_ flags 1390 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ') 1391 1392 def test_tap(self): 1393 copy_unit_to_networkd_unit_path('25-tap.netdev') 1394 start_networkd() 1395 1396 self.wait_online(['tap99:off'], setup_state='unmanaged') 1397 1398 output = check_output('ip -d link show tap99') 1399 print(output) 1400 # Old ip command does not support IFF_ flags 1401 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ') 1402 1403 @expectedFailureIfModuleIsNotAvailable('vrf') 1404 def test_vrf(self): 1405 copy_unit_to_networkd_unit_path('25-vrf.netdev', '26-netdev-link-local-addressing-yes.network') 1406 start_networkd() 1407 1408 self.wait_online(['vrf99:carrier']) 1409 1410 @expectedFailureIfModuleIsNotAvailable('vcan') 1411 def test_vcan(self): 1412 copy_unit_to_networkd_unit_path('25-vcan.netdev', '26-netdev-link-local-addressing-yes.network') 1413 start_networkd() 1414 1415 self.wait_online(['vcan99:carrier']) 1416 1417 @expectedFailureIfModuleIsNotAvailable('vxcan') 1418 def test_vxcan(self): 1419 copy_unit_to_networkd_unit_path('25-vxcan.netdev', '26-netdev-link-local-addressing-yes.network') 1420 start_networkd() 1421 1422 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier']) 1423 1424 @expectedFailureIfModuleIsNotAvailable('wireguard') 1425 def test_wireguard(self): 1426 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network', 1427 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network', 1428 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt', 1429 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network') 1430 start_networkd() 1431 self.wait_online(['wg99:routable', 'wg98:routable', 'wg97:carrier']) 1432 1433 output = check_output('ip -4 address show dev wg99') 1434 print(output) 1435 self.assertIn('inet 192.168.124.1/24 scope global wg99', output) 1436 1437 output = check_output('ip -4 address show dev wg98') 1438 print(output) 1439 self.assertIn('inet 192.168.123.123/24 scope global wg98', output) 1440 1441 output = check_output('ip -6 address show dev wg98') 1442 print(output) 1443 self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output) 1444 1445 output = check_output('ip -4 route show dev wg99 table 1234') 1446 print(output) 1447 self.assertIn('192.168.26.0/24 proto static metric 123', output) 1448 1449 output = check_output('ip -6 route show dev wg99 table 1234') 1450 print(output) 1451 self.assertIn('fd31:bf08:57cb::/48 proto static metric 123 pref medium', output) 1452 1453 output = check_output('ip -6 route show dev wg98 table 1234') 1454 print(output) 1455 self.assertIn('fd8d:4d6d:3ccb:500:c79:2339:edce:ece1 proto static metric 123 pref medium', output) 1456 self.assertIn('fd8d:4d6d:3ccb:500:1dbf:ca8a:32d3:dd81 proto static metric 123 pref medium', output) 1457 self.assertIn('fd8d:4d6d:3ccb:500:1e54:1415:35d0:a47c proto static metric 123 pref medium', output) 1458 self.assertIn('fd8d:4d6d:3ccb:500:270d:b5dd:4a3f:8909 proto static metric 123 pref medium', output) 1459 self.assertIn('fd8d:4d6d:3ccb:500:5660:679d:3532:94d8 proto static metric 123 pref medium', output) 1460 self.assertIn('fd8d:4d6d:3ccb:500:6825:573f:30f3:9472 proto static metric 123 pref medium', output) 1461 self.assertIn('fd8d:4d6d:3ccb:500:6f2e:6888:c6fd:dfb9 proto static metric 123 pref medium', output) 1462 self.assertIn('fd8d:4d6d:3ccb:500:8d4d:bab:7280:a09a proto static metric 123 pref medium', output) 1463 self.assertIn('fd8d:4d6d:3ccb:500:900c:d437:ec27:8822 proto static metric 123 pref medium', output) 1464 self.assertIn('fd8d:4d6d:3ccb:500:9742:9931:5217:18d5 proto static metric 123 pref medium', output) 1465 self.assertIn('fd8d:4d6d:3ccb:500:9c11:d820:2e96:9be0 proto static metric 123 pref medium', output) 1466 self.assertIn('fd8d:4d6d:3ccb:500:a072:80da:de4f:add1 proto static metric 123 pref medium', output) 1467 self.assertIn('fd8d:4d6d:3ccb:500:a3f3:df38:19b0:721 proto static metric 123 pref medium', output) 1468 self.assertIn('fd8d:4d6d:3ccb:500:a94b:cd6a:a32d:90e6 proto static metric 123 pref medium', output) 1469 self.assertIn('fd8d:4d6d:3ccb:500:b39c:9cdc:755a:ead3 proto static metric 123 pref medium', output) 1470 self.assertIn('fd8d:4d6d:3ccb:500:b684:4f81:2e3e:132e proto static metric 123 pref medium', output) 1471 self.assertIn('fd8d:4d6d:3ccb:500:bad5:495d:8e9c:3427 proto static metric 123 pref medium', output) 1472 self.assertIn('fd8d:4d6d:3ccb:500:bfe5:c3c3:5d77:fcb proto static metric 123 pref medium', output) 1473 self.assertIn('fd8d:4d6d:3ccb:500:c624:6bf7:4c09:3b59 proto static metric 123 pref medium', output) 1474 self.assertIn('fd8d:4d6d:3ccb:500:d4f9:5dc:9296:a1a proto static metric 123 pref medium', output) 1475 self.assertIn('fd8d:4d6d:3ccb:500:dcdd:d33b:90c9:6088 proto static metric 123 pref medium', output) 1476 self.assertIn('fd8d:4d6d:3ccb:500:e2e1:ae15:103f:f376 proto static metric 123 pref medium', output) 1477 self.assertIn('fd8d:4d6d:3ccb:500:f349:c4f0:10c1:6b4 proto static metric 123 pref medium', output) 1478 self.assertIn('fd8d:4d6d:3ccb:c79:2339:edce::/96 proto static metric 123 pref medium', output) 1479 self.assertIn('fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 proto static metric 123 pref medium', output) 1480 self.assertIn('fd8d:4d6d:3ccb:1e54:1415:35d0::/96 proto static metric 123 pref medium', output) 1481 self.assertIn('fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 proto static metric 123 pref medium', output) 1482 self.assertIn('fd8d:4d6d:3ccb:5660:679d:3532::/96 proto static metric 123 pref medium', output) 1483 self.assertIn('fd8d:4d6d:3ccb:6825:573f:30f3::/96 proto static metric 123 pref medium', output) 1484 self.assertIn('fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 proto static metric 123 pref medium', output) 1485 self.assertIn('fd8d:4d6d:3ccb:8d4d:bab:7280::/96 proto static metric 123 pref medium', output) 1486 self.assertIn('fd8d:4d6d:3ccb:900c:d437:ec27::/96 proto static metric 123 pref medium', output) 1487 self.assertIn('fd8d:4d6d:3ccb:9742:9931:5217::/96 proto static metric 123 pref medium', output) 1488 self.assertIn('fd8d:4d6d:3ccb:9c11:d820:2e96::/96 proto static metric 123 pref medium', output) 1489 self.assertIn('fd8d:4d6d:3ccb:a072:80da:de4f::/96 proto static metric 123 pref medium', output) 1490 self.assertIn('fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 proto static metric 123 pref medium', output) 1491 self.assertIn('fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 proto static metric 123 pref medium', output) 1492 self.assertIn('fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 proto static metric 123 pref medium', output) 1493 self.assertIn('fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 proto static metric 123 pref medium', output) 1494 self.assertIn('fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 proto static metric 123 pref medium', output) 1495 self.assertIn('fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 proto static metric 123 pref medium', output) 1496 self.assertIn('fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 proto static metric 123 pref medium', output) 1497 self.assertIn('fd8d:4d6d:3ccb:d4f9:5dc:9296::/96 proto static metric 123 pref medium', output) 1498 self.assertIn('fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 proto static metric 123 pref medium', output) 1499 self.assertIn('fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 proto static metric 123 pref medium', output) 1500 self.assertIn('fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 proto static metric 123 pref medium', output) 1501 1502 if shutil.which('wg'): 1503 call('wg') 1504 1505 output = check_output('wg show wg99 listen-port') 1506 self.assertEqual(output, '51820') 1507 output = check_output('wg show wg99 fwmark') 1508 self.assertEqual(output, '0x4d2') 1509 output = check_output('wg show wg99 private-key') 1510 self.assertEqual(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=') 1511 output = check_output('wg show wg99 allowed-ips') 1512 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t192.168.124.3/32', output) 1513 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t192.168.124.2/32', output) 1514 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128', output) 1515 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48', output) 1516 output = check_output('wg show wg99 persistent-keepalive') 1517 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\toff', output) 1518 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\toff', output) 1519 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\toff', output) 1520 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20', output) 1521 output = check_output('wg show wg99 endpoints') 1522 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t(none)', output) 1523 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t(none)', output) 1524 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\t(none)', output) 1525 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820', output) 1526 output = check_output('wg show wg99 preshared-keys') 1527 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t6Fsg8XN0DE6aPQgAX4r2oazEYJOGqyHUz3QRH/jCB+I=', output) 1528 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\tit7nd33chCT/tKT2ZZWfYyp43Zs+6oif72hexnSNMqA=', output) 1529 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tcPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=', output) 1530 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\tIIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=', output) 1531 1532 output = check_output('wg show wg98 private-key') 1533 self.assertEqual(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=') 1534 1535 output = check_output('wg show wg97 listen-port') 1536 self.assertEqual(output, '51821') 1537 output = check_output('wg show wg97 fwmark') 1538 self.assertEqual(output, '0x4d3') 1539 1540 def test_geneve(self): 1541 copy_unit_to_networkd_unit_path('25-geneve.netdev', '26-netdev-link-local-addressing-yes.network') 1542 start_networkd() 1543 1544 self.wait_online(['geneve99:degraded']) 1545 1546 output = check_output('ip -d link show geneve99') 1547 print(output) 1548 self.assertRegex(output, '192.168.22.1') 1549 self.assertRegex(output, '6082') 1550 self.assertRegex(output, 'udpcsum') 1551 self.assertRegex(output, 'udp6zerocsumrx') 1552 1553 def test_ipip_tunnel(self): 1554 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip.network', 1555 '25-ipip-tunnel.netdev', '25-tunnel.network', 1556 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1557 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1558 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network') 1559 start_networkd() 1560 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded']) 1561 1562 output = check_output('ip -d link show ipiptun99') 1563 print(output) 1564 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98') 1565 output = check_output('ip -d link show ipiptun98') 1566 print(output) 1567 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98') 1568 output = check_output('ip -d link show ipiptun97') 1569 print(output) 1570 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98') 1571 output = check_output('ip -d link show ipiptun96') 1572 print(output) 1573 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98') 1574 1575 def test_gre_tunnel(self): 1576 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretun.network', 1577 '25-gre-tunnel.netdev', '25-tunnel.network', 1578 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1579 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1580 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network') 1581 start_networkd() 1582 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded']) 1583 1584 output = check_output('ip -d link show gretun99') 1585 print(output) 1586 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98') 1587 self.assertRegex(output, 'ikey 1.2.3.103') 1588 self.assertRegex(output, 'okey 1.2.4.103') 1589 self.assertRegex(output, 'iseq') 1590 self.assertRegex(output, 'oseq') 1591 output = check_output('ip -d link show gretun98') 1592 print(output) 1593 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98') 1594 self.assertRegex(output, 'ikey 0.0.0.104') 1595 self.assertRegex(output, 'okey 0.0.0.104') 1596 self.assertNotRegex(output, 'iseq') 1597 self.assertNotRegex(output, 'oseq') 1598 output = check_output('ip -d link show gretun97') 1599 print(output) 1600 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98') 1601 self.assertRegex(output, 'ikey 0.0.0.105') 1602 self.assertRegex(output, 'okey 0.0.0.105') 1603 self.assertNotRegex(output, 'iseq') 1604 self.assertNotRegex(output, 'oseq') 1605 output = check_output('ip -d link show gretun96') 1606 print(output) 1607 self.assertRegex(output, 'gre remote any local any dev dummy98') 1608 self.assertRegex(output, 'ikey 0.0.0.106') 1609 self.assertRegex(output, 'okey 0.0.0.106') 1610 self.assertNotRegex(output, 'iseq') 1611 self.assertNotRegex(output, 'oseq') 1612 1613 def test_ip6gre_tunnel(self): 1614 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretun.network', 1615 '25-ip6gre-tunnel.netdev', '25-tunnel.network', 1616 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1617 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1618 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network') 1619 start_networkd(5) 1620 1621 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here. 1622 1623 self.check_link_exists('dummy98') 1624 self.check_link_exists('ip6gretun99') 1625 self.check_link_exists('ip6gretun98') 1626 self.check_link_exists('ip6gretun97') 1627 self.check_link_exists('ip6gretun96') 1628 1629 output = check_output('ip -d link show ip6gretun99') 1630 print(output) 1631 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') 1632 output = check_output('ip -d link show ip6gretun98') 1633 print(output) 1634 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98') 1635 output = check_output('ip -d link show ip6gretun97') 1636 print(output) 1637 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98') 1638 output = check_output('ip -d link show ip6gretun96') 1639 print(output) 1640 self.assertRegex(output, 'ip6gre remote any local any dev dummy98') 1641 1642 def test_gretap_tunnel(self): 1643 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap.network', 1644 '25-gretap-tunnel.netdev', '25-tunnel.network', 1645 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') 1646 start_networkd() 1647 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded']) 1648 1649 output = check_output('ip -d link show gretap99') 1650 print(output) 1651 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98') 1652 self.assertRegex(output, 'ikey 0.0.0.106') 1653 self.assertRegex(output, 'okey 0.0.0.106') 1654 self.assertRegex(output, 'iseq') 1655 self.assertRegex(output, 'oseq') 1656 output = check_output('ip -d link show gretap98') 1657 print(output) 1658 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98') 1659 self.assertRegex(output, 'ikey 0.0.0.107') 1660 self.assertRegex(output, 'okey 0.0.0.107') 1661 self.assertRegex(output, 'iseq') 1662 self.assertRegex(output, 'oseq') 1663 1664 def test_ip6gretap_tunnel(self): 1665 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretap.network', 1666 '25-ip6gretap-tunnel.netdev', '25-tunnel.network', 1667 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') 1668 start_networkd() 1669 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded']) 1670 1671 output = check_output('ip -d link show ip6gretap99') 1672 print(output) 1673 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') 1674 output = check_output('ip -d link show ip6gretap98') 1675 print(output) 1676 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98') 1677 1678 def test_vti_tunnel(self): 1679 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti.network', 1680 '25-vti-tunnel.netdev', '25-tunnel.network', 1681 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1682 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1683 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network') 1684 start_networkd() 1685 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded']) 1686 1687 output = check_output('ip -d link show vtitun99') 1688 print(output) 1689 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98') 1690 output = check_output('ip -d link show vtitun98') 1691 print(output) 1692 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98') 1693 output = check_output('ip -d link show vtitun97') 1694 print(output) 1695 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98') 1696 output = check_output('ip -d link show vtitun96') 1697 print(output) 1698 self.assertRegex(output, 'vti remote any local any dev dummy98') 1699 1700 def test_vti6_tunnel(self): 1701 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6.network', 1702 '25-vti6-tunnel.netdev', '25-tunnel.network', 1703 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1704 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network') 1705 start_networkd() 1706 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded']) 1707 1708 output = check_output('ip -d link show vti6tun99') 1709 print(output) 1710 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') 1711 output = check_output('ip -d link show vti6tun98') 1712 print(output) 1713 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98') 1714 output = check_output('ip -d link show vti6tun97') 1715 print(output) 1716 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') 1717 1718 def test_ip6tnl_tunnel(self): 1719 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl.network', 1720 '25-ip6tnl-tunnel.netdev', '25-tunnel.network', 1721 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1722 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1723 '25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network', 1724 '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network', 1725 '25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network') 1726 start_networkd() 1727 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 1728 'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded', 1729 'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded']) 1730 1731 output = check_output('ip -d link show ip6tnl99') 1732 print(output) 1733 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output) 1734 output = check_output('ip -d link show ip6tnl98') 1735 print(output) 1736 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98') 1737 output = check_output('ip -d link show ip6tnl97') 1738 print(output) 1739 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') 1740 output = check_output('ip -d link show ip6tnl-external') 1741 print(output) 1742 self.assertIn('ip6tnl-external@NONE:', output) 1743 self.assertIn('ip6tnl external ', output) 1744 output = check_output('ip -d link show ip6tnl-slaac') 1745 print(output) 1746 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output) 1747 1748 output = check_output('ip -6 address show veth99') 1749 print(output) 1750 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output) 1751 1752 output = check_output('ip -4 route show default') 1753 print(output) 1754 self.assertIn('default dev ip6tnl-slaac proto static', output) 1755 1756 def test_sit_tunnel(self): 1757 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit.network', 1758 '25-sit-tunnel.netdev', '25-tunnel.network', 1759 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network', 1760 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', 1761 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network') 1762 start_networkd() 1763 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded']) 1764 1765 output = check_output('ip -d link show sittun99') 1766 print(output) 1767 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98") 1768 output = check_output('ip -d link show sittun98') 1769 print(output) 1770 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98") 1771 output = check_output('ip -d link show sittun97') 1772 print(output) 1773 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98") 1774 output = check_output('ip -d link show sittun96') 1775 print(output) 1776 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98") 1777 1778 def test_isatap_tunnel(self): 1779 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap.network', 1780 '25-isatap-tunnel.netdev', '25-tunnel.network') 1781 start_networkd() 1782 self.wait_online(['isataptun99:routable', 'dummy98:degraded']) 1783 1784 output = check_output('ip -d link show isataptun99') 1785 print(output) 1786 self.assertRegex(output, "isatap ") 1787 1788 def test_6rd_tunnel(self): 1789 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd.network', 1790 '25-6rd-tunnel.netdev', '25-tunnel.network') 1791 start_networkd() 1792 self.wait_online(['sittun99:routable', 'dummy98:degraded']) 1793 1794 output = check_output('ip -d link show sittun99') 1795 print(output) 1796 self.assertRegex(output, '6rd-prefix 2602::/24') 1797 1798 @expectedFailureIfERSPANModuleIsNotAvailable() 1799 def test_erspan_tunnel(self): 1800 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network', 1801 '25-erspan-tunnel.netdev', '25-tunnel.network', 1802 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network') 1803 start_networkd() 1804 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) 1805 1806 output = check_output('ip -d link show erspan99') 1807 print(output) 1808 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200') 1809 self.assertRegex(output, 'ikey 0.0.0.101') 1810 self.assertRegex(output, 'okey 0.0.0.101') 1811 self.assertRegex(output, 'iseq') 1812 self.assertRegex(output, 'oseq') 1813 output = check_output('ip -d link show erspan98') 1814 print(output) 1815 self.assertRegex(output, 'erspan remote 172.16.1.100 local any') 1816 self.assertRegex(output, '102') 1817 self.assertRegex(output, 'ikey 0.0.0.102') 1818 self.assertRegex(output, 'okey 0.0.0.102') 1819 self.assertRegex(output, 'iseq') 1820 self.assertRegex(output, 'oseq') 1821 1822 def test_tunnel_independent(self): 1823 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network') 1824 start_networkd() 1825 1826 self.wait_online(['ipiptun99:carrier']) 1827 1828 def test_tunnel_independent_loopback(self): 1829 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network') 1830 start_networkd() 1831 1832 self.wait_online(['ipiptun99:carrier']) 1833 1834 @expectedFailureIfModuleIsNotAvailable('xfrm_interface') 1835 def test_xfrm(self): 1836 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-xfrm.network', 1837 '25-xfrm.netdev', '25-xfrm-independent.netdev', 1838 '26-netdev-link-local-addressing-yes.network') 1839 start_networkd() 1840 1841 self.wait_online(['dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded']) 1842 1843 output = check_output('ip -d link show dev xfrm98') 1844 print(output) 1845 self.assertIn('xfrm98@dummy98:', output) 1846 self.assertIn('xfrm if_id 0x98 ', output) 1847 1848 output = check_output('ip -d link show dev xfrm99') 1849 print(output) 1850 self.assertIn('xfrm99@lo:', output) 1851 self.assertIn('xfrm if_id 0x99 ', output) 1852 1853 @expectedFailureIfModuleIsNotAvailable('fou') 1854 def test_fou(self): 1855 # The following redundant check is necessary for CentOS CI. 1856 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated. 1857 self.assertTrue(is_module_available('fou')) 1858 1859 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev', 1860 '25-fou-ipip.netdev', '25-fou-sit.netdev', 1861 '25-fou-gre.netdev', '25-fou-gretap.netdev') 1862 start_networkd() 1863 1864 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged') 1865 1866 output = check_output('ip fou show') 1867 print(output) 1868 self.assertRegex(output, 'port 55555 ipproto 4') 1869 self.assertRegex(output, 'port 55556 ipproto 47') 1870 1871 output = check_output('ip -d link show ipiptun96') 1872 print(output) 1873 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555') 1874 output = check_output('ip -d link show sittun96') 1875 print(output) 1876 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555') 1877 output = check_output('ip -d link show gretun96') 1878 print(output) 1879 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556') 1880 output = check_output('ip -d link show gretap96') 1881 print(output) 1882 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556') 1883 1884 def test_vxlan(self): 1885 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-vxlan-test1.network', 1886 '25-vxlan.netdev', '25-vxlan.network', 1887 '25-vxlan-ipv6.netdev', '25-vxlan-ipv6.network', 1888 '25-vxlan-independent.netdev', '26-netdev-link-local-addressing-yes.network', 1889 '25-veth.netdev', '25-vxlan-veth99.network', '25-ipv6-prefix.network', 1890 '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network') 1891 start_networkd() 1892 1893 self.wait_online(['test1:degraded', 'veth99:routable', 'veth-peer:degraded', 1894 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded']) 1895 1896 output = check_output('ip -d link show vxlan99') 1897 print(output) 1898 self.assertIn('999', output) 1899 self.assertIn('5555', output) 1900 self.assertIn('l2miss', output) 1901 self.assertIn('l3miss', output) 1902 self.assertIn('udpcsum', output) 1903 self.assertIn('udp6zerocsumtx', output) 1904 self.assertIn('udp6zerocsumrx', output) 1905 self.assertIn('remcsumtx', output) 1906 self.assertIn('remcsumrx', output) 1907 self.assertIn('gbp', output) 1908 1909 output = check_output('bridge fdb show dev vxlan99') 1910 print(output) 1911 self.assertIn('00:11:22:33:44:55 dst 10.0.0.5 self permanent', output) 1912 self.assertIn('00:11:22:33:44:66 dst 10.0.0.6 self permanent', output) 1913 self.assertIn('00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent', output) 1914 1915 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env) 1916 print(output) 1917 self.assertIn('VNI: 999', output) 1918 self.assertIn('Destination Port: 5555', output) 1919 self.assertIn('Underlying Device: test1', output) 1920 1921 output = check_output('bridge fdb show dev vxlan97') 1922 print(output) 1923 self.assertIn('00:00:00:00:00:00 dst fe80::23b:d2ff:fe95:967f via test1 self permanent', output) 1924 self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output) 1925 self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output) 1926 1927 output = check_output('ip -d link show vxlan-slaac') 1928 print(output) 1929 self.assertIn('vxlan id 4831584 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output) 1930 1931 output = check_output('ip -6 address show veth99') 1932 print(output) 1933 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output) 1934 1935 @unittest.skip(reason="Causes kernel panic on recent kernels: https://bugzilla.kernel.org/show_bug.cgi?id=208315") 1936 def test_macsec(self): 1937 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key', 1938 '26-macsec.network', '12-dummy.netdev') 1939 start_networkd() 1940 1941 self.wait_online(['dummy98:degraded', 'macsec99:routable']) 1942 1943 output = check_output('ip -d link show macsec99') 1944 print(output) 1945 self.assertRegex(output, 'macsec99@dummy98') 1946 self.assertRegex(output, 'macsec sci [0-9a-f]*000b') 1947 self.assertRegex(output, 'encrypt on') 1948 1949 output = check_output('ip macsec show macsec99') 1950 print(output) 1951 self.assertRegex(output, 'encrypt on') 1952 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1') 1953 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000') 1954 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000') 1955 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on') 1956 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000') 1957 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000') 1958 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000') 1959 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000') 1960 self.assertNotRegex(output, 'key 02030405067080900000000000000000') 1961 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on') 1962 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000') 1963 1964 def test_nlmon(self): 1965 copy_unit_to_networkd_unit_path('25-nlmon.netdev', '26-netdev-link-local-addressing-yes.network') 1966 start_networkd() 1967 1968 self.wait_online(['nlmon99:carrier']) 1969 1970 @expectedFailureIfModuleIsNotAvailable('ifb') 1971 def test_ifb(self): 1972 copy_unit_to_networkd_unit_path('25-ifb.netdev', '26-netdev-link-local-addressing-yes.network') 1973 start_networkd() 1974 1975 self.wait_online(['ifb99:degraded']) 1976 1977class NetworkdL2TPTests(unittest.TestCase, Utilities): 1978 1979 links =[ 1980 'l2tp-ses1', 1981 'l2tp-ses2', 1982 'l2tp-ses3', 1983 'l2tp-ses4', 1984 'test1'] 1985 1986 units = [ 1987 '11-dummy.netdev', 1988 '25-l2tp-dummy.network', 1989 '25-l2tp.network', 1990 '25-l2tp-ip.netdev', 1991 '25-l2tp-udp.netdev'] 1992 1993 l2tp_tunnel_ids = [ '10' ] 1994 1995 def setUp(self): 1996 remove_l2tp_tunnels(self.l2tp_tunnel_ids) 1997 remove_links(self.links) 1998 stop_networkd(show_logs=False) 1999 2000 def tearDown(self): 2001 remove_l2tp_tunnels(self.l2tp_tunnel_ids) 2002 remove_links(self.links) 2003 remove_unit_from_networkd_path(self.units) 2004 stop_networkd(show_logs=True) 2005 2006 @expectedFailureIfModuleIsNotAvailable('l2tp_eth') 2007 def test_l2tp_udp(self): 2008 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', 2009 '25-l2tp-udp.netdev', '25-l2tp.network') 2010 start_networkd() 2011 2012 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded']) 2013 2014 output = check_output('ip l2tp show tunnel tunnel_id 10') 2015 print(output) 2016 self.assertRegex(output, "Tunnel 10, encap UDP") 2017 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101") 2018 self.assertRegex(output, "Peer tunnel 11") 2019 self.assertRegex(output, "UDP source / dest ports: 3000/4000") 2020 self.assertRegex(output, "UDP checksum: enabled") 2021 2022 output = check_output('ip l2tp show session tid 10 session_id 15') 2023 print(output) 2024 self.assertRegex(output, "Session 15 in tunnel 10") 2025 self.assertRegex(output, "Peer session 16, tunnel 11") 2026 self.assertRegex(output, "interface name: l2tp-ses1") 2027 2028 output = check_output('ip l2tp show session tid 10 session_id 17') 2029 print(output) 2030 self.assertRegex(output, "Session 17 in tunnel 10") 2031 self.assertRegex(output, "Peer session 18, tunnel 11") 2032 self.assertRegex(output, "interface name: l2tp-ses2") 2033 2034 @expectedFailureIfModuleIsNotAvailable('l2tp_ip') 2035 def test_l2tp_ip(self): 2036 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', 2037 '25-l2tp-ip.netdev', '25-l2tp.network') 2038 start_networkd() 2039 2040 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded']) 2041 2042 output = check_output('ip l2tp show tunnel tunnel_id 10') 2043 print(output) 2044 self.assertRegex(output, "Tunnel 10, encap IP") 2045 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101") 2046 self.assertRegex(output, "Peer tunnel 12") 2047 2048 output = check_output('ip l2tp show session tid 10 session_id 25') 2049 print(output) 2050 self.assertRegex(output, "Session 25 in tunnel 10") 2051 self.assertRegex(output, "Peer session 26, tunnel 12") 2052 self.assertRegex(output, "interface name: l2tp-ses3") 2053 2054 output = check_output('ip l2tp show session tid 10 session_id 27') 2055 print(output) 2056 self.assertRegex(output, "Session 27 in tunnel 10") 2057 self.assertRegex(output, "Peer session 28, tunnel 12") 2058 self.assertRegex(output, "interface name: l2tp-ses4") 2059 2060class NetworkdNetworkTests(unittest.TestCase, Utilities): 2061 links = [ 2062 'bond199', 2063 'dummy98', 2064 'dummy99', 2065 'gretun97', 2066 'ip6gretun97', 2067 'test1', 2068 'veth-peer', 2069 'veth99', 2070 'vlan99', 2071 'vrf99', 2072 ] 2073 2074 units = [ 2075 '11-dummy.netdev', 2076 '12-dummy.netdev', 2077 '12-dummy.network', 2078 '21-vlan.netdev', 2079 '21-vlan-test1.network', 2080 '23-active-slave.network', 2081 '24-keep-configuration-static.network', 2082 '24-search-domain.network', 2083 '25-address-ipv4acd-veth99.network', 2084 '25-address-link-section.network', 2085 '25-address-peer-ipv4.network', 2086 '25-address-static.network', 2087 '25-activation-policy.network', 2088 '25-bind-carrier.network', 2089 '25-bond-active-backup-slave.netdev', 2090 '25-fibrule-invert.network', 2091 '25-fibrule-port-range.network', 2092 '25-fibrule-uidrange.network', 2093 '25-gre-tunnel-remote-any.netdev', 2094 '25-ip6gre-tunnel-remote-any.netdev', 2095 '25-ipv6-address-label-section.network', 2096 '25-ipv6-proxy-ndp.network', 2097 '25-link-local-addressing-no.network', 2098 '25-link-local-addressing-yes.network', 2099 '25-link-section-unmanaged.network', 2100 '25-neighbor-section.network', 2101 '25-neighbor-next.network', 2102 '25-neighbor-ipv6.network', 2103 '25-neighbor-ip-dummy.network', 2104 '25-neighbor-ip.network', 2105 '25-nexthop-dummy.network', 2106 '25-nexthop-nothing.network', 2107 '25-nexthop.network', 2108 '25-qdisc-cake.network', 2109 '25-qdisc-clsact-and-htb.network', 2110 '25-qdisc-drr.network', 2111 '25-qdisc-ets.network', 2112 '25-qdisc-fq_pie.network', 2113 '25-qdisc-hhf.network', 2114 '25-qdisc-ingress-netem-compat.network', 2115 '25-qdisc-pie.network', 2116 '25-qdisc-qfq.network', 2117 '25-prefix-route-with-vrf.network', 2118 '25-prefix-route-without-vrf.network', 2119 '25-route-ipv6-src.network', 2120 '25-route-static.network', 2121 '25-route-via-ipv6.network', 2122 '25-route-vrf.network', 2123 '25-gateway-static.network', 2124 '25-gateway-next-static.network', 2125 '25-sysctl-disable-ipv6.network', 2126 '25-sysctl.network', 2127 '25-test1.network', 2128 '25-veth-peer.network', 2129 '25-veth.netdev', 2130 '25-vrf.netdev', 2131 '25-vrf.network', 2132 '26-link-local-addressing-ipv6.network', 2133 '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network', 2134 '25-dhcp-server-with-ipv6-prefix.network', 2135 '25-ipv6ra-prefix-client-with-static-ipv4-address.network', 2136 '25-ipv6-prefix-with-delay.network', 2137 '25-routing-policy-rule-dummy98.network', 2138 '25-routing-policy-rule-test1.network', 2139 '25-routing-policy-rule-reconfigure1.network', 2140 '25-routing-policy-rule-reconfigure2.network', 2141 ] 2142 2143 networkd_conf_dropins = [ 2144 'networkd-manage-foreign-routes-no.conf', 2145 ] 2146 2147 routing_policy_rule_tables = ['7', '8', '9', '10', '1011'] 2148 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']] 2149 2150 def setUp(self): 2151 remove_blackhole_nexthops() 2152 remove_routing_policy_rule_tables(self.routing_policy_rule_tables) 2153 remove_routes(self.routes) 2154 remove_links(self.links) 2155 stop_networkd(show_logs=False) 2156 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 2157 2158 def tearDown(self): 2159 remove_blackhole_nexthops() 2160 remove_routing_policy_rule_tables(self.routing_policy_rule_tables) 2161 remove_routes(self.routes) 2162 remove_links(self.links) 2163 remove_unit_from_networkd_path(self.units) 2164 remove_networkd_conf_dropin(self.networkd_conf_dropins) 2165 stop_networkd(show_logs=True) 2166 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 2167 2168 def test_address_static(self): 2169 # test for #22515. The address will be removed and replaced with /64 prefix. 2170 rc = call('ip link add dummy98 type dummy') 2171 self.assertEqual(rc, 0) 2172 rc = call('ip link set dev dummy98 up') 2173 self.assertEqual(rc, 0) 2174 rc = call('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98') 2175 self.assertEqual(rc, 0) 2176 self.wait_address('dummy98', '2001:db8:0:f101::15/128', ipv='-6') 2177 rc = call('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98') 2178 self.assertEqual(rc, 0) 2179 self.wait_address('dummy98', '10.3.2.3/16 brd 10.3.255.250', ipv='-4') 2180 2181 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev') 2182 start_networkd() 2183 2184 self.wait_online(['dummy98:routable']) 2185 2186 output = check_output('ip -4 address show dev dummy98') 2187 print(output) 2188 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) 2189 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) 2190 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) 2191 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output) 2192 self.assertIn('inet 10.8.8.1/16 scope global dummy98', output) 2193 self.assertIn('inet 10.8.8.2/16 brd 10.8.8.128 scope global secondary dummy98', output) 2194 self.assertRegex(output, 'inet 10.9.0.1/16 (metric 128 |)brd 10.9.255.255 scope global dummy98') 2195 2196 # test for ENOBUFS issue #17012 2197 for i in range(1,254): 2198 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output) 2199 2200 # invalid sections 2201 self.assertNotIn('10.10.0.1/16', output) 2202 self.assertNotIn('10.10.0.2/16', output) 2203 2204 output = check_output('ip -4 address show dev dummy98 label 32') 2205 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output) 2206 2207 output = check_output('ip -4 address show dev dummy98 label 33') 2208 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output) 2209 2210 output = check_output('ip -4 address show dev dummy98 label 34') 2211 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34') 2212 2213 output = check_output('ip -4 address show dev dummy98 label 35') 2214 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35') 2215 2216 output = check_output('ip -4 route show dev dummy98') 2217 print(output) 2218 self.assertIn('10.9.0.0/16 proto kernel scope link src 10.9.0.1 metric 128', output) 2219 2220 output = check_output('ip -6 address show dev dummy98') 2221 print(output) 2222 self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output) 2223 self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output) 2224 self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output) 2225 self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output) 2226 self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output) 2227 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output) 2228 self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global') 2229 2230 # Tests for #20891. 2231 # 1. set preferred lifetime forever to drop the deprecated flag for testing #20891. 2232 self.assertEqual(call('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever'), 0) 2233 self.assertEqual(call('ip address change 2001:db8:1:f101::1/64 dev dummy98 preferred_lft forever'), 0) 2234 output = check_output('ip -4 address show dev dummy98') 2235 print(output) 2236 self.assertNotIn('deprecated', output) 2237 output = check_output('ip -6 address show dev dummy98') 2238 print(output) 2239 self.assertNotIn('deprecated', output) 2240 2241 # 2. reconfigure the interface. 2242 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env) 2243 self.wait_online(['dummy98:routable']) 2244 2245 # 3. check the deprecated flag is set for the address configured with PreferredLifetime=0 2246 output = check_output('ip -4 address show dev dummy98') 2247 print(output) 2248 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output) 2249 output = check_output('ip -6 address show dev dummy98') 2250 print(output) 2251 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output) 2252 2253 # test for ENOBUFS issue #17012 2254 output = check_output('ip -4 address show dev dummy98') 2255 for i in range(1,254): 2256 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output) 2257 2258 # TODO: check json string 2259 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 2260 2261 def test_address_ipv4acd(self): 2262 check_output('ip netns add ns99') 2263 check_output('ip link add veth99 type veth peer veth-peer') 2264 check_output('ip link set veth-peer netns ns99') 2265 check_output('ip link set veth99 up') 2266 check_output('ip netns exec ns99 ip link set veth-peer up') 2267 check_output('ip netns exec ns99 ip address add 192.168.100.10/24 dev veth-peer') 2268 2269 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network', dropins=False) 2270 start_networkd() 2271 self.wait_online(['veth99:routable']) 2272 2273 output = check_output('ip -4 address show dev veth99') 2274 print(output) 2275 self.assertNotIn('192.168.100.10/24', output) 2276 self.assertIn('192.168.100.11/24', output) 2277 2278 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network.d/conflict-address.conf') 2279 run(*networkctl_cmd, 'reload', env=env) 2280 time.sleep(1) 2281 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env) 2282 self.assertTrue(rc == 1) 2283 2284 output = check_output('ip -4 address show dev veth99') 2285 print(output) 2286 self.assertNotIn('192.168.100.10/24', output) 2287 self.assertIn('192.168.100.11/24', output) 2288 2289 def test_address_peer_ipv4(self): 2290 # test for issue #17304 2291 copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev') 2292 2293 for trial in range(2): 2294 if trial == 0: 2295 start_networkd() 2296 else: 2297 restart_networkd() 2298 2299 self.wait_online(['dummy98:routable']) 2300 2301 output = check_output('ip -4 address show dev dummy98') 2302 self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output) 2303 2304 @expectedFailureIfModuleIsNotAvailable('vrf') 2305 def test_prefix_route(self): 2306 copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev', 2307 '25-prefix-route-without-vrf.network', '11-dummy.netdev', 2308 '25-vrf.netdev', '25-vrf.network') 2309 for trial in range(2): 2310 if trial == 0: 2311 start_networkd() 2312 else: 2313 restart_networkd(3) 2314 2315 self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier']) 2316 2317 output = check_output('ip route show table 42 dev dummy98') 2318 print('### ip route show table 42 dev dummy98') 2319 print(output) 2320 self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1') 2321 self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1') 2322 self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1') 2323 self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1') 2324 self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1') 2325 self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1') 2326 self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1') 2327 output = check_output('ip -6 route show table 42 dev dummy98') 2328 print('### ip -6 route show table 42 dev dummy98') 2329 print(output) 2330 if trial == 0: 2331 # Kernel's bug? 2332 self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium') 2333 #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium') 2334 self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium') 2335 self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium') 2336 self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium') 2337 self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium') 2338 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium') 2339 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium') 2340 2341 print() 2342 2343 output = check_output('ip route show dev test1') 2344 print('### ip route show dev test1') 2345 print(output) 2346 self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1') 2347 output = check_output('ip route show table local dev test1') 2348 print('### ip route show table local dev test1') 2349 print(output) 2350 self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1') 2351 self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1') 2352 self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1') 2353 self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1') 2354 self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1') 2355 self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1') 2356 output = check_output('ip -6 route show dev test1') 2357 print('### ip -6 route show dev test1') 2358 print(output) 2359 self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium') 2360 self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium') 2361 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium') 2362 output = check_output('ip -6 route show table local dev test1') 2363 print('### ip -6 route show table local dev test1') 2364 print(output) 2365 self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium') 2366 self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium') 2367 self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium') 2368 self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium') 2369 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium') 2370 2371 def test_configure_without_carrier(self): 2372 copy_unit_to_networkd_unit_path('11-dummy.netdev') 2373 start_networkd() 2374 self.wait_operstate('test1', 'off', '') 2375 check_output('ip link set dev test1 up carrier off') 2376 2377 copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False) 2378 restart_networkd() 2379 self.wait_online(['test1:no-carrier']) 2380 2381 carrier_map = {'on': '1', 'off': '0'} 2382 routable_map = {'on': 'routable', 'off': 'no-carrier'} 2383 for carrier in ['off', 'on', 'off']: 2384 with self.subTest(carrier=carrier): 2385 if carrier_map[carrier] != read_link_attr('test1', 'carrier'): 2386 check_output(f'ip link set dev test1 carrier {carrier}') 2387 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}']) 2388 2389 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 2390 print(output) 2391 self.assertRegex(output, '192.168.0.15') 2392 self.assertRegex(output, '192.168.0.1') 2393 self.assertRegex(output, routable_map[carrier]) 2394 2395 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self): 2396 copy_unit_to_networkd_unit_path('11-dummy.netdev') 2397 start_networkd() 2398 self.wait_operstate('test1', 'off', '') 2399 check_output('ip link set dev test1 up carrier off') 2400 2401 copy_unit_to_networkd_unit_path('25-test1.network') 2402 restart_networkd() 2403 self.wait_online(['test1:no-carrier']) 2404 2405 carrier_map = {'on': '1', 'off': '0'} 2406 routable_map = {'on': 'routable', 'off': 'no-carrier'} 2407 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]: 2408 with self.subTest(carrier=carrier, have_config=have_config): 2409 if carrier_map[carrier] != read_link_attr('test1', 'carrier'): 2410 check_output(f'ip link set dev test1 carrier {carrier}') 2411 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}']) 2412 2413 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 2414 print(output) 2415 if have_config: 2416 self.assertRegex(output, '192.168.0.15') 2417 self.assertRegex(output, '192.168.0.1') 2418 else: 2419 self.assertNotRegex(output, '192.168.0.15') 2420 self.assertNotRegex(output, '192.168.0.1') 2421 self.assertRegex(output, routable_map[carrier]) 2422 2423 def test_routing_policy_rule(self): 2424 copy_unit_to_networkd_unit_path('25-routing-policy-rule-test1.network', '11-dummy.netdev') 2425 start_networkd() 2426 self.wait_online(['test1:degraded']) 2427 2428 output = check_output('ip rule list iif test1 priority 111') 2429 print(output) 2430 self.assertRegex(output, '111:') 2431 self.assertRegex(output, 'from 192.168.100.18') 2432 self.assertRegex(output, r'tos (0x08|throughput)\s') 2433 self.assertRegex(output, 'iif test1') 2434 self.assertRegex(output, 'oif test1') 2435 self.assertRegex(output, 'lookup 7') 2436 2437 output = check_output('ip rule list iif test1 priority 101') 2438 print(output) 2439 self.assertRegex(output, '101:') 2440 self.assertRegex(output, 'from all') 2441 self.assertRegex(output, 'iif test1') 2442 self.assertRegex(output, 'lookup 9') 2443 2444 output = check_output('ip -6 rule list iif test1 priority 100') 2445 print(output) 2446 self.assertRegex(output, '100:') 2447 self.assertRegex(output, 'from all') 2448 self.assertRegex(output, 'iif test1') 2449 self.assertRegex(output, 'lookup 8') 2450 2451 output = check_output('ip rule list iif test1 priority 102') 2452 print(output) 2453 self.assertRegex(output, '102:') 2454 self.assertRegex(output, 'from 0.0.0.0/8') 2455 self.assertRegex(output, 'iif test1') 2456 self.assertRegex(output, 'lookup 10') 2457 2458 # TODO: check json string 2459 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 2460 2461 def test_routing_policy_rule_issue_11280(self): 2462 copy_unit_to_networkd_unit_path('25-routing-policy-rule-test1.network', '11-dummy.netdev', 2463 '25-routing-policy-rule-dummy98.network', '12-dummy.netdev') 2464 2465 for _ in range(3): 2466 # Remove state files only first time 2467 start_networkd(3) 2468 self.wait_online(['test1:degraded', 'dummy98:degraded']) 2469 time.sleep(1) 2470 2471 output = check_output('ip rule list table 7') 2472 print(output) 2473 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7') 2474 2475 output = check_output('ip rule list table 8') 2476 print(output) 2477 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8') 2478 2479 stop_networkd(remove_state_files=False) 2480 2481 def test_routing_policy_rule_reconfigure(self): 2482 copy_unit_to_networkd_unit_path('25-routing-policy-rule-reconfigure2.network', '11-dummy.netdev') 2483 start_networkd() 2484 self.wait_online(['test1:degraded']) 2485 2486 output = check_output('ip rule list table 1011') 2487 print(output) 2488 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output) 2489 self.assertIn('10112: from all oif test1 lookup 1011', output) 2490 self.assertIn('10113: from all iif test1 lookup 1011', output) 2491 self.assertIn('10114: from 192.168.8.254 lookup 1011', output) 2492 2493 output = check_output('ip -6 rule list table 1011') 2494 print(output) 2495 self.assertIn('10112: from all oif test1 lookup 1011', output) 2496 2497 copy_unit_to_networkd_unit_path('25-routing-policy-rule-reconfigure1.network', '11-dummy.netdev') 2498 run(*networkctl_cmd, 'reload', env=env) 2499 time.sleep(1) 2500 self.wait_online(['test1:degraded']) 2501 2502 output = check_output('ip rule list table 1011') 2503 print(output) 2504 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output) 2505 self.assertIn('10112: from all oif test1 lookup 1011', output) 2506 self.assertIn('10113: from all iif test1 lookup 1011', output) 2507 self.assertIn('10114: from 192.168.8.254 lookup 1011', output) 2508 2509 output = check_output('ip -6 rule list table 1011') 2510 print(output) 2511 self.assertNotIn('10112: from all oif test1 lookup 1011', output) 2512 self.assertIn('10113: from all iif test1 lookup 1011', output) 2513 2514 run('ip rule delete priority 10111') 2515 run('ip rule delete priority 10112') 2516 run('ip rule delete priority 10113') 2517 run('ip rule delete priority 10114') 2518 run('ip -6 rule delete priority 10113') 2519 2520 output = check_output('ip rule list table 1011') 2521 print(output) 2522 self.assertEqual(output, '') 2523 2524 output = check_output('ip -6 rule list table 1011') 2525 print(output) 2526 self.assertEqual(output, '') 2527 2528 run(*networkctl_cmd, 'reconfigure', 'test1', env=env) 2529 self.wait_online(['test1:degraded']) 2530 2531 output = check_output('ip rule list table 1011') 2532 print(output) 2533 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output) 2534 self.assertIn('10112: from all oif test1 lookup 1011', output) 2535 self.assertIn('10113: from all iif test1 lookup 1011', output) 2536 self.assertIn('10114: from 192.168.8.254 lookup 1011', output) 2537 2538 output = check_output('ip -6 rule list table 1011') 2539 print(output) 2540 self.assertIn('10113: from all iif test1 lookup 1011', output) 2541 2542 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable() 2543 def test_routing_policy_rule_port_range(self): 2544 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev') 2545 start_networkd() 2546 self.wait_online(['test1:degraded']) 2547 2548 output = check_output('ip rule') 2549 print(output) 2550 self.assertRegex(output, '111') 2551 self.assertRegex(output, 'from 192.168.100.18') 2552 self.assertRegex(output, '1123-1150') 2553 self.assertRegex(output, '3224-3290') 2554 self.assertRegex(output, 'tcp') 2555 self.assertRegex(output, 'lookup 7') 2556 2557 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable() 2558 def test_routing_policy_rule_invert(self): 2559 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev') 2560 start_networkd() 2561 self.wait_online(['test1:degraded']) 2562 2563 output = check_output('ip rule') 2564 print(output) 2565 self.assertRegex(output, '111') 2566 self.assertRegex(output, 'not.*?from.*?192.168.100.18') 2567 self.assertRegex(output, 'tcp') 2568 self.assertRegex(output, 'lookup 7') 2569 2570 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable() 2571 def test_routing_policy_rule_uidrange(self): 2572 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev') 2573 start_networkd() 2574 self.wait_online(['test1:degraded']) 2575 2576 output = check_output('ip rule') 2577 print(output) 2578 self.assertRegex(output, '111') 2579 self.assertRegex(output, 'from 192.168.100.18') 2580 self.assertRegex(output, 'lookup 7') 2581 self.assertRegex(output, 'uidrange 100-200') 2582 2583 def _test_route_static(self, manage_foreign_routes): 2584 if not manage_foreign_routes: 2585 copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf') 2586 2587 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev') 2588 start_networkd() 2589 self.wait_online(['dummy98:routable']) 2590 2591 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) 2592 print(output) 2593 2594 print('### ip -6 route show dev dummy98') 2595 output = check_output('ip -6 route show dev dummy98') 2596 print(output) 2597 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output) 2598 self.assertIn('2001:1234:5:8f63::1 proto kernel', output) 2599 self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output) 2600 2601 print('### ip -6 route show default') 2602 output = check_output('ip -6 route show default') 2603 print(output) 2604 self.assertIn('default', output) 2605 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output) 2606 2607 print('### ip -4 route show dev dummy98') 2608 output = check_output('ip -4 route show dev dummy98') 2609 print(output) 2610 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output) 2611 self.assertIn('149.10.124.64 proto static scope link', output) 2612 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output) 2613 self.assertIn('192.168.1.1 proto static scope link initcwnd 20', output) 2614 self.assertIn('192.168.1.2 proto static scope link initrwnd 30', output) 2615 self.assertIn('192.168.1.3 proto static scope link advmss 30', output) 2616 self.assertIn('multicast 149.10.123.4 proto static', output) 2617 2618 print('### ip -4 route show dev dummy98 default') 2619 output = check_output('ip -4 route show dev dummy98 default') 2620 print(output) 2621 self.assertIn('default via 149.10.125.65 proto static onlink', output) 2622 self.assertIn('default via 149.10.124.64 proto static', output) 2623 self.assertIn('default proto static', output) 2624 2625 print('### ip -4 route show table local dev dummy98') 2626 output = check_output('ip -4 route show table local dev dummy98') 2627 print(output) 2628 self.assertIn('local 149.10.123.1 proto static scope host', output) 2629 self.assertIn('anycast 149.10.123.2 proto static scope link', output) 2630 self.assertIn('broadcast 149.10.123.3 proto static scope link', output) 2631 2632 print('### ip route show type blackhole') 2633 output = check_output('ip route show type blackhole') 2634 print(output) 2635 self.assertIn('blackhole 202.54.1.2 proto static', output) 2636 2637 print('### ip route show type unreachable') 2638 output = check_output('ip route show type unreachable') 2639 print(output) 2640 self.assertIn('unreachable 202.54.1.3 proto static', output) 2641 2642 print('### ip route show type prohibit') 2643 output = check_output('ip route show type prohibit') 2644 print(output) 2645 self.assertIn('prohibit 202.54.1.4 proto static', output) 2646 2647 print('### ip -6 route show type blackhole') 2648 output = check_output('ip -6 route show type blackhole') 2649 print(output) 2650 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output) 2651 2652 print('### ip -6 route show type unreachable') 2653 output = check_output('ip -6 route show type unreachable') 2654 print(output) 2655 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output) 2656 2657 print('### ip -6 route show type prohibit') 2658 output = check_output('ip -6 route show type prohibit') 2659 print(output) 2660 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output) 2661 2662 print('### ip route show 192.168.10.1') 2663 output = check_output('ip route show 192.168.10.1') 2664 print(output) 2665 self.assertIn('192.168.10.1 proto static', output) 2666 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output) 2667 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output) 2668 2669 print('### ip route show 192.168.10.2') 2670 output = check_output('ip route show 192.168.10.2') 2671 print(output) 2672 # old ip command does not show IPv6 gateways... 2673 self.assertIn('192.168.10.2 proto static', output) 2674 self.assertIn('nexthop', output) 2675 self.assertIn('dev dummy98 weight 10', output) 2676 self.assertIn('dev dummy98 weight 5', output) 2677 2678 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff') 2679 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff') 2680 print(output) 2681 # old ip command does not show 'nexthop' keyword and weight... 2682 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output) 2683 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output) 2684 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output) 2685 2686 # TODO: check json string 2687 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 2688 2689 copy_unit_to_networkd_unit_path('25-address-static.network') 2690 check_output(*networkctl_cmd, 'reload', env=env) 2691 time.sleep(1) 2692 self.wait_online(['dummy98:routable']) 2693 2694 # check all routes managed by Manager are removed 2695 print('### ip route show type blackhole') 2696 output = check_output('ip route show type blackhole') 2697 print(output) 2698 self.assertEqual(output, '') 2699 2700 print('### ip route show type unreachable') 2701 output = check_output('ip route show type unreachable') 2702 print(output) 2703 self.assertEqual(output, '') 2704 2705 print('### ip route show type prohibit') 2706 output = check_output('ip route show type prohibit') 2707 print(output) 2708 self.assertEqual(output, '') 2709 2710 print('### ip -6 route show type blackhole') 2711 output = check_output('ip -6 route show type blackhole') 2712 print(output) 2713 self.assertEqual(output, '') 2714 2715 print('### ip -6 route show type unreachable') 2716 output = check_output('ip -6 route show type unreachable') 2717 print(output) 2718 self.assertEqual(output, '') 2719 2720 print('### ip -6 route show type prohibit') 2721 output = check_output('ip -6 route show type prohibit') 2722 print(output) 2723 self.assertEqual(output, '') 2724 2725 remove_unit_from_networkd_path(['25-address-static.network']) 2726 check_output(*networkctl_cmd, 'reload', env=env) 2727 time.sleep(1) 2728 self.wait_online(['dummy98:routable']) 2729 2730 # check all routes managed by Manager are reconfigured 2731 print('### ip route show type blackhole') 2732 output = check_output('ip route show type blackhole') 2733 print(output) 2734 self.assertIn('blackhole 202.54.1.2 proto static', output) 2735 2736 print('### ip route show type unreachable') 2737 output = check_output('ip route show type unreachable') 2738 print(output) 2739 self.assertIn('unreachable 202.54.1.3 proto static', output) 2740 2741 print('### ip route show type prohibit') 2742 output = check_output('ip route show type prohibit') 2743 print(output) 2744 self.assertIn('prohibit 202.54.1.4 proto static', output) 2745 2746 print('### ip -6 route show type blackhole') 2747 output = check_output('ip -6 route show type blackhole') 2748 print(output) 2749 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output) 2750 2751 print('### ip -6 route show type unreachable') 2752 output = check_output('ip -6 route show type unreachable') 2753 print(output) 2754 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output) 2755 2756 print('### ip -6 route show type prohibit') 2757 output = check_output('ip -6 route show type prohibit') 2758 print(output) 2759 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output) 2760 2761 rc = call("ip link del dummy98") 2762 self.assertEqual(rc, 0) 2763 time.sleep(2) 2764 2765 # check all routes managed by Manager are removed 2766 print('### ip route show type blackhole') 2767 output = check_output('ip route show type blackhole') 2768 print(output) 2769 self.assertEqual(output, '') 2770 2771 print('### ip route show type unreachable') 2772 output = check_output('ip route show type unreachable') 2773 print(output) 2774 self.assertEqual(output, '') 2775 2776 print('### ip route show type prohibit') 2777 output = check_output('ip route show type prohibit') 2778 print(output) 2779 self.assertEqual(output, '') 2780 2781 print('### ip -6 route show type blackhole') 2782 output = check_output('ip -6 route show type blackhole') 2783 print(output) 2784 self.assertEqual(output, '') 2785 2786 print('### ip -6 route show type unreachable') 2787 output = check_output('ip -6 route show type unreachable') 2788 print(output) 2789 self.assertEqual(output, '') 2790 2791 print('### ip -6 route show type prohibit') 2792 output = check_output('ip -6 route show type prohibit') 2793 print(output) 2794 self.assertEqual(output, '') 2795 2796 self.tearDown() 2797 2798 def test_route_static(self): 2799 for manage_foreign_routes in [True, False]: 2800 with self.subTest(manage_foreign_routes=manage_foreign_routes): 2801 self._test_route_static(manage_foreign_routes) 2802 2803 @expectedFailureIfRTA_VIAIsNotSupported() 2804 def test_route_via_ipv6(self): 2805 copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev') 2806 start_networkd() 2807 self.wait_online(['dummy98:routable']) 2808 2809 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) 2810 print(output) 2811 2812 print('### ip -6 route show dev dummy98') 2813 output = check_output('ip -6 route show dev dummy98') 2814 print(output) 2815 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static') 2816 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel') 2817 2818 print('### ip -4 route show dev dummy98') 2819 output = check_output('ip -4 route show dev dummy98') 2820 print(output) 2821 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58') 2822 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static') 2823 2824 @expectedFailureIfModuleIsNotAvailable('vrf') 2825 def test_route_vrf(self): 2826 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev', 2827 '25-vrf.netdev', '25-vrf.network') 2828 start_networkd() 2829 self.wait_online(['dummy98:routable', 'vrf99:carrier']) 2830 2831 output = check_output('ip route show vrf vrf99') 2832 print(output) 2833 self.assertRegex(output, 'default via 192.168.100.1') 2834 2835 output = check_output('ip route show') 2836 print(output) 2837 self.assertNotRegex(output, 'default via 192.168.100.1') 2838 2839 def test_gateway_reconfigure(self): 2840 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev') 2841 start_networkd() 2842 self.wait_online(['dummy98:routable']) 2843 print('### ip -4 route show dev dummy98 default') 2844 output = check_output('ip -4 route show dev dummy98 default') 2845 print(output) 2846 self.assertRegex(output, 'default via 149.10.124.59 proto static') 2847 self.assertNotRegex(output, '149.10.124.60') 2848 2849 remove_unit_from_networkd_path(['25-gateway-static.network']) 2850 copy_unit_to_networkd_unit_path('25-gateway-next-static.network') 2851 restart_networkd(3) 2852 self.wait_online(['dummy98:routable']) 2853 print('### ip -4 route show dev dummy98 default') 2854 output = check_output('ip -4 route show dev dummy98 default') 2855 print(output) 2856 self.assertNotRegex(output, '149.10.124.59') 2857 self.assertRegex(output, 'default via 149.10.124.60 proto static') 2858 2859 def test_ip_route_ipv6_src_route(self): 2860 # a dummy device does not make the addresses go through tentative state, so we 2861 # reuse a bond from an earlier test, which does make the addresses go through 2862 # tentative state, and do our test on that 2863 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') 2864 start_networkd() 2865 self.wait_online(['dummy98:enslaved', 'bond199:routable']) 2866 2867 output = check_output('ip -6 route list dev bond199') 2868 print(output) 2869 self.assertRegex(output, 'abcd::/16') 2870 self.assertRegex(output, 'src') 2871 self.assertRegex(output, '2001:1234:56:8f63::2') 2872 2873 def test_ip_link_mac_address(self): 2874 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev') 2875 start_networkd() 2876 self.wait_online(['dummy98:degraded']) 2877 2878 output = check_output('ip link show dummy98') 2879 print(output) 2880 self.assertRegex(output, '00:01:02:aa:bb:cc') 2881 2882 def test_ip_link_unmanaged(self): 2883 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev') 2884 start_networkd(5) 2885 2886 self.check_link_exists('dummy98') 2887 2888 self.wait_operstate('dummy98', 'off', setup_state='unmanaged') 2889 2890 def test_ipv6_address_label(self): 2891 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev') 2892 start_networkd() 2893 self.wait_online(['dummy98:degraded']) 2894 2895 output = check_output('ip addrlabel list') 2896 print(output) 2897 self.assertRegex(output, '2004:da8:1::/64') 2898 2899 def test_ipv6_proxy_ndp(self): 2900 copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev') 2901 start_networkd() 2902 2903 self.wait_online(['dummy98:routable']) 2904 2905 output = check_output('ip neighbor show proxy dev dummy98') 2906 print(output) 2907 for i in range(1,5): 2908 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy') 2909 2910 def test_neighbor_section(self): 2911 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev') 2912 start_networkd() 2913 self.wait_online(['dummy98:degraded'], timeout='40s') 2914 2915 print('### ip neigh list dev dummy98') 2916 output = check_output('ip neigh list dev dummy98') 2917 print(output) 2918 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') 2919 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT') 2920 2921 # TODO: check json string 2922 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 2923 2924 def test_neighbor_reconfigure(self): 2925 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev') 2926 start_networkd() 2927 self.wait_online(['dummy98:degraded'], timeout='40s') 2928 2929 print('### ip neigh list dev dummy98') 2930 output = check_output('ip neigh list dev dummy98') 2931 print(output) 2932 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') 2933 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT') 2934 2935 remove_unit_from_networkd_path(['25-neighbor-section.network']) 2936 copy_unit_to_networkd_unit_path('25-neighbor-next.network') 2937 restart_networkd(3) 2938 self.wait_online(['dummy98:degraded'], timeout='40s') 2939 print('### ip neigh list dev dummy98') 2940 output = check_output('ip neigh list dev dummy98') 2941 print(output) 2942 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') 2943 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT') 2944 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT') 2945 2946 def test_neighbor_gre(self): 2947 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network', 2948 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev') 2949 start_networkd() 2950 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s') 2951 2952 output = check_output('ip neigh list dev gretun97') 2953 print(output) 2954 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT') 2955 2956 output = check_output('ip neigh list dev ip6gretun97') 2957 print(output) 2958 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT') 2959 2960 # TODO: check json string 2961 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 2962 2963 def test_link_local_addressing(self): 2964 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev', 2965 '25-link-local-addressing-no.network', '12-dummy.netdev') 2966 start_networkd() 2967 self.wait_online(['test1:degraded', 'dummy98:carrier']) 2968 2969 output = check_output('ip address show dev test1') 2970 print(output) 2971 self.assertRegex(output, 'inet .* scope link') 2972 self.assertRegex(output, 'inet6 .* scope link') 2973 2974 output = check_output('ip address show dev dummy98') 2975 print(output) 2976 self.assertNotRegex(output, 'inet6* .* scope link') 2977 2978 # Documentation/networking/ip-sysctl.txt 2979 # 2980 # addr_gen_mode - INTEGER 2981 # Defines how link-local and autoconf addresses are generated. 2982 # 2983 # 0: generate address based on EUI64 (default) 2984 # 1: do no generate a link-local address, use EUI64 for addresses generated 2985 # from autoconf 2986 # 2: generate stable privacy addresses, using the secret from 2987 # stable_secret (RFC7217) 2988 # 3: generate stable privacy addresses, using a random secret if unset 2989 2990 self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef') 2991 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2') 2992 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1') 2993 2994 def test_link_local_addressing_ipv6ll(self): 2995 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev') 2996 start_networkd() 2997 self.wait_online(['dummy98:degraded']) 2998 2999 # An IPv6LL address exists by default. 3000 output = check_output('ip address show dev dummy98') 3001 print(output) 3002 self.assertRegex(output, 'inet6 .* scope link') 3003 3004 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network') 3005 check_output(*networkctl_cmd, 'reload', env=env) 3006 time.sleep(1) 3007 self.wait_online(['dummy98:carrier']) 3008 3009 # Check if the IPv6LL address is removed. 3010 output = check_output('ip address show dev dummy98') 3011 print(output) 3012 self.assertNotRegex(output, 'inet6 .* scope link') 3013 3014 remove_unit_from_networkd_path(['25-link-local-addressing-no.network']) 3015 check_output(*networkctl_cmd, 'reload', env=env) 3016 time.sleep(1) 3017 self.wait_online(['dummy98:degraded']) 3018 3019 # Check if a new IPv6LL address is assigned. 3020 output = check_output('ip address show dev dummy98') 3021 print(output) 3022 self.assertRegex(output, 'inet6 .* scope link') 3023 3024 def test_sysctl(self): 3025 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev') 3026 start_networkd() 3027 self.wait_online(['dummy98:degraded']) 3028 3029 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1') 3030 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2') 3031 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3') 3032 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5') 3033 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1') 3034 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1') 3035 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1') 3036 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1') 3037 3038 def test_sysctl_disable_ipv6(self): 3039 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev') 3040 3041 print('## Disable ipv6') 3042 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1') 3043 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1') 3044 3045 start_networkd() 3046 self.wait_online(['dummy98:routable']) 3047 3048 output = check_output('ip -4 address show dummy98') 3049 print(output) 3050 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98') 3051 output = check_output('ip -6 address show dummy98') 3052 print(output) 3053 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global') 3054 self.assertRegex(output, 'inet6 .* scope link') 3055 output = check_output('ip -4 route show dev dummy98') 3056 print(output) 3057 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') 3058 output = check_output('ip -6 route show default') 3059 print(output) 3060 self.assertRegex(output, 'default') 3061 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff') 3062 3063 check_output('ip link del dummy98') 3064 3065 print('## Enable ipv6') 3066 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0') 3067 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0') 3068 3069 restart_networkd(3) 3070 self.wait_online(['dummy98:routable']) 3071 3072 output = check_output('ip -4 address show dummy98') 3073 print(output) 3074 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98') 3075 output = check_output('ip -6 address show dummy98') 3076 print(output) 3077 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global') 3078 self.assertRegex(output, 'inet6 .* scope link') 3079 output = check_output('ip -4 route show dev dummy98') 3080 print(output) 3081 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') 3082 output = check_output('ip -6 route show default') 3083 print(output) 3084 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff') 3085 3086 def test_bind_carrier(self): 3087 check_output('ip link add dummy98 type dummy') 3088 check_output('ip link set dummy98 up') 3089 time.sleep(2) 3090 3091 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev') 3092 start_networkd() 3093 self.wait_online(['test1:routable']) 3094 3095 output = check_output('ip address show test1') 3096 print(output) 3097 self.assertRegex(output, 'UP,LOWER_UP') 3098 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') 3099 self.wait_operstate('test1', 'routable') 3100 3101 check_output('ip link add dummy99 type dummy') 3102 check_output('ip link set dummy99 up') 3103 time.sleep(2) 3104 output = check_output('ip address show test1') 3105 print(output) 3106 self.assertRegex(output, 'UP,LOWER_UP') 3107 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') 3108 self.wait_operstate('test1', 'routable') 3109 3110 check_output('ip link del dummy98') 3111 time.sleep(2) 3112 output = check_output('ip address show test1') 3113 print(output) 3114 self.assertRegex(output, 'UP,LOWER_UP') 3115 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') 3116 self.wait_operstate('test1', 'routable') 3117 3118 check_output('ip link set dummy99 down') 3119 time.sleep(2) 3120 output = check_output('ip address show test1') 3121 print(output) 3122 self.assertNotRegex(output, 'UP,LOWER_UP') 3123 self.assertRegex(output, 'DOWN') 3124 self.assertNotRegex(output, '192.168.10') 3125 self.wait_operstate('test1', 'off') 3126 3127 check_output('ip link set dummy99 up') 3128 time.sleep(2) 3129 output = check_output('ip address show test1') 3130 print(output) 3131 self.assertRegex(output, 'UP,LOWER_UP') 3132 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') 3133 self.wait_operstate('test1', 'routable') 3134 3135 def _test_activation_policy(self, test, interface): 3136 conffile = '25-activation-policy.network' 3137 if test: 3138 conffile = f'{conffile}.d/{test}.conf' 3139 if interface == 'vlan99': 3140 copy_unit_to_networkd_unit_path('21-vlan.netdev', '21-vlan-test1.network') 3141 copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False) 3142 start_networkd() 3143 3144 always = test.startswith('always') 3145 initial_up = test != 'manual' and not test.endswith('down') # note: default is up 3146 expect_up = initial_up 3147 next_up = not expect_up 3148 3149 if test.endswith('down'): 3150 self.wait_activated(interface) 3151 3152 for iteration in range(4): 3153 with self.subTest(iteration=iteration, expect_up=expect_up): 3154 operstate = 'routable' if expect_up else 'off' 3155 setup_state = 'configured' if expect_up else ('configuring' if iteration == 0 else None) 3156 self.wait_operstate(interface, operstate, setup_state=setup_state, setup_timeout=20) 3157 3158 if expect_up: 3159 self.assertIn('UP', check_output(f'ip link show {interface}')) 3160 self.assertIn('192.168.10.30/24', check_output(f'ip address show {interface}')) 3161 self.assertIn('default via 192.168.10.1', check_output(f'ip route show dev {interface}')) 3162 else: 3163 self.assertIn('DOWN', check_output(f'ip link show {interface}')) 3164 3165 if next_up: 3166 check_output(f'ip link set dev {interface} up') 3167 else: 3168 check_output(f'ip link set dev {interface} down') 3169 expect_up = initial_up if always else next_up 3170 next_up = not next_up 3171 if always: 3172 time.sleep(1) 3173 3174 def test_activation_policy(self): 3175 for interface in ['test1', 'vlan99']: 3176 with self.subTest(interface=interface): 3177 for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']: 3178 with self.subTest(test=test): 3179 self.setUp() 3180 self._test_activation_policy(test, interface) 3181 self.tearDown() 3182 3183 def _test_activation_policy_required_for_online(self, policy, required): 3184 conffile = '25-activation-policy.network' 3185 units = ['11-dummy.netdev', '12-dummy.netdev', '12-dummy.network', conffile] 3186 if policy: 3187 units += [f'{conffile}.d/{policy}.conf'] 3188 if required: 3189 units += [f'{conffile}.d/required-{required}.conf'] 3190 copy_unit_to_networkd_unit_path(*units, dropins=False) 3191 start_networkd() 3192 3193 if policy.endswith('down'): 3194 self.wait_activated('test1') 3195 3196 if policy.endswith('down') or policy == 'manual': 3197 self.wait_operstate('test1', 'off', setup_state='configuring') 3198 else: 3199 self.wait_online(['test1']) 3200 3201 if policy == 'always-down': 3202 # if always-down, required for online is forced to no 3203 expected = False 3204 elif required: 3205 # otherwise if required for online is specified, it should match that 3206 expected = required == 'yes' 3207 elif policy: 3208 # otherwise if only policy specified, required for online defaults to 3209 # true if policy is up, always-up, or bound 3210 expected = policy.endswith('up') or policy == 'bound' 3211 else: 3212 # default is true, if neither are specified 3213 expected = True 3214 3215 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env) 3216 print(output) 3217 3218 yesno = 'yes' if expected else 'no' 3219 self.assertRegex(output, f'Required For Online: {yesno}') 3220 3221 def test_activation_policy_required_for_online(self): 3222 for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']: 3223 for required in ['yes', 'no', '']: 3224 with self.subTest(policy=policy, required=required): 3225 self.setUp() 3226 self._test_activation_policy_required_for_online(policy, required) 3227 self.tearDown() 3228 3229 def test_domain(self): 3230 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network') 3231 start_networkd() 3232 self.wait_online(['dummy98:routable']) 3233 3234 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) 3235 print(output) 3236 self.assertRegex(output, 'Address: 192.168.42.100') 3237 self.assertRegex(output, 'DNS: 192.168.42.1') 3238 self.assertRegex(output, 'Search Domains: one') 3239 3240 def test_keep_configuration_static(self): 3241 check_output('systemctl stop systemd-networkd.socket') 3242 check_output('systemctl stop systemd-networkd.service') 3243 3244 check_output('ip link add name dummy98 type dummy') 3245 check_output('ip address add 10.1.2.3/16 dev dummy98') 3246 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500') 3247 output = check_output('ip address show dummy98') 3248 print(output) 3249 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98') 3250 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98') 3251 output = check_output('ip route show dev dummy98') 3252 print(output) 3253 3254 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network') 3255 start_networkd() 3256 self.wait_online(['dummy98:routable']) 3257 3258 output = check_output('ip address show dummy98') 3259 print(output) 3260 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98') 3261 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98') 3262 3263 @expectedFailureIfNexthopIsNotAvailable() 3264 def test_nexthop(self): 3265 def check_nexthop(self): 3266 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable']) 3267 3268 output = check_output('ip nexthop list dev veth99') 3269 print(output) 3270 self.assertIn('id 1 via 192.168.5.1 dev veth99', output) 3271 self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output) 3272 self.assertIn('id 3 dev veth99', output) 3273 self.assertIn('id 4 dev veth99', output) 3274 self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink') 3275 self.assertIn('id 8 via fe80:0:222:4dff:ff:ff:ff:ff dev veth99', output) 3276 self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99') 3277 3278 output = check_output('ip nexthop list dev dummy98') 3279 print(output) 3280 self.assertIn('id 20 via 192.168.20.1 dev dummy98', output) 3281 3282 # kernel manages blackhole nexthops on lo 3283 output = check_output('ip nexthop list dev lo') 3284 print(output) 3285 self.assertIn('id 6 blackhole', output) 3286 self.assertIn('id 7 blackhole', output) 3287 3288 # group nexthops are shown with -0 option 3289 output = check_output('ip -0 nexthop list id 21') 3290 print(output) 3291 self.assertRegex(output, r'id 21 group (1,3/20|20/1,3)') 3292 3293 output = check_output('ip route show dev veth99 10.10.10.10') 3294 print(output) 3295 self.assertEqual('10.10.10.10 nhid 1 via 192.168.5.1 proto static', output) 3296 3297 output = check_output('ip route show dev veth99 10.10.10.11') 3298 print(output) 3299 self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output) 3300 3301 output = check_output('ip route show dev veth99 10.10.10.12') 3302 print(output) 3303 self.assertEqual('10.10.10.12 nhid 5 via 192.168.10.1 proto static onlink', output) 3304 3305 output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1') 3306 print(output) 3307 self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output) 3308 3309 output = check_output('ip route show 10.10.10.13') 3310 print(output) 3311 self.assertEqual('blackhole 10.10.10.13 nhid 6 dev lo proto static', output) 3312 3313 output = check_output('ip -6 route show 2001:1234:5:8f62::2') 3314 print(output) 3315 self.assertEqual('blackhole 2001:1234:5:8f62::2 nhid 7 dev lo proto static metric 1024 pref medium', output) 3316 3317 output = check_output('ip route show 10.10.10.14') 3318 print(output) 3319 self.assertIn('10.10.10.14 nhid 21 proto static', output) 3320 self.assertIn('nexthop via 192.168.20.1 dev dummy98 weight 1', output) 3321 self.assertIn('nexthop via 192.168.5.1 dev veth99 weight 3', output) 3322 3323 # TODO: check json string 3324 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 3325 3326 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network', 3327 '12-dummy.netdev', '25-nexthop-dummy.network') 3328 start_networkd() 3329 3330 check_nexthop(self) 3331 3332 remove_unit_from_networkd_path(['25-nexthop.network']) 3333 copy_unit_to_networkd_unit_path('25-nexthop-nothing.network') 3334 rc = call(*networkctl_cmd, 'reload', env=env) 3335 self.assertEqual(rc, 0) 3336 time.sleep(1) 3337 3338 self.wait_online(['veth99:routable', 'veth-peer:routable']) 3339 3340 output = check_output('ip nexthop list dev veth99') 3341 print(output) 3342 self.assertEqual(output, '') 3343 output = check_output('ip nexthop list dev lo') 3344 print(output) 3345 self.assertEqual(output, '') 3346 3347 remove_unit_from_networkd_path(['25-nexthop-nothing.network']) 3348 copy_unit_to_networkd_unit_path('25-nexthop.network') 3349 rc = call(*networkctl_cmd, 'reconfigure', 'dummy98', env=env) 3350 self.assertEqual(rc, 0) 3351 rc = call(*networkctl_cmd, 'reload', env=env) 3352 self.assertEqual(rc, 0) 3353 time.sleep(1) 3354 3355 check_nexthop(self) 3356 3357 rc = call('ip link del veth99') 3358 self.assertEqual(rc, 0) 3359 time.sleep(2) 3360 3361 output = check_output('ip nexthop list dev lo') 3362 print(output) 3363 self.assertEqual(output, '') 3364 3365 def test_qdisc(self): 3366 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev', 3367 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev') 3368 check_output('modprobe sch_teql max_equalizers=2') 3369 start_networkd() 3370 3371 self.wait_online(['dummy98:routable', 'test1:routable']) 3372 3373 output = check_output('tc qdisc show dev test1') 3374 print(output) 3375 self.assertRegex(output, 'qdisc netem') 3376 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') 3377 self.assertRegex(output, 'qdisc ingress') 3378 3379 output = check_output('tc qdisc show dev dummy98') 3380 print(output) 3381 self.assertRegex(output, 'qdisc clsact') 3382 3383 self.assertRegex(output, 'qdisc htb 2: root') 3384 self.assertRegex(output, r'default (0x30|30)') 3385 3386 self.assertRegex(output, 'qdisc netem 30: parent 2:30') 3387 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%') 3388 self.assertRegex(output, 'qdisc fq_codel') 3389 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn') 3390 3391 self.assertRegex(output, 'qdisc teql1 31: parent 2:31') 3392 3393 self.assertRegex(output, 'qdisc fq 32: parent 2:32') 3394 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511') 3395 self.assertRegex(output, 'quantum 1500') 3396 self.assertRegex(output, 'initial_quantum 13000') 3397 self.assertRegex(output, 'maxrate 1Mbit') 3398 3399 self.assertRegex(output, 'qdisc codel 33: parent 2:33') 3400 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn') 3401 3402 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34') 3403 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn') 3404 3405 self.assertRegex(output, 'qdisc tbf 35: parent 2:35') 3406 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms') 3407 3408 self.assertRegex(output, 'qdisc sfq 36: parent 2:36') 3409 self.assertRegex(output, 'perturb 5sec') 3410 3411 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37') 3412 self.assertRegex(output, 'limit 100000p') 3413 3414 self.assertRegex(output, 'qdisc gred 38: parent 2:38') 3415 self.assertRegex(output, 'vqs 12 default 10 grio') 3416 3417 self.assertRegex(output, 'qdisc sfb 39: parent 2:39') 3418 self.assertRegex(output, 'limit 200000') 3419 3420 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a') 3421 self.assertRegex(output, 'limit 1000000') 3422 3423 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b') 3424 self.assertRegex(output, 'limit 1023p') 3425 3426 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c') 3427 3428 output = check_output('tc -d class show dev dummy98') 3429 print(output) 3430 self.assertRegex(output, 'class htb 2:30 root leaf 30:') 3431 self.assertRegex(output, 'class htb 2:31 root leaf 31:') 3432 self.assertRegex(output, 'class htb 2:32 root leaf 32:') 3433 self.assertRegex(output, 'class htb 2:33 root leaf 33:') 3434 self.assertRegex(output, 'class htb 2:34 root leaf 34:') 3435 self.assertRegex(output, 'class htb 2:35 root leaf 35:') 3436 self.assertRegex(output, 'class htb 2:36 root leaf 36:') 3437 self.assertRegex(output, 'class htb 2:37 root leaf 37:') 3438 self.assertRegex(output, 'class htb 2:38 root leaf 38:') 3439 self.assertRegex(output, 'class htb 2:39 root leaf 39:') 3440 self.assertRegex(output, 'class htb 2:3a root leaf 3a:') 3441 self.assertRegex(output, 'class htb 2:3b root leaf 3b:') 3442 self.assertRegex(output, 'class htb 2:3c root leaf 3c:') 3443 self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit') 3444 self.assertRegex(output, 'burst 123456') 3445 self.assertRegex(output, 'cburst 123457') 3446 3447 def test_qdisc2(self): 3448 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev', 3449 '25-qdisc-qfq.network', '11-dummy.netdev') 3450 start_networkd() 3451 3452 self.wait_online(['dummy98:routable', 'test1:routable']) 3453 3454 output = check_output('tc qdisc show dev dummy98') 3455 print(output) 3456 self.assertRegex(output, 'qdisc drr 2: root') 3457 output = check_output('tc class show dev dummy98') 3458 print(output) 3459 self.assertRegex(output, 'class drr 2:30 root quantum 2000b') 3460 3461 output = check_output('tc qdisc show dev test1') 3462 print(output) 3463 self.assertRegex(output, 'qdisc qfq 2: root') 3464 output = check_output('tc class show dev test1') 3465 print(output) 3466 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000') 3467 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000') 3468 3469 @expectedFailureIfCAKEIsNotAvailable() 3470 def test_qdisc_cake(self): 3471 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev') 3472 start_networkd() 3473 self.wait_online(['dummy98:routable']) 3474 3475 output = check_output('tc qdisc show dev dummy98') 3476 print(output) 3477 self.assertIn('qdisc cake 3a: root', output) 3478 self.assertIn('bandwidth 500Mbit', output) 3479 self.assertIn('autorate-ingress', output) 3480 self.assertIn('diffserv8', output) 3481 self.assertIn('dual-dsthost', output) 3482 self.assertIn(' nat', output) 3483 self.assertIn(' wash', output) 3484 self.assertIn(' split-gso', output) 3485 self.assertIn(' raw', output) 3486 self.assertIn(' atm', output) 3487 self.assertIn('overhead 128', output) 3488 self.assertIn('mpu 20', output) 3489 self.assertIn('fwmark 0xff00', output) 3490 3491 @expectedFailureIfPIEIsNotAvailable() 3492 def test_qdisc_pie(self): 3493 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev') 3494 start_networkd() 3495 self.wait_online(['dummy98:routable']) 3496 3497 output = check_output('tc qdisc show dev dummy98') 3498 print(output) 3499 self.assertRegex(output, 'qdisc pie 3a: root') 3500 self.assertRegex(output, 'limit 200000') 3501 3502 @expectedFailureIfHHFIsNotAvailable() 3503 def test_qdisc_hhf(self): 3504 copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev') 3505 start_networkd() 3506 self.wait_online(['dummy98:routable']) 3507 3508 output = check_output('tc qdisc show dev dummy98') 3509 print(output) 3510 self.assertRegex(output, 'qdisc hhf 3a: root') 3511 self.assertRegex(output, 'limit 1022p') 3512 3513 @expectedFailureIfETSIsNotAvailable() 3514 def test_qdisc_ets(self): 3515 copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev') 3516 start_networkd() 3517 self.wait_online(['dummy98:routable']) 3518 3519 output = check_output('tc qdisc show dev dummy98') 3520 print(output) 3521 3522 self.assertRegex(output, 'qdisc ets 3a: root') 3523 self.assertRegex(output, 'bands 10 strict 3') 3524 self.assertRegex(output, 'quanta 1 2 3 4 5') 3525 self.assertRegex(output, 'priomap 3 4 5 6 7') 3526 3527 @expectedFailureIfFQPIEIsNotAvailable() 3528 def test_qdisc_fq_pie(self): 3529 copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev') 3530 start_networkd() 3531 self.wait_online(['dummy98:routable']) 3532 3533 output = check_output('tc qdisc show dev dummy98') 3534 print(output) 3535 3536 self.assertRegex(output, 'qdisc fq_pie 3a: root') 3537 self.assertRegex(output, 'limit 200000p') 3538 3539 def test_wait_online_ipv4(self): 3540 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network') 3541 start_networkd() 3542 3543 self.wait_online(['veth99:routable'], ipv4=True) 3544 3545 self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1) 3546 3547 def test_wait_online_ipv6(self): 3548 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix-with-delay.network', '25-ipv6ra-prefix-client-with-static-ipv4-address.network') 3549 start_networkd() 3550 3551 self.wait_online(['veth99:routable'], ipv6=True) 3552 3553 self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1) 3554 3555class NetworkdStateFileTests(unittest.TestCase, Utilities): 3556 links = [ 3557 'dummy98', 3558 ] 3559 3560 units = [ 3561 '12-dummy.netdev', 3562 '25-state-file-tests.network', 3563 ] 3564 3565 def setUp(self): 3566 remove_links(self.links) 3567 stop_networkd(show_logs=False) 3568 3569 def tearDown(self): 3570 remove_links(self.links) 3571 remove_unit_from_networkd_path(self.units) 3572 stop_networkd(show_logs=True) 3573 3574 def test_state_file(self): 3575 copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-state-file-tests.network') 3576 start_networkd() 3577 self.wait_online(['dummy98:routable']) 3578 3579 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env) 3580 print(output) 3581 ifindex = output.split()[0] 3582 3583 path = os.path.join('/run/systemd/netif/links/', ifindex) 3584 self.assertTrue(os.path.exists(path)) 3585 3586 # make link state file updated 3587 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env) 3588 3589 # TODO: check json string 3590 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 3591 3592 with open(path) as f: 3593 data = f.read() 3594 self.assertRegex(data, r'IPV4_ADDRESS_STATE=routable') 3595 self.assertRegex(data, r'IPV6_ADDRESS_STATE=routable') 3596 self.assertRegex(data, r'ADMIN_STATE=configured') 3597 self.assertRegex(data, r'OPER_STATE=routable') 3598 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes') 3599 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable') 3600 self.assertRegex(data, r'REQUIRED_FAMILY_FOR_ONLINE=both') 3601 self.assertRegex(data, r'ACTIVATION_POLICY=up') 3602 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/25-state-file-tests.network') 3603 self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') 3604 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') 3605 self.assertRegex(data, r'DOMAINS=hogehoge') 3606 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') 3607 self.assertRegex(data, r'LLMNR=no') 3608 self.assertRegex(data, r'MDNS=yes') 3609 self.assertRegex(data, r'DNSSEC=no') 3610 3611 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env) 3612 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env) 3613 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env) 3614 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env) 3615 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env) 3616 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env) 3617 3618 # TODO: check json string 3619 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 3620 3621 with open(path) as f: 3622 data = f.read() 3623 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333') 3624 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org') 3625 self.assertRegex(data, r'DOMAINS=hogehogehoge') 3626 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') 3627 self.assertRegex(data, r'LLMNR=yes') 3628 self.assertRegex(data, r'MDNS=no') 3629 self.assertRegex(data, r'DNSSEC=yes') 3630 3631 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env) 3632 3633 # TODO: check json string 3634 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 3635 3636 with open(path) as f: 3637 data = f.read() 3638 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333') 3639 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') 3640 self.assertRegex(data, r'DOMAINS=hogehogehoge') 3641 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') 3642 self.assertRegex(data, r'LLMNR=yes') 3643 self.assertRegex(data, r'MDNS=no') 3644 self.assertRegex(data, r'DNSSEC=yes') 3645 3646 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env) 3647 3648 # TODO: check json string 3649 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 3650 3651 with open(path) as f: 3652 data = f.read() 3653 self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') 3654 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') 3655 self.assertRegex(data, r'DOMAINS=hogehoge') 3656 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') 3657 self.assertRegex(data, r'LLMNR=no') 3658 self.assertRegex(data, r'MDNS=yes') 3659 self.assertRegex(data, r'DNSSEC=no') 3660 3661class NetworkdBondTests(unittest.TestCase, Utilities): 3662 links = [ 3663 'bond199', 3664 'bond99', 3665 'dummy98', 3666 'test1'] 3667 3668 units = [ 3669 '11-dummy.netdev', 3670 '12-dummy.netdev', 3671 '23-active-slave.network', 3672 '23-bond199.network', 3673 '23-keep-master.network', 3674 '23-primary-slave.network', 3675 '25-bond-active-backup-slave.netdev', 3676 '25-bond.netdev', 3677 '25-bond99.network', 3678 '25-bond-slave.network'] 3679 3680 def setUp(self): 3681 remove_links(self.links) 3682 stop_networkd(show_logs=False) 3683 3684 def tearDown(self): 3685 remove_links(self.links) 3686 remove_unit_from_networkd_path(self.units) 3687 stop_networkd(show_logs=True) 3688 3689 def test_bond_keep_master(self): 3690 check_output('ip link add bond199 type bond mode active-backup') 3691 check_output('ip link add dummy98 type dummy') 3692 check_output('ip link set dummy98 master bond199') 3693 3694 copy_unit_to_networkd_unit_path('23-keep-master.network') 3695 start_networkd() 3696 self.wait_online(['dummy98:enslaved']) 3697 3698 output = check_output('ip -d link show bond199') 3699 print(output) 3700 self.assertRegex(output, 'active_slave dummy98') 3701 3702 output = check_output('ip -d link show dummy98') 3703 print(output) 3704 self.assertRegex(output, 'master bond199') 3705 3706 def test_bond_active_slave(self): 3707 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') 3708 start_networkd() 3709 self.wait_online(['dummy98:enslaved', 'bond199:degraded']) 3710 3711 output = check_output('ip -d link show bond199') 3712 print(output) 3713 self.assertRegex(output, 'active_slave dummy98') 3714 3715 def test_bond_primary_slave(self): 3716 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') 3717 start_networkd() 3718 self.wait_online(['dummy98:enslaved', 'bond199:degraded']) 3719 3720 output = check_output('ip -d link show bond199') 3721 print(output) 3722 self.assertRegex(output, 'primary dummy98') 3723 3724 def test_bond_operstate(self): 3725 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev', 3726 '25-bond99.network','25-bond-slave.network') 3727 start_networkd() 3728 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable']) 3729 3730 output = check_output('ip -d link show dummy98') 3731 print(output) 3732 self.assertRegex(output, 'SLAVE,UP,LOWER_UP') 3733 3734 output = check_output('ip -d link show test1') 3735 print(output) 3736 self.assertRegex(output, 'SLAVE,UP,LOWER_UP') 3737 3738 output = check_output('ip -d link show bond99') 3739 print(output) 3740 self.assertRegex(output, 'MASTER,UP,LOWER_UP') 3741 3742 self.wait_operstate('dummy98', 'enslaved') 3743 self.wait_operstate('test1', 'enslaved') 3744 self.wait_operstate('bond99', 'routable') 3745 3746 check_output('ip link set dummy98 down') 3747 3748 self.wait_operstate('dummy98', 'off') 3749 self.wait_operstate('test1', 'enslaved') 3750 self.wait_operstate('bond99', 'degraded-carrier') 3751 3752 check_output('ip link set dummy98 up') 3753 3754 self.wait_operstate('dummy98', 'enslaved') 3755 self.wait_operstate('test1', 'enslaved') 3756 self.wait_operstate('bond99', 'routable') 3757 3758 check_output('ip link set dummy98 down') 3759 check_output('ip link set test1 down') 3760 3761 self.wait_operstate('dummy98', 'off') 3762 self.wait_operstate('test1', 'off') 3763 3764 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False): 3765 # Huh? Kernel does not recognize that all slave interfaces are down? 3766 # Let's confirm that networkd's operstate is consistent with ip's result. 3767 self.assertNotRegex(output, 'NO-CARRIER') 3768 3769class NetworkdBridgeTests(unittest.TestCase, Utilities): 3770 links = [ 3771 'bridge99', 3772 'dummy98', 3773 'test1', 3774 'vlan99', 3775 ] 3776 3777 units = [ 3778 '11-dummy.netdev', 3779 '12-dummy.netdev', 3780 '21-vlan.netdev', 3781 '21-vlan.network', 3782 '23-keep-master.network', 3783 '26-bridge.netdev', 3784 '26-bridge-configure-without-carrier.network', 3785 '26-bridge-issue-20373.netdev', 3786 '26-bridge-mdb-master.network', 3787 '26-bridge-mdb-slave.network', 3788 '26-bridge-slave-interface-1.network', 3789 '26-bridge-slave-interface-2.network', 3790 '26-bridge-vlan-master-issue-20373.network', 3791 '26-bridge-vlan-master.network', 3792 '26-bridge-vlan-slave-issue-20373.network', 3793 '26-bridge-vlan-slave.network', 3794 '25-bridge99-ignore-carrier-loss.network', 3795 '25-bridge99.network' 3796 ] 3797 3798 routing_policy_rule_tables = ['100'] 3799 3800 def setUp(self): 3801 remove_routing_policy_rule_tables(self.routing_policy_rule_tables) 3802 remove_links(self.links) 3803 stop_networkd(show_logs=False) 3804 3805 def tearDown(self): 3806 remove_routing_policy_rule_tables(self.routing_policy_rule_tables) 3807 remove_links(self.links) 3808 remove_unit_from_networkd_path(self.units) 3809 stop_networkd(show_logs=True) 3810 3811 def test_bridge_vlan(self): 3812 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network', 3813 '26-bridge.netdev', '26-bridge-vlan-master.network') 3814 start_networkd() 3815 self.wait_online(['test1:enslaved', 'bridge99:degraded']) 3816 3817 output = check_output('bridge vlan show dev test1') 3818 print(output) 3819 self.assertNotRegex(output, '4063') 3820 for i in range(4064, 4095): 3821 self.assertRegex(output, f'{i}') 3822 self.assertNotRegex(output, '4095') 3823 3824 output = check_output('bridge vlan show dev bridge99') 3825 print(output) 3826 self.assertNotRegex(output, '4059') 3827 for i in range(4060, 4095): 3828 self.assertRegex(output, f'{i}') 3829 self.assertNotRegex(output, '4095') 3830 3831 def test_bridge_vlan_issue_20373(self): 3832 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network', 3833 '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network', 3834 '21-vlan.netdev', '21-vlan.network') 3835 start_networkd() 3836 self.wait_online(['test1:enslaved', 'bridge99:degraded', 'vlan99:routable']) 3837 3838 output = check_output('bridge vlan show dev test1') 3839 print(output) 3840 self.assertIn('100 PVID Egress Untagged', output) 3841 self.assertIn('560', output) 3842 self.assertIn('600', output) 3843 3844 output = check_output('bridge vlan show dev bridge99') 3845 print(output) 3846 self.assertIn('1 PVID Egress Untagged', output) 3847 self.assertIn('100', output) 3848 self.assertIn('600', output) 3849 3850 def test_bridge_mdb(self): 3851 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network', 3852 '26-bridge.netdev', '26-bridge-mdb-master.network') 3853 start_networkd() 3854 self.wait_online(['test1:enslaved', 'bridge99:degraded']) 3855 3856 output = check_output('bridge mdb show dev bridge99') 3857 print(output) 3858 self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064') 3859 self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065') 3860 3861 # Old kernel may not support bridge MDB entries on bridge master 3862 if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0: 3863 self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066') 3864 self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067') 3865 3866 def test_bridge_keep_master(self): 3867 check_output('ip link add bridge99 type bridge') 3868 check_output('ip link set bridge99 up') 3869 check_output('ip link add dummy98 type dummy') 3870 check_output('ip link set dummy98 master bridge99') 3871 3872 copy_unit_to_networkd_unit_path('23-keep-master.network') 3873 start_networkd() 3874 self.wait_online(['dummy98:enslaved']) 3875 3876 output = check_output('ip -d link show dummy98') 3877 print(output) 3878 self.assertRegex(output, 'master bridge99') 3879 self.assertRegex(output, 'bridge') 3880 3881 output = check_output('bridge -d link show dummy98') 3882 print(output) 3883 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400') 3884 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1') 3885 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1') 3886 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1') 3887 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0') 3888 # CONFIG_BRIDGE_IGMP_SNOOPING=y 3889 if os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast'): 3890 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1') 3891 if os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress'): 3892 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1') 3893 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0') 3894 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23') 3895 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1') 3896 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1') 3897 3898 def test_bridge_property(self): 3899 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', 3900 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', 3901 '25-bridge99.network') 3902 start_networkd() 3903 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable']) 3904 3905 output = check_output('ip -d link show test1') 3906 print(output) 3907 self.assertRegex(output, 'master') 3908 self.assertRegex(output, 'bridge') 3909 3910 output = check_output('ip -d link show dummy98') 3911 print(output) 3912 self.assertRegex(output, 'master') 3913 self.assertRegex(output, 'bridge') 3914 3915 output = check_output('ip addr show bridge99') 3916 print(output) 3917 self.assertRegex(output, '192.168.0.15/24') 3918 3919 output = check_output('bridge -d link show dummy98') 3920 print(output) 3921 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400') 3922 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1') 3923 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'isolated'), '1') 3924 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1') 3925 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1') 3926 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0') 3927 # CONFIG_BRIDGE_IGMP_SNOOPING=y 3928 if os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast'): 3929 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1') 3930 if os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress'): 3931 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1') 3932 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0') 3933 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23') 3934 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1') 3935 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1') 3936 3937 output = check_output('bridge -d link show test1') 3938 print(output) 3939 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0') 3940 3941 check_output('ip address add 192.168.0.16/24 dev bridge99') 3942 time.sleep(1) 3943 3944 output = check_output('ip addr show bridge99') 3945 print(output) 3946 self.assertRegex(output, '192.168.0.16/24') 3947 3948 # for issue #6088 3949 print('### ip -6 route list table all dev bridge99') 3950 output = check_output('ip -6 route list table all dev bridge99') 3951 print(output) 3952 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium') 3953 3954 self.assertEqual(call('ip link del test1'), 0) 3955 3956 self.wait_operstate('bridge99', 'degraded-carrier') 3957 3958 check_output('ip link del dummy98') 3959 3960 self.wait_operstate('bridge99', 'no-carrier') 3961 3962 output = check_output('ip address show bridge99') 3963 print(output) 3964 self.assertRegex(output, 'NO-CARRIER') 3965 self.assertNotRegex(output, '192.168.0.15/24') 3966 self.assertRegex(output, '192.168.0.16/24') # foreign address is kept 3967 3968 print('### ip -6 route list table all dev bridge99') 3969 output = check_output('ip -6 route list table all dev bridge99') 3970 print(output) 3971 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium') 3972 3973 def test_bridge_configure_without_carrier(self): 3974 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network', 3975 '11-dummy.netdev') 3976 start_networkd() 3977 3978 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations 3979 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']: 3980 with self.subTest(test=test): 3981 if test == 'no-slave': 3982 # bridge has no slaves; it's up but *might* not have carrier 3983 self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30) 3984 # due to a bug in the kernel, newly-created bridges are brought up 3985 # *with* carrier, unless they have had any setting changed; e.g. 3986 # their mac set, priority set, etc. Then, they will lose carrier 3987 # as soon as a (down) slave interface is added, and regain carrier 3988 # again once the slave interface is brought up. 3989 #self.check_link_attr('bridge99', 'carrier', '0') 3990 elif test == 'add-slave': 3991 # add slave to bridge, but leave it down; bridge is definitely no-carrier 3992 self.check_link_attr('test1', 'operstate', 'down') 3993 check_output('ip link set dev test1 master bridge99') 3994 self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None) 3995 self.check_link_attr('bridge99', 'carrier', '0') 3996 elif test == 'slave-up': 3997 # bring up slave, which will have carrier; bridge gains carrier 3998 check_output('ip link set dev test1 up') 3999 self.wait_online(['bridge99:routable']) 4000 self.check_link_attr('bridge99', 'carrier', '1') 4001 elif test == 'slave-no-carrier': 4002 # drop slave carrier; bridge loses carrier 4003 check_output('ip link set dev test1 carrier off') 4004 self.wait_online(['bridge99:no-carrier:no-carrier']) 4005 self.check_link_attr('bridge99', 'carrier', '0') 4006 elif test == 'slave-carrier': 4007 # restore slave carrier; bridge gains carrier 4008 check_output('ip link set dev test1 carrier on') 4009 self.wait_online(['bridge99:routable']) 4010 self.check_link_attr('bridge99', 'carrier', '1') 4011 elif test == 'slave-down': 4012 # bring down slave; bridge loses carrier 4013 check_output('ip link set dev test1 down') 4014 self.wait_online(['bridge99:no-carrier:no-carrier']) 4015 self.check_link_attr('bridge99', 'carrier', '0') 4016 4017 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env) 4018 self.assertRegex(output, '10.1.2.3') 4019 self.assertRegex(output, '10.1.2.1') 4020 4021 def test_bridge_ignore_carrier_loss(self): 4022 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', 4023 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', 4024 '25-bridge99-ignore-carrier-loss.network') 4025 start_networkd() 4026 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable']) 4027 4028 check_output('ip address add 192.168.0.16/24 dev bridge99') 4029 time.sleep(1) 4030 4031 check_output('ip link del test1') 4032 check_output('ip link del dummy98') 4033 time.sleep(3) 4034 4035 output = check_output('ip address show bridge99') 4036 print(output) 4037 self.assertRegex(output, 'NO-CARRIER') 4038 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99') 4039 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99') 4040 4041 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self): 4042 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network', 4043 '25-bridge99-ignore-carrier-loss.network') 4044 start_networkd() 4045 self.wait_online(['bridge99:no-carrier']) 4046 4047 for trial in range(4): 4048 check_output('ip link add dummy98 type dummy') 4049 check_output('ip link set dummy98 up') 4050 if trial < 3: 4051 check_output('ip link del dummy98') 4052 4053 self.wait_online(['bridge99:routable', 'dummy98:enslaved']) 4054 4055 output = check_output('ip address show bridge99') 4056 print(output) 4057 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99') 4058 4059 output = check_output('ip rule list table 100') 4060 print(output) 4061 self.assertIn('from all to 8.8.8.8 lookup 100', output) 4062 4063class NetworkdSRIOVTests(unittest.TestCase, Utilities): 4064 units = [ 4065 '25-sriov-udev.network', 4066 '25-sriov.link', 4067 '25-sriov.network', 4068 ] 4069 4070 def setUp(self): 4071 stop_networkd(show_logs=False) 4072 call('rmmod netdevsim', stderr=subprocess.DEVNULL) 4073 4074 def tearDown(self): 4075 remove_unit_from_networkd_path(self.units) 4076 stop_networkd(show_logs=True) 4077 call('rmmod netdevsim', stderr=subprocess.DEVNULL) 4078 4079 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable() 4080 def test_sriov(self): 4081 call('modprobe netdevsim', stderr=subprocess.DEVNULL) 4082 4083 with open('/sys/bus/netdevsim/new_device', mode='w') as f: 4084 f.write('99 1') 4085 4086 call('udevadm settle') 4087 call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL) 4088 with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f: 4089 f.write('3') 4090 4091 copy_unit_to_networkd_unit_path('25-sriov.network') 4092 start_networkd() 4093 self.wait_online(['eni99np1:routable']) 4094 4095 output = check_output('ip link show dev eni99np1') 4096 print(output) 4097 self.assertRegex(output, 4098 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4099 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' 4100 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off' 4101 ) 4102 4103 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable() 4104 def test_sriov_udev(self): 4105 call('modprobe netdevsim', stderr=subprocess.DEVNULL) 4106 4107 copy_unit_to_networkd_unit_path('25-sriov.link', '25-sriov-udev.network') 4108 call('udevadm control --reload') 4109 4110 with open('/sys/bus/netdevsim/new_device', mode='w') as f: 4111 f.write('99 1') 4112 4113 start_networkd() 4114 self.wait_online(['eni99np1:routable']) 4115 4116 output = check_output('ip link show dev eni99np1') 4117 print(output) 4118 self.assertRegex(output, 4119 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4120 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' 4121 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off' 4122 ) 4123 self.assertNotIn('vf 3', output) 4124 self.assertNotIn('vf 4', output) 4125 4126 with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f: 4127 f.write('[Link]\nSR-IOVVirtualFunctions=4\n') 4128 4129 call('udevadm control --reload') 4130 call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') 4131 4132 output = check_output('ip link show dev eni99np1') 4133 print(output) 4134 self.assertRegex(output, 4135 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4136 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' 4137 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *' 4138 'vf 3' 4139 ) 4140 self.assertNotIn('vf 4', output) 4141 4142 with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f: 4143 f.write('[Link]\nSR-IOVVirtualFunctions=\n') 4144 4145 call('udevadm control --reload') 4146 call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') 4147 4148 output = check_output('ip link show dev eni99np1') 4149 print(output) 4150 self.assertRegex(output, 4151 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4152 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' 4153 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *' 4154 'vf 3' 4155 ) 4156 self.assertNotIn('vf 4', output) 4157 4158 with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f: 4159 f.write('[Link]\nSR-IOVVirtualFunctions=2\n') 4160 4161 call('udevadm control --reload') 4162 call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') 4163 4164 output = check_output('ip link show dev eni99np1') 4165 print(output) 4166 self.assertRegex(output, 4167 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4168 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off' 4169 ) 4170 self.assertNotIn('vf 2', output) 4171 self.assertNotIn('vf 3', output) 4172 self.assertNotIn('vf 4', output) 4173 4174 with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f: 4175 f.write('[Link]\nSR-IOVVirtualFunctions=\n') 4176 4177 call('udevadm control --reload') 4178 call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1') 4179 4180 output = check_output('ip link show dev eni99np1') 4181 print(output) 4182 self.assertRegex(output, 4183 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *' 4184 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' 4185 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off' 4186 ) 4187 self.assertNotIn('vf 3', output) 4188 self.assertNotIn('vf 4', output) 4189 4190class NetworkdLLDPTests(unittest.TestCase, Utilities): 4191 links = ['veth99'] 4192 4193 units = [ 4194 '23-emit-lldp.network', 4195 '24-lldp.network', 4196 '25-veth.netdev'] 4197 4198 def setUp(self): 4199 remove_links(self.links) 4200 stop_networkd(show_logs=False) 4201 4202 def tearDown(self): 4203 remove_links(self.links) 4204 remove_unit_from_networkd_path(self.units) 4205 stop_networkd(show_logs=True) 4206 4207 def test_lldp(self): 4208 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev') 4209 start_networkd() 4210 self.wait_online(['veth99:degraded', 'veth-peer:degraded']) 4211 4212 for trial in range(10): 4213 if trial > 0: 4214 time.sleep(1) 4215 4216 output = check_output(*networkctl_cmd, 'lldp', env=env) 4217 print(output) 4218 if re.search(r'veth99 .* veth-peer', output): 4219 break 4220 else: 4221 self.fail() 4222 4223class NetworkdRATests(unittest.TestCase, Utilities): 4224 links = ['veth99'] 4225 4226 units = [ 4227 '25-veth.netdev', 4228 '25-ipv6-prefix.network', 4229 '25-ipv6-prefix-veth.network', 4230 '25-ipv6-prefix-veth-token-static.network', 4231 '25-ipv6-prefix-veth-token-prefixstable.network', 4232 '25-ipv6-prefix-veth-token-prefixstable-without-address.network'] 4233 4234 def setUp(self): 4235 remove_links(self.links) 4236 stop_networkd(show_logs=False) 4237 4238 def tearDown(self): 4239 remove_links(self.links) 4240 remove_unit_from_networkd_path(self.units) 4241 stop_networkd(show_logs=True) 4242 4243 def test_ipv6_prefix_delegation(self): 4244 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth.network') 4245 start_networkd() 4246 self.wait_online(['veth99:routable', 'veth-peer:degraded']) 4247 4248 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) 4249 print(output) 4250 self.assertRegex(output, 'fe80::') 4251 self.assertRegex(output, '2002:da8:1::1') 4252 4253 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env) 4254 print(output) 4255 self.assertIn('hogehoge.test', output) 4256 4257 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4258 print(output) 4259 self.assertRegex(output, '2002:da8:1:0') 4260 4261 def test_ipv6_token_static(self): 4262 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network') 4263 start_networkd() 4264 self.wait_online(['veth99:routable', 'veth-peer:degraded']) 4265 4266 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4267 print(output) 4268 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') 4269 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe') 4270 self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d') 4271 self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe') 4272 4273 def test_ipv6_token_prefixstable(self): 4274 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable.network') 4275 start_networkd() 4276 self.wait_online(['veth99:routable', 'veth-peer:degraded']) 4277 4278 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4279 print(output) 4280 self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output) 4281 self.assertIn('2002:da8:2:0:1034:56ff:fe78:9abc', output) # EUI64 4282 4283 def test_ipv6_token_prefixstable_without_address(self): 4284 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable-without-address.network') 4285 start_networkd() 4286 self.wait_online(['veth99:routable', 'veth-peer:degraded']) 4287 4288 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4289 print(output) 4290 self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output) 4291 self.assertIn('2002:da8:2:0:f689:561a:8eda:7443', output) 4292 4293class NetworkdDHCPServerTests(unittest.TestCase, Utilities): 4294 links = [ 4295 'dummy98', 4296 'veth99', 4297 ] 4298 4299 units = [ 4300 '12-dummy.netdev', 4301 '25-veth.netdev', 4302 '25-dhcp-client.network', 4303 '25-dhcp-client-static-lease.network', 4304 '25-dhcp-client-timezone-router.network', 4305 '25-dhcp-server.network', 4306 '25-dhcp-server-downstream.network', 4307 '25-dhcp-server-static-lease.network', 4308 '25-dhcp-server-timezone-router.network', 4309 '25-dhcp-server-uplink.network', 4310 ] 4311 4312 def setUp(self): 4313 remove_links(self.links) 4314 stop_networkd(show_logs=False) 4315 4316 def tearDown(self): 4317 remove_links(self.links) 4318 remove_unit_from_networkd_path(self.units) 4319 stop_networkd(show_logs=True) 4320 4321 def test_dhcp_server(self): 4322 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server.network') 4323 start_networkd() 4324 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4325 4326 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4327 print(output) 4328 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)') 4329 self.assertIn('Gateway: 192.168.5.3', output) 4330 self.assertRegex(output, 'DNS: 192.168.5.1\n *192.168.5.10') 4331 self.assertRegex(output, 'NTP: 192.168.5.1\n *192.168.5.11') 4332 4333 def test_dhcp_server_with_uplink(self): 4334 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-downstream.network', 4335 '12-dummy.netdev', '25-dhcp-server-uplink.network') 4336 start_networkd() 4337 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4338 4339 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4340 print(output) 4341 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)') 4342 self.assertIn('Gateway: 192.168.5.3', output) 4343 self.assertIn('DNS: 192.168.5.1', output) 4344 self.assertIn('NTP: 192.168.5.1', output) 4345 4346 def test_emit_router_timezone(self): 4347 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client-timezone-router.network', '25-dhcp-server-timezone-router.network') 4348 start_networkd() 4349 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4350 4351 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4352 print(output) 4353 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)') 4354 self.assertIn('Gateway: 192.168.5.1', output) 4355 self.assertIn('Time Zone: Europe/Berlin', output) 4356 4357 def test_dhcp_server_static_lease(self): 4358 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-client-static-lease.network', '25-dhcp-server-static-lease.network') 4359 start_networkd() 4360 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4361 4362 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4363 print(output) 4364 self.assertIn('Address: 10.1.1.200 (DHCP4 via 10.1.1.1)', output) 4365 4366class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities): 4367 links = [ 4368 'client', 4369 'server', 4370 'client-peer', 4371 'server-peer', 4372 ] 4373 4374 units = [ 4375 '25-agent-veth-client.netdev', 4376 '25-agent-veth-server.netdev', 4377 '25-agent-client.network', 4378 '25-agent-server.network', 4379 '25-agent-client-peer.network', 4380 '25-agent-server-peer.network', 4381 ] 4382 4383 def setUp(self): 4384 remove_links(self.links) 4385 stop_networkd(show_logs=False) 4386 4387 def tearDown(self): 4388 remove_links(self.links) 4389 remove_unit_from_networkd_path(self.units) 4390 stop_networkd(show_logs=True) 4391 4392 def test_relay_agent(self): 4393 copy_unit_to_networkd_unit_path(*self.units) 4394 start_networkd() 4395 4396 self.wait_online(['client:routable']) 4397 4398 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env) 4399 print(output) 4400 self.assertRegex(output, r'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)') 4401 4402class NetworkdDHCPClientTests(unittest.TestCase, Utilities): 4403 links = [ 4404 'veth99', 4405 'vrf99'] 4406 4407 units = [ 4408 '25-veth.netdev', 4409 '25-vrf.netdev', 4410 '25-vrf.network', 4411 '25-dhcp-client-allow-list.network', 4412 '25-dhcp-client-anonymize.network', 4413 '25-dhcp-client-decline.network', 4414 '25-dhcp-client-gateway-ipv4.network', 4415 '25-dhcp-client-gateway-ipv6.network', 4416 '25-dhcp-client-gateway-onlink-implicit.network', 4417 '25-dhcp-client-ipv4-dhcp-settings.network', 4418 '25-dhcp-client-ipv4-only-ipv6-disabled.network', 4419 '25-dhcp-client-ipv4-only.network', 4420 '25-dhcp-client-ipv4-use-routes-use-gateway.network', 4421 '25-dhcp-client-ipv6-only.network', 4422 '25-dhcp-client-keep-configuration-dhcp-on-stop.network', 4423 '25-dhcp-client-keep-configuration-dhcp.network', 4424 '25-dhcp-client-listen-port.network', 4425 '25-dhcp-client-reassign-static-routes-ipv4.network', 4426 '25-dhcp-client-reassign-static-routes-ipv6.network', 4427 '25-dhcp-client-route-metric.network', 4428 '25-dhcp-client-route-table.network', 4429 '25-dhcp-client-use-dns-ipv4-and-ra.network', 4430 '25-dhcp-client-use-dns-ipv4.network', 4431 '25-dhcp-client-use-dns-no.network', 4432 '25-dhcp-client-use-dns-yes.network', 4433 '25-dhcp-client-use-domains.network', 4434 '25-dhcp-client-vrf.network', 4435 '25-dhcp-client-with-ipv4ll.network', 4436 '25-dhcp-client-with-static-address.network', 4437 '25-dhcp-client.network', 4438 '25-dhcp-server-decline.network', 4439 '25-dhcp-server-veth-peer.network', 4440 '25-dhcp-v4-server-veth-peer.network', 4441 '25-static.network'] 4442 4443 def setUp(self): 4444 stop_dnsmasq() 4445 remove_dnsmasq_lease_file() 4446 remove_dnsmasq_log_file() 4447 remove_links(self.links) 4448 stop_networkd(show_logs=False) 4449 4450 def tearDown(self): 4451 stop_dnsmasq() 4452 remove_dnsmasq_lease_file() 4453 remove_dnsmasq_log_file() 4454 remove_links(self.links) 4455 remove_unit_from_networkd_path(self.units) 4456 stop_networkd(show_logs=True) 4457 4458 def test_dhcp_client_ipv6_only(self): 4459 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only.network') 4460 4461 start_networkd() 4462 self.wait_online(['veth-peer:carrier']) 4463 start_dnsmasq() 4464 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4465 4466 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4467 print(output) 4468 self.assertRegex(output, '2600::') 4469 self.assertNotRegex(output, '192.168.5') 4470 4471 output = check_output('ip addr show dev veth99') 4472 print(output) 4473 self.assertRegex(output, '2600::') 4474 self.assertNotRegex(output, '192.168.5') 4475 self.assertNotRegex(output, 'tentative') 4476 4477 # Confirm that ipv6 token is not set in the kernel 4478 output = check_output('ip token show dev veth99') 4479 print(output) 4480 self.assertRegex(output, 'token :: dev veth99') 4481 4482 def test_dhcp_client_ipv4_only(self): 4483 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only-ipv6-disabled.network') 4484 4485 start_networkd() 4486 self.wait_online(['veth-peer:carrier']) 4487 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m') 4488 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4489 4490 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4491 print(output) 4492 self.assertNotRegex(output, '2600::') 4493 self.assertRegex(output, '192.168.5') 4494 self.assertRegex(output, '192.168.5.6') 4495 self.assertRegex(output, '192.168.5.7') 4496 4497 # checking routes to DNS servers 4498 output = check_output('ip route show dev veth99') 4499 print(output) 4500 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024') 4501 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024') 4502 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024') 4503 4504 stop_dnsmasq() 4505 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m') 4506 4507 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 4508 print('Wait for the dynamic address to be renewed') 4509 time.sleep(125) 4510 4511 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4512 4513 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4514 print(output) 4515 self.assertNotRegex(output, '2600::') 4516 self.assertRegex(output, '192.168.5') 4517 self.assertNotRegex(output, '192.168.5.6') 4518 self.assertRegex(output, '192.168.5.7') 4519 self.assertRegex(output, '192.168.5.8') 4520 4521 # checking routes to DNS servers 4522 output = check_output('ip route show dev veth99') 4523 print(output) 4524 self.assertNotRegex(output, r'192.168.5.6') 4525 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024') 4526 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024') 4527 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024') 4528 4529 def test_dhcp_client_ipv4_use_routes_gateway(self): 4530 for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4): 4531 self.setUp() 4532 with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless): 4533 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless) 4534 self.tearDown() 4535 4536 def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless): 4537 testunit = '25-dhcp-client-ipv4-use-routes-use-gateway.network' 4538 testunits = ['25-veth.netdev', '25-dhcp-server-veth-peer.network', testunit] 4539 testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf') 4540 testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf') 4541 testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf') 4542 copy_unit_to_networkd_unit_path(*testunits, dropins=False) 4543 4544 start_networkd() 4545 self.wait_online(['veth-peer:carrier']) 4546 additional_options = '--dhcp-option=option:dns-server,192.168.5.10,8.8.8.8 --dhcp-option=option:ntp-server,192.168.5.11,9.9.9.9 --dhcp-option=option:static-route,192.168.5.100,192.168.5.2,8.8.8.8,192.168.5.3' 4547 if classless: 4548 additional_options += ' --dhcp-option=option:classless-static-route,0.0.0.0/0,192.168.5.4,8.0.0.0/8,192.168.5.5' 4549 start_dnsmasq(additional_options=additional_options, lease_time='2m') 4550 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4551 4552 output = check_output('ip -4 route show dev veth99') 4553 print(output) 4554 4555 # Check UseRoutes= 4556 if use_routes: 4557 if classless: 4558 self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024') 4559 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024') 4560 self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4561 self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4562 else: 4563 self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4564 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024') 4565 self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4566 else: 4567 self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024') 4568 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024') 4569 self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4570 self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4571 self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4572 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024') 4573 self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4574 4575 # Check UseGateway= 4576 if use_gateway and (not classless or not use_routes): 4577 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') 4578 else: 4579 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') 4580 4581 # Check route to gateway 4582 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes): 4583 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4584 else: 4585 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4586 4587 # Check RoutesToDNS= and RoutesToNTP= 4588 if dns_and_ntp_routes: 4589 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4590 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4591 if classless and use_routes: 4592 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024') 4593 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024') 4594 else: 4595 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') 4596 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') 4597 else: 4598 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4599 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4600 self.assertNotRegex(output, r'8.8.8.8 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024') 4601 self.assertNotRegex(output, r'9.9.9.9 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024') 4602 4603 # TODO: check json string 4604 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 4605 4606 def test_dhcp_client_ipv4_ipv6(self): 4607 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network') 4608 start_networkd() 4609 self.wait_online(['veth-peer:carrier']) 4610 start_dnsmasq() 4611 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4612 4613 # link become 'routable' when at least one protocol provide an valid address. 4614 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 4615 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 4616 4617 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4618 print(output) 4619 self.assertRegex(output, '2600::') 4620 self.assertRegex(output, '192.168.5') 4621 4622 def test_dhcp_client_settings(self): 4623 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-dhcp-settings.network') 4624 4625 start_networkd() 4626 self.wait_online(['veth-peer:carrier']) 4627 start_dnsmasq() 4628 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4629 4630 print('## ip address show dev veth99') 4631 output = check_output('ip address show dev veth99') 4632 print(output) 4633 self.assertRegex(output, '12:34:56:78:9a:bc') 4634 self.assertRegex(output, '192.168.5') 4635 self.assertRegex(output, '1492') 4636 self.assertRegex(output, 'test-label') 4637 4638 print('## ip route show table main dev veth99') 4639 output = check_output('ip route show table main dev veth99') 4640 print(output) 4641 # See issue #8726 4642 main_table_is_empty = output == '' 4643 if not main_table_is_empty: 4644 self.assertNotRegex(output, 'proto dhcp') 4645 4646 print('## ip route show table 211 dev veth99') 4647 output = check_output('ip route show table 211 dev veth99') 4648 print(output) 4649 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp') 4650 if main_table_is_empty: 4651 self.assertRegex(output, '192.168.5.0/24 proto dhcp') 4652 self.assertRegex(output, '192.168.5.1 proto dhcp scope link') 4653 4654 print('## dnsmasq log') 4655 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True)) 4656 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc')) 4657 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname')) 4658 self.assertTrue(search_words_in_dnsmasq_log('26:mtu')) 4659 4660 def test_dhcp_client_settings_anonymize(self): 4661 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-anonymize.network') 4662 start_networkd() 4663 self.wait_online(['veth-peer:carrier']) 4664 start_dnsmasq() 4665 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4666 4667 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True)) 4668 self.assertFalse(search_words_in_dnsmasq_log('test-hostname')) 4669 self.assertFalse(search_words_in_dnsmasq_log('26:mtu')) 4670 4671 def test_dhcp_client_listen_port(self): 4672 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-listen-port.network') 4673 start_networkd() 4674 self.wait_online(['veth-peer:carrier']) 4675 start_dnsmasq('--dhcp-alternate-port=67,5555') 4676 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4677 4678 output = check_output('ip -4 address show dev veth99') 4679 print(output) 4680 self.assertRegex(output, '192.168.5.* dynamic') 4681 4682 def test_dhcp_client_with_static_address(self): 4683 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-v4-server-veth-peer.network', 4684 '25-dhcp-client-with-static-address.network') 4685 start_networkd() 4686 self.wait_online(['veth-peer:carrier']) 4687 start_dnsmasq() 4688 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4689 4690 output = check_output('ip address show dev veth99 scope global') 4691 print(output) 4692 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99') 4693 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic veth99') 4694 4695 output = check_output('ip route show dev veth99') 4696 print(output) 4697 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') 4698 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250') 4699 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') 4700 4701 def test_dhcp_route_table_id(self): 4702 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-v4-server-veth-peer.network', '25-dhcp-client-route-table.network') 4703 start_networkd() 4704 self.wait_online(['veth-peer:carrier']) 4705 start_dnsmasq() 4706 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4707 4708 output = check_output('ip route show table 12') 4709 print(output) 4710 self.assertRegex(output, 'veth99 proto dhcp') 4711 self.assertRegex(output, '192.168.5.1') 4712 4713 def test_dhcp_route_metric(self): 4714 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-v4-server-veth-peer.network', '25-dhcp-client-route-metric.network') 4715 start_networkd() 4716 self.wait_online(['veth-peer:carrier']) 4717 start_dnsmasq() 4718 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4719 4720 output = check_output('ip route show dev veth99') 4721 print(output) 4722 self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output) 4723 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output) 4724 self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output) 4725 4726 def test_dhcp_client_reassign_static_routes_ipv4(self): 4727 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 4728 '25-dhcp-client-reassign-static-routes-ipv4.network') 4729 start_networkd() 4730 self.wait_online(['veth-peer:carrier']) 4731 start_dnsmasq(lease_time='2m') 4732 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4733 4734 output = check_output('ip address show dev veth99 scope global') 4735 print(output) 4736 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 4737 4738 output = check_output('ip route show dev veth99') 4739 print(output) 4740 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*') 4741 self.assertRegex(output, r'192.168.5.0/24 proto static') 4742 self.assertRegex(output, r'192.168.6.0/24 proto static') 4743 self.assertRegex(output, r'192.168.7.0/24 proto static') 4744 4745 stop_dnsmasq() 4746 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m') 4747 4748 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 4749 print('Wait for the dynamic address to be renewed') 4750 time.sleep(125) 4751 4752 self.wait_online(['veth99:routable']) 4753 4754 output = check_output('ip route show dev veth99') 4755 print(output) 4756 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*') 4757 self.assertRegex(output, r'192.168.5.0/24 proto static') 4758 self.assertRegex(output, r'192.168.6.0/24 proto static') 4759 self.assertRegex(output, r'192.168.7.0/24 proto static') 4760 4761 def test_dhcp_client_reassign_static_routes_ipv6(self): 4762 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 4763 '25-dhcp-client-reassign-static-routes-ipv6.network') 4764 start_networkd() 4765 self.wait_online(['veth-peer:carrier']) 4766 start_dnsmasq(lease_time='2m') 4767 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4768 4769 output = check_output('ip address show dev veth99 scope global') 4770 print(output) 4771 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)') 4772 4773 output = check_output('ip -6 route show dev veth99') 4774 print(output) 4775 self.assertRegex(output, r'2600::/64 proto ra metric 1024') 4776 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium') 4777 4778 stop_dnsmasq() 4779 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m') 4780 4781 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 4782 print('Wait for the dynamic address to be renewed') 4783 time.sleep(125) 4784 4785 self.wait_online(['veth99:routable']) 4786 4787 output = check_output('ip -6 route show dev veth99') 4788 print(output) 4789 self.assertRegex(output, r'2600::/64 proto ra metric 1024') 4790 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium') 4791 4792 def test_dhcp_keep_configuration_dhcp(self): 4793 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-v4-server-veth-peer.network', '25-dhcp-client-keep-configuration-dhcp.network') 4794 start_networkd() 4795 self.wait_online(['veth-peer:carrier']) 4796 start_dnsmasq(lease_time='2m') 4797 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4798 4799 output = check_output('ip address show dev veth99 scope global') 4800 print(output) 4801 self.assertRegex(output, r'192.168.5.*') 4802 4803 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4804 print(output) 4805 self.assertRegex(output, r'192.168.5.*') 4806 4807 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease. 4808 stop_dnsmasq() 4809 4810 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 4811 print('Wait for the dynamic address to be expired') 4812 time.sleep(125) 4813 4814 print('The lease address should be kept after lease expired') 4815 output = check_output('ip address show dev veth99 scope global') 4816 print(output) 4817 self.assertRegex(output, r'192.168.5.*') 4818 4819 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4820 print(output) 4821 self.assertRegex(output, r'192.168.5.*') 4822 4823 check_output('systemctl stop systemd-networkd.socket') 4824 check_output('systemctl stop systemd-networkd.service') 4825 4826 print('The lease address should be kept after networkd stopped') 4827 output = check_output('ip address show dev veth99 scope global') 4828 print(output) 4829 self.assertRegex(output, r'192.168.5.*') 4830 4831 with open(os.path.join(network_unit_file_path, '25-dhcp-client-keep-configuration-dhcp.network'), mode='a') as f: 4832 f.write('[Network]\nDHCP=no\n') 4833 4834 start_networkd() 4835 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4836 4837 print('Still the lease address should be kept after networkd restarted') 4838 output = check_output('ip address show dev veth99 scope global') 4839 print(output) 4840 self.assertRegex(output, r'192.168.5.*') 4841 4842 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 4843 print(output) 4844 self.assertRegex(output, r'192.168.5.*') 4845 4846 def test_dhcp_keep_configuration_dhcp_on_stop(self): 4847 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-v4-server-veth-peer.network', '25-dhcp-client-keep-configuration-dhcp-on-stop.network') 4848 start_networkd() 4849 self.wait_online(['veth-peer:carrier']) 4850 start_dnsmasq(lease_time='2m') 4851 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4852 4853 output = check_output('ip address show dev veth99 scope global') 4854 print(output) 4855 self.assertRegex(output, r'192.168.5.*') 4856 4857 stop_dnsmasq() 4858 check_output('systemctl stop systemd-networkd.socket') 4859 check_output('systemctl stop systemd-networkd.service') 4860 4861 output = check_output('ip address show dev veth99 scope global') 4862 print(output) 4863 self.assertRegex(output, r'192.168.5.*') 4864 4865 restart_networkd(3) 4866 self.wait_online(['veth-peer:routable']) 4867 4868 output = check_output('ip address show dev veth99 scope global') 4869 print(output) 4870 self.assertNotRegex(output, r'192.168.5.*') 4871 4872 def test_dhcp_client_reuse_address_as_static(self): 4873 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network') 4874 start_networkd() 4875 self.wait_online(['veth-peer:carrier']) 4876 start_dnsmasq() 4877 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4878 4879 # link become 'routable' when at least one protocol provide an valid address. 4880 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 4881 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 4882 4883 output = check_output('ip address show dev veth99 scope global') 4884 print(output) 4885 self.assertRegex(output, '192.168.5') 4886 self.assertRegex(output, '2600::') 4887 4888 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output) 4889 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output) 4890 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()]) 4891 print(static_network) 4892 4893 remove_unit_from_networkd_path(['25-dhcp-client.network']) 4894 4895 with open(os.path.join(network_unit_file_path, '25-static.network'), mode='w') as f: 4896 f.write(static_network) 4897 4898 # When networkd started, the links are already configured, so let's wait for 5 seconds 4899 # the links to be re-configured. 4900 restart_networkd(5) 4901 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4902 4903 output = check_output('ip -4 address show dev veth99 scope global') 4904 print(output) 4905 self.assertRegex(output, '192.168.5') 4906 self.assertRegex(output, 'valid_lft forever preferred_lft forever') 4907 4908 output = check_output('ip -6 address show dev veth99 scope global') 4909 print(output) 4910 self.assertRegex(output, '2600::') 4911 self.assertRegex(output, 'valid_lft forever preferred_lft forever') 4912 4913 @expectedFailureIfModuleIsNotAvailable('vrf') 4914 def test_dhcp_client_vrf(self): 4915 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-vrf.network', 4916 '25-vrf.netdev', '25-vrf.network') 4917 start_networkd() 4918 self.wait_online(['veth-peer:carrier']) 4919 start_dnsmasq() 4920 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier']) 4921 4922 # link become 'routable' when at least one protocol provide an valid address. 4923 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 4924 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 4925 4926 print('## ip -d link show dev vrf99') 4927 output = check_output('ip -d link show dev vrf99') 4928 print(output) 4929 self.assertRegex(output, 'vrf table 42') 4930 4931 print('## ip address show vrf vrf99') 4932 output = check_output('ip address show vrf vrf99') 4933 print(output) 4934 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 4935 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') 4936 self.assertRegex(output, 'inet6 .* scope link') 4937 4938 print('## ip address show dev veth99') 4939 output = check_output('ip address show dev veth99') 4940 print(output) 4941 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 4942 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') 4943 self.assertRegex(output, 'inet6 .* scope link') 4944 4945 print('## ip route show vrf vrf99') 4946 output = check_output('ip route show vrf vrf99') 4947 print(output) 4948 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.') 4949 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5') 4950 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5') 4951 4952 print('## ip route show table main dev veth99') 4953 output = check_output('ip route show table main dev veth99') 4954 print(output) 4955 self.assertEqual(output, '') 4956 4957 def test_dhcp_client_gateway_ipv4(self): 4958 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 4959 '25-dhcp-client-gateway-ipv4.network') 4960 start_networkd() 4961 self.wait_online(['veth-peer:carrier']) 4962 start_dnsmasq() 4963 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4964 4965 output = check_output('ip route list dev veth99') 4966 print(output) 4967 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*') 4968 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output) 4969 4970 with open(os.path.join(network_unit_file_path, '25-dhcp-client-gateway-ipv4.network'), mode='a') as f: 4971 f.write('[DHCPv4]\nUseGateway=no\n') 4972 4973 rc = call(*networkctl_cmd, 'reload', env=env) 4974 self.assertEqual(rc, 0) 4975 4976 time.sleep(2) 4977 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4978 4979 output = check_output('ip route list dev veth99') 4980 print(output) 4981 self.assertNotRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*') 4982 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output) 4983 4984 def test_dhcp_client_gateway_ipv6(self): 4985 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 4986 '25-dhcp-client-gateway-ipv6.network') 4987 start_networkd() 4988 self.wait_online(['veth-peer:carrier']) 4989 start_dnsmasq() 4990 self.wait_online(['veth99:routable', 'veth-peer:routable']) 4991 4992 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff') 4993 print(output) 4994 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd') 4995 4996 def test_dhcp_client_gateway_onlink_implicit(self): 4997 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 4998 '25-dhcp-client-gateway-onlink-implicit.network') 4999 start_networkd() 5000 self.wait_online(['veth-peer:carrier']) 5001 start_dnsmasq() 5002 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5003 5004 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 5005 print(output) 5006 self.assertRegex(output, '192.168.5') 5007 5008 output = check_output('ip route list dev veth99 10.0.0.0/8') 5009 print(output) 5010 self.assertRegex(output, 'onlink') 5011 output = check_output('ip route list dev veth99 192.168.100.0/24') 5012 print(output) 5013 self.assertRegex(output, 'onlink') 5014 5015 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self): 5016 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 5017 '25-dhcp-client-with-ipv4ll.network') 5018 start_networkd() 5019 self.wait_online(['veth-peer:carrier']) 5020 start_dnsmasq(lease_time='2m') 5021 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5022 5023 output = check_output('ip address show dev veth99') 5024 print(output) 5025 5026 output = check_output('ip -6 address show dev veth99 scope global dynamic') 5027 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic') 5028 output = check_output('ip -6 address show dev veth99 scope link') 5029 self.assertRegex(output, r'inet6 .* scope link') 5030 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5031 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') 5032 output = check_output('ip -4 address show dev veth99 scope link') 5033 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') 5034 5035 print('Wait for the dynamic address to be expired') 5036 time.sleep(130) 5037 5038 output = check_output('ip address show dev veth99') 5039 print(output) 5040 5041 output = check_output('ip -6 address show dev veth99 scope global dynamic') 5042 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic') 5043 output = check_output('ip -6 address show dev veth99 scope link') 5044 self.assertRegex(output, r'inet6 .* scope link') 5045 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5046 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') 5047 output = check_output('ip -4 address show dev veth99 scope link') 5048 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') 5049 5050 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True) 5051 5052 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self): 5053 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 5054 '25-dhcp-client-with-ipv4ll.network') 5055 start_networkd() 5056 # we need to increase timeout above default, as this will need to wait for 5057 # systemd-networkd to get the dhcpv4 transient failure event 5058 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s') 5059 5060 output = check_output('ip address show dev veth99') 5061 print(output) 5062 5063 output = check_output('ip -6 address show dev veth99 scope global dynamic') 5064 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic') 5065 output = check_output('ip -6 address show dev veth99 scope link') 5066 self.assertRegex(output, r'inet6 .* scope link') 5067 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5068 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') 5069 output = check_output('ip -4 address show dev veth99 scope link') 5070 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') 5071 5072 start_dnsmasq(lease_time='2m') 5073 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4') 5074 self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4') 5075 5076 def test_dhcp_client_route_remove_on_renew(self): 5077 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', 5078 '25-dhcp-client-ipv4-only-ipv6-disabled.network') 5079 start_networkd() 5080 self.wait_online(['veth-peer:carrier']) 5081 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m') 5082 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5083 5084 # test for issue #12490 5085 5086 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5087 print(output) 5088 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 5089 address1=None 5090 for line in output.splitlines(): 5091 if 'brd 192.168.5.255 scope global dynamic veth99' in line: 5092 address1 = line.split()[1].split('/')[0] 5093 break 5094 5095 output = check_output('ip -4 route show dev veth99') 5096 print(output) 5097 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024') 5098 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024') 5099 5100 stop_dnsmasq() 5101 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m') 5102 5103 print('Wait for the dynamic address to be expired') 5104 time.sleep(130) 5105 5106 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5107 print(output) 5108 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 5109 address2=None 5110 for line in output.splitlines(): 5111 if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line: 5112 address2 = line.split()[1].split('/')[0] 5113 break 5114 5115 self.assertNotEqual(address1, address2) 5116 5117 output = check_output('ip -4 route show dev veth99') 5118 print(output) 5119 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024') 5120 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024') 5121 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024') 5122 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024') 5123 5124 def test_dhcp_client_use_dns_yes(self): 5125 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-use-dns-yes.network') 5126 5127 start_networkd() 5128 self.wait_online(['veth-peer:carrier']) 5129 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') 5130 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5131 5132 # link become 'routable' when at least one protocol provide an valid address. 5133 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 5134 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 5135 5136 time.sleep(3) 5137 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) 5138 print(output) 5139 self.assertRegex(output, '192.168.5.1') 5140 self.assertRegex(output, '2600::1') 5141 5142 # TODO: check json string 5143 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 5144 5145 def test_dhcp_client_use_dns_no(self): 5146 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-use-dns-no.network') 5147 5148 start_networkd() 5149 self.wait_online(['veth-peer:carrier']) 5150 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') 5151 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5152 5153 # link become 'routable' when at least one protocol provide an valid address. 5154 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 5155 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 5156 5157 time.sleep(3) 5158 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) 5159 print(output) 5160 self.assertNotRegex(output, '192.168.5.1') 5161 self.assertNotRegex(output, '2600::1') 5162 5163 def test_dhcp_client_use_dns_ipv4(self): 5164 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-use-dns-ipv4.network') 5165 5166 start_networkd() 5167 self.wait_online(['veth-peer:carrier']) 5168 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') 5169 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5170 5171 # link become 'routable' when at least one protocol provide an valid address. 5172 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 5173 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 5174 5175 time.sleep(3) 5176 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) 5177 print(output) 5178 self.assertRegex(output, '192.168.5.1') 5179 self.assertNotRegex(output, '2600::1') 5180 5181 def test_dhcp_client_use_dns_ipv4_and_ra(self): 5182 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-use-dns-ipv4-and-ra.network') 5183 5184 start_networkd() 5185 self.wait_online(['veth-peer:carrier']) 5186 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') 5187 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5188 5189 # link become 'routable' when at least one protocol provide an valid address. 5190 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') 5191 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') 5192 5193 time.sleep(3) 5194 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) 5195 print(output) 5196 self.assertRegex(output, '192.168.5.1') 5197 self.assertRegex(output, '2600::1') 5198 5199 def test_dhcp_client_use_domains(self): 5200 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-use-domains.network') 5201 5202 start_networkd() 5203 self.wait_online(['veth-peer:carrier']) 5204 start_dnsmasq('--dhcp-option=option:domain-search,example.com') 5205 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5206 5207 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) 5208 print(output) 5209 self.assertRegex(output, 'Search Domains: example.com') 5210 5211 time.sleep(3) 5212 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env) 5213 print(output) 5214 self.assertRegex(output, 'example.com') 5215 5216 def test_dhcp_client_decline(self): 5217 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-decline.network', '25-dhcp-client-decline.network') 5218 5219 start_networkd() 5220 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5221 5222 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5223 print(output) 5224 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 5225 5226 def test_dhcp_client_allow_list(self): 5227 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp-server-decline.network', '25-dhcp-client-allow-list.network') 5228 5229 start_networkd() 5230 self.wait_online(['veth99:routable', 'veth-peer:routable']) 5231 5232 output = check_output('ip -4 address show dev veth99 scope global dynamic') 5233 print(output) 5234 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') 5235 5236class NetworkdDHCPPDTests(unittest.TestCase, Utilities): 5237 links = [ 5238 'dummy97', 5239 'dummy98', 5240 'dummy99', 5241 'test1', 5242 'veth97', 5243 'veth98', 5244 'veth99', 5245 ] 5246 5247 units = [ 5248 '11-dummy.netdev', 5249 '12-dummy.netdev', 5250 '13-dummy.netdev', 5251 '25-veth.netdev', 5252 '25-veth-downstream-veth97.netdev', 5253 '25-veth-downstream-veth98.netdev', 5254 '80-6rd-tunnel.network', 5255 '25-dhcp-pd-downstream-dummy97.network', 5256 '25-dhcp-pd-downstream-dummy98.network', 5257 '25-dhcp-pd-downstream-dummy99.network', 5258 '25-dhcp-pd-downstream-test1.network', 5259 '25-dhcp-pd-downstream-veth97.network', 5260 '25-dhcp-pd-downstream-veth97-peer.network', 5261 '25-dhcp-pd-downstream-veth98.network', 5262 '25-dhcp-pd-downstream-veth98-peer.network', 5263 '25-dhcp4-6rd-server.network', 5264 '25-dhcp4-6rd-upstream.network', 5265 '25-dhcp6pd-server.network', 5266 '25-dhcp6pd-upstream.network', 5267 ] 5268 5269 def setUp(self): 5270 stop_isc_dhcpd() 5271 stop_dnsmasq() 5272 remove_links(self.links) 5273 stop_networkd(show_logs=False) 5274 5275 def tearDown(self): 5276 stop_isc_dhcpd() 5277 stop_dnsmasq() 5278 remove_links(self.links) 5279 remove_unit_from_networkd_path(self.units) 5280 stop_networkd(show_logs=True) 5281 5282 def test_dhcp6pd(self): 5283 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp6pd-server.network', '25-dhcp6pd-upstream.network', 5284 '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network', 5285 '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network', 5286 '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network', 5287 '25-dhcp-pd-downstream-dummy97.network', 5288 '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network', 5289 '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network') 5290 5291 start_networkd() 5292 self.wait_online(['veth-peer:routable']) 5293 start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf', ip='-6') 5294 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded', 5295 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) 5296 5297 print('### ip -6 address show dev veth-peer scope global') 5298 output = check_output('ip -6 address show dev veth-peer scope global') 5299 print(output) 5300 self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output) 5301 5302 # Link Subnet IDs 5303 # test1: 0x00 5304 # dummy97: 0x01 (The link will appear later) 5305 # dummy98: 0x00 5306 # dummy99: auto -> 0x02 (No address assignment) 5307 # veth97: 0x08 5308 # veth98: 0x09 5309 # veth99: 0x10 5310 5311 print('### ip -6 address show dev veth99 scope global') 5312 output = check_output('ip -6 address show dev veth99 scope global') 5313 print(output) 5314 # IA_NA 5315 self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') 5316 # address in IA_PD (Token=static) 5317 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic') 5318 # address in IA_PD (Token=eui64) 5319 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic') 5320 # address in IA_PD (temporary) 5321 # Note that the temporary addresses may appear after the link enters configured state 5322 self.wait_address('veth99', 'inet6 3ffe:501:ffff:[2-9a-f]10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5323 5324 print('### ip -6 address show dev test1 scope global') 5325 output = check_output('ip -6 address show dev test1 scope global') 5326 print(output) 5327 # address in IA_PD (Token=static) 5328 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5329 # address in IA_PD (temporary) 5330 self.wait_address('test1', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5331 5332 print('### ip -6 address show dev dummy98 scope global') 5333 output = check_output('ip -6 address show dev dummy98 scope global') 5334 print(output) 5335 # address in IA_PD (Token=static) 5336 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5337 # address in IA_PD (temporary) 5338 self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5339 5340 print('### ip -6 address show dev dummy99 scope global') 5341 output = check_output('ip -6 address show dev dummy99 scope global') 5342 print(output) 5343 # Assign=no 5344 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02') 5345 5346 print('### ip -6 address show dev veth97 scope global') 5347 output = check_output('ip -6 address show dev veth97 scope global') 5348 print(output) 5349 # address in IA_PD (Token=static) 5350 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5351 # address in IA_PD (Token=eui64) 5352 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr') 5353 # address in IA_PD (temporary) 5354 self.wait_address('veth97', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5355 5356 print('### ip -6 address show dev veth97-peer scope global') 5357 output = check_output('ip -6 address show dev veth97-peer scope global') 5358 print(output) 5359 # NDisc address (Token=static) 5360 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') 5361 # NDisc address (Token=eui64) 5362 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr') 5363 # NDisc address (temporary) 5364 self.wait_address('veth97-peer', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5365 5366 print('### ip -6 address show dev veth98 scope global') 5367 output = check_output('ip -6 address show dev veth98 scope global') 5368 print(output) 5369 # address in IA_PD (Token=static) 5370 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5371 # address in IA_PD (Token=eui64) 5372 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr') 5373 # address in IA_PD (temporary) 5374 self.wait_address('veth98', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5375 5376 print('### ip -6 address show dev veth98-peer scope global') 5377 output = check_output('ip -6 address show dev veth98-peer scope global') 5378 print(output) 5379 # NDisc address (Token=static) 5380 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') 5381 # NDisc address (Token=eui64) 5382 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr') 5383 # NDisc address (temporary) 5384 self.wait_address('veth98-peer', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5385 5386 print('### ip -6 route show type unreachable') 5387 output = check_output('ip -6 route show type unreachable') 5388 print(output) 5389 self.assertRegex(output, 'unreachable 3ffe:501:ffff:[2-9a-f]00::/56 dev lo proto dhcp') 5390 5391 print('### ip -6 route show dev veth99') 5392 output = check_output('ip -6 route show dev veth99') 5393 print(output) 5394 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]10::/64 proto kernel metric [0-9]* expires') 5395 5396 print('### ip -6 route show dev test1') 5397 output = check_output('ip -6 route show dev test1') 5398 print(output) 5399 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires') 5400 5401 print('### ip -6 route show dev dummy98') 5402 output = check_output('ip -6 route show dev dummy98') 5403 print(output) 5404 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires') 5405 5406 print('### ip -6 route show dev dummy99') 5407 output = check_output('ip -6 route show dev dummy99') 5408 print(output) 5409 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires') 5410 5411 print('### ip -6 route show dev veth97') 5412 output = check_output('ip -6 route show dev veth97') 5413 print(output) 5414 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto kernel metric [0-9]* expires') 5415 5416 print('### ip -6 route show dev veth97-peer') 5417 output = check_output('ip -6 route show dev veth97-peer') 5418 print(output) 5419 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto ra metric [0-9]* expires') 5420 5421 print('### ip -6 route show dev veth98') 5422 output = check_output('ip -6 route show dev veth98') 5423 print(output) 5424 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto kernel metric [0-9]* expires') 5425 5426 print('### ip -6 route show dev veth98-peer') 5427 output = check_output('ip -6 route show dev veth98-peer') 5428 print(output) 5429 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto ra metric [0-9]* expires') 5430 5431 # Test case for a downstream which appears later 5432 check_output('ip link add dummy97 type dummy') 5433 self.wait_online(['dummy97:routable']) 5434 5435 print('### ip -6 address show dev dummy97 scope global') 5436 output = check_output('ip -6 address show dev dummy97 scope global') 5437 print(output) 5438 # address in IA_PD (Token=static) 5439 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5440 # address in IA_PD (temporary) 5441 self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5442 5443 print('### ip -6 route show dev dummy97') 5444 output = check_output('ip -6 route show dev dummy97') 5445 print(output) 5446 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires') 5447 5448 # Test case for reconfigure 5449 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env) 5450 self.wait_online(['dummy98:routable']) 5451 5452 print('### ip -6 address show dev dummy98 scope global') 5453 output = check_output('ip -6 address show dev dummy98 scope global') 5454 print(output) 5455 # address in IA_PD (Token=static) 5456 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5457 # address in IA_PD (temporary) 5458 self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5459 5460 print('### ip -6 address show dev dummy99 scope global') 5461 output = check_output('ip -6 address show dev dummy99 scope global') 5462 print(output) 5463 # Assign=no 5464 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02') 5465 5466 print('### ip -6 route show dev dummy98') 5467 output = check_output('ip -6 route show dev dummy98') 5468 print(output) 5469 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires') 5470 5471 print('### ip -6 route show dev dummy99') 5472 output = check_output('ip -6 route show dev dummy99') 5473 print(output) 5474 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires') 5475 5476 def verify_dhcp4_6rd(self, tunnel_name): 5477 print('### ip -4 address show dev veth-peer scope global') 5478 output = check_output('ip -4 address show dev veth-peer scope global') 5479 print(output) 5480 self.assertIn('inet 10.0.0.1/8 brd 10.255.255.255 scope global veth-peer', output) 5481 5482 # Link Subnet IDs 5483 # test1: 0x00 5484 # dummy97: 0x01 (The link will appear later) 5485 # dummy98: 0x00 5486 # dummy99: auto -> 0x0[23] (No address assignment) 5487 # 6rd-XXX: auto -> 0x0[23] 5488 # veth97: 0x08 5489 # veth98: 0x09 5490 # veth99: 0x10 5491 5492 print('### ip -4 address show dev veth99 scope global') 5493 output = check_output('ip -4 address show dev veth99 scope global') 5494 print(output) 5495 self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99') 5496 5497 print('### ip -6 address show dev veth99 scope global') 5498 output = check_output('ip -6 address show dev veth99 scope global') 5499 print(output) 5500 # address in IA_PD (Token=static) 5501 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5502 # address in IA_PD (Token=eui64) 5503 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr') 5504 # address in IA_PD (temporary) 5505 # Note that the temporary addresses may appear after the link enters configured state 5506 self.wait_address('veth99', 'inet6 2001:db8:6464:[0-9a-f]+10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5507 5508 print('### ip -6 address show dev test1 scope global') 5509 output = check_output('ip -6 address show dev test1 scope global') 5510 print(output) 5511 # address in IA_PD (Token=static) 5512 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5513 # address in IA_PD (temporary) 5514 self.wait_address('test1', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5515 5516 print('### ip -6 address show dev dummy98 scope global') 5517 output = check_output('ip -6 address show dev dummy98 scope global') 5518 print(output) 5519 # address in IA_PD (Token=static) 5520 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5521 # address in IA_PD (temporary) 5522 self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5523 5524 print('### ip -6 address show dev dummy99 scope global') 5525 output = check_output('ip -6 address show dev dummy99 scope global') 5526 print(output) 5527 # Assign=no 5528 self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]') 5529 5530 print('### ip -6 address show dev veth97 scope global') 5531 output = check_output('ip -6 address show dev veth97 scope global') 5532 print(output) 5533 # address in IA_PD (Token=static) 5534 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5535 # address in IA_PD (Token=eui64) 5536 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr') 5537 # address in IA_PD (temporary) 5538 self.wait_address('veth97', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5539 5540 print('### ip -6 address show dev veth97-peer scope global') 5541 output = check_output('ip -6 address show dev veth97-peer scope global') 5542 print(output) 5543 # NDisc address (Token=static) 5544 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') 5545 # NDisc address (Token=eui64) 5546 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr') 5547 # NDisc address (temporary) 5548 self.wait_address('veth97-peer', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5549 5550 print('### ip -6 address show dev veth98 scope global') 5551 output = check_output('ip -6 address show dev veth98 scope global') 5552 print(output) 5553 # address in IA_PD (Token=static) 5554 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5555 # address in IA_PD (Token=eui64) 5556 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr') 5557 # address in IA_PD (temporary) 5558 self.wait_address('veth98', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5559 5560 print('### ip -6 address show dev veth98-peer scope global') 5561 output = check_output('ip -6 address show dev veth98-peer scope global') 5562 print(output) 5563 # NDisc address (Token=static) 5564 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr') 5565 # NDisc address (Token=eui64) 5566 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr') 5567 # NDisc address (temporary) 5568 self.wait_address('veth98-peer', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5569 5570 print('### ip -6 route show type unreachable') 5571 output = check_output('ip -6 route show type unreachable') 5572 print(output) 5573 self.assertRegex(output, 'unreachable 2001:db8:6464:[0-9a-f]+00::/56 dev lo proto dhcp') 5574 5575 print('### ip -6 route show dev veth99') 5576 output = check_output('ip -6 route show dev veth99') 5577 print(output) 5578 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+10::/64 proto kernel metric [0-9]* expires') 5579 5580 print('### ip -6 route show dev test1') 5581 output = check_output('ip -6 route show dev test1') 5582 print(output) 5583 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires') 5584 5585 print('### ip -6 route show dev dummy98') 5586 output = check_output('ip -6 route show dev dummy98') 5587 print(output) 5588 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires') 5589 5590 print('### ip -6 route show dev dummy99') 5591 output = check_output('ip -6 route show dev dummy99') 5592 print(output) 5593 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto dhcp metric [0-9]* expires') 5594 5595 print('### ip -6 route show dev veth97') 5596 output = check_output('ip -6 route show dev veth97') 5597 print(output) 5598 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto kernel metric [0-9]* expires') 5599 5600 print('### ip -6 route show dev veth97-peer') 5601 output = check_output('ip -6 route show dev veth97-peer') 5602 print(output) 5603 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto ra metric [0-9]* expires') 5604 5605 print('### ip -6 route show dev veth98') 5606 output = check_output('ip -6 route show dev veth98') 5607 print(output) 5608 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto kernel metric [0-9]* expires') 5609 5610 print('### ip -6 route show dev veth98-peer') 5611 output = check_output('ip -6 route show dev veth98-peer') 5612 print(output) 5613 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto ra metric [0-9]* expires') 5614 5615 print('### ip -6 address show dev dummy97 scope global') 5616 output = check_output('ip -6 address show dev dummy97 scope global') 5617 print(output) 5618 # address in IA_PD (Token=static) 5619 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') 5620 # address in IA_PD (temporary) 5621 self.wait_address('dummy97', 'inet6 2001:db8:6464:[0-9a-f]+01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') 5622 5623 print('### ip -6 route show dev dummy97') 5624 output = check_output('ip -6 route show dev dummy97') 5625 print(output) 5626 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+01::/64 proto kernel metric [0-9]* expires') 5627 5628 print('### ip -d link show dev {}'.format(tunnel_name)) 5629 output = check_output('ip -d link show dev {}'.format(tunnel_name)) 5630 print(output) 5631 self.assertIn('link/sit 10.100.100.', output) 5632 self.assertIn('local 10.100.100.', output) 5633 self.assertIn('ttl 64', output) 5634 self.assertIn('6rd-prefix 2001:db8::/32', output) 5635 self.assertIn('6rd-relay_prefix 10.0.0.0/8', output) 5636 5637 print('### ip -6 address show dev {}'.format(tunnel_name)) 5638 output = check_output('ip -6 address show dev {}'.format(tunnel_name)) 5639 print(output) 5640 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global dynamic') 5641 self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global') 5642 5643 print('### ip -6 route show dev {}'.format(tunnel_name)) 5644 output = check_output('ip -6 route show dev {}'.format(tunnel_name)) 5645 print(output) 5646 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto kernel metric [0-9]* expires') 5647 self.assertRegex(output, '::/96 proto kernel metric [0-9]*') 5648 5649 print('### ip -6 route show default') 5650 output = check_output('ip -6 route show default') 5651 print(output) 5652 self.assertIn('default', output) 5653 self.assertIn('via ::10.0.0.1 dev {}'.format(tunnel_name), output) 5654 5655 def test_dhcp4_6rd(self): 5656 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-dhcp4-6rd-server.network', '25-dhcp4-6rd-upstream.network', 5657 '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network', 5658 '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network', 5659 '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network', 5660 '25-dhcp-pd-downstream-dummy97.network', 5661 '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network', 5662 '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network', 5663 '80-6rd-tunnel.network') 5664 5665 start_networkd() 5666 self.wait_online(['veth-peer:routable']) 5667 5668 # ipv4masklen: 8 5669 # 6rd-prefix: 2001:db8::/32 5670 # br-addresss: 10.0.0.1 5671 5672 start_dnsmasq(additional_options='--dhcp-option=212,08:20:20:01:0d:b8:00:00:00:00:00:00:00:00:00:00:00:00:0a:00:00:01', ipv4_range='10.100.100.100,10.100.100.200', ipv4_router='10.0.0.1', lease_time='2m') 5673 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded', 5674 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) 5675 5676 # Test case for a downstream which appears later 5677 check_output('ip link add dummy97 type dummy') 5678 self.wait_online(['dummy97:routable']) 5679 5680 # Find tunnel name 5681 tunnel_name = None 5682 for name in os.listdir('/sys/class/net/'): 5683 if name.startswith('6rd-'): 5684 tunnel_name = name 5685 break 5686 5687 self.wait_online(['{}:routable'.format(tunnel_name)]) 5688 5689 self.verify_dhcp4_6rd(tunnel_name) 5690 5691 # Test case for reconfigure 5692 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env) 5693 self.wait_online(['dummy98:routable', 'dummy99:degraded']) 5694 5695 self.verify_dhcp4_6rd(tunnel_name) 5696 5697 # Test for renewing/rebinding lease 5698 print('wait for 120 sec') 5699 time.sleep(30) 5700 print('wait for 90 sec') 5701 time.sleep(30) 5702 print('wait for 60 sec') 5703 time.sleep(30) 5704 print('wait for 30 sec') 5705 time.sleep(30) 5706 5707 dump_dnsmasq_log_file() 5708 5709 self.wait_online(['veth99:routable', 'test1:routable', 'dummy97:routable', 'dummy98:routable', 'dummy99:degraded', 5710 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) 5711 5712 self.verify_dhcp4_6rd(tunnel_name) 5713 5714class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): 5715 links = [ 5716 'dummy98', 5717 'veth99', 5718 ] 5719 5720 units = [ 5721 '12-dummy.netdev', 5722 '25-veth.netdev', 5723 '25-ipv6ra-prefix-client-deny-list.network', 5724 '25-ipv6ra-prefix-client.network', 5725 '25-ipv6ra-prefix.network', 5726 '25-ipv6ra-uplink.network', 5727 ] 5728 5729 def setUp(self): 5730 remove_links(self.links) 5731 stop_networkd(show_logs=False) 5732 5733 def tearDown(self): 5734 remove_links(self.links) 5735 remove_unit_from_networkd_path(self.units) 5736 stop_networkd(show_logs=True) 5737 5738 def test_ipv6_route_prefix(self): 5739 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6ra-prefix-client.network', '25-ipv6ra-prefix.network', 5740 '12-dummy.netdev', '25-ipv6ra-uplink.network') 5741 5742 start_networkd() 5743 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable']) 5744 5745 output = check_output('ip address show dev veth-peer') 5746 print(output) 5747 self.assertIn('inet6 2001:db8:0:1:', output) 5748 self.assertNotIn('inet6 2001:db8:0:2:', output) 5749 self.assertNotIn('inet6 2001:db8:0:3:', output) 5750 5751 output = check_output('ip -6 route show dev veth-peer') 5752 print(output) 5753 self.assertIn('2001:db8:0:1::/64 proto ra', output) 5754 self.assertNotIn('2001:db8:0:2::/64 proto ra', output) 5755 self.assertNotIn('2001:db8:0:3::/64 proto ra', output) 5756 self.assertIn('2001:db0:fff::/64 via ', output) 5757 self.assertNotIn('2001:db1:fff::/64 via ', output) 5758 self.assertNotIn('2001:db2:fff::/64 via ', output) 5759 5760 output = check_output('ip address show dev veth99') 5761 print(output) 5762 self.assertNotIn('inet6 2001:db8:0:1:', output) 5763 self.assertIn('inet6 2001:db8:0:2:1a:2b:3c:4d', output) 5764 self.assertIn('inet6 2001:db8:0:2:fa:de:ca:fe', output) 5765 self.assertNotIn('inet6 2001:db8:0:3:', output) 5766 5767 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env) 5768 print(output) 5769 self.assertRegex(output, '2001:db8:1:1::2') 5770 5771 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env) 5772 print(output) 5773 self.assertIn('example.com', output) 5774 5775 # TODO: check json string 5776 check_output(*networkctl_cmd, '--json=short', 'status', env=env) 5777 5778 def test_ipv6_route_prefix_deny_list(self): 5779 copy_unit_to_networkd_unit_path('25-veth.netdev', '25-ipv6ra-prefix-client-deny-list.network', '25-ipv6ra-prefix.network', 5780 '12-dummy.netdev', '25-ipv6ra-uplink.network') 5781 5782 start_networkd() 5783 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable']) 5784 5785 output = check_output('ip address show dev veth-peer') 5786 print(output) 5787 self.assertIn('inet6 2001:db8:0:1:', output) 5788 self.assertNotIn('inet6 2001:db8:0:2:', output) 5789 5790 output = check_output('ip -6 route show dev veth-peer') 5791 print(output) 5792 self.assertIn('2001:db8:0:1::/64 proto ra', output) 5793 self.assertNotIn('2001:db8:0:2::/64 proto ra', output) 5794 self.assertIn('2001:db0:fff::/64 via ', output) 5795 self.assertNotIn('2001:db1:fff::/64 via ', output) 5796 5797 output = check_output('ip address show dev veth99') 5798 print(output) 5799 self.assertNotIn('inet6 2001:db8:0:1:', output) 5800 self.assertIn('inet6 2001:db8:0:2:', output) 5801 5802 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env) 5803 print(output) 5804 self.assertRegex(output, '2001:db8:1:1::2') 5805 5806 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env) 5807 print(output) 5808 self.assertIn('example.com', output) 5809 5810class NetworkdMTUTests(unittest.TestCase, Utilities): 5811 links = ['dummy98'] 5812 5813 units = [ 5814 '12-dummy.netdev', 5815 '12-dummy-mtu.netdev', 5816 '12-dummy-mtu.link', 5817 '12-dummy.network', 5818 ] 5819 5820 def setUp(self): 5821 remove_links(self.links) 5822 stop_networkd(show_logs=False) 5823 5824 def tearDown(self): 5825 remove_links(self.links) 5826 remove_unit_from_networkd_path(self.units) 5827 stop_networkd(show_logs=True) 5828 5829 def check_mtu(self, mtu, ipv6_mtu=None, reset=True): 5830 if not ipv6_mtu: 5831 ipv6_mtu = mtu 5832 5833 # test normal start 5834 start_networkd() 5835 self.wait_online(['dummy98:routable']) 5836 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu) 5837 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu) 5838 5839 # test normal restart 5840 restart_networkd() 5841 self.wait_online(['dummy98:routable']) 5842 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu) 5843 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu) 5844 5845 if reset: 5846 self.reset_check_mtu(mtu, ipv6_mtu) 5847 5848 def reset_check_mtu(self, mtu, ipv6_mtu=None): 5849 ''' test setting mtu/ipv6_mtu with interface already up ''' 5850 stop_networkd() 5851 5852 # note - changing the device mtu resets the ipv6 mtu 5853 run('ip link set up mtu 1501 dev dummy98') 5854 run('ip link set up mtu 1500 dev dummy98') 5855 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500') 5856 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500') 5857 5858 self.check_mtu(mtu, ipv6_mtu, reset=False) 5859 5860 def test_mtu_network(self): 5861 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf') 5862 self.check_mtu('1600') 5863 5864 def test_mtu_netdev(self): 5865 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False) 5866 # note - MTU set by .netdev happens ONLY at device creation! 5867 self.check_mtu('1600', reset=False) 5868 5869 def test_mtu_link(self): 5870 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False) 5871 # must reload udev because it only picks up new files after 3 second delay 5872 call('udevadm control --reload') 5873 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent! 5874 self.check_mtu('1600', reset=False) 5875 5876 def test_ipv6_mtu(self): 5877 ''' set ipv6 mtu without setting device mtu ''' 5878 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf') 5879 self.check_mtu('1500', '1400') 5880 5881 def test_ipv6_mtu_toolarge(self): 5882 ''' try set ipv6 mtu over device mtu (it shouldn't work) ''' 5883 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf') 5884 self.check_mtu('1500', '1500') 5885 5886 def test_mtu_network_ipv6_mtu(self): 5887 ''' set ipv6 mtu and set device mtu via network file ''' 5888 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf') 5889 self.check_mtu('1600', '1550') 5890 5891 def test_mtu_netdev_ipv6_mtu(self): 5892 ''' set ipv6 mtu and set device mtu via netdev file ''' 5893 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf') 5894 self.check_mtu('1600', '1550', reset=False) 5895 5896 def test_mtu_link_ipv6_mtu(self): 5897 ''' set ipv6 mtu and set device mtu via link file ''' 5898 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf') 5899 # must reload udev because it only picks up new files after 3 second delay 5900 call('udevadm control --reload') 5901 self.check_mtu('1600', '1550', reset=False) 5902 5903 5904if __name__ == '__main__': 5905 parser = argparse.ArgumentParser() 5906 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir') 5907 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin') 5908 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin') 5909 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin') 5910 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin') 5911 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin') 5912 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin') 5913 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin') 5914 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind) 5915 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug) 5916 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options') 5917 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options') 5918 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options') 5919 parser.add_argument('--with-coverage', help='Loosen certain sandbox restrictions to make gcov happy', dest='with_coverage', type=bool, nargs='?', const=True, default=with_coverage) 5920 ns, unknown_args = parser.parse_known_args(namespace=unittest) 5921 5922 if ns.build_dir: 5923 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: 5924 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.') 5925 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd') 5926 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved') 5927 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd') 5928 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online') 5929 networkctl_bin = os.path.join(ns.build_dir, 'networkctl') 5930 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl') 5931 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl') 5932 else: 5933 if ns.networkd_bin: 5934 networkd_bin = ns.networkd_bin 5935 if ns.resolved_bin: 5936 resolved_bin = ns.resolved_bin 5937 if ns.udevd_bin: 5938 udevd_bin = ns.udevd_bin 5939 if ns.wait_online_bin: 5940 wait_online_bin = ns.wait_online_bin 5941 if ns.networkctl_bin: 5942 networkctl_bin = ns.networkctl_bin 5943 if ns.resolvectl_bin: 5944 resolvectl_bin = ns.resolvectl_bin 5945 if ns.timedatectl_bin: 5946 timedatectl_bin = ns.timedatectl_bin 5947 5948 use_valgrind = ns.use_valgrind 5949 enable_debug = ns.enable_debug 5950 asan_options = ns.asan_options 5951 lsan_options = ns.lsan_options 5952 ubsan_options = ns.ubsan_options 5953 with_coverage = ns.with_coverage 5954 5955 if use_valgrind: 5956 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin] 5957 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin] 5958 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin] 5959 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin] 5960 else: 5961 networkctl_cmd = [networkctl_bin] 5962 resolvectl_cmd = [resolvectl_bin] 5963 timedatectl_cmd = [timedatectl_bin] 5964 wait_online_cmd = [wait_online_bin] 5965 5966 if enable_debug: 5967 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' }) 5968 if asan_options: 5969 env.update({ 'ASAN_OPTIONS' : asan_options }) 5970 if lsan_options: 5971 env.update({ 'LSAN_OPTIONS' : lsan_options }) 5972 if ubsan_options: 5973 env.update({ 'UBSAN_OPTIONS' : ubsan_options }) 5974 5975 sys.argv[1:] = unknown_args 5976 unittest.main(verbosity=3) 5977