summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-07-21 11:21:44 +0200
committerThomas Haller <thaller@redhat.com>2020-07-23 15:29:25 +0200
commitb5c563329ac3edc8334bd05ad8f8e8d7fd9c8a8d (patch)
treeae936c1cf72c33b852e078a096e6885899f01093
parentea1f0fc0a6350c78f06121720c6b1af58f1f987a (diff)
downloadNetworkManager-b5c563329ac3edc8334bd05ad8f8e8d7fd9c8a8d.tar.gz
l3cfg: notify NML3Cfg about NMPlatform changes in an idle handler
We need to react to platform changes. Also, we usually want to delay the reaction to an idle handler. Instead of subscribing each NML3Cfg instance itself to platform changes, let only NMNetns do that. The goal is of course that each platform event only needs to notify the NML3Cfg instance, which collects the events and schedules them on the idle handler.
-rw-r--r--src/nm-l3cfg.c7
-rw-r--r--src/nm-l3cfg.h6
-rw-r--r--src/nm-netns.c70
-rw-r--r--src/nm-types.h11
4 files changed, 92 insertions, 2 deletions
diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c
index aaaad02b6e..6d2f26b8d8 100644
--- a/src/nm-l3cfg.c
+++ b/src/nm-l3cfg.c
@@ -35,6 +35,13 @@ G_DEFINE_TYPE (NML3Cfg, nm_l3cfg, G_TYPE_OBJECT)
/*****************************************************************************/
+void
+_nm_l3cfg_notify_platform_change_on_idle (NML3Cfg *self, guint32 obj_type_flags)
+{
+}
+
+/*****************************************************************************/
+
static void
set_property (GObject *object,
guint prop_id,
diff --git a/src/nm-l3cfg.h b/src/nm-l3cfg.h
index 4f035e231a..731b2b46fe 100644
--- a/src/nm-l3cfg.h
+++ b/src/nm-l3cfg.h
@@ -28,6 +28,12 @@ GType nm_l3cfg_get_type (void);
NML3Cfg *nm_l3cfg_new (NMNetns *netns, int ifindex);
+/*****************************************************************************/
+
+void _nm_l3cfg_notify_platform_change_on_idle (NML3Cfg *self, guint32 obj_type_flags);
+
+/*****************************************************************************/
+
static inline int
nm_l3cfg_get_ifindex (const NML3Cfg *self)
{
diff --git a/src/nm-netns.c b/src/nm-netns.c
index cafb73164c..ebefeea649 100644
--- a/src/nm-netns.c
+++ b/src/nm-netns.c
@@ -23,10 +23,13 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
);
typedef struct {
+ NMNetns *_self_signal_user_data;
NMPlatform *platform;
NMPNetns *platform_netns;
NMPRulesManager *rules_manager;
GHashTable *l3cfgs;
+ CList l3cfg_signal_pending_lst_head;
+ guint signal_pending_idle_id;
} NMNetnsPrivate;
struct _NMNetns {
@@ -88,7 +91,9 @@ nm_netns_get_multi_idx (NMNetns *self)
typedef struct {
int ifindex;
+ guint32 signal_pending_flag;
NML3Cfg *l3cfg;
+ CList signal_pending_lst;
} L3CfgData;
static void
@@ -96,6 +101,8 @@ _l3cfg_data_free (gpointer ptr)
{
L3CfgData *l3cfg_data = ptr;
+ c_list_unlink_stale (&l3cfg_data->signal_pending_lst);
+
nm_g_slice_free (l3cfg_data);
}
@@ -140,8 +147,9 @@ nm_netns_access_l3cfg (NMNetns *self,
l3cfg_data = g_slice_new (L3CfgData);
*l3cfg_data = (L3CfgData) {
- .ifindex = ifindex,
- .l3cfg = nm_l3cfg_new (self, ifindex),
+ .ifindex = ifindex,
+ .l3cfg = nm_l3cfg_new (self, ifindex),
+ .signal_pending_lst = C_LIST_INIT (l3cfg_data->signal_pending_lst),
};
if (!g_hash_table_add (priv->l3cfgs, l3cfg_data))
@@ -160,6 +168,52 @@ nm_netns_access_l3cfg (NMNetns *self,
/*****************************************************************************/
+static gboolean
+_platform_signal_on_idle_cb (gpointer user_data)
+{
+ gs_unref_object NMNetns *self = g_object_ref (NM_NETNS (user_data));
+ NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
+ L3CfgData *l3cfg_data;
+
+ while ((l3cfg_data = c_list_first_entry (&priv->l3cfg_signal_pending_lst_head, L3CfgData, signal_pending_lst))) {
+ c_list_unlink (&l3cfg_data->signal_pending_lst);
+ _nm_l3cfg_notify_platform_change_on_idle (l3cfg_data->l3cfg,
+ nm_steal_int (&l3cfg_data->signal_pending_flag));
+ }
+
+ priv->signal_pending_idle_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+_platform_signal_cb (NMPlatform *platform,
+ int obj_type_i,
+ int ifindex,
+ gconstpointer platform_object,
+ int change_type_i,
+ NMNetns **p_self)
+{
+ NMNetns *self = NM_NETNS (*p_self);
+ NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
+ const NMPObjectType obj_type = obj_type_i;
+ L3CfgData *l3cfg_data;
+
+ l3cfg_data = g_hash_table_lookup (priv->l3cfgs, &ifindex);
+ if (!l3cfg_data)
+ return;
+
+ l3cfg_data->signal_pending_flag |= nmp_object_type_to_flags (obj_type);
+
+ if (!c_list_is_empty (&l3cfg_data->signal_pending_lst))
+ return;
+
+ c_list_link_tail (&priv->l3cfg_signal_pending_lst_head, &l3cfg_data->signal_pending_lst);
+ if (priv->signal_pending_idle_id == 0)
+ priv->signal_pending_idle_id = g_idle_add (_platform_signal_on_idle_cb, self);
+}
+
+/*****************************************************************************/
+
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
@@ -186,6 +240,10 @@ set_property (GObject *object, guint prop_id,
static void
nm_netns_init (NMNetns *self)
{
+ NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
+
+ priv->_self_signal_user_data = self;
+ c_list_init (&priv->l3cfg_signal_pending_lst_head);
}
static void
@@ -226,6 +284,8 @@ constructed (GObject *object)
NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG);
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
+
+ g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_platform_signal_cb), &priv->_self_signal_user_data);
}
NMNetns *
@@ -243,6 +303,12 @@ dispose (GObject *object)
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
nm_assert (nm_g_hash_table_size (priv->l3cfgs) == 0);
+ nm_assert (c_list_is_empty (&priv->l3cfg_signal_pending_lst_head));
+
+ nm_clear_g_source (&priv->signal_pending_idle_id);
+
+ if (priv->platform)
+ g_signal_handlers_disconnect_by_data (priv->platform, &priv->_self_signal_user_data);
g_clear_object (&priv->platform);
g_clear_pointer (&priv->l3cfgs, g_hash_table_unref);
diff --git a/src/nm-types.h b/src/nm-types.h
index 5835c64188..6277e4d811 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -236,6 +236,17 @@ typedef enum {
NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1,
} NMPObjectType;
+static inline guint32
+nmp_object_type_to_flags (NMPObjectType obj_type)
+{
+ G_STATIC_ASSERT_EXPR (NMP_OBJECT_TYPE_MAX < 32);
+
+ nm_assert (_NM_INT_NOT_NEGATIVE (obj_type));
+ nm_assert (obj_type < NMP_OBJECT_TYPE_MAX);
+
+ return ((guint32) 1u) << obj_type;
+}
+
/**
* NMIPConfigMergeFlags:
* @NM_IP_CONFIG_MERGE_DEFAULT: no flags set