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)
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
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')
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:
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)
links = [
'6rdtun99',
+ 'bareudp99',
'bond99',
'bridge99',
'dropin-test',
'vtitun98',
'vtitun99',
'vxcan99',
+ 'vxlan98',
'vxlan99',
'wg97',
'wg98',
'21-vlan.netdev',
'21-vlan.network',
'25-6rd-tunnel.netdev',
+ '25-bareudp.netdev',
'25-bond.netdev',
'25-bond-balanced-tlb.netdev',
'25-bridge.netdev',
'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',
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()
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)
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')
'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):
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')
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)
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()
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')
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')
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')
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')
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')
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:')
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',
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',
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()
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')
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')
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')
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')
'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',
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',
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', setup_state=None)
+ 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
# 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'], setup_state=None)
+ 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
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')
'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)
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']
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)
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')
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)