mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-14 12:05:03 +00:00
core: add support for team device
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
This commit is contained in:
parent
64cdb1a7f0
commit
23836e8146
|
@ -51,6 +51,7 @@
|
|||
#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge"
|
||||
#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic"
|
||||
|
@ -118,6 +119,7 @@ typedef enum {
|
|||
* @NM_DEVICE_TYPE_VLAN: an 802.1Q VLAN interface
|
||||
* @NM_DEVICE_TYPE_ADSL: ADSL modem
|
||||
* @NM_DEVICE_TYPE_BRIDGE: a bridge master interface
|
||||
* @NM_DEVICE_TYPE_TEAM: a team master interface
|
||||
*
|
||||
* #NMDeviceType values indicate the type of hardware represented by
|
||||
* an #NMDevice.
|
||||
|
@ -138,6 +140,7 @@ typedef enum {
|
|||
NM_DEVICE_TYPE_ADSL = 12,
|
||||
NM_DEVICE_TYPE_BRIDGE = 13,
|
||||
NM_DEVICE_TYPE_GENERIC = 14,
|
||||
NM_DEVICE_TYPE_TEAM = 15,
|
||||
} NMDeviceType;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,6 +13,7 @@ EXTRA_DIST = \
|
|||
nm-device-wimax.xml \
|
||||
nm-device-infiniband.xml \
|
||||
nm-device-bond.xml \
|
||||
nm-device-team.xml \
|
||||
nm-device-bridge.xml \
|
||||
nm-device-vlan.xml \
|
||||
nm-device-generic.xml \
|
||||
|
|
34
introspection/nm-device-team.xml
Normal file
34
introspection/nm-device-team.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
<interface name="org.freedesktop.NetworkManager.Device.Team">
|
||||
|
||||
<property name="HwAddress" type="s" access="read">
|
||||
<tp:docstring>
|
||||
Hardware address of the device.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Carrier" type="b" access="read">
|
||||
<tp:docstring>
|
||||
Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not).
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Slaves" type="ao" access="read">
|
||||
<tp:docstring>
|
||||
Array of object paths representing devices which are currently
|
||||
slaved to this device.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<signal name="PropertiesChanged">
|
||||
<arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
|
||||
<tp:docstring>
|
||||
A dictionary mapping property names to variant boxed values
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
|
@ -51,6 +51,7 @@ src/devices/nm-device-bt.c
|
|||
src/devices/nm-device-ethernet.c
|
||||
src/devices/nm-device-infiniband.c
|
||||
src/devices/nm-device-olpc-mesh.c
|
||||
src/devices/nm-device-team.c
|
||||
src/devices/nm-device-vlan.c
|
||||
src/nm-manager.c
|
||||
src/nm-netlink-monitor.c
|
||||
|
|
|
@ -88,6 +88,8 @@ nm_sources = \
|
|||
devices/nm-device-olpc-mesh.c \
|
||||
devices/nm-device-olpc-mesh.h \
|
||||
devices/nm-device-private.h \
|
||||
devices/nm-device-team.c \
|
||||
devices/nm-device-team.h \
|
||||
devices/nm-device-tun.c \
|
||||
devices/nm-device-tun.h \
|
||||
devices/nm-device-veth.c \
|
||||
|
@ -323,6 +325,7 @@ glue_sources = \
|
|||
nm-device-macvlan-glue.h \
|
||||
nm-device-modem-glue.h \
|
||||
nm-device-olpc-mesh-glue.h \
|
||||
nm-device-team-glue.h \
|
||||
nm-device-tun-glue.h \
|
||||
nm-device-veth-glue.h \
|
||||
nm-device-vlan-glue.h \
|
||||
|
|
352
src/devices/nm-device-team.c
Normal file
352
src/devices/nm-device-team.c
Normal file
|
@ -0,0 +1,352 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* 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 <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include "nm-device-team.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-device-private.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-enum-types.h"
|
||||
|
||||
#include "nm-device-team-glue.h"
|
||||
|
||||
|
||||
G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE)
|
||||
|
||||
#define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate))
|
||||
|
||||
#define NM_TEAM_ERROR (nm_team_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} NMDeviceTeamPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SLAVES,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static GQuark
|
||||
nm_team_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("nm-team-error");
|
||||
return quark;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static guint32
|
||||
get_generic_capabilities (NMDevice *dev)
|
||||
{
|
||||
return NM_DEVICE_CAP_CARRIER_DETECT;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *dev)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (dev)->is_up)
|
||||
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_compatible (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
GError **error)
|
||||
{
|
||||
const char *iface;
|
||||
NMSettingTeam *s_team;
|
||||
|
||||
if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection, error))
|
||||
return FALSE;
|
||||
|
||||
s_team = nm_connection_get_setting_team (connection);
|
||||
if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) {
|
||||
g_set_error (error, NM_TEAM_ERROR, NM_TEAM_ERROR_CONNECTION_NOT_TEAM,
|
||||
"The connection was not a team connection.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Team connections must specify the virtual interface name */
|
||||
iface = nm_connection_get_virtual_iface_name (connection);
|
||||
if (!iface || strcmp (nm_device_get_iface (device), iface)) {
|
||||
g_set_error (error, NM_TEAM_ERROR, NM_TEAM_ERROR_CONNECTION_NOT_TEAM,
|
||||
"The team connection virtual interface name did not match.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: match team properties like mode, etc? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
complete_connection (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
const GSList *existing_connections,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingTeam *s_team, *tmp;
|
||||
guint32 i = 0;
|
||||
char *name;
|
||||
const GSList *iter;
|
||||
gboolean found;
|
||||
|
||||
nm_utils_complete_generic (connection,
|
||||
NM_SETTING_TEAM_SETTING_NAME,
|
||||
existing_connections,
|
||||
_("Team connection %d"),
|
||||
NULL,
|
||||
TRUE);
|
||||
|
||||
s_team = nm_connection_get_setting_team (connection);
|
||||
if (!s_team) {
|
||||
s_team = (NMSettingTeam *) nm_setting_team_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_team));
|
||||
}
|
||||
|
||||
/* Grab the first name that doesn't exist in either our connections
|
||||
* or a device on the system.
|
||||
*/
|
||||
while (i < 500 && !nm_setting_team_get_interface_name (s_team)) {
|
||||
name = g_strdup_printf ("team%u", i);
|
||||
/* check interface names */
|
||||
if (!nm_platform_link_exists (name)) {
|
||||
/* check existing team connections */
|
||||
for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) {
|
||||
NMConnection *candidate = iter->data;
|
||||
|
||||
tmp = nm_connection_get_setting_team (candidate);
|
||||
if (tmp && nm_connection_is_type (candidate, NM_SETTING_TEAM_SETTING_NAME)) {
|
||||
if (g_strcmp0 (nm_setting_team_get_interface_name (tmp), name) == 0) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_INTERFACE_NAME, name, NULL);
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
i++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
match_l2_config (NMDevice *self, NMConnection *connection)
|
||||
{
|
||||
/* FIXME */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
||||
{
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingTeam *s_team;
|
||||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||
connection = nm_device_get_connection (dev);
|
||||
g_assert (connection);
|
||||
s_team = nm_connection_get_setting_team (connection);
|
||||
g_assert (s_team);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
||||
{
|
||||
gboolean success, no_firmware = FALSE;
|
||||
const char *iface = nm_device_get_ip_iface (device);
|
||||
const char *slave_iface = nm_device_get_ip_iface (slave);
|
||||
|
||||
nm_device_take_down (slave, TRUE);
|
||||
|
||||
success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
|
||||
nm_device_bring_up (slave, TRUE, &no_firmware);
|
||||
|
||||
if (success) {
|
||||
nm_log_info (LOGD_TEAM, "(%s): enslaved team port %s", iface, slave_iface);
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
release_slave (NMDevice *device, NMDevice *slave)
|
||||
{
|
||||
gboolean success, no_firmware = FALSE;
|
||||
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
|
||||
nm_log_info (LOGD_TEAM, "(%s): released team port %s (success %d)",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave),
|
||||
success);
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
|
||||
/* Kernel team code "closes" the port when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released port.
|
||||
*/
|
||||
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
||||
nm_log_warn (LOGD_TEAM, "(%s): released team port could not be brought up.",
|
||||
nm_device_get_iface (slave));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMDevice *
|
||||
nm_device_team_new (const char *iface)
|
||||
{
|
||||
g_return_val_if_fail (iface != NULL, NULL);
|
||||
|
||||
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM,
|
||||
NM_DEVICE_IFACE, iface,
|
||||
NM_DEVICE_DRIVER, "team",
|
||||
NM_DEVICE_TYPE_DESC, "Team",
|
||||
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM,
|
||||
NM_DEVICE_IS_MASTER, TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (nm_device_team_parent_class)->constructed (object);
|
||||
|
||||
nm_log_dbg (LOGD_HW | LOGD_TEAM, "(%s): kernel ifindex %d",
|
||||
nm_device_get_iface (NM_DEVICE (object)),
|
||||
nm_device_get_ifindex (NM_DEVICE (object)));
|
||||
}
|
||||
|
||||
static void
|
||||
nm_device_team_init (NMDeviceTeam * self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GPtrArray *slaves;
|
||||
GSList *list, *iter;
|
||||
|
||||
switch (prop_id) {
|
||||
break;
|
||||
case PROP_SLAVES:
|
||||
slaves = g_ptr_array_new ();
|
||||
list = nm_device_master_get_slaves (NM_DEVICE (object));
|
||||
for (iter = list; iter; iter = iter->next)
|
||||
g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data))));
|
||||
g_slist_free (list);
|
||||
g_value_take_boxed (value, slaves);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nm_device_team_class_init (NMDeviceTeamClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->constructed = constructed;
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
|
||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||
parent_class->is_available = is_available;
|
||||
parent_class->check_connection_compatible = check_connection_compatible;
|
||||
parent_class->complete_connection = complete_connection;
|
||||
|
||||
parent_class->match_l2_config = match_l2_config;
|
||||
|
||||
parent_class->act_stage1_prepare = act_stage1_prepare;
|
||||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
/* properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_SLAVES,
|
||||
g_param_spec_boxed (NM_DEVICE_TEAM_SLAVES,
|
||||
"Slaves",
|
||||
"Slaves",
|
||||
DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
&dbus_glib_nm_device_team_object_info);
|
||||
|
||||
dbus_g_error_domain_register (NM_TEAM_ERROR, NULL, NM_TYPE_TEAM_ERROR);
|
||||
}
|
61
src/devices/nm-device-team.h
Normal file
61
src/devices/nm-device-team.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* 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 NM_DEVICE_TEAM_H
|
||||
#define NM_DEVICE_TEAM_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "nm-device.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NM_TYPE_DEVICE_TEAM (nm_device_team_get_type ())
|
||||
#define NM_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeam))
|
||||
#define NM_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass))
|
||||
#define NM_IS_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_TEAM))
|
||||
#define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM))
|
||||
#define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass))
|
||||
|
||||
typedef enum {
|
||||
NM_TEAM_ERROR_CONNECTION_NOT_TEAM = 0, /*< nick=ConnectionNotTeam >*/
|
||||
NM_TEAM_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/
|
||||
NM_TEAM_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/
|
||||
} NMTeamError;
|
||||
|
||||
#define NM_DEVICE_TEAM_SLAVES "slaves"
|
||||
|
||||
typedef struct {
|
||||
NMDevice parent;
|
||||
} NMDeviceTeam;
|
||||
|
||||
typedef struct {
|
||||
NMDeviceClass parent;
|
||||
|
||||
} NMDeviceTeamClass;
|
||||
|
||||
|
||||
GType nm_device_team_get_type (void);
|
||||
|
||||
NMDevice *nm_device_team_new (const char *iface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_DEVICE_TEAM_H */
|
|
@ -280,7 +280,7 @@ typedef struct {
|
|||
/* allow autoconnect feature */
|
||||
gboolean autoconnect;
|
||||
|
||||
/* master interface for bridge/bond slave */
|
||||
/* master interface for bridge/bond/team slave */
|
||||
NMDevice * master;
|
||||
gboolean enslaved;
|
||||
|
||||
|
@ -806,16 +806,18 @@ nm_device_get_priority (NMDevice *dev)
|
|||
return 4;
|
||||
case NM_DEVICE_TYPE_BOND:
|
||||
return 5;
|
||||
case NM_DEVICE_TYPE_VLAN:
|
||||
case NM_DEVICE_TYPE_TEAM:
|
||||
return 6;
|
||||
case NM_DEVICE_TYPE_MODEM:
|
||||
case NM_DEVICE_TYPE_VLAN:
|
||||
return 7;
|
||||
case NM_DEVICE_TYPE_BT:
|
||||
case NM_DEVICE_TYPE_MODEM:
|
||||
return 8;
|
||||
case NM_DEVICE_TYPE_WIFI:
|
||||
case NM_DEVICE_TYPE_BT:
|
||||
return 9;
|
||||
case NM_DEVICE_TYPE_OLPC_MESH:
|
||||
case NM_DEVICE_TYPE_WIFI:
|
||||
return 10;
|
||||
case NM_DEVICE_TYPE_OLPC_MESH:
|
||||
return 11;
|
||||
default:
|
||||
return 20;
|
||||
}
|
||||
|
@ -901,8 +903,8 @@ free_slave_info (SlaveInfo *info)
|
|||
* @slave: the slave device to enslave
|
||||
* @connection: the slave device's connection
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
|
||||
* then this function enslaves @slave.
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function enslaves @slave.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
||||
* other devices.
|
||||
|
@ -955,8 +957,8 @@ nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connectio
|
|||
* @slave: the slave device to release
|
||||
* @failed: %TRUE if the release was unexpected, ie the master failed
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
|
||||
* then this function releases the previously enslaved @slave.
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function releases the previously enslaved @slave.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
|
||||
* other devices, or if @slave was never enslaved.
|
||||
|
@ -1050,9 +1052,9 @@ carrier_changed (NMDevice *device, gboolean carrier)
|
|||
}
|
||||
|
||||
if (nm_device_is_master (device)) {
|
||||
/* Bridge/bond carrier does not affect its own activation, but
|
||||
* when carrier comes on, if there are slaves waiting, it will
|
||||
* restart them.
|
||||
/* Bridge/bond/team carrier does not affect its own activation,
|
||||
* but when carrier comes on, if there are slaves waiting,
|
||||
* it will restart them.
|
||||
*/
|
||||
if (!carrier)
|
||||
return;
|
||||
|
@ -1064,8 +1066,9 @@ carrier_changed (NMDevice *device, gboolean carrier)
|
|||
|
||||
return;
|
||||
} else if (nm_device_get_enslaved (device) && !carrier) {
|
||||
/* Slaves don't deactivate when they lose carrier; for bonds
|
||||
* in particular that would be actively counterproductive.
|
||||
/* Slaves don't deactivate when they lose carrier; for
|
||||
* bonds/teams in particular that would be actively
|
||||
* counterproductive.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
@ -1231,7 +1234,7 @@ slave_state_changed (NMDevice *slave,
|
|||
|
||||
if (release) {
|
||||
nm_device_release_one_slave (self, slave, FALSE);
|
||||
/* Bridge/bond interfaces are left up until manually deactivated */
|
||||
/* Bridge/bond/team interfaces are left up until manually deactivated */
|
||||
if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): last slave removed; remaining activated",
|
||||
nm_device_get_iface (self));
|
||||
|
@ -1244,8 +1247,8 @@ slave_state_changed (NMDevice *slave,
|
|||
* @dev: the master device
|
||||
* @slave: the slave device to enslave
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
|
||||
* then this function adds @slave to the slave list for later enslavement.
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function adds @slave to the slave list for later enslavement.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure
|
||||
*/
|
||||
|
@ -1316,7 +1319,7 @@ nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex)
|
|||
* nm_device_is_master:
|
||||
* @dev: the device
|
||||
*
|
||||
* Returns: whether @dev can enslave other devices (eg, bridge or bond)
|
||||
* Returns: whether @dev can enslave other devices (eg, bridge or bond or team)
|
||||
*/
|
||||
gboolean
|
||||
nm_device_is_master (NMDevice *dev)
|
||||
|
@ -1405,7 +1408,7 @@ nm_device_slave_notify_enslaved (NMDevice *dev,
|
|||
* @device: the #NMDevice
|
||||
*
|
||||
* Returns: %TRUE if the device is enslaved to a master device (eg bridge or
|
||||
* bond), %FALSE if not
|
||||
* bond or team), %FALSE if not
|
||||
*/
|
||||
gboolean
|
||||
nm_device_get_enslaved (NMDevice *device)
|
||||
|
|
|
@ -49,7 +49,7 @@ nm_log_handler (const gchar *log_domain,
|
|||
LOGD_SUPPLICANT | LOGD_AGENTS | LOGD_SETTINGS | LOGD_SUSPEND | \
|
||||
LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | LOGD_WIMAX | \
|
||||
LOGD_INFINIBAND | LOGD_FIREWALL | LOGD_ADSL | LOGD_BOND | \
|
||||
LOGD_VLAN | LOGD_BRIDGE | LOGD_DBUS_PROPS)
|
||||
LOGD_VLAN | LOGD_BRIDGE | LOGD_DBUS_PROPS | LOGD_TEAM)
|
||||
|
||||
#define LOGD_DEFAULT (LOGD_ALL & ~(LOGD_WIFI_SCAN | LOGD_DBUS_PROPS))
|
||||
|
||||
|
@ -103,6 +103,7 @@ static const LogDesc domain_descs[] = {
|
|||
{ LOGD_VLAN, "VLAN" },
|
||||
{ LOGD_BRIDGE, "BRIDGE" },
|
||||
{ LOGD_DBUS_PROPS,"DBUS_PROPS" },
|
||||
{ LOGD_TEAM, "TEAM" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ enum {
|
|||
LOGD_VLAN = 0x10000000,
|
||||
LOGD_BRIDGE = 0x20000000,
|
||||
LOGD_DBUS_PROPS = 0x40000000,
|
||||
LOGD_TEAM = 0x80000000,
|
||||
};
|
||||
|
||||
#define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6)
|
||||
|
|
|
@ -360,8 +360,8 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
|||
* existing connection made before this instance of NM started
|
||||
* @device: the device/interface to configure according to @connection
|
||||
* @master: if the activation depends on another device (ie, bond or bridge
|
||||
* master to which this device will be enslaved) pass the #NMDevice that this
|
||||
* activation request be enslaved to
|
||||
* or team master to which this device will be enslaved) pass the #NMDevice
|
||||
* that this activation request be enslaved to
|
||||
*
|
||||
* Begins activation of @device using the given @connection and other details.
|
||||
*
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nm-device-modem.h"
|
||||
#include "nm-device-infiniband.h"
|
||||
#include "nm-device-bond.h"
|
||||
#include "nm-device-team.h"
|
||||
#include "nm-device-bridge.h"
|
||||
#include "nm-device-vlan.h"
|
||||
#include "nm-device-adsl.h"
|
||||
|
@ -1102,6 +1103,9 @@ get_virtual_iface_name (NMManager *self,
|
|||
if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
|
||||
return g_strdup (nm_connection_get_virtual_iface_name (connection));
|
||||
|
||||
if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
|
||||
return g_strdup (nm_connection_get_virtual_iface_name (connection));
|
||||
|
||||
if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
|
||||
return g_strdup (nm_connection_get_virtual_iface_name (connection));
|
||||
|
||||
|
@ -1172,6 +1176,7 @@ static gboolean
|
|||
connection_needs_virtual_device (NMConnection *connection)
|
||||
{
|
||||
if ( nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
|
||||
|| nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
|
||||
|| nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)
|
||||
|| nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME))
|
||||
return TRUE;
|
||||
|
@ -1328,6 +1333,14 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
|
|||
}
|
||||
|
||||
device = nm_device_bond_new (iface);
|
||||
} else if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) {
|
||||
if (!nm_platform_team_add (iface)) {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): failed to add team master interface for '%s'",
|
||||
iface, nm_connection_get_id (connection));
|
||||
goto out;
|
||||
}
|
||||
|
||||
device = nm_device_team_new (iface);
|
||||
} else if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) {
|
||||
gboolean result;
|
||||
|
||||
|
@ -2305,6 +2318,9 @@ platform_link_added_cb (NMPlatform *platform,
|
|||
case NM_LINK_TYPE_BOND:
|
||||
device = nm_device_bond_new (link->name);
|
||||
break;
|
||||
case NM_LINK_TYPE_TEAM:
|
||||
device = nm_device_team_new (link->name);
|
||||
break;
|
||||
case NM_LINK_TYPE_BRIDGE:
|
||||
/* FIXME: always create device when we handle bridges non-destructively */
|
||||
if (bridge_created_by_nm (self, link->name))
|
||||
|
@ -2700,7 +2716,9 @@ ensure_master_active_connection (NMManager *self,
|
|||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMConnection *candidate = NM_CONNECTION (iter->data);
|
||||
|
||||
/* Ensure eg bond slave and the candidate master is a bond master */
|
||||
/* Ensure eg bond/team slave and the candidate master is a
|
||||
* bond/team master
|
||||
*/
|
||||
if (!is_compatible_with_slave (candidate, connection))
|
||||
continue;
|
||||
|
||||
|
@ -2915,10 +2933,11 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
/* Virtual connections (VLAN, bond, etc) may not specify a device
|
||||
* path because the device may not be created yet, or it be given
|
||||
* by the connection's properties instead. Find the device the
|
||||
* connection refers to, or create it if needed.
|
||||
/* Virtual connections (VLAN, bond, team, etc) may not specify
|
||||
* a device path because the device may not be created yet,
|
||||
* or it be given by the connection's properties instead.
|
||||
* Find the device the connection refers to, or create it
|
||||
* if needed.
|
||||
*/
|
||||
if (!connection_needs_virtual_device (connection)) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||
|
@ -2996,7 +3015,9 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
nm_device_get_ip_iface (master_device));
|
||||
}
|
||||
|
||||
/* Ensure eg bond slave and the candidate master is a bond master */
|
||||
/* Ensure eg bond/team slave and the candidate master is
|
||||
* a bond/team master
|
||||
*/
|
||||
if (master_connection && !is_compatible_with_slave (master_connection, connection)) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
|
||||
"The master connection was not compatible");
|
||||
|
|
Loading…
Reference in a new issue