summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-09-25 17:05:58 +0200
committerThomas Haller <thaller@redhat.com>2020-09-30 09:49:23 +0200
commitef198d0202341569f848f3bbf76a6751a1f621b8 (patch)
tree2ad06924252651fe77b9b616ed721cb85dda0b72
parent5ed1027cab967779abac14881d3fb1bac4d8d7af (diff)
downloadNetworkManager-ef198d0202341569f848f3bbf76a6751a1f621b8.tar.gz
l3cfg: in NML3Cfg also track the current NMPlatformLink of the platform cache
NML3Cfg tends to perform actions on an idle handler. That means, when it configures something on platform, it tends to ignore the changes and process them later. That means the currently tracked NMPObject with the platform link may not be the same as NMPlatform currently has cached. Instead, track them both, and extend the API so that it's clear that there is a difference. You now need to say whether you want the instance from the platform cache (the "next") or the currently used instance. Of course, after the idle handler runs, "next" and the current one converge. This is useful because we want to reason about the link state (also) by looking a our NML3Cfg instance. Since it already is connected to platform, it can expose the same NMPObject.
-rw-r--r--src/nm-l3cfg.c36
-rw-r--r--src/nm-l3cfg.h37
2 files changed, 46 insertions, 27 deletions
diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c
index 78d4a2045e..949d53e1a8 100644
--- a/src/nm-l3cfg.c
+++ b/src/nm-l3cfg.c
@@ -609,13 +609,19 @@ _load_link(NML3Cfg *self, gboolean initial)
gboolean nacd_link_now_up;
AcdData * acd_data;
- obj = nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE);
+ if (initial) {
+ obj = nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE);
+ self->priv.plobj_next = nmp_object_ref(obj);
+ } else {
+ obj = self->priv.plobj_next;
+ nm_assert(obj == nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE));
+ }
- if (initial && obj == self->priv.pllink)
+ if (initial && obj == self->priv.plobj)
return;
- obj_old = g_steal_pointer(&self->priv.pllink);
- self->priv.pllink = nmp_object_ref(obj);
+ obj_old = g_steal_pointer(&self->priv.plobj);
+ self->priv.plobj = nmp_object_ref(obj);
if (obj && NM_FLAGS_HAS(NMP_OBJECT_CAST_LINK(obj)->n_ifi_flags, IFF_UP)
&& (!obj_old || !NM_FLAGS_HAS(NMP_OBJECT_CAST_LINK(obj_old)->n_ifi_flags, IFF_UP)))
@@ -641,7 +647,7 @@ _load_link(NML3Cfg *self, gboolean initial)
} else if (nacd_new_valid)
nacd_changed = TRUE;
ifname_old = nmp_object_link_get_ifname(obj_old);
- ifname = nmp_object_link_get_ifname(self->priv.pllink);
+ ifname = nmp_object_link_get_ifname(self->priv.plobj);
if (initial) {
_LOGT("link ifname changed: %s%s%s (initial)", NM_PRINT_FMT_QUOTE_STRING(ifname));
@@ -671,7 +677,7 @@ _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags)
{
NML3ConfigNotifyPayload payload;
- if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_LINK)))
+ if (self->priv.plobj_next != self->priv.plobj)
_load_link(self, FALSE);
payload = (NML3ConfigNotifyPayload){
@@ -703,6 +709,15 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self,
obj_type = NMP_OBJECT_GET_TYPE(obj);
switch (obj_type) {
+ case NMP_OBJECT_TYPE_LINK:
+ {
+ const NMPObject *plobj;
+
+ plobj = (change_type != NM_PLATFORM_SIGNAL_REMOVED) ? obj : NULL;
+ nm_assert(plobj == nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE));
+ nmp_object_ref_set(&self->priv.plobj_next, plobj);
+ break;
+ }
case NMP_OBJECT_TYPE_IP4_ADDRESS:
_l3_acd_ipv4_addresses_on_link_update(self,
NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address,
@@ -1067,9 +1082,9 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data)
_LOGW("IPv4 address collision detection sees conflict on interface %i%s%s%s for "
"address %s from host %s",
self->priv.ifindex,
- NM_PRINT_FMT_QUOTED(self->priv.pllink,
+ NM_PRINT_FMT_QUOTED(self->priv.plobj,
" (",
- NMP_OBJECT_CAST_LINK(self->priv.pllink)->name,
+ NMP_OBJECT_CAST_LINK(self->priv.plobj)->name,
")",
""),
addr_str ?: _nm_utils_inet4_ntop(acd_data->addr, sbuf_addr),
@@ -1188,7 +1203,7 @@ again:
return NULL;
}
- valid = _acd_has_valid_link(self->priv.pllink, &addr_bin, &acd_not_supported);
+ valid = _acd_has_valid_link(self->priv.plobj, &addr_bin, &acd_not_supported);
if (!valid)
goto failed_create_acd;
@@ -3331,7 +3346,8 @@ finalize(GObject *object)
nm_clear_l3cd(&self->priv.p->combined_l3cd_merged);
nm_clear_l3cd(&self->priv.p->combined_l3cd_commited);
- nm_clear_pointer(&self->priv.pllink, nmp_object_unref);
+ nm_clear_pointer(&self->priv.plobj, nmp_object_unref);
+ nm_clear_pointer(&self->priv.plobj_next, nmp_object_unref);
nm_clear_pointer(&self->priv.p->acd_ipv4_addresses_on_link, g_hash_table_unref);
diff --git a/src/nm-l3cfg.h b/src/nm-l3cfg.h
index 6d7fce2a38..e122947004 100644
--- a/src/nm-l3cfg.h
+++ b/src/nm-l3cfg.h
@@ -75,7 +75,8 @@ struct _NML3Cfg {
struct _NML3CfgPrivate *p;
NMNetns * netns;
NMPlatform * platform;
- const NMPObject * pllink;
+ const NMPObject * plobj;
+ const NMPObject * plobj_next;
int ifindex;
bool changed_configs : 1;
} priv;
@@ -117,34 +118,36 @@ nm_l3cfg_get_ifindex(const NML3Cfg *self)
return self->priv.ifindex;
}
-static inline const char *
-nm_l3cfg_get_ifname(const NML3Cfg *self)
-{
- nm_assert(NM_IS_L3CFG(self));
-
- return nmp_object_link_get_ifname(self->priv.pllink);
-}
-
static inline const NMPObject *
-nm_l3cfg_get_plobj(const NML3Cfg *self)
+nm_l3cfg_get_plobj(const NML3Cfg *self, gboolean get_next)
{
if (!self)
return NULL;
nm_assert(NM_IS_L3CFG(self));
- return self->priv.pllink;
+ if (get_next) {
+ /* This is the instance that we just got reported in the last signal from
+ * the platform cache. It's probably exactly the same as if you would look
+ * into the platform cache.
+ *
+ * On the other hand, we pick up changes only on an idle handler. So the last
+ * decisions were not made based on this, but instead of "plobj". */
+ return self->priv.plobj_next;
+ }
+ return self->priv.plobj;
}
static inline const NMPlatformLink *
-nm_l3cfg_get_pllink(const NML3Cfg *self)
+nm_l3cfg_get_pllink(const NML3Cfg *self, gboolean get_next)
{
- if (!self)
- return NULL;
-
- nm_assert(NM_IS_L3CFG(self));
+ return NMP_OBJECT_CAST_LINK(nm_l3cfg_get_plobj(self, get_next));
+}
- return NMP_OBJECT_CAST_LINK(self->priv.pllink);
+static inline const char *
+nm_l3cfg_get_ifname(const NML3Cfg *self, gboolean get_next)
+{
+ return nmp_object_link_get_ifname(nm_l3cfg_get_plobj(self, get_next));
}
static inline NMNetns *