Merge pull request #21036 from yuwata/network-dhcp6-pd-manage-prefix-with-hashmap

network: dhcp6-pd: manage prefix with hashmap
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-10-19 09:22:32 +02:00
committed by GitHub
3 changed files with 67 additions and 63 deletions
+65 -63
View File
@@ -56,64 +56,62 @@ static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred, &lifetime_valid) >= 0;
}
static int dhcp6_pd_get_link_by_prefix(Manager *manager, const struct in6_addr *prefix, Link **ret) {
union in_addr_union u;
static void link_remove_dhcp6_pd_prefix(Link *link, const struct in6_addr *prefix) {
void *key;
assert(link);
assert(link->manager);
assert(prefix);
if (hashmap_get(link->manager->links_by_dhcp6_pd_prefix, prefix) != link)
return;
hashmap_remove2(link->manager->links_by_dhcp6_pd_prefix, prefix, &key);
free(key);
}
static int link_add_dhcp6_pd_prefix(Link *link, const struct in6_addr *prefix) {
_cleanup_free_ struct in6_addr *copy = NULL;
int r;
assert(link);
assert(prefix);
copy = newdup(struct in6_addr, prefix, 1);
if (!copy)
return -ENOMEM;
r = hashmap_ensure_put(&link->manager->links_by_dhcp6_pd_prefix, &in6_addr_hash_ops_free, copy, link);
if (r < 0)
return r;
if (r > 0)
TAKE_PTR(copy);
return 0;
}
static int link_get_by_dhcp6_pd_prefix(Manager *manager, const struct in6_addr *prefix, Link **ret) {
Link *link;
assert(manager);
assert(prefix);
u.in6 = *prefix;
link = hashmap_get(manager->links_by_dhcp6_pd_prefix, prefix);
if (!link)
return -ENODEV;
HASHMAP_FOREACH(link, manager->links_by_index) {
if (!link_dhcp6_pd_is_enabled(link))
continue;
if (link->network->dhcp6_pd_assign) {
Address *address;
SET_FOREACH(address, link->addresses) {
if (address->source != NETWORK_CONFIG_SOURCE_DHCP6PD)
continue;
assert(address->family == AF_INET6);
if (in_addr_prefix_covers(AF_INET6, &u, 64, &address->in_addr) > 0) {
if (ret)
*ret = link;
return 0;
}
}
} else {
Route *route;
SET_FOREACH(route, link->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_DHCP6PD)
continue;
assert(route->family == AF_INET6);
if (in6_addr_equal(&route->dst.in6, prefix)) {
if (ret)
*ret = link;
return 0;
}
}
}
}
return -ENOENT;
if (ret)
*ret = link;
return 0;
}
static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_prefix, uint8_t pd_prefix_len, struct in6_addr *ret) {
union in_addr_union u;
assert(link);
assert(pd_prefix);
if (!link_dhcp6_pd_is_enabled(link))
return -ENOENT;
u.in6 = *pd_prefix;
if (link->network->dhcp6_pd_assign) {
Address *address;
@@ -122,14 +120,14 @@ static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_pr
continue;
assert(address->family == AF_INET6);
if (in_addr_prefix_covers(AF_INET6, &u, pd_prefix_len, &address->in_addr) <= 0)
if (in6_addr_prefix_covers(pd_prefix, pd_prefix_len, &address->in_addr.in6) <= 0)
continue;
if (ret) {
union in_addr_union prefix = address->in_addr;
struct in6_addr prefix = address->in_addr.in6;
in_addr_mask(AF_INET6, &prefix, 64);
*ret = prefix.in6;
in6_addr_mask(&prefix, 64);
*ret = prefix;
}
return 0;
}
@@ -141,7 +139,7 @@ static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_pr
continue;
assert(route->family == AF_INET6);
if (in_addr_prefix_covers(AF_INET6, &u, pd_prefix_len, &route->dst) > 0) {
if (in6_addr_prefix_covers(pd_prefix, pd_prefix_len, &route->dst.in6) > 0) {
if (ret)
*ret = route->dst.in6;
return 0;
@@ -175,6 +173,8 @@ int dhcp6_pd_remove(Link *link, bool only_marked) {
if (link->radv)
(void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64);
link_remove_dhcp6_pd_prefix(link, &route->dst.in6);
k = route_remove(route);
if (k < 0)
r = k;
@@ -183,17 +183,20 @@ int dhcp6_pd_remove(Link *link, bool only_marked) {
}
SET_FOREACH(address, link->addresses) {
struct in6_addr prefix;
if (address->source != NETWORK_CONFIG_SOURCE_DHCP6PD)
continue;
if (only_marked && !address_is_marked(address))
continue;
if (link->radv) {
union in_addr_union prefix = address->in_addr;
prefix = address->in_addr.in6;
in6_addr_mask(&prefix, 64);
in_addr_mask(AF_INET6, &prefix, 64);
(void) sd_radv_remove_prefix(link->radv, &prefix.in6, 64);
}
if (link->radv)
(void) sd_radv_remove_prefix(link->radv, &prefix, 64);
link_remove_dhcp6_pd_prefix(link, &prefix);
k = address_remove(address);
if (k < 0)
@@ -440,7 +443,7 @@ static int dhcp6_pd_assign_prefix(
if (r < 0)
return r;
return 0;
return link_add_dhcp6_pd_prefix(link, prefix);
}
static bool link_has_preferred_subnet_id(Link *link) {
@@ -487,9 +490,9 @@ static int dhcp6_get_preferred_delegated_prefix(
/* Verify that the prefix we did calculate fits in the pd prefix.
* This should not fail as we checked the prefix size beforehand */
assert_se(in_addr_prefix_covers(AF_INET6, (const union in_addr_union*) pd_prefix, pd_prefix_len, &prefix) > 0);
assert_se(in6_addr_prefix_covers(pd_prefix, pd_prefix_len, &prefix.in6) > 0);
if (dhcp6_pd_get_link_by_prefix(link->manager, &prefix.in6, &assigned_link) >= 0 &&
if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix.in6, &assigned_link) >= 0 &&
assigned_link != link) {
_cleanup_free_ char *assigned_buf = NULL;
@@ -506,7 +509,7 @@ static int dhcp6_get_preferred_delegated_prefix(
for (uint64_t n = 0; n < n_prefixes; n++) {
/* If we do not have an allocation preference just iterate
* through the address space and return the first free prefix. */
if (dhcp6_pd_get_link_by_prefix(link->manager, &prefix.in6, &assigned_link) < 0 ||
if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix.in6, &assigned_link) < 0 ||
assigned_link == link) {
*ret = prefix.in6;
return 0;
@@ -847,7 +850,6 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
uint32_t lifetime_preferred, lifetime_valid;
struct in6_addr pd_prefix;
union in_addr_union prefix;
uint8_t pd_prefix_len;
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len,
@@ -876,8 +878,8 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
assert(pd_prefix_len <= 64);
prefix.in6 = pd_prefix;
r = in_addr_mask(AF_INET6, &prefix, pd_prefix_len);
/* Mask prefix for safety. */
r = in6_addr_mask(&pd_prefix, pd_prefix_len);
if (r < 0)
return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m");
@@ -885,13 +887,13 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
uint64_t n_prefixes = UINT64_C(1) << (64 - pd_prefix_len);
_cleanup_free_ char *buf = NULL;
(void) in6_addr_prefix_to_string(&prefix.in6, pd_prefix_len, &buf);
(void) in6_addr_prefix_to_string(&pd_prefix, pd_prefix_len, &buf);
log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s",
n_prefixes, strna(buf));
}
r = dhcp6_pd_prefix_distribute(dhcp6_link,
&prefix.in6,
&pd_prefix,
pd_prefix_len,
lifetime_preferred,
lifetime_valid,
@@ -900,7 +902,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
return r;
r = dhcp6_pd_prefix_distribute(dhcp6_link,
&prefix.in6,
&pd_prefix,
pd_prefix_len,
lifetime_preferred,
lifetime_valid,
+1
View File
@@ -485,6 +485,7 @@ Manager* manager_free(Manager *m) {
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
m->links_by_name = hashmap_free(m->links_by_name);
m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr);
m->links_by_dhcp6_pd_prefix = hashmap_free(m->links_by_dhcp6_pd_prefix);
m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref);
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
+1
View File
@@ -48,6 +48,7 @@ struct Manager {
Hashmap *links_by_index;
Hashmap *links_by_name;
Hashmap *links_by_hw_addr;
Hashmap *links_by_dhcp6_pd_prefix;
Hashmap *netdevs;
OrderedHashmap *networks;
OrderedSet *address_pools;