X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=test%2Ftest-network%2Fsystemd-networkd-tests.py;h=3e57b335ceeef1b25bddb1da68447c9f50cdfb5a;hb=05d418fed94ce94ff21f05ea85ad1a4922fdcbcf;hp=66dc46a6b4cea5ca1b8dac50b35bd922903b2ecc;hpb=51b367b86d6f650064bac6201365c2dbd5f76eba;p=thirdparty%2Fsystemd.git diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 66dc46a6b4c..3e57b335cee 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -158,6 +158,33 @@ def expectedFailureIfAlternativeNameIsNotAvailable(): return f +def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable(): + def f(func): + call('rmmod netdevsim', stderr=subprocess.DEVNULL) + rc = call('modprobe netdevsim', stderr=subprocess.DEVNULL) + if rc != 0: + return unittest.expectedFailure(func) + + try: + with open('/sys/bus/netdevsim/new_device', mode='w') as f: + f.write('99 1') + except Exception as error: + return unittest.expectedFailure(func) + + call('udevadm settle') + call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL) + try: + with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f: + f.write('3') + except Exception as error: + call('rmmod netdevsim', stderr=subprocess.DEVNULL) + return unittest.expectedFailure(func) + + call('rmmod netdevsim', stderr=subprocess.DEVNULL) + return func + + return f + def expectedFailureIfCAKEIsNotAvailable(): def f(func): call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) @@ -194,6 +221,30 @@ def expectedFailureIfHHFIsNotAvailable(): return f +def expectedFailureIfETSIsNotAvailable(): + def f(func): + call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) + rc = call('tc qdisc add dev dummy98 parent root ets bands 10', stderr=subprocess.DEVNULL) + call('ip link del dummy98', stderr=subprocess.DEVNULL) + if rc == 0: + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfFQPIEIsNotAvailable(): + def f(func): + call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL) + rc = call('tc qdisc add dev dummy98 parent root fq_pie', stderr=subprocess.DEVNULL) + call('ip link del dummy98', stderr=subprocess.DEVNULL) + if rc == 0: + return func + else: + return unittest.expectedFailure(func) + + return f + def setUpModule(): global running_units @@ -289,7 +340,7 @@ def tearDownModule(): shutil.rmtree(networkd_ci_path) - for u in ['systemd-networkd.service', 'systemd-resolved.service']: + for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service']: check_output(f'systemctl stop {u}') shutil.rmtree('/run/systemd/system/systemd-networkd.service.d') @@ -425,7 +476,8 @@ def remove_networkd_state_files(): def stop_networkd(show_logs=True, remove_state_files=True): if show_logs: invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value') - check_output('systemctl stop systemd-networkd') + check_output('systemctl stop systemd-networkd.socket') + check_output('systemctl stop systemd-networkd.service') if show_logs: print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)) if remove_state_files: @@ -518,7 +570,7 @@ class Utilities(): if i > 0: time.sleep(1) output = check_output(f'ip {ipv} address show dev {link} scope {scope}') - if re.search(address_regex, output): + if re.search(address_regex, output) and 'tentative' not in output: break else: self.assertRegex(output, address_regex) @@ -692,6 +744,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): links = [ '6rdtun99', + 'bareudp99', 'bond99', 'bridge99', 'dropin-test', @@ -745,6 +798,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): 'vtitun98', 'vtitun99', 'vxcan99', + 'vxlan98', 'vxlan99', 'wg97', 'wg98', @@ -765,6 +819,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '21-vlan.netdev', '21-vlan.network', '25-6rd-tunnel.netdev', + '25-bareudp.netdev', '25-bond.netdev', '25-bond-balanced-tlb.netdev', '25-bridge.netdev', @@ -830,6 +885,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-vti-tunnel-remote-any.netdev', '25-vti-tunnel.netdev', '25-vxcan.netdev', + '25-vxlan-independent.netdev', '25-vxlan.netdev', '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network', @@ -910,6 +966,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring') self.wait_operstate('test1', 'degraded') + @expectedFailureIfModuleIsNotAvailable('bareudp') + def test_bareudp(self): + copy_unit_to_networkd_unit_path('25-bareudp.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['bareudp99:degraded']) + + output = check_output('ip -d link show bareudp99') + print(output) + self.assertRegex(output, 'dstport 1000 ') + self.assertRegex(output, 'ethertype ip ') + def test_bridge(self): copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network') start_networkd() @@ -1476,10 +1544,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): def test_vxlan(self): copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network', + '25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network', '11-dummy.netdev', 'vxlan-test1.network') start_networkd() - self.wait_online(['test1:degraded', 'vxlan99:degraded']) + self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded']) output = check_output('ip -d link show vxlan99') print(output) @@ -1506,6 +1575,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertRegex(output, 'Destination Port: 5555') self.assertRegex(output, 'Underlying Device: test1') + output = check_output('ip -d link show vxlan98') + print(output) + def test_macsec(self): copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key', 'macsec.network', '12-dummy.netdev') @@ -1673,26 +1745,34 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): '25-qdisc-cake.network', '25-qdisc-clsact-and-htb.network', '25-qdisc-drr.network', + '25-qdisc-ets.network', + '25-qdisc-fq_pie.network', '25-qdisc-hhf.network', '25-qdisc-ingress-netem-compat.network', '25-qdisc-pie.network', '25-qdisc-qfq.network', + '25-prefix-route-with-vrf.network', + '25-prefix-route-without-vrf.network', '25-route-ipv6-src.network', '25-route-static.network', '25-route-vrf.network', '25-gateway-static.network', '25-gateway-next-static.network', + '25-sriov.network', '25-sysctl-disable-ipv6.network', '25-sysctl.network', '25-test1.network', '25-veth-peer.network', '25-veth.netdev', '25-vrf.netdev', + '25-vrf.network', '26-link-local-addressing-ipv6.network', 'routing-policy-rule-dummy98.network', - 'routing-policy-rule-test1.network'] + 'routing-policy-rule-test1.network', + 'routing-policy-rule-reconfigure.network', + ] - routing_policy_rule_tables = ['7', '8', '9'] + routing_policy_rule_tables = ['7', '8', '9', '1011'] routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']] def setUp(self): @@ -1720,6 +1800,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') + # test for ENOBUFS issue #17012 + for i in range(1,254): + self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') + # invalid sections self.assertNotRegex(output, '10.10.0.1/16') self.assertNotRegex(output, '10.10.0.2/16') @@ -1745,6 +1829,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global') self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global') + restart_networkd() + self.wait_online(['dummy98:routable']) + + # test for ENOBUFS issue #17012 + output = check_output('ip -4 address show dev dummy98') + for i in range(1,254): + self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') + def test_address_preferred_lifetime_zero_ipv6(self): copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev') start_networkd(5) @@ -1774,6 +1866,77 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertNotRegex(output, '192.168.100.10/24') + @expectedFailureIfModuleIsNotAvailable('vrf') + def test_prefix_route(self): + copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev', + '25-prefix-route-without-vrf.network', '11-dummy.netdev', + '25-vrf.netdev', '25-vrf.network') + for trial in range(2): + if trial == 0: + start_networkd() + else: + restart_networkd(3) + + self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier']) + + output = check_output('ip route show table 42 dev dummy98') + print('### ip route show table 42 dev dummy98') + print(output) + self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1') + self.assertRegex(output, 'broadcast 10.20.33.0 proto kernel scope link src 10.20.33.1') + self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1') + self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1') + self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1') + self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1') + self.assertRegex(output, 'broadcast 10.20.55.0 proto kernel scope link src 10.20.55.1') + self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1') + self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1') + output = check_output('ip -6 route show table 42 dev dummy98') + print('### ip -6 route show table 42 dev dummy98') + print(output) + if trial == 0: + # Kernel's bug? + self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium') + #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium') + self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium') + self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium') + self.assertRegex(output, 'ff00::/8 metric 256 pref medium') + + print() + + output = check_output('ip route show dev test1') + print('### ip route show dev test1') + print(output) + self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1') + output = check_output('ip route show table local dev test1') + print('### ip route show table local dev test1') + print(output) + self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1') + self.assertRegex(output, 'broadcast 10.21.33.0 proto kernel scope link src 10.21.33.1') + self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1') + self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1') + self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1') + self.assertRegex(output, 'broadcast 10.21.55.0 proto kernel scope link src 10.21.55.1') + self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1') + self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1') + output = check_output('ip -6 route show dev test1') + print('### ip -6 route show dev test1') + print(output) + self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium') + self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium') + self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium') + output = check_output('ip -6 route show table local dev test1') + print('### ip -6 route show table local dev test1') + print(output) + self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium') + self.assertRegex(output, 'ff00::/8 metric 256 pref medium') + def test_configure_without_carrier(self): copy_unit_to_networkd_unit_path('11-dummy.netdev') start_networkd() @@ -1854,13 +2017,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'iif test1') self.assertRegex(output, 'lookup 8') - output = check_output('ip -6 rule list iif test1 priority 101') - print(output) - self.assertRegex(output, '101:') - self.assertRegex(output, 'from all') - self.assertRegex(output, 'iif test1') - self.assertRegex(output, 'lookup 9') - def test_routing_policy_rule_issue_11280(self): copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev', 'routing-policy-rule-dummy98.network', '12-dummy.netdev') @@ -1881,6 +2037,39 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): stop_networkd(remove_state_files=False) + def test_routing_policy_rule_reconfigure(self): + copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output('ip rule list table 1011') + print(output) + self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011') + self.assertRegex(output, '10112: from all oif test1 lookup 1011') + self.assertRegex(output, '10113: from all iif test1 lookup 1011') + self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011') + + run('ip rule delete priority 10111') + run('ip rule delete priority 10112') + run('ip rule delete priority 10113') + run('ip rule delete priority 10114') + run('ip rule delete priority 10115') + + output = check_output('ip rule list table 1011') + print(output) + self.assertEqual(output, '') + + run(*networkctl_cmd, 'reconfigure', 'test1', env=env) + + self.wait_online(['test1:degraded']) + + output = check_output('ip rule list table 1011') + print(output) + self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011') + self.assertRegex(output, '10112: from all oif test1 lookup 1011') + self.assertRegex(output, '10113: from all iif test1 lookup 1011') + self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011') + @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable() def test_routing_policy_rule_port_range(self): copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev') @@ -2224,7 +2413,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet6 .* scope link') output = check_output('ip -4 route show dev dummy98') print(output) - self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') + self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') output = check_output('ip -6 route show dev dummy98') print(output) self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static') @@ -2247,7 +2436,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet6 .* scope link') output = check_output('ip -4 route show dev dummy98') print(output) - self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') + self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') output = check_output('ip -6 route show dev dummy98') print(output) self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static') @@ -2313,7 +2502,8 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'Search Domains: one') def test_keep_configuration_static(self): - check_output('systemctl stop systemd-networkd') + check_output('systemctl stop systemd-networkd.socket') + check_output('systemctl stop systemd-networkd.service') check_output('ip link add name dummy98 type dummy') check_output('ip address add 10.1.2.3/16 dev dummy98') @@ -2407,7 +2597,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c') - output = check_output('tc class show dev dummy98') + output = check_output('tc -d class show dev dummy98') print(output) self.assertRegex(output, 'class htb 2:30 root leaf 30:') self.assertRegex(output, 'class htb 2:31 root leaf 31:') @@ -2422,7 +2612,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'class htb 2:3a root leaf 3a:') self.assertRegex(output, 'class htb 2:3b root leaf 3b:') self.assertRegex(output, 'class htb 2:3c root leaf 3c:') - self.assertRegex(output, 'prio 1 rate 1Mbit ceil 500Kbit') + self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit') + self.assertRegex(output, 'burst 123456') + self.assertRegex(output, 'cburst 123457') def test_qdisc2(self): copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev', @@ -2480,6 +2672,58 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'qdisc hhf 3a: root') self.assertRegex(output, 'limit 1022p') + @expectedFailureIfETSIsNotAvailable() + def test_qdisc_ets(self): + copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + + self.assertRegex(output, 'qdisc ets 3a: root') + self.assertRegex(output, 'bands 10 strict 3') + self.assertRegex(output, 'quanta 1 2 3 4 5') + self.assertRegex(output, 'priomap 3 4 5 6 7') + + @expectedFailureIfFQPIEIsNotAvailable() + def test_qdisc_fq_pie(self): + copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + + self.assertRegex(output, 'qdisc fq_pie 3a: root') + self.assertRegex(output, 'limit 200000p') + + @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable() + def test_sriov(self): + call('rmmod netdevsim', stderr=subprocess.DEVNULL) + call('modprobe netdevsim', stderr=subprocess.DEVNULL) + with open('/sys/bus/netdevsim/new_device', mode='w') as f: + f.write('99 1') + + call('udevadm settle') + call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL) + with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f: + f.write('3') + + copy_unit_to_networkd_unit_path('25-sriov.network') + start_networkd() + self.wait_online(['eni99np1:routable']) + + output = check_output('ip link show dev eni99np1') + print(output) + self.assertRegex(output, + '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 *' + 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *' + 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off' + ) + + call('rmmod netdevsim', stderr=subprocess.DEVNULL) + class NetworkdStateFileTests(unittest.TestCase, Utilities): links = [ 'dummy98', @@ -2510,7 +2754,9 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): path = os.path.join('/run/systemd/netif/links/', ifindex) self.assertTrue(os.path.exists(path)) - time.sleep(2) + + # make link state file updated + check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env) with open(path) as f: data = f.read() @@ -2519,7 +2765,7 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes') self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable') self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network') - self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11') + self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') self.assertRegex(data, r'DOMAINS=hogehoge') self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') @@ -2528,17 +2774,16 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): self.assertRegex(data, r'DNSSEC=no') self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24') - check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env) + check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env) check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env) check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env) check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env) check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env) check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env) - time.sleep(2) with open(path) as f: data = f.read() - self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13') + self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333') self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org') self.assertRegex(data, r'DOMAINS=hogehogehoge') self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') @@ -2547,11 +2792,10 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): self.assertRegex(data, r'DNSSEC=yes') check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env) - time.sleep(2) with open(path) as f: data = f.read() - self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13') + self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333') self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') self.assertRegex(data, r'DOMAINS=hogehogehoge') self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') @@ -2560,11 +2804,10 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): self.assertRegex(data, r'DNSSEC=yes') check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env) - time.sleep(2) with open(path) as f: data = f.read() - self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11') + self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') self.assertRegex(data, r'DOMAINS=hogehoge') self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') @@ -2673,6 +2916,8 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): '12-dummy.netdev', '26-bridge.netdev', '26-bridge-configure-without-carrier.network', + '26-bridge-mdb-master.network', + '26-bridge-mdb-slave.network', '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', '26-bridge-vlan-master.network', @@ -2713,6 +2958,22 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): self.assertRegex(output, f'{i}') self.assertNotRegex(output, '4095') + def test_bridge_mdb(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network', + '26-bridge.netdev', '26-bridge-mdb-master.network') + start_networkd() + self.wait_online(['test1:enslaved', 'bridge99:degraded']) + + output = check_output('bridge mdb show dev bridge99') + print(output) + self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064') + self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065') + + # Old kernel may not support bridge MDB entries on bridge master + if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0: + self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066') + self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067') + def test_bridge_property(self): copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', @@ -2797,8 +3058,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): with self.subTest(test=test): if test == 'no-slave': # bridge has no slaves; it's up but *might* not have carrier - # It may take very long time that the interface become configured state. - self.wait_online(['bridge99:no-carrier'], timeout='2m') + self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30) # due to a bug in the kernel, newly-created bridges are brought up # *with* carrier, unless they have had any setting changed; e.g. # their mac set, priority set, etc. Then, they will lose carrier @@ -2809,7 +3069,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): # add slave to bridge, but leave it down; bridge is definitely no-carrier self.check_link_attr('test1', 'operstate', 'down') check_output('ip link set dev test1 master bridge99') - self.wait_online(['bridge99:no-carrier:no-carrier']) + self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None) self.check_link_attr('bridge99', 'carrier', '0') elif test == 'slave-up': # bring up slave, which will have carrier; bridge gains carrier @@ -2833,7 +3093,6 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): self.check_link_attr('bridge99', 'carrier', '0') output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env) - print(output) self.assertRegex(output, '10.1.2.3') self.assertRegex(output, '10.1.2.1') @@ -2914,9 +3173,8 @@ class NetworkdRATests(unittest.TestCase, Utilities): 'ipv6-prefix.network', 'ipv6-prefix-veth.network', 'ipv6-prefix-veth-token-static.network', - 'ipv6-prefix-veth-token-static-explicit.network', - 'ipv6-prefix-veth-token-static-multiple.network', - 'ipv6-prefix-veth-token-prefixstable.network'] + 'ipv6-prefix-veth-token-prefixstable.network', + 'ipv6-prefix-veth-token-prefixstable-without-address.network'] def setUp(self): remove_links(self.links) @@ -2949,34 +3207,29 @@ class NetworkdRATests(unittest.TestCase, Utilities): output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) print(output) self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') + self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe') + self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d') + self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe') - def test_ipv6_token_static_explicit(self): - copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network') - start_networkd() - self.wait_online(['veth99:routable', 'veth-peer:degraded']) - - output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) - print(output) - self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') - - def test_ipv6_token_static_multiple(self): - copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network') + def test_ipv6_token_prefixstable(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network') start_networkd() self.wait_online(['veth99:routable', 'veth-peer:degraded']) output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) print(output) - self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') - self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe') + self.assertRegex(output, '2002:da8:1:0') + self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI - def test_ipv6_token_prefixstable(self): - copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network') + def test_ipv6_token_prefixstable_without_address(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network') start_networkd() self.wait_online(['veth99:routable', 'veth-peer:degraded']) output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) print(output) self.assertRegex(output, '2002:da8:1:0') + self.assertRegex(output, '2002:da8:2:0') class NetworkdDHCPServerTests(unittest.TestCase, Utilities): links = ['veth99'] @@ -3088,6 +3341,12 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.assertRegex(output, '2600::') self.assertNotRegex(output, '192.168.5') + output = check_output('ip addr show dev veth99') + print(output) + self.assertRegex(output, '2600::') + self.assertNotRegex(output, '192.168.5') + self.assertNotRegex(output, 'tentative') + # Confirm that ipv6 token is not set in the kernel output = check_output('ip token show dev veth99') print(output) @@ -3432,7 +3691,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, r'192.168.5.*') - check_output('systemctl stop systemd-networkd') + check_output('systemctl stop systemd-networkd.socket') + check_output('systemctl stop systemd-networkd.service') print('The lease address should be kept after networkd stopped') output = check_output('ip address show dev veth99 scope global') @@ -3467,7 +3727,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.assertRegex(output, r'192.168.5.*') stop_dnsmasq(dnsmasq_pid_file) - check_output('systemctl stop systemd-networkd') + check_output('systemctl stop systemd-networkd.socket') + check_output('systemctl stop systemd-networkd.service') output = check_output('ip address show dev veth99 scope global') print(output)