[network-manager-applet/danw/sriov] connection-editor: improve handling of NPAR/SR-IOV devices (rh #804527)



commit 384648d5ffdf658a7a1c62425388a5f875c20e59
Author: Dan Winship <danw gnome org>
Date:   Sun Oct 20 09:57:32 2013 -0400

    connection-editor: improve handling of NPAR/SR-IOV devices (rh #804527)
    
    Use NMDevice's new :physical-port property to recognize when two
    devices are just virtual devices sharing the same physical port, and
    refuse to add multiple such slaves to a single bond/team connection.
    
    Also, while we're at it, prevent adding exactly the same device to a
    bond/bridge/team multiple times.

 src/connection-editor/nm-connection-editor.c |   16 ++++-
 src/connection-editor/nm-connection-editor.h |    3 +-
 src/connection-editor/page-bond.c            |    1 +
 src/connection-editor/page-master.c          |   98 +++++++++++++++++++++++++-
 src/connection-editor/page-master.h          |    2 +
 src/connection-editor/page-team.c            |    1 +
 6 files changed, 116 insertions(+), 5 deletions(-)
---
diff --git a/src/connection-editor/nm-connection-editor.c b/src/connection-editor/nm-connection-editor.c
index 3024244..b97ec4b 100644
--- a/src/connection-editor/nm-connection-editor.c
+++ b/src/connection-editor/nm-connection-editor.c
@@ -84,6 +84,7 @@
 G_DEFINE_TYPE (NMConnectionEditor, nm_connection_editor, G_TYPE_OBJECT)
 
 enum {
+       EDITOR_SAVE,
        EDITOR_DONE,
        EDITOR_LAST_SIGNAL
 };
@@ -95,6 +96,7 @@ static GHashTable *active_editors;
 static gboolean nm_connection_editor_set_connection (NMConnectionEditor *editor,
                                                      NMConnection *connection,
                                                      GError **error);
+static void nm_connection_editor_save (NMConnectionEditor *self);
 
 struct GetSecretsInfo {
        NMConnectionEditor *self;
@@ -376,7 +378,17 @@ nm_connection_editor_class_init (NMConnectionEditorClass *klass)
        /* virtual methods */
        object_class->dispose = dispose;
 
+       klass->save = nm_connection_editor_save;
+
        /* Signals */
+       editor_signals[EDITOR_SAVE] =
+               g_signal_new ("save",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (NMConnectionEditorClass, save),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
        editor_signals[EDITOR_DONE] =
                g_signal_new ("done",
                              G_OBJECT_CLASS_TYPE (object_class),
@@ -965,7 +977,7 @@ updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer u
 }
 
 static void
-ok_button_clicked_save_connection (NMConnectionEditor *self)
+nm_connection_editor_save (NMConnectionEditor *self)
 {
        NMSettingConnection *s_con;
        gboolean everyone = FALSE;
@@ -1019,7 +1031,7 @@ ok_button_clicked_cb (GtkWidget *widget, gpointer user_data)
        if (self->busy)
                return;
 
-       ok_button_clicked_save_connection (self);
+       g_signal_emit (self, editor_signals[EDITOR_SAVE], 0);
 }
 
 static void
diff --git a/src/connection-editor/nm-connection-editor.h b/src/connection-editor/nm-connection-editor.h
index 4798b0f..cdcd4d9 100644
--- a/src/connection-editor/nm-connection-editor.h
+++ b/src/connection-editor/nm-connection-editor.h
@@ -71,7 +71,8 @@ typedef struct {
        GObjectClass parent_class;
 
        /* Signals */
-       void (*done)  (NMConnectionEditor *editor, gint result, GError *error);
+       void (*save) (NMConnectionEditor *editor);
+       void (*done) (NMConnectionEditor *editor, gint result, GError *error);
 } NMConnectionEditorClass;
 
 GType               nm_connection_editor_get_type (void);
diff --git a/src/connection-editor/page-bond.c b/src/connection-editor/page-bond.c
index cf6abc3..492f928 100644
--- a/src/connection-editor/page-bond.c
+++ b/src/connection-editor/page-bond.c
@@ -544,6 +544,7 @@ validate (CEPage *page, NMConnection *connection, GError **error)
 static void
 ce_page_bond_init (CEPageBond *self)
 {
+       CE_PAGE_MASTER (self)->aggregating = TRUE;
 }
 
 static void
diff --git a/src/connection-editor/page-master.c b/src/connection-editor/page-master.c
index 76d320b..4268205 100644
--- a/src/connection-editor/page-master.c
+++ b/src/connection-editor/page-master.c
@@ -249,12 +249,105 @@ connections_selection_changed_cb (GtkTreeSelection *selection, gpointer user_dat
 }
 
 static void
-add_response_cb (NMConnectionEditor *editor, NMRemoteConnection *connection,
-                 gboolean added, gpointer user_data)
+add_response_cb (NMConnectionEditor *editor, GtkResponseType response, gpointer user_data)
 {
        g_object_unref (editor);
 }
 
+static NMDevice *
+get_device_for_connection (NMClient *client, NMConnection *conn)
+{
+       const GPtrArray *devices;
+       NMSettingConnection *s_con;
+       int i;
+
+       devices = nm_client_get_devices (client);
+       if (!devices)
+               return NULL;
+
+       /* Make sure the connection is actually locked to a specific device */
+       s_con = nm_connection_get_setting_connection (conn);
+       if (   !nm_setting_connection_get_interface_name (s_con)
+           && !nm_connection_get_virtual_iface_name (conn)) {
+               NMSetting *s_hw;
+               GByteArray *mac_address;
+
+               s_hw = nm_connection_get_setting_by_name (conn, nm_setting_connection_get_connection_type 
(s_con));
+               if (!s_hw || !g_object_class_find_property (G_OBJECT_GET_CLASS (s_hw), "mac-address"))
+                       return NULL;
+
+               g_object_get (G_OBJECT (s_hw), "mac-address", &mac_address, NULL);
+               if (!mac_address)
+                       return NULL;
+               g_byte_array_unref (mac_address);
+       }
+
+       /* OK, now find that device */
+       for (i = 0; i < devices->len; i++) {
+               NMDevice *device = devices->pdata[i];
+
+               if (nm_device_connection_compatible (device, conn, NULL))
+                       return device;
+       }
+
+       return NULL;
+}
+
+static void
+check_save_cb (NMConnectionEditor *editor, gpointer user_data)
+{
+       CEPageMaster *self = user_data;
+       CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
+       NMConnection *conn, *conn2;
+       NMDevice *dev, *dev2;
+       const char *id, *id2;
+       GtkTreeIter iter;
+
+       conn = editor->connection;
+       dev = get_device_for_connection (CE_PAGE (self)->client, conn);
+       if (!dev)
+               return;
+       id = nm_device_get_physical_port_id (dev);
+
+       if (!gtk_tree_model_get_iter_first (priv->connections_model, &iter))
+               return;
+       do {
+               gtk_tree_model_get (priv->connections_model, &iter, 0, &conn2, -1);
+               g_object_unref (conn2); /* gtk_tree_model_get() adds a ref */
+               dev2 = get_device_for_connection (CE_PAGE (self)->client, conn2);
+               if (!dev2)
+                       continue;
+               if (dev == dev2) {
+                       nm_connection_editor_error (GTK_WINDOW (editor->window),
+                                                   _("Cannot add slave"),
+                                                   _("Slave '%s' is invalid because it uses "
+                                                     "the same device (%s) as slave '%s'"),
+                                                   nm_connection_get_id (conn),
+                                                   nm_device_get_iface (dev),
+                                                   nm_connection_get_id (conn2));
+                       g_signal_stop_emission_by_name (editor, "save");
+                       return;
+               }
+
+               id2 = nm_device_get_physical_port_id (dev2);
+               if (priv->aggregating && id && id2 && !strcmp (id, id2)) {
+                       nm_connection_editor_error (GTK_WINDOW (editor->window),
+                                                   _("Cannot add slave"),
+                                                   _("Slave '%s' is invalid because it uses "
+                                                     "a different virtual device on the same "
+                                                     "physical port as slave '%s'"),
+                                                   nm_connection_get_id (conn),
+                                                   nm_connection_get_id (conn2));
+                       g_signal_stop_emission_by_name (editor, "save");
+                       return;
+               }
+       } while (gtk_tree_model_iter_next (priv->connections_model, &iter));
+
+       /* No duplicates, allow the signal emission to continue and let the
+        * connection be saved.
+        */
+}
+
 static void
 add_connection (NMConnection *connection,
                 gpointer user_data)
@@ -303,6 +396,7 @@ add_connection (NMConnection *connection,
                return;
        }
 
+       g_signal_connect (editor, "save", G_CALLBACK (check_save_cb), self);
        g_signal_connect (editor, "done", G_CALLBACK (add_response_cb), self);
        nm_connection_editor_run (editor);
 }
diff --git a/src/connection-editor/page-master.h b/src/connection-editor/page-master.h
index 5bd0575..56cc6c4 100644
--- a/src/connection-editor/page-master.h
+++ b/src/connection-editor/page-master.h
@@ -38,6 +38,8 @@
 
 typedef struct {
        CEPage parent;
+
+       gboolean aggregating;
 } CEPageMaster;
 
 typedef struct {
diff --git a/src/connection-editor/page-team.c b/src/connection-editor/page-team.c
index bbae0bf..e3c6e20 100644
--- a/src/connection-editor/page-team.c
+++ b/src/connection-editor/page-team.c
@@ -310,6 +310,7 @@ validate (CEPage *page, NMConnection *connection, GError **error)
 static void
 ce_page_team_init (CEPageTeam *self)
 {
+       CE_PAGE_MASTER (self)->aggregating = TRUE;
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]