summary refs log tree commit diff
path: root/src/core/devices/ovs/nm-device-ovs-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/devices/ovs/nm-device-ovs-interface.c')
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c100
1 files changed, 42 insertions, 58 deletions
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 06a1da15..512aa5c3 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -26,16 +26,18 @@ typedef struct {
     NMOvsdb *ovsdb;
 
     struct {
-        /* The source for the idle handler to set the TUN ifindex */
-        GSource *tun_set_ifindex_idle_source;
-        /* The cloned MAC to set */
-        char *cloned_mac;
-        /* The id for the signal watching the TUN link to appear/change */
+        /* The signal id for the TUN link-changed event */
         gulong tun_link_signal_id;
-        /* The TUN ifindex to set in the idle handler */
+        /* The idle handler source for the TUN link-changed event */
+        GSource *tun_link_idle_source;
+        /* The ifindex for the TUN link-changed event */
         int tun_ifindex;
+
+        /* The cloned MAC to set */
+        char *cloned_mac;
         /* Whether we have determined the cloned MAC */
         bool cloned_mac_evaluated : 1;
+
         /* Whether we are waiting for the kernel link */
         bool waiting : 1;
     } wait_link;
@@ -261,39 +263,33 @@ ready_for_ip_config(NMDevice *device, gboolean is_manual)
 }
 
 static gboolean
-_set_ip_ifindex_tun(gpointer user_data)
+_netdev_tun_link_cb_in_idle(gpointer user_data)
 {
     NMDevice                    *device = user_data;
     NMDeviceOvsInterface        *self   = NM_DEVICE_OVS_INTERFACE(device);
     NMDeviceOvsInterfacePrivate *priv   = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
 
-    _LOGT(LOGD_CORE,
-          "ovs-wait-link: setting ip-ifindex %d from tun interface",
-          priv->wait_link.tun_ifindex);
-
-    nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
-
-    nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
-
-    if (check_waiting_for_link(device, "set-ip-ifindex-tun")) {
-        /* If the link is not ready, it means the MAC is not set yet. We don't have
-         * a convenient way to monitor for ip-ifindex changes other than listening
-         * for platform events again.*/
-        nm_assert(!priv->wait_link.tun_link_signal_id);
-        priv->wait_link.tun_link_signal_id = g_signal_connect(nm_device_get_platform(device),
-                                                              NM_PLATFORM_SIGNAL_LINK_CHANGED,
-                                                              G_CALLBACK(_netdev_tun_link_cb),
-                                                              self);
-        return G_SOURCE_CONTINUE;
+    if (nm_device_get_ip_ifindex(device) <= 0) {
+        _LOGT(LOGD_CORE,
+              "ovs-wait-link: setting ip-ifindex %d from tun link",
+              priv->wait_link.tun_ifindex);
+        nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
     }
 
-    _LOGT(LOGD_CORE, "tun link is ready");
+    if (check_waiting_for_link(device, "tun-link-changed")) {
+        nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
+        return G_SOURCE_CONTINUE;
+    }
 
+    _LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready");
     nm_device_link_properties_set(device, FALSE);
+    nm_device_bring_up(device);
 
     nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
     nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
     nm_device_activate_schedule_stage3_ip_config(device, FALSE);
+    nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
+    nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
 
     return G_SOURCE_CONTINUE;
 }
@@ -309,40 +305,28 @@ _netdev_tun_link_cb(NMPlatform     *platform,
     const NMPlatformSignalChangeType change_type = change_type_i;
     NMDeviceOvsInterface            *self        = NM_DEVICE_OVS_INTERFACE(device);
     NMDeviceOvsInterfacePrivate     *priv        = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
-    int                              ip_ifindex;
 
-    if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
+    /* This is the handler for the link-changed platform events. It is triggered for all
+     * link changes. Keep only the ones matching our device. */
+    if (!NM_IN_SET(change_type, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_SIGNAL_CHANGED))
         return;
-
-    ip_ifindex = nm_device_get_ip_ifindex(device);
-    if (ip_ifindex > 0) {
-        /* When we have an ifindex, we are only waiting for the MAC to settle */
-        if (change_type != NM_PLATFORM_SIGNAL_CHANGED)
-            return;
-
-        if (!check_waiting_for_link(device, "tun-link-changed")) {
-            _LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready, cloned MAC is set");
-
-            nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
-            nm_device_link_properties_set(device, FALSE);
-
-            nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
-            nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
-            nm_device_activate_schedule_stage3_ip_config(device, FALSE);
-        }
-        return;
-    }
-
-    /* No ip-ifindex on the device, set it when the link appears */
-    if (change_type != NM_PLATFORM_SIGNAL_ADDED)
+    if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
         return;
 
     _LOGT(LOGD_CORE,
-          "ovs-wait-link: found matching tun interface, schedule set-ip-ifindex(%d)",
+          "ovs-wait-link: got platform event \'%s\' for ifindex %d, scheduling idle handler",
+          change_type == NM_PLATFORM_SIGNAL_ADDED ? "added" : "changed",
           ifindex);
-    nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
-    priv->wait_link.tun_ifindex                 = ifindex;
-    priv->wait_link.tun_set_ifindex_idle_source = nm_g_idle_add_source(_set_ip_ifindex_tun, device);
+
+    /* The handler is invoked by the platform synchronously in the netlink receive loop.
+     * We can't perform other platform operations (like bringing the interface up) since
+     * the code there is not re-entrant. Schedule an idle handler. */
+    nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
+    priv->wait_link.tun_link_idle_source =
+        nm_g_idle_add_source(_netdev_tun_link_cb_in_idle, device);
+    priv->wait_link.tun_ifindex = ifindex;
+
+    return;
 }
 
 static gboolean
@@ -464,7 +448,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
         nm_device_activate_schedule_stage3_ip_config(device, TRUE);
         return;
     }
-    nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+    nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
     nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
 
     nm_device_link_properties_set(device, FALSE);
@@ -488,7 +472,7 @@ deactivate(NMDevice *device)
     priv->wait_link.cloned_mac_evaluated = FALSE;
     nm_clear_g_free(&priv->wait_link.cloned_mac);
     nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
-    nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+    nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
 }
 
 typedef struct {
@@ -581,7 +565,7 @@ deactivate_async(NMDevice                  *device,
     _LOGT(LOGD_CORE, "deactivate: start async");
 
     nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
-    nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+    nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
     priv->wait_link.tun_ifindex          = -1;
     priv->wait_link.cloned_mac_evaluated = FALSE;
     nm_clear_g_free(&priv->wait_link.cloned_mac);
@@ -682,7 +666,7 @@ dispose(GObject *object)
 
     nm_assert(!priv->wait_link.waiting);
     nm_assert(priv->wait_link.tun_link_signal_id == 0);
-    nm_assert(!priv->wait_link.tun_set_ifindex_idle_source);
+    nm_assert(!priv->wait_link.tun_link_idle_source);
 
     if (priv->ovsdb) {
         g_signal_handlers_disconnect_by_func(priv->ovsdb, G_CALLBACK(ovsdb_ready), self);