about summary refs log tree commit diff
path: root/src/core/devices/ovs/nm-device-ovs-interface.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
committerSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
commit1e636d8e5e986b9f2260c36bb87fb499d724085c (patch)
treeac613b9372adf622496a7d616050d7e1c09b4fba /src/core/devices/ovs/nm-device-ovs-interface.c
parentf4966e573c855d4667e6c236d8197d9949020e21 (diff)
parent1a31bc3c63474ca02c83b02add85ea4e740e5597 (diff)
Merge remote-tracking branch 'debian/debian/master' into ubuntu/master
Diffstat (limited to 'src/core/devices/ovs/nm-device-ovs-interface.c')
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c95
1 files changed, 86 insertions, 9 deletions
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 74707d24..6b9d3d7e 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -13,6 +13,7 @@
 #include "devices/nm-device-private.h"
 #include "nm-active-connection.h"
 #include "nm-setting-connection.h"
+#include "nm-setting-ovs-bridge.h"
 #include "nm-setting-ovs-interface.h"
 #include "nm-setting-ovs-port.h"
 
@@ -23,7 +24,10 @@
 
 typedef struct {
     NMOvsdb *ovsdb;
-    bool     waiting_for_interface : 1;
+    GSource *wait_link_idle_source;
+    gulong   wait_link_signal_id;
+    int      wait_link_ifindex;
+    bool     wait_link_is_waiting : 1;
 } NMDeviceOvsInterfacePrivate;
 
 struct _NMDeviceOvsInterface {
@@ -115,10 +119,10 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
 {
     NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device);
 
-    if (!pllink || !priv->waiting_for_interface)
+    if (!pllink || !priv->wait_link_is_waiting)
         return;
 
-    priv->waiting_for_interface = FALSE;
+    priv->wait_link_is_waiting = FALSE;
 
     if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) {
         if (!nm_device_hw_addr_set_cloned(device,
@@ -199,17 +203,83 @@ ready_for_ip_config(NMDevice *device)
     return nm_device_get_ip_ifindex(device) > 0;
 }
 
+static gboolean
+_set_ip_ifindex_tun(gpointer user_data)
+{
+    NMDevice                    *device = user_data;
+    NMDeviceOvsInterface        *self   = NM_DEVICE_OVS_INTERFACE(device);
+    NMDeviceOvsInterfacePrivate *priv   = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
+
+    nm_clear_g_source_inst(&priv->wait_link_idle_source);
+
+    priv->wait_link_is_waiting = FALSE;
+    nm_device_set_ip_ifindex(device, priv->wait_link_ifindex);
+
+    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 G_SOURCE_CONTINUE;
+}
+
+static void
+_netdev_tun_link_cb(NMPlatform     *platform,
+                    int             obj_type_i,
+                    int             ifindex,
+                    NMPlatformLink *pllink,
+                    int             change_type_i,
+                    NMDevice       *device)
+{
+    const NMPlatformSignalChangeType change_type = change_type_i;
+    NMDeviceOvsInterface            *self        = NM_DEVICE_OVS_INTERFACE(device);
+    NMDeviceOvsInterfacePrivate     *priv        = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
+
+    if (change_type == NM_PLATFORM_SIGNAL_ADDED) {
+        if (pllink->type == NM_LINK_TYPE_TUN
+            && nm_streq0(pllink->name, nm_device_get_iface(device))) {
+            nm_clear_g_signal_handler(platform, &priv->wait_link_signal_id);
+
+            priv->wait_link_ifindex = ifindex;
+
+            priv->wait_link_idle_source = nm_g_idle_add_source(_set_ip_ifindex_tun, device);
+        }
+    }
+}
+
 static void
 act_stage3_ip_config(NMDevice *device, int addr_family)
 {
-    NMDeviceOvsInterface        *self = NM_DEVICE_OVS_INTERFACE(device);
-    NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
+    NMActiveConnection          *controller_act = NULL;
+    NMSettingOvsBridge          *s_ovs_bridge   = NULL;
+    NMDeviceOvsInterface        *self           = NM_DEVICE_OVS_INTERFACE(device);
+    NMDeviceOvsInterfacePrivate *priv           = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
 
     if (!_is_internal_interface(device)) {
         nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
         return;
     }
 
+    /* When the ovs-bridge controller is using netdev datapath, the interface
+     * link created is a tun device instead of a ovs-interface. NetworkManager must
+     * detect the creation of the tun link and attach the ifindex to the
+     * ovs-interface device. */
+    controller_act = NM_ACTIVE_CONNECTION(nm_device_get_act_request(device));
+    if (controller_act && nm_device_get_ip_ifindex(device) <= 0 && priv->wait_link_signal_id == 0) {
+        controller_act = nm_active_connection_get_master(controller_act);
+        if (controller_act) {
+            controller_act = nm_active_connection_get_master(controller_act);
+            if (controller_act)
+                s_ovs_bridge = nm_connection_get_setting_ovs_bridge(
+                    nm_active_connection_get_applied_connection(controller_act));
+            if (s_ovs_bridge
+                && nm_streq0(nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge), "netdev"))
+                priv->wait_link_signal_id = g_signal_connect(nm_device_get_platform(device),
+                                                             NM_PLATFORM_SIGNAL_LINK_CHANGED,
+                                                             G_CALLBACK(_netdev_tun_link_cb),
+                                                             self);
+        }
+    }
+
     /* FIXME(l3cfg): we should create the IP ifindex before stage3 start.
      *
      * For now it's here because when the ovs-interface enters stage3, then it's added to the
@@ -219,11 +289,15 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
      * This should change. */
     if (nm_device_get_ip_ifindex(device) <= 0) {
         _LOGT(LOGD_DEVICE, "waiting for link to appear");
-        priv->waiting_for_interface = TRUE;
+        priv->wait_link_is_waiting = TRUE;
         nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
         return;
     }
 
+    priv->wait_link_is_waiting = FALSE;
+    nm_clear_g_source_inst(&priv->wait_link_idle_source);
+    nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link_signal_id);
+
     if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) {
         nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
         return;
@@ -244,7 +318,8 @@ deactivate(NMDevice *device)
     NMDeviceOvsInterface        *self = NM_DEVICE_OVS_INTERFACE(device);
     NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
 
-    priv->waiting_for_interface = FALSE;
+    priv->wait_link_is_waiting = FALSE;
+    nm_clear_g_source_inst(&priv->wait_link_idle_source);
 }
 
 typedef struct {
@@ -351,7 +426,7 @@ deactivate_async(NMDevice                  *device,
         .callback_user_data = callback_user_data,
     };
 
-    if (!priv->waiting_for_interface
+    if (!priv->wait_link_is_waiting
         && !nm_platform_link_get_by_ifname(nm_device_get_platform(device),
                                            nm_device_get_iface(device))) {
         _LOGT(LOGD_CORE, "deactivate: link not present, proceeding");
@@ -360,7 +435,9 @@ deactivate_async(NMDevice                  *device,
         return;
     }
 
-    if (priv->waiting_for_interface) {
+    nm_clear_g_source_inst(&priv->wait_link_idle_source);
+
+    if (priv->wait_link_is_waiting) {
         /* At this point we have issued an INSERT and a DELETE
          * command for the interface to ovsdb. We don't know if
          * vswitchd will see the two updates or only one. We