diff options
author | Thomas Haller <thaller@redhat.com> | 2020-07-21 11:21:44 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-07-23 15:29:25 +0200 |
commit | b5c563329ac3edc8334bd05ad8f8e8d7fd9c8a8d (patch) | |
tree | ae936c1cf72c33b852e078a096e6885899f01093 | |
parent | ea1f0fc0a6350c78f06121720c6b1af58f1f987a (diff) | |
download | NetworkManager-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.c | 7 | ||||
-rw-r--r-- | src/nm-l3cfg.h | 6 | ||||
-rw-r--r-- | src/nm-netns.c | 70 | ||||
-rw-r--r-- | src/nm-types.h | 11 |
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 |