diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index 9961eae820..ed5445de1a 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -166,6 +166,12 @@ typedef struct { /* This flag is only used temporarily to do a bulk update and * clear all the ones that are no longer in used. */ bool os_dirty : 1; + + /* Indicates whether this is configured dynamically or statically on l3cd. */ + bool os_dynamic : 1; + + /* Indicates that this dynamic obj-state is marked as dirty. */ + bool is_dynamic_dirty : 1; } ObjStateData; G_STATIC_ASSERT(G_STRUCT_OFFSET(ObjStateData, obj) == 0); @@ -831,6 +837,8 @@ _obj_state_data_new(const NMPObject *obj, const NMPObject *plobj) .os_was_in_platform = !!plobj, .os_nm_configured = FALSE, .os_dirty = FALSE, + .os_dynamic = FALSE, + .is_dynamic_dirty = FALSE, .os_failedobj_expiry_msec = 0, .os_failedobj_prioq_idx = NM_PRIOQ_IDX_NULL, .os_zombie_lst = C_LIST_INIT(obj_state->os_zombie_lst), @@ -1001,7 +1009,7 @@ out: } static void -_obj_states_track_new(NML3Cfg *self, const NMPObject *obj) +_obj_states_track_new(NML3Cfg *self, const NMPObject *obj, bool is_dynamic) { char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; ObjStateData *obj_state; @@ -1009,6 +1017,7 @@ _obj_states_track_new(NML3Cfg *self, const NMPObject *obj) obj_state = _obj_state_data_new( obj, nm_platform_lookup_obj(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)); + obj_state->os_dynamic = is_dynamic; c_list_link_tail(&self->priv.p->obj_state_lst_head, &obj_state->os_lst); g_hash_table_add(self->priv.p->obj_state_hash, obj_state); _LOGD("obj-state: track: %s", _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); @@ -1064,7 +1073,7 @@ _obj_states_update_all(NML3Cfg *self) } obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj); if (!obj_state) { - _obj_states_track_new(self, obj); + _obj_states_track_new(self, obj, FALSE); continue; } @@ -1194,6 +1203,52 @@ _commit_collect_addresses(NML3Cfg *self, int addr_family, NML3CfgCommitType comm (gpointer) &sync_filter_data); } +static void +_obj_states_mark_dynamic_as_dirty(NML3Cfg *self) +{ + ObjStateData *obj_state; + + c_list_for_each_entry (obj_state, &self->priv.p->obj_state_lst_head, os_lst) { + if (!obj_state->os_dynamic) + continue; + obj_state->is_dynamic_dirty = TRUE; + } +} + +static void +_obj_states_dynamic_remove_track(NML3Cfg *self) +{ + GHashTableIter h_iter; + ObjStateData *obj_state; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; + + g_hash_table_iter_init(&h_iter, self->priv.p->obj_state_hash); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_state, NULL)) { + if (!c_list_is_empty(&obj_state->os_zombie_lst)) + continue; + if (!obj_state->os_dynamic) + continue; + if (!obj_state->is_dynamic_dirty) + continue; + + if (obj_state->os_nm_configured) { + nm_assert(obj_state->os_failedobj_prioq_idx == NM_PRIOQ_IDX_NULL); + c_list_link_tail(&self->priv.p->obj_state_zombie_lst_head, &obj_state->os_zombie_lst); + obj_state->os_zombie_count = ZOMBIE_COUNT_START; + _LOGD("obj-state: now dynamic zombie: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + continue; + } + + _LOGD("obj-state: dynamic untrack: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + nm_prioq_remove(&self->priv.p->failedobj_prioq, + obj_state, + &obj_state->os_failedobj_prioq_idx); + g_hash_table_iter_remove(&h_iter); + } +} + static void _commit_collect_routes(NML3Cfg *self, int addr_family, @@ -1273,6 +1328,7 @@ loop_done: &singlehop_routes, NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_REAPPLY)); + _obj_states_mark_dynamic_as_dirty(self); if (singlehop_routes) { for (i = 0; i < singlehop_routes->len; i++) { const NMPObject *obj = singlehop_routes->pdata[i]; @@ -1280,7 +1336,9 @@ loop_done: obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj); if (!obj_state) - _obj_states_track_new(self, obj); + _obj_states_track_new(self, obj, TRUE); + else + obj_state->is_dynamic_dirty = FALSE; if (!_obj_states_sync_filter(self, obj, commit_type)) continue; @@ -4893,6 +4951,9 @@ _l3_commit_one(NML3Cfg *self, if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE) route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN; + if (IS_IPv4) + _obj_states_dynamic_remove_track(self); + if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY) { gs_unref_array GArray *ipv6_temp_addrs_keep = NULL;