Re: [patch network-manager-applet v2] add support for team devices



Hi, any comments please? I discussed this with jklimes and he seems
happy with it.

Please comment or apply.

Thanks

Jiri

Thu, Sep 05, 2013 at 11:27:24AM CEST, jiri resnulli us wrote:
Signed-off-by: Jiri Pirko <jiri resnulli us>

v1->v2: included patches suggested by jklimes
---
src/Makefile.am                              |   2 +
src/applet-device-team.c                     | 165 ++++++++++++++++
src/applet-device-team.h                     |  27 +++
src/applet.c                                 |  12 ++
src/applet.h                                 |   1 +
src/connection-editor/Makefile.am            |   6 +
src/connection-editor/ce-page-team-port.ui   |  38 ++++
src/connection-editor/ce-page-team.ui        | 185 ++++++++++++++++++
src/connection-editor/new-connection.c       |   7 +
src/connection-editor/nm-connection-editor.c |  12 +-
src/connection-editor/nm-connection-list.c   |   3 +-
src/connection-editor/page-team-port.c       | 165 ++++++++++++++++
src/connection-editor/page-team-port.h       |  55 ++++++
src/connection-editor/page-team.c            | 269 +++++++++++++++++++++++++++
src/connection-editor/page-team.h            |  61 ++++++
src/libnm-gtk/nm-ui-utils.c                  |   5 +
16 files changed, 1011 insertions(+), 2 deletions(-)
create mode 100644 src/applet-device-team.c
create mode 100644 src/applet-device-team.h
create mode 100644 src/connection-editor/ce-page-team-port.ui
create mode 100644 src/connection-editor/ce-page-team.ui
create mode 100644 src/connection-editor/page-team-port.c
create mode 100644 src/connection-editor/page-team-port.h
create mode 100644 src/connection-editor/page-team.c
create mode 100644 src/connection-editor/page-team.h

diff --git a/src/Makefile.am b/src/Makefile.am
index e9fd33b..44554cf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,8 @@ nm_applet_SOURCES = \
      applet-device-vlan.c \
      applet-device-bond.h \
      applet-device-bond.c \
+      applet-device-team.h \
+      applet-device-team.c \
      applet-device-bridge.h \
      applet-device-bridge.c \
      applet-device-infiniband.h \
