diff options
Diffstat (limited to 'test/test-network')
12 files changed, 179 insertions, 24 deletions
diff --git a/test/test-network/conf/agent-client-peer.network b/test/test-network/conf/agent-client-peer.network new file mode 100644 index 0000000000..0db83dc9d2 --- /dev/null +++ b/test/test-network/conf/agent-client-peer.network @@ -0,0 +1,9 @@ +[Match] +Name=client-peer +[Network] +Address=192.168.6.2/24 +DHCPServer=yes +IPForward=ipv4 +[DHCPServer] +RelayTarget=192.168.5.1 +BindToInterface=no diff --git a/test/test-network/conf/agent-client.network b/test/test-network/conf/agent-client.network new file mode 100644 index 0000000000..773dc8a4fb --- /dev/null +++ b/test/test-network/conf/agent-client.network @@ -0,0 +1,5 @@ +[Match] +Name=client +[Network] +DHCP=yes +IPForward=ipv4 diff --git a/test/test-network/conf/agent-server-peer.network b/test/test-network/conf/agent-server-peer.network new file mode 100644 index 0000000000..fdb235e1ff --- /dev/null +++ b/test/test-network/conf/agent-server-peer.network @@ -0,0 +1,5 @@ +[Match] +Name=server-peer +[Network] +Address=192.168.5.2/24 +IPForward=ipv4 diff --git a/test/test-network/conf/agent-server.network b/test/test-network/conf/agent-server.network new file mode 100644 index 0000000000..d58abdf271 --- /dev/null +++ b/test/test-network/conf/agent-server.network @@ -0,0 +1,10 @@ +[Match] +Name=server +[Network] +Address=192.168.5.1/24 +IPForward=ipv4 +DHCPServer=yes +[DHCPServer] +BindToInterface=no +PoolOffset=150 +PoolSize=1 diff --git a/test/test-network/conf/agent-veth-client.netdev b/test/test-network/conf/agent-veth-client.netdev new file mode 100644 index 0000000000..ace785f5ca --- /dev/null +++ b/test/test-network/conf/agent-veth-client.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=client +Kind=veth +MACAddress=12:34:56:78:9a:bc + +[Peer] +Name=client-peer +MACAddress=12:34:56:78:9a:bd diff --git a/test/test-network/conf/agent-veth-server.netdev b/test/test-network/conf/agent-veth-server.netdev new file mode 100644 index 0000000000..3a3d3931ba --- /dev/null +++ b/test/test-network/conf/agent-veth-server.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=server +Kind=veth +MACAddress=12:34:56:78:9b:bc + +[Peer] +Name=server-peer +MACAddress=12:34:56:78:9b:bd diff --git a/test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network b/test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network new file mode 100644 index 0000000000..448cfb0e59 --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network @@ -0,0 +1,9 @@ +[Match] +Name=veth99 + +[NetworkEmulator] +DelaySec=9 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=true diff --git a/test/test-network/conf/dhcp-server-with-ipv6-prefix.network b/test/test-network/conf/dhcp-server-with-ipv6-prefix.network new file mode 100644 index 0000000000..05ebe3e7e2 --- /dev/null +++ b/test/test-network/conf/dhcp-server-with-ipv6-prefix.network @@ -0,0 +1,11 @@ +[Match] +Name=veth-peer + +[Network] +Address=192.168.5.1/24 +IPv6AcceptRA=no +DHCPServer=yes +IPv6SendRA=yes + +[IPv6Prefix] +Prefix=2002:da8:1:0::/64 diff --git a/test/test-network/conf/ipv6-prefix-with-delay.network b/test/test-network/conf/ipv6-prefix-with-delay.network new file mode 100644 index 0000000000..4fe3c9a04b --- /dev/null +++ b/test/test-network/conf/ipv6-prefix-with-delay.network @@ -0,0 +1,12 @@ +[Match] +Name=veth-peer + +[NetworkEmulator] +DelaySec=15 + +[Network] +IPv6AcceptRA=no +IPv6SendRA=yes + +[IPv6Prefix] +Prefix=2002:da8:1:0::/64 diff --git a/test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network b/test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network new file mode 100644 index 0000000000..13fd0adeff --- /dev/null +++ b/test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network @@ -0,0 +1,6 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=true +Address=192.168.5.1/24 diff --git a/test/test-network/conf/state-file-tests.network b/test/test-network/conf/state-file-tests.network index 1f7e7d16f0..d9db9a9ab9 100644 --- a/test/test-network/conf/state-file-tests.network +++ b/test/test-network/conf/state-file-tests.network @@ -3,6 +3,7 @@ Name=dummy98 [Link] RequiredForOnline=routable +RequiredFamilyForOnline=both [Network] IPv6AcceptRA=no @@ -14,3 +15,4 @@ MulticastDNS=yes DNSSEC=no Address=192.168.10.10/24 Address=192.168.12.12/24 +Address=2002:da8:1:0:1034:56ff:fe78:9abc/64 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index fc88fefd0f..148ff6e8c0 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -555,7 +555,7 @@ class Utilities(): self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}') return False - def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured', setup_timeout=5): + def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5): """Wait for the link(s) to reach the specified operstate and/or setup state. This is similar to wait_operstate() but can be used for multiple links, @@ -569,6 +569,9 @@ class Utilities(): Set 'bool_any' to True to wait for any (instead of all) of the given links. If this is set, no setup_state checks are done. + Set 'ipv4' or 'ipv6' to True to wait for IPv4 address or IPv6 address, respectively, of each of the given links. + This is applied only for the operational state 'degraded' or above. + Note that this function waits for the link(s) to reach *or exceed* the given operstate. However, the setup_state, if specified, must be matched *exactly*. @@ -578,6 +581,10 @@ class Utilities(): args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate] if bool_any: args += ['--any'] + if ipv4: + args += ['--ipv4'] + if ipv6: + args += ['--ipv6'] try: check_output(*args, env=env) except subprocess.CalledProcessError: @@ -1781,6 +1788,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): 'gretun97', 'ip6gretun97', 'test1', + 'veth-peer', 'veth99', 'vrf99', ] @@ -1842,6 +1850,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): '25-vrf.netdev', '25-vrf.network', '26-link-local-addressing-ipv6.network', + 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network', + 'dhcp-server-with-ipv6-prefix.network', + 'ipv6ra-prefix-client-with-static-ipv4-address.network', + 'ipv6-prefix-with-delay.network', 'routing-policy-rule-dummy98.network', 'routing-policy-rule-test1.network', 'routing-policy-rule-reconfigure1.network', @@ -3099,6 +3111,22 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): call('rmmod netdevsim', stderr=subprocess.DEVNULL) + def test_wait_online_ipv4(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network') + start_networkd() + + self.wait_online(['veth99:routable'], ipv4=True) + + self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1) + + def test_wait_online_ipv6(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix-with-delay.network', 'ipv6ra-prefix-client-with-static-ipv4-address.network') + start_networkd() + + self.wait_online(['veth99:routable'], ipv6=True) + + self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1) + class NetworkdStateFileTests(unittest.TestCase, Utilities): links = [ 'dummy98', @@ -3135,10 +3163,13 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities): with open(path) as f: data = f.read() + self.assertRegex(data, r'IPV4_ADDRESS_STATE=routable') + self.assertRegex(data, r'IPV6_ADDRESS_STATE=routable') self.assertRegex(data, r'ADMIN_STATE=configured') self.assertRegex(data, r'OPER_STATE=routable') self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes') self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable') + self.assertRegex(data, r'REQUIRED_FAMILY_FOR_ONLINE=both') self.assertRegex(data, r'ACTIVATION_POLICY=up') self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network') self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') @@ -3658,6 +3689,43 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities): self.assertRegex(output, '192.168.5.*') self.assertRegex(output, 'Europe/Berlin') +class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities): + links = [ + 'client', + 'server', + 'client-peer', + 'server-peer', + ] + + units = [ + 'agent-veth-client.netdev', + 'agent-veth-server.netdev', + 'agent-client.network', + 'agent-server.network', + 'agent-client-peer.network', + 'agent-server-peer.network', + ] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_relay_agent(self): + copy_unit_to_networkd_unit_path(*self.units) + start_networkd() + + #Test is disabled until BindToInterface DHCP server configuration option is supported + self.wait_online(['client:routable']) + + output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env) + print(output) + self.assertRegex(output, 'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)') + class NetworkdDHCPClientTests(unittest.TestCase, Utilities): links = [ 'veth99', @@ -3843,7 +3911,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) @@ -3946,7 +4014,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip address show dev veth99 scope global') print(output) self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99') - self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99') + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic veth99') output = check_output('ip route show dev veth99') print(output) @@ -3976,7 +4044,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip route show dev veth99') print(output) - self.assertRegex(output, 'metric 24') + self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output) + self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output) + self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output) def test_dhcp_client_reassign_static_routes_ipv4(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', @@ -3988,7 +4058,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip address show dev veth99 scope global') print(output) - self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') output = check_output('ip route show dev veth99') print(output) @@ -4133,7 +4203,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') output = check_output('ip address show dev veth99 scope global') @@ -4176,7 +4246,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') print('## ip -d link show dev vrf99') @@ -4187,14 +4257,14 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print('## ip address show vrf vrf99') output = check_output('ip address show vrf vrf99') print(output) - self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 .* scope link') print('## ip address show dev veth99') output = check_output('ip address show dev veth99') print(output) - self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 .* scope link') @@ -4270,9 +4340,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') print('Wait for the dynamic address to be expired') time.sleep(130) @@ -4285,9 +4355,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') search_words_in_dnsmasq_log('DHCPOFFER', show_all=True) @@ -4307,13 +4377,13 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') start_dnsmasq(lease_time='2m') - self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic', ipv='-4') - self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4') + self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4') + 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') def test_dhcp_client_route_remove_on_renew(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', @@ -4327,7 +4397,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -4 address show dev veth99 scope global dynamic') print(output) - self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') address1=None for line in output.splitlines(): if 'brd 192.168.5.255 scope global dynamic veth99' in line: @@ -4347,10 +4417,10 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -4 address show dev veth99 scope global dynamic') print(output) - self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') address2=None for line in output.splitlines(): - if 'brd 192.168.5.255 scope global dynamic veth99' in line: + if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line: address2 = line.split()[1].split('/')[0] break @@ -4372,7 +4442,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4390,7 +4460,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4408,7 +4478,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4426,7 +4496,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) |