1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-24 17:57:34 +03:00

network/tunnel: reuse existing 6rd sit tunnel (#34938)

split-out of #34909.
This commit is contained in:
Yu Watanabe 2024-10-31 04:04:55 +09:00 committed by GitHub
commit f7d5d7c593
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 84 deletions

View File

@ -34,7 +34,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode);
#define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
static int dhcp4_pd_create_6rd_tunnel_name(Link *link) {
_cleanup_free_ char *ifname_alloc = NULL;
uint8_t ipv4masklen, sixrd_prefixlen, *buf, *p;
struct in_addr ipv4address;
@ -47,13 +47,16 @@ int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
assert(link);
assert(link->dhcp_lease);
if (link->dhcp4_6rd_tunnel_name)
return 0; /* Already set. Do not change even if the 6rd option is changed. */
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
return r;
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
return r;
sz = sizeof(uint8_t) * 2 + sizeof(struct in6_addr) + sizeof(struct in_addr);
buf = newa(uint8_t, sz);
@ -80,21 +83,44 @@ int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
ifname_alloc = strdup(ifname);
if (!ifname_alloc)
return log_oom_debug();
return -ENOMEM;
*ret = TAKE_PTR(ifname_alloc);
link->dhcp4_6rd_tunnel_name = TAKE_PTR(ifname_alloc);
return 0;
}
static int dhcp4_pd_create_6rd_tunnel_message(
Link *link,
sd_netlink_message *m,
const struct in_addr *ipv4address,
uint8_t ipv4masklen,
const struct in6_addr *sixrd_prefix,
uint8_t sixrd_prefixlen) {
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint8_t ipv4masklen, sixrd_prefixlen;
struct in_addr ipv4address;
struct in6_addr sixrd_prefix;
Link *sit = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
assert(link->dhcp_lease);
assert(callback);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return r;
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return r;
r = dhcp4_pd_create_6rd_tunnel_name(link);
if (r < 0)
return r;
(void) link_get_by_name(link->manager, link->dhcp4_6rd_tunnel_name, &sit);
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, sit ? sit->ifindex : 0);
if (r < 0)
return r;
r = sd_netlink_message_append_string(m, IFLA_IFNAME, link->dhcp4_6rd_tunnel_name);
if (r < 0)
return r;
@ -107,7 +133,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
if (r < 0)
return r;
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, ipv4address);
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &ipv4address);
if (r < 0)
return r;
@ -115,7 +141,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
if (r < 0)
return r;
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, sixrd_prefix);
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &sixrd_prefix);
if (r < 0)
return r;
@ -123,7 +149,7 @@ static int dhcp4_pd_create_6rd_tunnel_message(
if (r < 0)
return r;
struct in_addr relay_prefix = *ipv4address;
struct in_addr relay_prefix = ipv4address;
(void) in4_addr_mask(&relay_prefix, ipv4masklen);
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_6RD_RELAY_PREFIX, relay_prefix.s_addr);
if (r < 0)
@ -141,48 +167,12 @@ static int dhcp4_pd_create_6rd_tunnel_message(
if (r < 0)
return r;
return 0;
}
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint8_t ipv4masklen, sixrd_prefixlen;
struct in_addr ipv4address;
struct in6_addr sixrd_prefix;
int r;
assert(link);
assert(link->ifindex > 0);
assert(link->manager);
assert(link->dhcp_lease);
assert(link->dhcp4_6rd_tunnel_name);
assert(callback);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, 0);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to create netlink message: %m");
r = dhcp4_pd_create_6rd_tunnel_message(link, m,
&ipv4address, ipv4masklen,
&sixrd_prefix, sixrd_prefixlen);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to fill netlink message: %m");
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_debug_errno(link, r, "Could not send netlink message: %m");
return r;
link_ref(link);
return 0;
}

View File

@ -69,7 +69,6 @@ typedef struct Tunnel {
uint8_t sixrd_prefixlen;
} Tunnel;
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret);
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback);
DEFINE_NETDEV_CAST(IPIP, Tunnel);

View File

