l3cfg: add NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE flag

It's a bit tricky how this flag works. It's needed for IPv6
link local addresses, which commits changes in %NM_L3_CFG_COMMIT_TYPE_ASSUME
mode. See the code comments how it works.

This commit only adds the flags and let's the NMPlatformIP{Address,Route}
properly track it. What is still needed is to actually implement any
meaning to that during the sync.
This commit is contained in:
Thomas Haller 2021-09-06 14:10:39 +02:00
parent a909a4b305
commit 8a3d913de8
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 55 additions and 4 deletions

View file

@ -1104,6 +1104,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx,
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
modified = TRUE;
}
/* OR assume_config_once flag */
if (obj_new->ip_address.a_assume_config_once
&& !obj_old->ip_address.a_assume_config_once) {
obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
obj_new_stackinit.ip_address.a_assume_config_once = TRUE;
modified = TRUE;
}
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
case NMP_OBJECT_TYPE_IP6_ROUTE:
@ -1113,6 +1121,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx,
obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
modified = TRUE;
}
/* OR assume_config_once flag */
if (obj_new->ip_route.r_assume_config_once
&& !obj_old->ip_route.r_assume_config_once) {
obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
obj_new_stackinit.ip_route.r_assume_config_once = TRUE;
modified = TRUE;
}
break;
default:
nm_assert_not_reached();
@ -2736,7 +2752,8 @@ nm_l3_config_data_merge(NML3ConfigData * self,
const NMPlatformIPAddress *a_src = NMP_OBJECT_CAST_IP_ADDRESS(obj);
NMPlatformIPXAddress a;
NML3ConfigMergeHookResult hook_result = {
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
.assume_config_once = NM_OPTION_BOOL_DEFAULT,
};
#define _ensure_a() \
@ -2766,6 +2783,12 @@ nm_l3_config_data_merge(NML3ConfigData * self,
a.a4.a_acd_not_ready = (!!hook_result.ip4acd_not_ready);
}
if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT
&& (!!hook_result.assume_config_once) != a_src->a_assume_config_once) {
_ensure_a();
a.ax.a_assume_config_once = (!!hook_result.assume_config_once);
}
nm_l3_config_data_add_address_full(self,
addr_family,
a_src == &a.ax ? NULL : obj,
@ -2784,7 +2807,8 @@ nm_l3_config_data_merge(NML3ConfigData * self,
const NMPlatformIPRoute * r_src = NMP_OBJECT_CAST_IP_ROUTE(obj);
NMPlatformIPXRoute r;
NML3ConfigMergeHookResult hook_result = {
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
.assume_config_once = NM_OPTION_BOOL_DEFAULT,
};
#define _ensure_r() \
@ -2807,6 +2831,12 @@ nm_l3_config_data_merge(NML3ConfigData * self,
nm_assert(hook_result.ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT);
if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT
&& (!!hook_result.assume_config_once) != r_src->r_assume_config_once) {
_ensure_r();
r.rx.r_assume_config_once = (!!hook_result.assume_config_once);
}
if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) {
if (r_src->table_any) {
_ensure_r();

View file

@ -137,6 +137,7 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex * mu
typedef struct {
NMOptionBool ip4acd_not_ready;
NMOptionBool assume_config_once;
} NML3ConfigMergeHookResult;
typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData * l3cd,

View file

@ -2923,6 +2923,7 @@ nm_l3cfg_remove_config_all_dirty(NML3Cfg *self, gconstpointer tag)
typedef struct {
NML3Cfg * self;
gconstpointer tag;
bool assume_config_once;
} L3ConfigMergeHookAddObjData;
static gboolean
@ -2940,6 +2941,9 @@ _l3_hook_add_obj_cb(const NML3ConfigData * l3cd,
nm_assert(obj);
nm_assert(hook_result);
nm_assert(hook_result->ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT);
nm_assert(hook_result->assume_config_once == NM_OPTION_BOOL_DEFAULT);
hook_result->assume_config_once = hook_data->assume_config_once;
switch (NMP_OBJECT_GET_TYPE(obj)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
@ -3058,6 +3062,9 @@ _l3cfg_update_combined_config(NML3Cfg * self,
continue;
hook_data.tag = l3cd_data->tag_confdata;
hook_data.assume_config_once =
NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE);
nm_l3_config_data_merge(l3cd,
l3cd_data->l3cd,
l3cd_data->merge_flags,

View file

@ -40,10 +40,23 @@ typedef enum _nm_packed {
* nm_l3cfg_add_config() the same NML3Cfg again (with a different
* tag), or by calling nm_l3cfg_add_config() again with this flag
* cleared (and the same tag).
* @NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE: a commit with
* %NM_L3_CFG_COMMIT_TYPE_ASSUME, means to not remove/add
* addresses that are missing/already exist. The assume mode
* is for taking over a device gracefully after restart, so
* it aims to preserve whatever was configured (or not configured).
* With this flag enabled, the first commit in assume mode will still
* add the addresses/routes. This is necessary for example with IPv6LL.
* Also while assuming a device, we want to configure things
* (like an IPv6 address), so we need to bypass the common
* "don't change" behavior. At least once. If the address/route
* is still not (no longer) configured on the subsequent
* commit, it's not getting added again.
*/
typedef enum _nm_packed {
NM_L3CFG_CONFIG_FLAGS_NONE = 0,
NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD = (1LL << 0),
NM_L3CFG_CONFIG_FLAGS_NONE = 0,
NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD = (1LL << 0),
NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE = (1LL << 1),
} NML3CfgConfigFlags;
typedef enum _nm_packed {