diff --git a/src/applet-device-team.c b/src/applet-device-team.c
new file mode 100644
index 0000000..9c03784
--- /dev/null
+++ b/src/applet-device-team.c
@@ -0,0 +1,165 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-team.h>
+#include <nm-device-team.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-team.h"
+#include "utils.h"
+#include "nm-ui-utils.h"
+
+static void
+team_add_menu_item (NMDevice *device,
+                    gboolean multiple_devices,
+                    GSList *connections,
+                    NMConnection *active,
+                    GtkWidget *menu,
+                    NMApplet *applet)
+{
+      char *text;
+      GtkWidget *item;
+
+      text = nma_utils_get_connection_device_name (connections->data);
+      item = applet_menu_item_create_device_item_helper (device, applet, text);
+      g_free (text);
+
+      gtk_widget_set_sensitive (item, FALSE);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+
+      if (g_slist_length (connections))
+              applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_ACTIVE, menu, applet);
+
+      /* Notify user of unmanaged or unavailable device */
+      if (device) {
+              item = nma_menu_device_get_menu_item (device, applet, NULL);
+              if (item) {
+                      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+                      gtk_widget_show (item);
+              }
+      }
+
+      if (!device || !nma_menu_device_check_unusable (device)) {
+              if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                      applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+              if (g_slist_length (connections))
+                      applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_INACTIVE, 
menu, applet);
+      }
+}
+
+static void
+team_notify_connected (NMDevice *device,
+                       const char *msg,
+                       NMApplet *applet)
+{
+      applet_do_notify_with_pref (applet,
+                                  _("Connection Established"),
+                                  msg ? msg : _("You are now connected to the teamed network."),
+                                  "nm-device-wired",
+                                  PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+}
+
+static GdkPixbuf *
+team_get_icon (NMDevice *device,
+               NMDeviceState state,
+               NMConnection *connection,
+               char **tip,
+               NMApplet *applet)
+{
+      NMSettingConnection *s_con;
+      GdkPixbuf *pixbuf = NULL;
+      const char *id;
+
+      id = nm_device_get_iface (NM_DEVICE (device));
+      if (connection) {
+              s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+              id = nm_setting_connection_get_id (s_con);
+      }
+
+      switch (state) {
+      case NM_DEVICE_STATE_PREPARE:
+              *tip = g_strdup_printf (_("Preparing team connection '%s'..."), id);
+              break;
+      case NM_DEVICE_STATE_CONFIG:
+              *tip = g_strdup_printf (_("Configuring team connection '%s'..."), id);
+              break;
+      case NM_DEVICE_STATE_NEED_AUTH:
+              *tip = g_strdup_printf (_("User authentication required for team connection '%s'..."), id);
+              break;
+      case NM_DEVICE_STATE_IP_CONFIG:
+              *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+              break;
+      case NM_DEVICE_STATE_ACTIVATED:
+              pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+              *tip = g_strdup_printf (_("Team connection '%s' active"), id);
+              break;
+      default:
+              break;
+      }
+
+      return pixbuf ? g_object_ref (pixbuf) : NULL;
+}
+
+static gboolean
+team_new_auto_connection (NMDevice *device,
+                          gpointer dclass_data,
+                          AppletNewAutoConnectionCallback callback,
+                          gpointer callback_data)
+{
+      return FALSE;
+}
+
+
+static gboolean
+team_get_secrets (SecretsRequest *req, GError **error)
+{
+      /* No 802.1x or PPPoE possible yet on teams */
+      return FALSE;
+}
+
+NMADeviceClass *
+applet_device_team_get_class (NMApplet *applet)
+{
+      NMADeviceClass *dclass;
+
+      dclass = g_slice_new0 (NMADeviceClass);
+      if (!dclass)
+              return NULL;
+
+      dclass->new_auto_connection = team_new_auto_connection;
+      dclass->add_menu_item = team_add_menu_item;
+      dclass->notify_connected = team_notify_connected;
+      dclass->get_icon = team_get_icon;
+      dclass->get_secrets = team_get_secrets;
+
+      return dclass;
+}
diff --git a/src/applet-device-team.h b/src/applet-device-team.h
new file mode 100644
index 0000000..76ef2eb
--- /dev/null
+++ b/src/applet-device-team.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __APPLET_DEVICE_TEAM_H__
+#define __APPLET_DEVICE_TEAM_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_team_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_TEAM_H__ */
diff --git a/src/applet.c b/src/applet.c
index 6c3e87b..106d9bd 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -46,6 +46,7 @@

#include <NetworkManagerVPN.h>
#include <nm-device-bond.h>
+#include <nm-device-team.h>
#include <nm-device-bridge.h>
#include <nm-device-bt.h>
#include <nm-device-ethernet.h>
@@ -72,6 +73,7 @@

#include "applet.h"
#include "applet-device-bond.h"
+#include "applet-device-team.h"
#include "applet-device-bridge.h"
#include "applet-device-bt.h"
#include "applet-device-cdma.h"
@@ -270,6 +272,8 @@ get_device_class (NMDevice *device, NMApplet *applet)
              return applet->vlan_class;
      else if (NM_IS_DEVICE_BOND (device))
              return applet->bond_class;
+      else if (NM_IS_DEVICE_TEAM (device))
+              return applet->team_class;
      else if (NM_IS_DEVICE_BRIDGE (device))
              return applet->bridge_class;
      else if (NM_IS_DEVICE_INFINIBAND (device))
@@ -310,6 +314,8 @@ get_device_class_from_connection (NMConnection *connection, NMApplet *applet)
              return applet->bt_class;
      else if (!strcmp (ctype, NM_SETTING_BOND_SETTING_NAME))
              return applet->bond_class;
+      else if (!strcmp (ctype, NM_SETTING_TEAM_SETTING_NAME))
+              return applet->team_class;
      else if (!strcmp (ctype, NM_SETTING_BRIDGE_SETTING_NAME))
              return applet->bridge_class;
      else if (!strcmp (ctype, NM_SETTING_VLAN_SETTING_NAME))
@@ -1703,6 +1709,8 @@ nma_menu_add_devices (GtkWidget *menu, NMApplet *applet)
                                    all_devices, all_connections, menu, applet);
      n_items += add_virtual_items (NM_SETTING_BOND_SETTING_NAME,
                                    all_devices, all_connections, menu, applet);
