summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-09-03 12:24:08 +0200
committerThomas Haller <thaller@redhat.com>2020-09-07 16:11:51 +0200
commit47e2ff0a712764d617609858261c48bbc85a2537 (patch)
tree8872c3973a17848cc8b39ff40e15871d1d91e053
parent4c07d345057c84a5005dea0385c8b3e9d1c6138d (diff)
downloadNetworkManager-47e2ff0a712764d617609858261c48bbc85a2537.tar.gz
l3cfg: add nm_l3cfg_commit_type*() API for tracking the level for committing changes
NML3Cfg manages one ifindex. In the future, we may want that multiple NMDevice and/or NMVpnConnection instances independently contribute their NML3ConfigData to the NML3Cfg instance. That means, at any time somebody may want to call nm_l3cfg_platform_commit() to apply the changes. Even ACD internally may do that, when configuration changes (e.g. an IP address passes ACD check). We thus need to know whether we are assuming, updating or reapplying the settings. Add API so users can register their "commit" preference.
-rw-r--r--src/nm-l3cfg.c119
-rw-r--r--src/nm-l3cfg.h28
2 files changed, 143 insertions, 4 deletions
diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c
index 3c8bb524e3..2086cd00e7 100644
--- a/src/nm-l3cfg.c
+++ b/src/nm-l3cfg.c
@@ -95,6 +95,11 @@ typedef struct {
bool announcing_failed_is_retrying:1;
} AcdData;
+struct _NML3CfgCommitTypeHandle {
+ CList commit_type_lst;
+ NML3CfgCommitType commit_type;
+};
+
typedef struct {
const NML3ConfigData *l3cd;
NML3ConfigMergeFlags merge_flags;
@@ -131,6 +136,8 @@ typedef struct _NML3CfgPrivate {
GArray *l3_config_datas;
const NML3ConfigData *combined_l3cd;
+ CList commit_type_lst_head;
+
GHashTable *routes_temporary_not_available_hash;
GHashTable *externally_removed_objs_hash;
@@ -231,6 +238,8 @@ static AcdData *_l3_acd_data_find (NML3Cfg *self,
static
NM_UTILS_ENUM2STR_DEFINE (_l3_cfg_commit_type_to_string, NML3CfgCommitType,
+ NM_UTILS_ENUM2STR (NM_L3_CFG_COMMIT_TYPE_AUTO, "auto"),
+ NM_UTILS_ENUM2STR (NM_L3_CFG_COMMIT_TYPE_NONE, "none"),
NM_UTILS_ENUM2STR (NM_L3_CFG_COMMIT_TYPE_ASSUME, "assume"),
NM_UTILS_ENUM2STR (NM_L3_CFG_COMMIT_TYPE_UPDATE, "update"),
NM_UTILS_ENUM2STR (NM_L3_CFG_COMMIT_TYPE_REAPPLY, "reapply"),
@@ -878,7 +887,7 @@ _l3_acd_platform_commit_acd_update (NML3Cfg *self)
_LOGT ("acd: acd update now");
self->priv.changed_configs = TRUE;
nm_l3cfg_platform_commit (self,
- NM_L3_CFG_COMMIT_TYPE_UPDATE,
+ NM_L3_CFG_COMMIT_TYPE_AUTO,
AF_INET,
NULL);
}
@@ -2756,7 +2765,8 @@ _platform_commit (NML3Cfg *self,
gboolean success = TRUE;
nm_assert (NM_IS_L3CFG (self));
- nm_assert (NM_IN_SET (commit_type, NM_L3_CFG_COMMIT_TYPE_REAPPLY,
+ nm_assert (NM_IN_SET (commit_type, NM_L3_CFG_COMMIT_TYPE_NONE,
+ NM_L3_CFG_COMMIT_TYPE_REAPPLY,
NM_L3_CFG_COMMIT_TYPE_UPDATE,
NM_L3_CFG_COMMIT_TYPE_ASSUME));
nm_assert_addr_family (addr_family);
@@ -2873,7 +2883,9 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
gboolean acd_was_pending;
g_return_val_if_fail (NM_IS_L3CFG (self), FALSE);
- nm_assert (NM_IN_SET (commit_type, NM_L3_CFG_COMMIT_TYPE_REAPPLY,
+ nm_assert (NM_IN_SET (commit_type, NM_L3_CFG_COMMIT_TYPE_AUTO,
+ NM_L3_CFG_COMMIT_TYPE_NONE,
+ NM_L3_CFG_COMMIT_TYPE_REAPPLY,
NM_L3_CFG_COMMIT_TYPE_UPDATE,
NM_L3_CFG_COMMIT_TYPE_ASSUME));
@@ -2884,6 +2896,9 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET))
nm_clear_g_source_inst (&self->priv.p->acd_ready_on_idle_source);
+ if (commit_type == NM_L3_CFG_COMMIT_TYPE_AUTO)
+ commit_type = nm_l3cfg_commit_type_get (self);
+
if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY)
_l3cfg_externally_removed_objs_drop (self, addr_family);
@@ -2908,6 +2923,101 @@ nm_l3cfg_platform_commit (NML3Cfg *self,
/*****************************************************************************/
+NML3CfgCommitType
+nm_l3cfg_commit_type_get (NML3Cfg *self)
+{
+ NML3CfgCommitTypeHandle *handle;
+
+ nm_assert (NM_IS_L3CFG (self));
+
+ handle = c_list_first_entry (&self->priv.p->commit_type_lst_head, NML3CfgCommitTypeHandle, commit_type_lst);
+ return handle
+ ? handle->commit_type
+ : NM_L3_CFG_COMMIT_TYPE_NONE;
+}
+
+/**
+ * nm_l3cfg_commit_type_register:
+ * @self: the #NML3Cfg
+ * @commit_type: the commit type to register
+ * @existing_handle: instead of being a new registration, update an existing handle.
+ * This may be %NULL, which is like having no previous registration.
+ *
+ * NML3Cfg needs to know whether it is in charge of an interface (and how "much").
+ * By default, it is not in charge, but various users can register themself with
+ * a certain @commit_type. The "higher" commit type is the used one when calling
+ * nm_l3cfg_platform_commit() with %NM_L3_CFG_COMMIT_TYPE_AUTO.
+ *
+ * Returns: a handle tracking the registration, or %NULL of @commit_type
+ * is %NM_L3_CFG_COMMIT_TYPE_NONE.
+ */
+NML3CfgCommitTypeHandle *
+nm_l3cfg_commit_type_register (NML3Cfg *self,
+ NML3CfgCommitType commit_type,
+ NML3CfgCommitTypeHandle *existing_handle)
+{
+ NML3CfgCommitTypeHandle *handle;
+ NML3CfgCommitTypeHandle *h;
+ gboolean linked;
+
+ nm_assert (NM_IS_L3CFG (self));
+ nm_assert (NM_IN_SET (commit_type, NM_L3_CFG_COMMIT_TYPE_NONE,
+ NM_L3_CFG_COMMIT_TYPE_ASSUME,
+ NM_L3_CFG_COMMIT_TYPE_UPDATE,
+ NM_L3_CFG_COMMIT_TYPE_REAPPLY));
+ nm_assert ( !existing_handle
+ || c_list_contains (&self->priv.p->commit_type_lst_head, &existing_handle->commit_type_lst));
+
+ if (existing_handle) {
+ if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) {
+ nm_l3cfg_commit_type_unregister (self, existing_handle);
+ return NULL;
+ }
+ if (existing_handle->commit_type == commit_type)
+ return existing_handle;
+ c_list_unlink_stale (&existing_handle->commit_type_lst);
+ handle = existing_handle;
+ } else {
+ if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE)
+ return NULL;
+ handle = g_slice_new (NML3CfgCommitTypeHandle);
+ handle->commit_type = commit_type;
+ if (c_list_is_empty (&self->priv.p->commit_type_lst_head))
+ g_object_ref (self);
+ }
+
+ linked = FALSE;
+ c_list_for_each_entry (h, &self->priv.p->commit_type_lst_head, commit_type_lst) {
+ if (handle->commit_type >= h->commit_type) {
+ c_list_link_before (&self->priv.p->commit_type_lst_head, &handle->commit_type_lst);
+ linked = TRUE;
+ }
+ }
+ if (!linked)
+ c_list_link_tail (&self->priv.p->commit_type_lst_head, &handle->commit_type_lst);
+
+ return handle;
+}
+
+void
+nm_l3cfg_commit_type_unregister (NML3Cfg *self,
+ NML3CfgCommitTypeHandle *handle)
+{
+ nm_assert (NM_IS_L3CFG (self));
+
+ if (!handle)
+ return;
+
+ nm_assert (c_list_contains (&self->priv.p->commit_type_lst_head, &handle->commit_type_lst));
+
+ c_list_unlink_stale (&handle->commit_type_lst);
+ if (c_list_is_empty (&self->priv.p->commit_type_lst_head))
+ g_object_unref (self);
+ nm_g_slice_free (handle);
+}
+
+/*****************************************************************************/
+
static void
set_property (GObject *object,
guint prop_id,
@@ -2941,6 +3051,7 @@ nm_l3cfg_init (NML3Cfg *self)
self->priv.p = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_L3CFG, NML3CfgPrivate);
c_list_init (&self->priv.p->acd_lst_head);
+ c_list_init (&self->priv.p->commit_type_lst_head);
}
static void
@@ -2979,6 +3090,8 @@ finalize (GObject *object)
{
NML3Cfg *self = NM_L3CFG (object);
+ nm_assert (c_list_is_empty (&self->priv.p->commit_type_lst_head));
+
nm_clear_g_source_inst (&self->priv.p->acd_ready_on_idle_source);
nm_assert (nm_g_array_len (self->priv.p->property_emit_list) == 0u);
diff --git a/src/nm-l3cfg.h b/src/nm-l3cfg.h
index a199f27cfb..4a3bab1111 100644
--- a/src/nm-l3cfg.h
+++ b/src/nm-l3cfg.h
@@ -148,7 +148,18 @@ gboolean nm_l3cfg_remove_config_all (NML3Cfg *self,
/*****************************************************************************/
-typedef enum {
+/* The numeric values of the enum matters: higher number mean more "important".
+ * E.g. "assume" tries to preserve the most settings, while "reapply" forces
+ * all configuration to match. */
+typedef enum _nm_packed {
+
+ /* the NML3Cfg instance tracks with nm_l3cfg_commit_setup_register() the requested commit type.
+ * Use _NM_L3_CFG_COMMIT_TYPE_AUTO to automatically choose the level as requested. */
+ NM_L3_CFG_COMMIT_TYPE_AUTO,
+
+ /* Don't touch the interface. */
+ NM_L3_CFG_COMMIT_TYPE_NONE,
+
/* ASSUME means to keep any pre-existing extra routes/addresses, while
* also not adding routes/addresses that are not present yet. This is to
* gracefully take over after restart, where the existing IP configuration
@@ -172,4 +183,19 @@ gboolean nm_l3cfg_platform_commit (NML3Cfg *self,
int addr_family,
gboolean *out_final_failure_for_temporary_not_available);
+/*****************************************************************************/
+
+NML3CfgCommitType nm_l3cfg_commit_type_get (NML3Cfg *self);
+
+typedef struct _NML3CfgCommitTypeHandle NML3CfgCommitTypeHandle;
+
+NML3CfgCommitTypeHandle *nm_l3cfg_commit_type_register (NML3Cfg *self,
+ NML3CfgCommitType commit_type,
+ NML3CfgCommitTypeHandle *existing_handle);
+
+void nm_l3cfg_commit_type_unregister (NML3Cfg *self,
+ NML3CfgCommitTypeHandle *handle);
+
+/*****************************************************************************/
+
#endif /* __NM_L3CFG_H__ */