[network-manager-applet/danw/sriov] connection-editor: improve handling of NPAR/SR-IOV devices (rh #804527)
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-applet/danw/sriov] connection-editor: improve handling of NPAR/SR-IOV devices (rh #804527)
- Date: Mon, 21 Oct 2013 20:02:19 +0000 (UTC)
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]