+      n_items += add_virtual_items (NM_SETTING_TEAM_SETTING_NAME,
+                                    all_devices, all_connections, menu, applet);
      n_items += add_device_items  (NM_DEVICE_TYPE_ETHERNET,
                                    all_devices, all_connections, menu, applet);
      n_items += add_device_items  (NM_DEVICE_TYPE_INFINIBAND,
@@ -3723,6 +3731,9 @@ constructor (GType type,
      applet->bond_class = applet_device_bond_get_class (applet);
      g_assert (applet->bond_class);

+      applet->team_class = applet_device_team_get_class (applet);
+      g_assert (applet->team_class);
+
      applet->bridge_class = applet_device_bridge_get_class (applet);
      g_assert (applet->bridge_class);

@@ -3773,6 +3784,7 @@ static void finalize (GObject *object)
      g_slice_free (NMADeviceClass, applet->wimax_class);
      g_slice_free (NMADeviceClass, applet->vlan_class);
      g_slice_free (NMADeviceClass, applet->bond_class);
+      g_slice_free (NMADeviceClass, applet->team_class);
      g_slice_free (NMADeviceClass, applet->bridge_class);
      g_slice_free (NMADeviceClass, applet->infiniband_class);

diff --git a/src/applet.h b/src/applet.h
index c567367..174e42a 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -118,6 +118,7 @@ typedef struct
      NMADeviceClass *wimax_class;
      NMADeviceClass *vlan_class;
      NMADeviceClass *bond_class;
+      NMADeviceClass *team_class;
      NMADeviceClass *bridge_class;
      NMADeviceClass *infiniband_class;

diff --git a/src/connection-editor/Makefile.am b/src/connection-editor/Makefile.am
index 4cc9005..09d1719 100644
--- a/src/connection-editor/Makefile.am
+++ b/src/connection-editor/Makefile.am
@@ -55,6 +55,10 @@ nm_connection_editor_SOURCES = \
      page-master.c \
      page-bond.h \
      page-bond.c \
+      page-team.h \
+      page-team.c \
+      page-team-port.h \
+      page-team-port.c \
      page-bridge.h \
      page-bridge.c \
      page-bridge-port.h \
@@ -97,6 +101,8 @@ ui_DATA = \
      ce-page-wimax.ui \
      ce-page-infiniband.ui \
      ce-page-bond.ui \
+      ce-page-team.ui \
+      ce-page-team-port.ui \
      ce-page-bridge.ui \
      ce-page-bridge-port.ui \
      ce-page-ip4.ui \
diff --git a/src/connection-editor/ce-page-team-port.ui b/src/connection-editor/ce-page-team-port.ui
new file mode 100644
index 0000000..382e9c1
--- /dev/null
+++ b/src/connection-editor/ce-page-team-port.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkTable" id="TeamPortPage">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="n_rows">3</property>
+    <property name="n_columns">2</property>
+    <property name="column_spacing">12</property>
+    <property name="row_spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="team_port_json_config_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_JSON config:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">team_port_json_config</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="team_port_json_config">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">●</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">2</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/src/connection-editor/ce-page-team.ui b/src/connection-editor/ce-page-team.ui
new file mode 100644
index 0000000..135d043
--- /dev/null
+++ b/src/connection-editor/ce-page-team.ui
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="master_connections_model">
+    <columns>
+      <!-- column-name connection -->
+      <column type="NMConnection"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkGrid" id="TeamPage">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="column_spacing">12</property>
+    <property name="row_spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="master_connections_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_Teamed connections:</property>
+        <property name="use_underline">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+        <property name="width">2</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="team_json_config_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_JSON config:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">team_json_config</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">8</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="team_json_config">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">●</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">8</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="hbox2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">10</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="master_connections">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">master_connections_model</property>
+                <property name="headers_visible">False</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection1"/>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="master_connection_name">
+                    <child>
+                      <object class="GtkCellRendererText" id="master_connection_renderer"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButtonBox" id="buttonbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <property name="layout_style">start</property>
+            <child>
+              <object class="GtkButton" id="master_connection_add">
+                <property name="label">gtk-add</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="master_connection_edit">
+                <property name="label" translatable="yes">_Edit</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="master_connection_delete">
+                <property name="label" translatable="yes">_Delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+        <property name="width">2</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="master_interface_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_Interface name:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">master_interface</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="master_interface">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">●</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/src/connection-editor/new-connection.c b/src/connection-editor/new-connection.c
index 5b306cf..ed3a742 100644
--- a/src/connection-editor/new-connection.c
+++ b/src/connection-editor/new-connection.c
@@ -32,6 +32,7 @@
#include "page-dsl.h"
#include "page-infiniband.h"
#include "page-bond.h"
+#include "page-team.h"
#include "page-bridge.h"
#include "page-vlan.h"
#include "page-vpn.h"
@@ -140,6 +141,12 @@ get_connection_type_list (void)
      data.virtual = TRUE;
      g_array_append_val (array, data);

+      data.name = _("Team");
+      data.new_connection_func = team_connection_new;
+      data.setting_type = NM_TYPE_SETTING_TEAM;
+      data.virtual = TRUE;
+      g_array_append_val (array, data);
+
      data.name = _("Bridge");
      data.new_connection_func = bridge_connection_new;
      data.setting_type = NM_TYPE_SETTING_BRIDGE;
diff --git a/src/connection-editor/nm-connection-editor.c b/src/connection-editor/nm-connection-editor.c
index 377b376..ad54872 100644
--- a/src/connection-editor/nm-connection-editor.c
+++ b/src/connection-editor/nm-connection-editor.c
@@ -48,6 +48,7 @@
#include <nm-setting-wimax.h>
#include <nm-setting-infiniband.h>
#include <nm-setting-bond.h>
+#include <nm-setting-team.h>
#include <nm-setting-bridge.h>
#include <nm-utils.h>

@@ -71,6 +72,8 @@
#include "page-wimax.h"
#include "page-infiniband.h"
#include "page-bond.h"
+#include "page-team.h"
+#include "page-team-port.h"
#include "page-bridge.h"
#include "page-bridge-port.h"
#include "page-vlan.h"
@@ -817,6 +820,9 @@ nm_connection_editor_set_connection (NMConnectionEditor *editor,
      } else if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
              if (!add_page (editor, ce_page_bond_new, editor->connection, error))
                      goto out;
+      } else if (!strcmp (connection_type, NM_SETTING_TEAM_SETTING_NAME)) {
+              if (!add_page (editor, ce_page_team_new, editor->connection, error))
+                      goto out;
      } else if (!strcmp (connection_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
              if (!add_page (editor, ce_page_bridge_new, editor->connection, error))
                      goto out;
@@ -830,7 +836,11 @@ nm_connection_editor_set_connection (NMConnectionEditor *editor,
      slave_type = nm_setting_connection_get_slave_type (s_con);
      if (!g_strcmp0 (slave_type, NM_SETTING_BOND_SETTING_NAME))
              add_ip4 = add_ip6 = FALSE;
-      else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
+      else if (!g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
+              add_ip4 = add_ip6 = FALSE;
+              if (!add_page (editor, ce_page_team_port_new, editor->connection, error))
+                      goto out;
+      } else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
              add_ip4 = add_ip6 = FALSE;
              if (!add_page (editor, ce_page_bridge_port_new, editor->connection, error))
                      goto out;
diff --git a/src/connection-editor/nm-connection-list.c b/src/connection-editor/nm-connection-list.c
index 9ae92eb..cee5bb5 100644
--- a/src/connection-editor/nm-connection-list.c
+++ b/src/connection-editor/nm-connection-list.c
@@ -571,7 +571,7 @@ tree_model_visible_func (GtkTreeModel *model,
      }

      /* A connection node is visible unless it is a slave to a known
-       * bond or bridge.
+       * bond or team or bridge.
       */
      s_con = nm_connection_get_setting_connection (connection);
      g_object_unref (connection);
@@ -582,6 +582,7 @@ tree_model_visible_func (GtkTreeModel *model,
              return TRUE;
      slave_type = nm_setting_connection_get_slave_type (s_con);
      if (   g_strcmp0 (slave_type, NM_SETTING_BOND_SETTING_NAME) != 0
+          && g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME) != 0
          && g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME) != 0)
              return TRUE;

diff --git a/src/connection-editor/page-team-port.c b/src/connection-editor/page-team-port.c
new file mode 100644
index 0000000..ca7936c
--- /dev/null
+++ b/src/connection-editor/page-team-port.c
@@ -0,0 +1,165 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-team-port.h>
+#include <nm-utils.h>
+
+#include "page-team-port.h"
+
+G_DEFINE_TYPE (CEPageTeamPort, ce_page_team_port, CE_TYPE_PAGE)
+
+#define CE_PAGE_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_TEAM_PORT, 
CEPageTeamPortPrivate))
+
+typedef struct {
+      NMSettingTeamPort *setting;
+
+      GtkEntry *json_config;
+
+} CEPageTeamPortPrivate;
+
+static void
+team_port_private_init (CEPageTeamPort *self)
+{
+      CEPageTeamPortPrivate *priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+      GtkBuilder *builder;
+
+      builder = CE_PAGE (self)->builder;
+
+      priv->json_config = GTK_ENTRY (gtk_builder_get_object (builder, "team_port_json_config"));
+}
+
+static void
+stuff_changed (GtkWidget *w, gpointer user_data)
+{
+      ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+populate_ui (CEPageTeamPort *self)
+{
+      CEPageTeamPortPrivate *priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+      NMSettingTeamPort *s_port = priv->setting;
+      const char *json_config;
+
+      json_config = nm_setting_team_port_get_config (s_port);
+      gtk_entry_set_text (priv->json_config, json_config ? json_config : "");
+}
+
+static void
+finish_setup (CEPageTeamPort *self, gpointer unused, GError *error, gpointer user_data)
+{
+      CEPageTeamPortPrivate *priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+
+      if (error)
+              return;
+
+      populate_ui (self);
+
+      g_signal_connect (priv->json_config, "changed", G_CALLBACK (stuff_changed), self);
+}
+
+CEPage *
+ce_page_team_port_new (NMConnection *connection,
+                         GtkWindow *parent_window,
+                         NMClient *client,
+                         NMRemoteSettings *settings,
+                         const char **out_secrets_setting_name,
+                         GError **error)
+{
+      CEPageTeamPort *self;
+      CEPageTeamPortPrivate *priv;
+
+      self = CE_PAGE_TEAM_PORT (ce_page_new (CE_TYPE_PAGE_TEAM_PORT,
+                                             connection,
+                                             parent_window,
+                                             client,
+                                             settings,
+                                             UIDIR "/ce-page-team-port.ui",
+                                             "TeamPortPage",
+                                             /* Translators: a "Team Port" is a network
+                                              * device that is part of a team.
+                                              */
+                                             _("Team Port")));
+      if (!self) {
+              g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load team port user 
interface."));
+              return NULL;
+      }
+
+      team_port_private_init (self);
+      priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+
+      priv->setting = nm_connection_get_setting_team_port (connection);
+      if (!priv->setting) {
+              priv->setting = NM_SETTING_TEAM_PORT (nm_setting_team_port_new ());
+              nm_connection_add_setting (connection, NM_SETTING (priv->setting));
+      }
+
+      g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+      return CE_PAGE (self);
+}
+
+static void
+ui_to_setting (CEPageTeamPort *self)
+{
+      CEPageTeamPortPrivate *priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+      const char *json_config;
+
+      json_config = gtk_entry_get_text (priv->json_config);
+      if (!g_strcmp0(json_config, ""))
+              json_config = NULL;
+      g_object_set (priv->setting,
+                    NM_SETTING_TEAM_PORT_CONFIG, json_config,
+                    NULL);
+}
+
+static gboolean
+validate (CEPage *page, NMConnection *connection, GError **error)
+{
+      CEPageTeamPort *self = CE_PAGE_TEAM_PORT (page);
+      CEPageTeamPortPrivate *priv = CE_PAGE_TEAM_PORT_GET_PRIVATE (self);
+
+      ui_to_setting (self);
+      return nm_setting_verify (NM_SETTING (priv->setting), NULL, error);
+}
+
+static void
+ce_page_team_port_init (CEPageTeamPort *self)
+{
+}
+
+static void
+ce_page_team_port_class_init (CEPageTeamPortClass *team_port_class)
+{
+      GObjectClass *object_class = G_OBJECT_CLASS (team_port_class);
+      CEPageClass *parent_class = CE_PAGE_CLASS (team_port_class);
+
+      g_type_class_add_private (object_class, sizeof (CEPageTeamPortPrivate));
+
+      /* virtual methods */
+      parent_class->validate = validate;
+}
diff --git a/src/connection-editor/page-team-port.h b/src/connection-editor/page-team-port.h
new file mode 100644
index 0000000..6eccb15
--- /dev/null
+++ b/src/connection-editor/page-team-port.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PAGE_TEAM_PORT_H__
+#define __PAGE_TEAM_PORT_H__
+
+#include <nm-connection.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ce-page.h"
+
+#define CE_TYPE_PAGE_TEAM_PORT            (ce_page_team_port_get_type ())
+#define CE_PAGE_TEAM_PORT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CE_TYPE_PAGE_TEAM_PORT, 
CEPageTeamPort))
+#define CE_PAGE_TEAM_PORT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CE_TYPE_PAGE_TEAM_PORT, 
CEPageTeamPortClass))
+#define CE_IS_PAGE_TEAM_PORT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CE_TYPE_PAGE_TEAM_PORT))
+#define CE_IS_PAGE_TEAM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CE_TYPE_PAGE_TEAM_PORT))
+#define CE_PAGE_TEAM_PORT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE_TEAM_PORT, 
CEPageTeamPortClass))
+
+typedef struct {
+      CEPage parent;
+} CEPageTeamPort;
+
+typedef struct {
+      CEPageClass parent;
+} CEPageTeamPortClass;
+
+GType ce_page_team_port_get_type (void);
+
+CEPage *ce_page_team_port_new (NMConnection *connection,
+                               GtkWindow *parent,
+                               NMClient *client,
+                               NMRemoteSettings *settings,
+                               const char **out_secrets_setting_name,
+                               GError **error);
+
+#endif  /* __PAGE_TEAM_PORT_H__ */
+
diff --git a/src/connection-editor/page-team.c b/src/connection-editor/page-team.c
new file mode 100644
index 0000000..8229440
--- /dev/null
+++ b/src/connection-editor/page-team.c
@@ -0,0 +1,269 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-team.h>
+
+#include "page-team.h"
+#include "nm-connection-editor.h"
+#include "new-connection.h"
+
+G_DEFINE_TYPE (CEPageTeam, ce_page_team, CE_TYPE_PAGE_MASTER)
+
+#define CE_PAGE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_TEAM, 
CEPageTeamPrivate))
+
+typedef struct {
+      NMSettingTeam *setting;
+
+      GtkWindow *toplevel;
+
+      GtkEntry *json_config;
+      GtkWidget *json_config_label;
+} CEPageTeamPrivate;
+
+static void
+team_private_init (CEPageTeam *self)
+{
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+      GtkBuilder *builder;
+
+      builder = CE_PAGE (self)->builder;
+
+      priv->json_config = GTK_ENTRY (gtk_builder_get_object (builder, "team_json_config"));
+      priv->json_config_label = GTK_WIDGET (gtk_builder_get_object (builder, "team_json_config_label"));
+
+      priv->toplevel = GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (priv->json_config),
+                                                            GTK_TYPE_WINDOW));
+}
+
+static void
+stuff_changed (GtkWidget *w, gpointer user_data)
+{
+      ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+populate_ui (CEPageTeam *self)
+{
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+      NMSettingTeam *s_team = priv->setting;
+      const char *json_config;
+
+      json_config = nm_setting_team_get_config (s_team);
+      gtk_entry_set_text (priv->json_config, json_config ? json_config : "");
+}
+
+static void
+create_connection (CEPageMaster *master, NMConnection *connection)
+{
+      NMSetting *s_port;
+
+      s_port = nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT);
+      if (!s_port) {
+              s_port = nm_setting_team_port_new ();
+              nm_connection_add_setting (connection, s_port);
+      }
+}
+
+static gboolean
+connection_type_filter (GType type, gpointer user_data)
+{
+      if (type == NM_TYPE_SETTING_WIRED ||
+          type == NM_TYPE_SETTING_WIRELESS ||
+          type == NM_TYPE_SETTING_VLAN ||
+          type == NM_TYPE_SETTING_INFINIBAND)
+              return TRUE;
+      else
+              return FALSE;
+}
+
+static void
+add_slave (CEPageMaster *master, NewConnectionResultFunc result_func)
+{
+      CEPageTeam *self = CE_PAGE_TEAM (master);
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+
+      new_connection_dialog (priv->toplevel,
+                             CE_PAGE (self)->settings,
+                             connection_type_filter,
+                             result_func,
+                             master);
+}
+
+static void
+finish_setup (CEPageTeam *self, gpointer unused, GError *error, gpointer user_data)
+{
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+
+      if (error)
+              return;
+
+      populate_ui (self);
+
+      g_signal_connect (priv->json_config, "changed", G_CALLBACK (stuff_changed), self);
+}
+
+CEPage *
+ce_page_team_new (NMConnection *connection,
+                                GtkWindow *parent_window,
+                                NMClient *client,
+                  NMRemoteSettings *settings,
+                                const char **out_secrets_setting_name,
+                                GError **error)
+{
+      CEPageTeam *self;
+      CEPageTeamPrivate *priv;
+
+      self = CE_PAGE_TEAM (ce_page_new (CE_TYPE_PAGE_TEAM,
+                                        connection,
+                                        parent_window,
+                                        client,
+                                        settings,
+                                        UIDIR "/ce-page-team.ui",
+                                        "TeamPage",
+                                        _("Team")));
+      if (!self) {
+              g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
+                                   _("Could not load team user interface."));
+              return NULL;
+      }
+
+      team_private_init (self);
+      priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+
+      priv->setting = nm_connection_get_setting_team (connection);
+      if (!priv->setting) {
+              priv->setting = NM_SETTING_TEAM (nm_setting_team_new ());
+              nm_connection_add_setting (connection, NM_SETTING (priv->setting));
+      }
+
+      g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
+
+      return CE_PAGE (self);
+}
+
+static void
+ui_to_setting (CEPageTeam *self)
+{
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+      const char *json_config;
+
+      json_config = gtk_entry_get_text (priv->json_config);
+      if (!g_strcmp0(json_config, ""))
+              json_config = NULL;
+      g_object_set (priv->setting,
+                    NM_SETTING_TEAM_CONFIG, json_config,
+                    NULL);
+}
+
+static gboolean
+validate (CEPage *page, NMConnection *connection, GError **error)
+{
+      CEPageTeam *self = CE_PAGE_TEAM (page);
+      CEPageTeamPrivate *priv = CE_PAGE_TEAM_GET_PRIVATE (self);
+
+      if (!CE_PAGE_CLASS (ce_page_team_parent_class)->validate (page, connection, error))
+              return FALSE;
+
+      ui_to_setting (self);
+      return nm_setting_verify (NM_SETTING (priv->setting), NULL, error);
+}
+
+static void
+ce_page_team_init (CEPageTeam *self)
+{
+}
+
+static void
+ce_page_team_class_init (CEPageTeamClass *team_class)
+{
+      GObjectClass *object_class = G_OBJECT_CLASS (team_class);
+      CEPageClass *parent_class = CE_PAGE_CLASS (team_class);
+      CEPageMasterClass *master_class = CE_PAGE_MASTER_CLASS (team_class);
+
+      g_type_class_add_private (object_class, sizeof (CEPageTeamPrivate));
+
+      /* virtual methods */
+      parent_class->validate = validate;
+      master_class->create_connection = create_connection;
+      master_class->add_slave = add_slave;
+}
+
+
+void
+team_connection_new (GtkWindow *parent,
+                     const char *detail,
+                     NMRemoteSettings *settings,
+                     PageNewConnectionResultFunc result_func,
+                     gpointer user_data)
+{
+      NMConnection *connection;
+      int team_num, max_team_num, num;
+      GSList *connections, *iter;
+      NMConnection *conn2;
+      NMSettingTeam *s_team;
+      const char *iface;
+      char *my_iface;
+
+      connection = ce_page_new_connection (_("Team connection %d"),
+                                           NM_SETTING_TEAM_SETTING_NAME,
+                                           TRUE,
+                                           settings,
+                                           user_data);
+      nm_connection_add_setting (connection, nm_setting_team_new ());
+
+      /* Find an available interface name */
+      team_num = max_team_num = 0;
+      connections = nm_remote_settings_list_connections (settings);
+      for (iter = connections; iter; iter = iter->next) {
+              conn2 = iter->data;
+
+              if (!nm_connection_is_type (conn2, NM_SETTING_TEAM_SETTING_NAME))
+                      continue;
+              s_team = nm_connection_get_setting_team (conn2);
+              if (!s_team)
+                      continue;
+              iface = nm_setting_team_get_interface_name (s_team);
+              if (!iface || strncmp (iface, "team", 4) != 0 || !g_ascii_isdigit (iface[4]))
+                      continue;
+
+              num = atoi (iface + 4);
+              if (num > max_team_num)
+                      max_team_num = num;
+              if (num == team_num)
+                      team_num = max_team_num + 1;
+      }
+      g_slist_free (connections);
+
+      my_iface = g_strdup_printf ("team%d", team_num);
+      s_team = nm_connection_get_setting_team (connection);
+      g_object_set (G_OBJECT (s_team),
+                    NM_SETTING_TEAM_INTERFACE_NAME, my_iface,
+                    NULL);
+      g_free (my_iface);
+
+      (*result_func) (connection, FALSE, NULL, user_data);
+}
+
diff --git a/src/connection-editor/page-team.h b/src/connection-editor/page-team.h
new file mode 100644
index 0000000..d1936b3
--- /dev/null
+++ b/src/connection-editor/page-team.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri resnulli us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PAGE_TEAM_H__
+#define __PAGE_TEAM_H__
+
+#include <nm-connection.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "page-master.h"
+
+#define CE_TYPE_PAGE_TEAM            (ce_page_team_get_type ())
+#define CE_PAGE_TEAM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CE_TYPE_PAGE_TEAM, CEPageTeam))
+#define CE_PAGE_TEAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CE_TYPE_PAGE_TEAM, CEPageTeamClass))
+#define CE_IS_PAGE_TEAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CE_TYPE_PAGE_TEAM))
+#define CE_IS_PAGE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CE_TYPE_PAGE_TEAM))
+#define CE_PAGE_TEAM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE_TEAM, CEPageTeamClass))
+
+typedef struct {
+      CEPageMaster parent;
+} CEPageTeam;
+
+typedef struct {
+      CEPageMasterClass parent;
+} CEPageTeamClass;
+
+GType ce_page_team_get_type (void);
+
+CEPage *ce_page_team_new (NMConnection *connection,
+                          GtkWindow *parent,
+                          NMClient *client,
+                          NMRemoteSettings *settings,
+                          const char **out_secrets_setting_name,
+                          GError **error);
+
+void team_connection_new (GtkWindow *parent,
+                          const char *detail,
+                          NMRemoteSettings *settings,
+                          PageNewConnectionResultFunc result_func,
+                          gpointer user_data);
+
+#endif  /* __PAGE_TEAM_H__ */
+
diff --git a/src/libnm-gtk/nm-ui-utils.c b/src/libnm-gtk/nm-ui-utils.c
index 4d28bae..69ede41 100644
--- a/src/libnm-gtk/nm-ui-utils.c
+++ b/src/libnm-gtk/nm-ui-utils.c
@@ -335,6 +335,8 @@ nma_utils_get_device_type_name (NMDevice *device)
              return _("InfiniBand");
      case NM_DEVICE_TYPE_BOND:
              return _("Bond");
+      case NM_DEVICE_TYPE_TEAM:
+              return _("Team");
      case NM_DEVICE_TYPE_BRIDGE:
              return _("Bridge");
      case NM_DEVICE_TYPE_VLAN:
@@ -353,6 +355,7 @@ get_device_type_name_with_iface (NMDevice *device)

      switch (nm_device_get_device_type (device)) {
      case NM_DEVICE_TYPE_BOND:
+      case NM_DEVICE_TYPE_TEAM:
      case NM_DEVICE_TYPE_BRIDGE:
      case NM_DEVICE_TYPE_VLAN:
              return g_strdup_printf ("%s (%s)", type_name, nm_device_get_iface (device));
@@ -557,6 +560,8 @@ nma_utils_get_connection_device_name (NMConnection *connection)

      if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME))
              display_type = _("Bond");
+      else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME))
+              display_type = _("Team");
      else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME))
              display_type = _("Bridge");
      else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
-- 
1.8.3.1




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