l3cfg: handle flag "ip4acd_not_ready" for IPv4 addresses

ACD is handled by NML3Cfg and it intercepts the IP addresses when
merging the NML3ConfigData.

Originally, I thought that in such a case, the merged l3cd instance
would simply not contain any addresses that ACD have still pending or
which have a conflict.

However, I think it's better (clearer and possibly useful), to still
merge such addresses, but flag them that they are ignored when syncing
the addresses to platform.
This commit is contained in:
Thomas Haller 2020-10-09 19:04:38 +02:00
parent e155e4a153
commit 79664aa106
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
3 changed files with 56 additions and 23 deletions

View file

@ -2546,13 +2546,25 @@ nm_l3_config_data_merge(NML3ConfigData * self,
src,
&obj,
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
if (hook_add_addr && !hook_add_addr(src, obj, hook_user_data))
NMPlatformIPXAddress addr_stack;
const NMPlatformIPAddress *addr = NULL;
NMTernary ip4acd_not_ready = NM_TERNARY_DEFAULT;
if (hook_add_addr && !hook_add_addr(src, obj, &ip4acd_not_ready, hook_user_data))
continue;
if (IS_IPv4 && ip4acd_not_ready != NM_TERNARY_DEFAULT
&& (!!ip4acd_not_ready) != NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) {
addr_stack.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj);
addr_stack.a4.ip4acd_not_ready = (!!ip4acd_not_ready);
addr = &addr_stack.ax;
} else
nm_assert(IS_IPv4 || ip4acd_not_ready == NM_TERNARY_DEFAULT);
nm_l3_config_data_add_address_full(self,
addr_family,
obj,
NULL,
addr ? NULL : obj,
addr,
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL);
}

View file

@ -141,6 +141,7 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex * mu
typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData *l3cd,
const NMPObject * obj,
NMTernary * out_ip4acd_not_ready,
gpointer user_data);
void nm_l3_config_data_merge(NML3ConfigData * self,

View file

@ -588,7 +588,11 @@ _l3cfg_externally_removed_objs_filter(/* const NMDedupMultiObj * */ gconstpointe
const NMPObject *obj = o;
GHashTable * externally_removed_objs_hash = user_data;
return !g_hash_table_contains(externally_removed_objs_hash, obj);
if (NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ADDRESS
&& NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready)
return FALSE;
return !nm_g_hash_table_contains(externally_removed_objs_hash, obj);
}
/*****************************************************************************/
@ -2580,13 +2584,18 @@ typedef struct {
} L3ConfigMergeHookAddObjData;
static gboolean
_l3_hook_add_addr_cb(const NML3ConfigData *l3cd, const NMPObject *obj, gpointer user_data)
_l3_hook_add_addr_cb(const NML3ConfigData *l3cd,
const NMPObject * obj,
NMTernary * out_ip4acd_not_ready,
gpointer user_data)
{
const L3ConfigMergeHookAddObjData *hook_data = user_data;
NML3Cfg * self = hook_data->self;
AcdData * acd_data;
in_addr_t addr;
nm_assert(out_ip4acd_not_ready && *out_ip4acd_not_ready == NM_TERNARY_DEFAULT);
if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP4_ADDRESS)
return TRUE;
@ -2914,29 +2923,40 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type)
}
if (self->priv.p->combined_l3cd_commited) {
GHashTable * externally_removed_objs_hash;
NMDedupMultiFcnSelectPredicate predicate;
const NMDedupMultiHeadEntry * head_entry;
if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY
&& self->priv.p->externally_removed_objs_cnt_addresses_x[IS_IPv4] > 0)
predicate = _l3cfg_externally_removed_objs_filter;
else
predicate = NULL;
addresses = nm_dedup_multi_objs_to_ptr_array_head(
nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited,
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)),
predicate,
self->priv.p->externally_removed_objs_hash);
&& self->priv.p->externally_removed_objs_cnt_addresses_x[IS_IPv4] > 0) {
predicate = _l3cfg_externally_removed_objs_filter;
externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash;
} else {
if (IS_IPv4)
predicate = _l3cfg_externally_removed_objs_filter;
else
predicate = NULL;
externally_removed_objs_hash = NULL;
}
head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited,
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4));
addresses = nm_dedup_multi_objs_to_ptr_array_head(head_entry,
predicate,
externally_removed_objs_hash);
if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY
&& self->priv.p->externally_removed_objs_cnt_routes_x[IS_IPv4] > 0)
predicate = _l3cfg_externally_removed_objs_filter;
else
predicate = NULL;
routes = nm_dedup_multi_objs_to_ptr_array_head(
nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited,
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)),
predicate,
self->priv.p->externally_removed_objs_hash);
&& self->priv.p->externally_removed_objs_cnt_routes_x[IS_IPv4] > 0) {
predicate = _l3cfg_externally_removed_objs_filter;
externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash;
} else {
predicate = NULL;
externally_removed_objs_hash = NULL;
}
head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited,
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4));
routes = nm_dedup_multi_objs_to_ptr_array_head(head_entry,
predicate,
externally_removed_objs_hash);
route_table_sync =
nm_l3_config_data_get_route_table_sync(self->priv.p->combined_l3cd_commited,