summary refs log tree commit diff
path: root/src/core/devices/ovs
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/devices/ovs')
-rw-r--r--src/core/devices/ovs/nm-device-ovs-bridge.c28
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c58
-rw-r--r--src/core/devices/ovs/nm-device-ovs-port.c28
-rw-r--r--src/core/devices/ovs/nm-ovs-factory.c27
-rw-r--r--src/core/devices/ovs/nm-ovsdb.c80
5 files changed, 152 insertions, 69 deletions
diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c
index c9b1f4c6..c9736eeb 100644
--- a/src/core/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/core/devices/ovs/nm-device-ovs-bridge.c
@@ -162,6 +162,11 @@ can_reapply_change(NMDevice   *device,
                                                  NM_SETTING_OVS_BRIDGE_STP_ENABLE);
     }
 
+    if (NM_IN_STRSET(setting_name,
+                     NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
+                     NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME))
+        return TRUE;
+
     return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
 }
 
@@ -194,16 +199,15 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
     device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
     device_class->link_types                       = NM_DEVICE_DEFINE_LINK_TYPES();
 
-    device_class->is_controller                       = TRUE;
-    device_class->get_type_description                = get_type_description;
-    device_class->create_and_realize                  = create_and_realize;
-    device_class->unrealize                           = unrealize;
-    device_class->get_generic_capabilities            = get_generic_capabilities;
-    device_class->act_stage3_ip_config                = act_stage3_ip_config;
-    device_class->ready_for_ip_config                 = ready_for_ip_config;
-    device_class->attach_port                         = attach_port;
-    device_class->detach_port                         = detach_port;
-    device_class->can_reapply_change                  = can_reapply_change;
-    device_class->can_reapply_change_ovs_external_ids = TRUE;
-    device_class->reapply_connection                  = nm_device_ovs_reapply_connection;
+    device_class->is_controller            = TRUE;
+    device_class->get_type_description     = get_type_description;
+    device_class->create_and_realize       = create_and_realize;
+    device_class->unrealize                = unrealize;
+    device_class->get_generic_capabilities = get_generic_capabilities;
+    device_class->act_stage3_ip_config     = act_stage3_ip_config;
+    device_class->ready_for_ip_config      = ready_for_ip_config;
+    device_class->attach_port              = attach_port;
+    device_class->detach_port              = detach_port;
+    device_class->can_reapply_change       = can_reapply_change;
+    device_class->reapply_connection       = nm_device_ovs_reapply_connection;
 }
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 512aa5c3..922ed345 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -16,6 +16,8 @@
 #include "nm-setting-ovs-bridge.h"
 #include "nm-setting-ovs-interface.h"
 #include "nm-setting-ovs-port.h"
+#include "nm-setting-ovs-external-ids.h"
+#include "nm-setting-ovs-other-config.h"
 
 #define _NMLOG_DEVICE_TYPE NMDeviceOvsInterface
 #include "devices/nm-device-logging.h"
@@ -631,6 +633,28 @@ can_update_from_platform_link(NMDevice *device, const NMPlatformLink *plink)
     return !plink || nm_device_get_state(device) != NM_DEVICE_STATE_DEACTIVATING;
 }
 
+static gboolean
+can_reapply_change(NMDevice   *device,
+                   const char *setting_name,
+                   NMSetting  *s_old,
+                   NMSetting  *s_new,
+                   GHashTable *diffs,
+                   GError    **error)
+{
+    NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class);
+
+    if (NM_IN_STRSET(setting_name,
+                     NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
+                     NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) {
+        /* TODO: it's currently not possible to reapply those settings on OVS
+         * system interfaces because they have type != "ovs-interface" (e.g.
+         * "ethernet") */
+        return TRUE;
+    }
+
+    return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
+}
+
 /*****************************************************************************/
 
 static void
@@ -696,21 +720,21 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass)
     device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
     device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH);
 