@ -961,7 +961,6 @@ static int dhcp4_pd_6rd_tunnel_create_handler(sd_netlink *rtnl, sd_netlink_messa
}
int dhcp4_pd_prefix_acquired(Link *uplink) {
_cleanup_free_ char *tunnel_name = NULL;
uint8_t ipv4masklen, sixrd_prefixlen, pd_prefixlen;
struct in6_addr sixrd_prefix, pd_prefix;
struct in_addr ipv4address;
@ -1010,28 +1009,10 @@ int dhcp4_pd_prefix_acquired(Link *uplink) {
if (r < 0)
return r;
/* Generate 6rd SIT tunnel device name. */
r = dhcp4_pd_create_6rd_tunnel_name(uplink, &tunnel_name);
/* Create or update 6rd SIT tunnel device. */
r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler);
if (r < 0)
return r;
/* Remove old tunnel device if exists. */
if (!streq_ptr(uplink->dhcp4_6rd_tunnel_name, tunnel_name)) {
Link *old_tunnel;
if (uplink->dhcp4_6rd_tunnel_name &&
link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, &old_tunnel) >= 0)
(void) link_remove(old_tunnel);
free_and_replace(uplink->dhcp4_6rd_tunnel_name, tunnel_name);
}
/* Create 6rd SIT tunnel device if it does not exist yet. */
if (link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, NULL) < 0) {
r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler);
if (r < 0)
return r;
}
return log_link_warning_errno(uplink, r, "Failed to create or update 6rd SIT tunnel: %m");
/* Then, assign subnet prefixes to downstream interfaces. */
HASHMAP_FOREACH(link, uplink->manager->links_by_index) {

View File

@ -7732,7 +7732,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
self.teardown_nftset('addr6', 'network6', 'ifindex')
def verify_dhcp4_6rd(self, tunnel_name):
def verify_dhcp4_6rd(self, tunnel_name, address_prefix, border_router):
print('### ip -4 address show dev veth-peer scope global')
output = check_output('ip -4 address show dev veth-peer scope global')
print(output)
@ -7751,7 +7751,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -4 address show dev veth99 scope global')
output = check_output('ip -4 address show dev veth99 scope global')
print(output)
self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99')
self.assertRegex(output, fr'inet {address_prefix}[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99')
print('### ip -6 address show dev veth99 scope global')
output = check_output('ip -6 address show dev veth99 scope global')
@ -7887,8 +7887,8 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print(f'### ip -d link show dev {tunnel_name}')
output = check_output(f'ip -d link show dev {tunnel_name}')
print(output)
self.assertIn('link/sit 10.100.100.', output)
self.assertIn('local 10.100.100.', output)
self.assertIn(f'link/sit {address_prefix}', output)
self.assertIn(f'local {address_prefix}', output)
self.assertIn('ttl 64', output)
self.assertIn('6rd-prefix 2001:db8::/32', output)
self.assertIn('6rd-relay_prefix 10.0.0.0/8', output)
@ -7897,7 +7897,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
output = check_output(f'ip -6 address show dev {tunnel_name}')
print(output)
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')
self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
self.assertRegex(output, fr'inet6 ::{address_prefix}[0-9]+/96 scope global')
print(f'### ip -6 route show dev {tunnel_name}')
output = check_output(f'ip -6 route show dev {tunnel_name}')
@ -7909,7 +7909,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
output = check_output('ip -6 route show default')
print(output)
self.assertIn('default', output)
self.assertIn(f'via ::10.0.0.1 dev {tunnel_name}', output)
self.assertIn(f'via ::{border_router} dev {tunnel_name}', output)
def test_dhcp4_6rd(self):
def get_dhcp_6rd_prefix(link):
@ -7969,13 +7969,19 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
self.wait_online(f'{tunnel_name}:routable')
self.verify_dhcp4_6rd(tunnel_name)
self.verify_dhcp4_6rd(tunnel_name, '10.100.100.1', '10.0.0.1')
# Test case for reconfigure
networkctl_reconfigure('dummy98', 'dummy99')
self.wait_online('dummy98:routable', 'dummy99:degraded')
self.verify_dhcp4_6rd(tunnel_name)
self.verify_dhcp4_6rd(tunnel_name, '10.100.100.1', '10.0.0.1')
# Change the address range and (border) router, then if check the same tunnel is reused.
stop_dnsmasq()
start_dnsmasq('--dhcp-option=212,08:20:20:01:0d:b8:00:00:00:00:00:00:00:00:00:00:00:00:0a:00:00:02',
ipv4_range='10.100.100.200,10.100.100.250',
ipv4_router='10.0.0.2')
print('Wait for the DHCP lease to be renewed/rebind')
time.sleep(120)
@ -7983,7 +7989,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
self.wait_online('veth99:routable', 'test1:routable', 'dummy97:routable', 'dummy98:routable', 'dummy99:degraded',
'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable')
self.verify_dhcp4_6rd(tunnel_name)
self.verify_dhcp4_6rd(tunnel_name, '10.100.100.2', '10.0.0.2')
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):