mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-21 01:57:57 +03:00
network: dhcp6-pd: exclude all explicitly specified subnet IDs when searching free IDs
When the upstream link gained a lease, then several downstream links may not appear yet. Previously, the explicitly specified subnet ID for a downstream link which appears later may be already assigned to an interface which does not request specific subnet ID. To avoid such situation, this makes all specified IDs are excluded when searching free IDs. As a side effect, we can avoid the second call of dhcp6_pd_distribute_prefix().
This commit is contained in:
parent
a74229c58e
commit
1a4ca0e2f3
@ -531,13 +531,20 @@ static int dhcp6_pd_get_preferred_prefix(
|
||||
}
|
||||
|
||||
for (uint64_t n = 0; ; n++) {
|
||||
/* If we do not have an allocation preference just iterate
|
||||
* through the address space and return the first free prefix. */
|
||||
|
||||
r = dhcp6_pd_calculate_prefix(pd_prefix, pd_prefix_len, n, &prefix);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r,
|
||||
"Couldn't find a suitable prefix. Ran out of address space.");
|
||||
|
||||
/* If we do not have an allocation preference just iterate
|
||||
* through the address space and return the first free prefix. */
|
||||
/* Do not use explicitly requested subnet IDs. Note that the corresponding link may not
|
||||
* appear yet. So, we need to check the ID is not used in any .network files. */
|
||||
if (set_contains(link->manager->dhcp6_pd_subnet_ids, &n))
|
||||
continue;
|
||||
|
||||
/* Check that the prefix is not assigned to another link. */
|
||||
if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix, &assigned_link) < 0 ||
|
||||
assigned_link == link) {
|
||||
*ret = prefix;
|
||||
@ -602,8 +609,7 @@ static int dhcp6_pd_distribute_prefix(
|
||||
const struct in6_addr *pd_prefix,
|
||||
uint8_t pd_prefix_len,
|
||||
usec_t lifetime_preferred_usec,
|
||||
usec_t lifetime_valid_usec,
|
||||
bool assign_preferred_subnet_id) {
|
||||
usec_t lifetime_valid_usec) {
|
||||
|
||||
Link *link;
|
||||
int r;
|
||||
@ -626,9 +632,6 @@ static int dhcp6_pd_distribute_prefix(
|
||||
if (link == dhcp6_link && !link->network->dhcp6_pd_assign)
|
||||
continue;
|
||||
|
||||
if (assign_preferred_subnet_id != link_has_preferred_subnet_id(link))
|
||||
continue;
|
||||
|
||||
r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
|
||||
if (r < 0) {
|
||||
if (link == dhcp6_link)
|
||||
@ -978,17 +981,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
||||
&pd_prefix,
|
||||
pd_prefix_len,
|
||||
lifetime_preferred_usec,
|
||||
lifetime_valid_usec,
|
||||
true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_pd_distribute_prefix(dhcp6_link,
|
||||
&pd_prefix,
|
||||
pd_prefix_len,
|
||||
lifetime_preferred_usec,
|
||||
lifetime_valid_usec,
|
||||
false);
|
||||
lifetime_valid_usec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -502,6 +502,7 @@ Manager* manager_free(Manager *m) {
|
||||
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->dhcp6_pd_subnet_ids = set_free(m->dhcp6_pd_subnet_ids);
|
||||
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
|
||||
|
||||
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
|
||||
@ -585,7 +586,7 @@ int manager_load_config(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return manager_build_dhcp6_pd_subnet_ids(m);
|
||||
}
|
||||
|
||||
bool manager_should_reload(Manager *m) {
|
||||
|
@ -52,6 +52,7 @@ struct Manager {
|
||||
Hashmap *netdevs;
|
||||
OrderedHashmap *networks;
|
||||
OrderedSet *address_pools;
|
||||
Set *dhcp6_pd_subnet_ids;
|
||||
|
||||
usec_t network_dirs_ts_usec;
|
||||
|
||||
|
@ -643,7 +643,7 @@ int network_reload(Manager *manager) {
|
||||
ordered_hashmap_free_with_destructor(manager->networks, network_unref);
|
||||
manager->networks = new_networks;
|
||||
|
||||
return 0;
|
||||
return manager_build_dhcp6_pd_subnet_ids(manager);
|
||||
|
||||
failure:
|
||||
ordered_hashmap_free_with_destructor(new_networks, network_unref);
|
||||
@ -651,6 +651,32 @@ failure:
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_build_dhcp6_pd_subnet_ids(Manager *manager) {
|
||||
Network *n;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
|
||||
set_clear(manager->dhcp6_pd_subnet_ids);
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(n, manager->networks) {
|
||||
if (n->unmanaged)
|
||||
continue;
|
||||
|
||||
if (!n->dhcp6_pd)
|
||||
continue;
|
||||
|
||||
if (n->dhcp6_pd_subnet_id < 0)
|
||||
continue;
|
||||
|
||||
r = set_ensure_put(&manager->dhcp6_pd_subnet_ids, &uint64_hash_ops, &n->dhcp6_pd_subnet_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Network *network_free(Network *network) {
|
||||
if (!network)
|
||||
return NULL;
|
||||
|
@ -365,6 +365,8 @@ int network_reload(Manager *manager);
|
||||
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename);
|
||||
int network_verify(Network *network);
|
||||
|
||||
int manager_build_dhcp6_pd_subnet_ids(Manager *manager);
|
||||
|
||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
||||
void network_apply_anonymize_if_set(Network *network);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user