-    device_class->can_auto_connect                    = can_auto_connect;
-    device_class->can_update_from_platform_link       = can_update_from_platform_link;
-    device_class->deactivate                          = deactivate;
-    device_class->deactivate_async                    = deactivate_async;
-    device_class->get_type_description                = get_type_description;
-    device_class->create_and_realize                  = create_and_realize;
-    device_class->get_generic_capabilities            = get_generic_capabilities;
-    device_class->is_available                        = is_available;
-    device_class->check_connection_compatible         = check_connection_compatible;
-    device_class->link_changed                        = link_changed;
-    device_class->act_stage3_ip_config                = act_stage3_ip_config;
-    device_class->ready_for_ip_config                 = ready_for_ip_config;
-    device_class->can_unmanaged_external_down         = can_unmanaged_external_down;
-    device_class->set_platform_mtu                    = set_platform_mtu;
-    device_class->get_configured_mtu                  = nm_device_get_configured_mtu_for_wired;
-    device_class->can_reapply_change_ovs_external_ids = TRUE;
-    device_class->reapply_connection                  = nm_device_ovs_reapply_connection;
+    device_class->can_auto_connect              = can_auto_connect;
+    device_class->can_update_from_platform_link = can_update_from_platform_link;
+    device_class->deactivate                    = deactivate;
+    device_class->deactivate_async              = deactivate_async;
+    device_class->get_type_description          = get_type_description;
+    device_class->create_and_realize            = create_and_realize;
+    device_class->get_generic_capabilities      = get_generic_capabilities;
+    device_class->is_available                  = is_available;
+    device_class->check_connection_compatible   = check_connection_compatible;
+    device_class->link_changed                  = link_changed;
+    device_class->act_stage3_ip_config          = act_stage3_ip_config;
+    device_class->ready_for_ip_config           = ready_for_ip_config;
+    device_class->can_unmanaged_external_down   = can_unmanaged_external_down;
+    device_class->set_platform_mtu              = set_platform_mtu;
+    device_class->get_configured_mtu            = nm_device_get_configured_mtu_for_wired;
+    device_class->can_reapply_change            = can_reapply_change;
+    device_class->reapply_connection            = nm_device_ovs_reapply_connection;
 }
diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c
index e9928548..0e3ef92c 100644
--- a/src/core/devices/ovs/nm-device-ovs-port.c
+++ b/src/core/devices/ovs/nm-device-ovs-port.c
@@ -16,6 +16,8 @@
 #include "nm-setting-connection.h"
 #include "nm-setting-ovs-port.h"
 #include "nm-setting-ovs-interface.h"
+#include "nm-setting-ovs-external-ids.h"
+#include "nm-setting-ovs-other-config.h"
 #include "nm-setting-wired.h"
 
 #define _NMLOG_DEVICE_TYPE NMDeviceOvsPort
@@ -279,6 +281,11 @@ can_reapply_change(NMDevice   *device,
                                                  NM_SETTING_OVS_PORT_TRUNKS);
     }
 
+    if (NM_IN_STRSET(setting_name,
+                     NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
+                     NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME))
+        return TRUE;
+
     return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
 }
 
@@ -311,15 +318,14 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
     device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME;
     device_class->link_types                       = NM_DEVICE_DEFINE_LINK_TYPES();
 
-    device_class->is_controller                       = TRUE;
-    device_class->get_type_description                = get_type_description;
-    device_class->create_and_realize                  = create_and_realize;
-    device_class->get_generic_capabilities            = get_generic_capabilities;
-    device_class->act_stage3_ip_config                = act_stage3_ip_config;
-    device_class->ready_for_ip_config                 = ready_for_ip_config;
-    device_class->attach_port                         = attach_port;
-    device_class->detach_port                         = detach_port;
-    device_class->can_reapply_change                  = can_reapply_change;
-    device_class->can_reapply_change_ovs_external_ids = TRUE;
-    device_class->reapply_connection                  = nm_device_ovs_reapply_connection;
+    device_class->is_controller            = TRUE;
+    device_class->get_type_description     = get_type_description;
+    device_class->create_and_realize       = create_and_realize;
+    device_class->get_generic_capabilities = get_generic_capabilities;
+    device_class->act_stage3_ip_config     = act_stage3_ip_config;
+    device_class->ready_for_ip_config      = ready_for_ip_config;
+    device_class->attach_port              = attach_port;
+    device_class->detach_port              = detach_port;
+    device_class->can_reapply_change       = can_reapply_change;
+    device_class->reapply_connection       = nm_device_ovs_reapply_connection;
 }
diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c
index 2ca1a0b5..4084356f 100644
--- a/src/core/devices/ovs/nm-ovs-factory.c
+++ b/src/core/devices/ovs/nm-ovs-factory.c
@@ -75,9 +75,6 @@ new_device_from_type(const char *name, NMDeviceType device_type)
     const char *type_desc;
     NMLinkType  link_type = NM_LINK_TYPE_NONE;
 
-    if (nm_manager_get_device(NM_MANAGER_GET, name, device_type))
-        return NULL;
-
     if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) {
         type      = NM_TYPE_DEVICE_OVS_INTERFACE;
         type_desc = "Open vSwitch Interface";
@@ -89,6 +86,7 @@ new_device_from_type(const char *name, NMDeviceType device_type)
         type      = NM_TYPE_DEVICE_OVS_BRIDGE;
         type_desc = "Open vSwitch Bridge";
     } else {
+        _LOGT(name, NULL, "Unrecognized link type: %d", device_type);
         return NULL;
     }
 
@@ -125,6 +123,11 @@ ovsdb_device_added(NMOvsdb         *ovsdb,
         return;
     }
 
+    if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) {
+        _LOGT(name, NULL, "Device already registered with manager, skipping.");
+        return;
+    }
+
     device = new_device_from_type(name, device_type);
     if (!device)
         return;
@@ -288,23 +291,31 @@ create_device(NMDeviceFactory      *self,
 {
     NMDeviceType device_type     = NM_DEVICE_TYPE_UNKNOWN;
     const char  *connection_type = NULL;
+    const char  *connection_uuid = NULL;
 
     if (g_strcmp0(iface, "ovs-system") == 0) {
         *out_ignore = TRUE;
         return NULL;
     }
 
-    if (connection)
+    if (connection) {
         connection_type = nm_connection_get_connection_type(connection);
+        connection_uuid = nm_connection_get_uuid(connection);
+    }
 
-    if (plink)
+    if (plink) {
+        _LOGD(iface, connection_uuid, "creating OVS interface (from a platform link)");
         device_type = NM_DEVICE_TYPE_OVS_INTERFACE;
-    else if (g_strcmp0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0)
+    } else if (nm_streq0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) {
+        _LOGD(iface, connection_uuid, "creating OVS interface (from setting)");
         device_type = NM_DEVICE_TYPE_OVS_INTERFACE;
-    else if (g_strcmp0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0)
+    } else if (nm_streq0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME)) {
+        _LOGD(iface, connection_uuid, "creating OVS port (from setting)");
         device_type = NM_DEVICE_TYPE_OVS_PORT;
-    else if (g_strcmp0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0)
+    } else if (nm_streq0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) {
+        _LOGD(iface, connection_uuid, "creating OVS bridge (from setting)");
         device_type = NM_DEVICE_TYPE_OVS_BRIDGE;
+    }
 
     return new_device_from_type(iface, device_type);
 }
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index 2dbc842a..164bfd35 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -900,15 +900,17 @@ _insert_interface(json_t       *params,
         s_ovs_patch = nm_connection_get_setting_ovs_patch(interface);
 
     if (s_ovs_dpdk) {
-        const char *devargs;
-        guint32     n_rxq;
-        guint32     n_rxq_desc;
-        guint32     n_txq_desc;
+        const char                  *devargs;
+        guint32                      n_rxq;
+        guint32                      n_rxq_desc;
+        guint32                      n_txq_desc;
+        NMSettingOvsDpdkLscInterrupt lsc_int;
 
         devargs    = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk);
         n_rxq      = nm_setting_ovs_dpdk_get_n_rxq(s_ovs_dpdk);
         n_rxq_desc = nm_setting_ovs_dpdk_get_n_rxq_desc(s_ovs_dpdk);
         n_txq_desc = nm_setting_ovs_dpdk_get_n_txq_desc(s_ovs_dpdk);
+        lsc_int    = nm_setting_ovs_dpdk_get_lsc_interrupt(s_ovs_dpdk);
 
         dpdk_array = json_array();
 
@@ -930,6 +932,17 @@ _insert_interface(json_t       *params,
                 json_pack("[s,s]", "n_txq_desc", nm_sprintf_buf(sbuf, "%u", n_txq_desc)));
         }
 
+        switch (lsc_int) {
+        case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_IGNORE:
+            break;
+        case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_ENABLED:
+            json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "true"));
+            break;
+        case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_DISABLED:
+            json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "false"));
+            break;
+        }
+
         json_array_append_new(options, dpdk_array);
 
     } else if (s_ovs_patch) {
@@ -1374,88 +1387,113 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
     nm_auto_decref_json json_t *bridges     = NULL;
     nm_auto_decref_json json_t *new_bridges = NULL;
     gboolean                    bridges_changed;
-    gboolean                    ports_changed;
-    gboolean                    interfaces_changed;
-    int                         pi;
-    int                         ii;
 
     bridges         = json_array();
     new_bridges     = json_array();
     bridges_changed = FALSE;
 
+    /* Loop over all bridges */
     g_hash_table_iter_init(&iter, priv->bridges);
     while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) {
-        nm_auto_decref_json json_t *ports     = NULL;
-        nm_auto_decref_json json_t *new_ports = NULL;
+        nm_auto_decref_json json_t *ports         = NULL;
+        nm_auto_decref_json json_t *new_ports     = NULL;
+        guint                       num_nm_ports  = 0;
+        gboolean                    ports_changed = FALSE;
+        int                         pi;
 
-        ports         = json_array();
-        new_ports     = json_array();
-        ports_changed = FALSE;
+        ports     = json_array();
+        new_ports = json_array();
 
+        /* Add the bridge UUID to the list of known bridges for the "expect" condition */
         json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
 
+        if (!ovs_bridge->connection_uuid) {
+            /* Externally created, don't touch it */
+            json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
+            continue;
+        }
+
+        /* Loop over all bridge's ports */
         for (pi = 0; pi < ovs_bridge->ports->len; pi++) {
-            nm_auto_decref_json json_t *interfaces     = NULL;
-            nm_auto_decref_json json_t *new_interfaces = NULL;
+            nm_auto_decref_json json_t *interfaces         = NULL;
+            nm_auto_decref_json json_t *new_interfaces     = NULL;
+            guint                       num_nm_interfaces  = 0;
+            gboolean                    interfaces_changed = FALSE;
+            int                         ii;
 
             interfaces     = json_array();
             new_interfaces = json_array();
             port_uuid      = g_ptr_array_index(ovs_bridge->ports, pi);
             ovs_port       = g_hash_table_lookup(priv->ports, &port_uuid);
 
+            /* Add the port UUID to the list of known bridge port for the "expect" condition */
             json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid));
 
-            interfaces_changed = FALSE;
-
             if (!ovs_port) {
                 /* This would be a violation of ovsdb's reference integrity (a bug). */
                 _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid);
                 continue;
             }
 
+            /* Loop over all port's interfaces */
             for (ii = 0; ii < ovs_port->interfaces->len; ii++) {
                 interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii);
                 ovs_interface  = g_hash_table_lookup(priv->interfaces, &interface_uuid);
 
+                /* Add the interface UUID to the list of known port interfaces for the "expect" condition */
                 json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid));
 
                 if (ovs_interface) {
                     if (nm_streq(ovs_interface->name, ifname)) {
-                        /* skip the interface */
+                        /* We are deleting this interface, don't count it */
                         interfaces_changed = TRUE;
                         continue;
                     }
+                    if (ovs_interface->connection_uuid)
+                        num_nm_interfaces++;
                 } else {
                     /* This would be a violation of ovsdb's reference integrity (a bug). */
                     _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid);
                 }
 
+                /* Add the interface to the list of new interfaces to set on the port */
                 json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
             }
 
-            if (json_array_size(new_interfaces) == 0) {
+            if (num_nm_interfaces == 0) {
+                /* The port no longer has any NM interface. Don't add it to "new_ports" and set
+                 * ports_changed=TRUE, so that it will be deleted. */
                 ports_changed = TRUE;
             } else {
                 if (interfaces_changed) {
+                    /* An interface needs to be deleted from this port */
                     _expect_port_interfaces(params, ovs_port->name, interfaces);
                     _set_port_interfaces(params, ovs_port->name, new_interfaces);
                 }
+                /* The port is still alive */
                 json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid));
+                if (ovs_port->connection_uuid)
+                    num_nm_ports++;
             }
         }
 
-        if (json_array_size(new_ports) == 0) {
+        if (num_nm_ports == 0) {
+            /* The bridge no longer has any NM port. Don't add it to "new_bridges" and set
+             * bridges_changed=TRUE, so that it will be deleted. */
             bridges_changed = TRUE;
         } else {
             if (ports_changed) {
+                /* A port needs to be deleted from this bridge */
                 _expect_bridge_ports(params, ovs_bridge->name, ports);
                 _set_bridge_ports(params, ovs_bridge->name, new_ports);
             }
+            /* The bridge is still alive */
             json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
         }
     }
 
     if (bridges_changed) {
+        /* A port needs to be deleted from this bridge */
         _expect_ovs_bridges(params, priv->db_uuid, bridges);
         _set_ovs_bridges(params, priv->db_uuid, new_bridges);
     }
@@ -2211,7 +2249,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
                                            ovs_bridge->connection_uuid,
                                            ""),
                       (strtmp1 = _strdict_to_string(ovs_bridge->external_ids)),
-                      (strtmp2 = _strdict_to_string(ovs_bridge->external_ids)));
+                      (strtmp2 = _strdict_to_string(ovs_bridge->other_config)));
             }
         } else {
             gs_free char *strtmp1 = NULL;