2012-02-15 17:31:37 -06:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2011 - 2012 Red Hat, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
|
|
|
|
|
|
#include <netinet/ether.h>
|
|
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
#include "gsystem-local-alloc.h"
|
2012-02-15 17:31:37 -06:00
|
|
|
#include "nm-device-bond.h"
|
|
|
|
|
#include "nm-logging.h"
|
|
|
|
|
#include "nm-utils.h"
|
|
|
|
|
#include "NetworkManagerUtils.h"
|
|
|
|
|
#include "nm-device-private.h"
|
2013-01-21 15:12:24 +01:00
|
|
|
#include "nm-platform.h"
|
2012-10-17 16:10:03 -04:00
|
|
|
#include "nm-dbus-glib-types.h"
|
2013-05-07 12:18:41 -04:00
|
|
|
#include "nm-dbus-manager.h"
|
2012-02-15 17:31:37 -06:00
|
|
|
#include "nm-enum-types.h"
|
|
|
|
|
|
|
|
|
|
#include "nm-device-bond-glue.h"
|
|
|
|
|
|
|
|
|
|
|
2013-05-07 16:18:19 -04:00
|
|
|
G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE)
|
2012-02-15 17:31:37 -06:00
|
|
|
|
|
|
|
|
#define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate))
|
|
|
|
|
|
|
|
|
|
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2013-05-01 09:28:16 -04:00
|
|
|
int dummy;
|
2012-02-15 17:31:37 -06:00
|
|
|
} NMDeviceBondPrivate;
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
PROP_0,
|
2012-10-17 16:10:03 -04:00
|
|
|
PROP_SLAVES,
|
2012-02-15 17:31:37 -06:00
|
|
|
|
|
|
|
|
LAST_PROP
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
|
|
|
|
static GQuark
|
|
|
|
|
nm_bond_error_quark (void)
|
|
|
|
|
{
|
|
|
|
|
static GQuark quark = 0;
|
|
|
|
|
if (!quark)
|
|
|
|
|
quark = g_quark_from_static_string ("nm-bond-error");
|
|
|
|
|
return quark;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
|
|
|
|
static guint32
|
2012-09-27 12:12:15 -04:00
|
|
|
get_generic_capabilities (NMDevice *dev)
|
2012-02-15 17:31:37 -06:00
|
|
|
{
|
2013-05-17 10:58:38 -05:00
|
|
|
return NM_DEVICE_CAP_CARRIER_DETECT;
|
2012-02-15 17:31:37 -06:00
|
|
|
}
|
|
|
|
|
|
2013-01-21 18:16:32 -06:00
|
|
|
static gboolean
|
2013-03-19 09:17:41 -04:00
|
|
|
is_available (NMDevice *dev)
|
2013-01-21 18:16:32 -06:00
|
|
|
{
|
2013-06-13 15:13:58 -05:00
|
|
|
if (NM_DEVICE_GET_CLASS (dev)->is_up)
|
|
|
|
|
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
|
2013-01-21 18:16:32 -06:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 17:31:37 -06:00
|
|
|
static gboolean
|
2013-03-06 16:16:54 -05:00
|
|
|
check_connection_compatible (NMDevice *device,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
GError **error)
|
2012-02-15 17:31:37 -06:00
|
|
|
{
|
|
|
|
|
const char *iface;
|
|
|
|
|
NMSettingBond *s_bond;
|
|
|
|
|
|
2013-03-07 07:44:36 -05:00
|
|
|
if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-02-15 17:31:37 -06:00
|
|
|
s_bond = nm_connection_get_setting_bond (connection);
|
|
|
|
|
if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) {
|
|
|
|
|
g_set_error (error, NM_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND,
|
|
|
|
|
"The connection was not a bond connection.");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Bond 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_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND,
|
|
|
|
|
"The bond connection virtual interface name did not match.");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: match bond properties like mode, etc? */
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2012-09-27 12:12:15 -04:00
|
|
|
complete_connection (NMDevice *device,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
const char *specific_object,
|
|
|
|
|
const GSList *existing_connections,
|
|
|
|
|
GError **error)
|
2012-02-15 17:31:37 -06:00
|
|
|
{
|
|
|
|
|
NMSettingBond *s_bond, *tmp;
|
|
|
|
|
guint32 i = 0;
|
|
|
|
|
char *name;
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
gboolean found;
|
|
|
|
|
|
|
|
|
|
nm_utils_complete_generic (connection,
|
|
|
|
|
NM_SETTING_BOND_SETTING_NAME,
|
|
|
|
|
existing_connections,
|
|
|
|
|
_("Bond connection %d"),
|
|
|
|
|
NULL,
|
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
|
|
s_bond = nm_connection_get_setting_bond (connection);
|
|
|
|
|
if (!s_bond) {
|
|
|
|
|
s_bond = (NMSettingBond *) nm_setting_bond_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_bond));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Grab the first name that doesn't exist in either our connections
|
|
|
|
|
* or a device on the system.
|
|
|
|
|
*/
|
|
|
|
|
while (i < 500 && !nm_setting_bond_get_interface_name (s_bond)) {
|
|
|
|
|
name = g_strdup_printf ("bond%u", i);
|
|
|
|
|
/* check interface names */
|
2013-01-21 15:12:24 +01:00
|
|
|
if (!nm_platform_link_exists (name)) {
|
2012-02-15 17:31:37 -06:00
|
|
|
/* check existing bond connections */
|
|
|
|
|
for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
NMConnection *candidate = iter->data;
|
|
|
|
|
|
|
|
|
|
tmp = nm_connection_get_setting_bond (candidate);
|
|
|
|
|
if (tmp && nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) {
|
|
|
|
|
if (g_strcmp0 (nm_setting_bond_get_interface_name (tmp), name) == 0) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
|
g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, name, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2013-03-06 14:58:03 -05:00
|
|
|
match_l2_config (NMDevice *self, NMConnection *connection)
|
2012-02-15 17:31:37 -06:00
|
|
|
{
|
2013-03-06 14:58:03 -05:00
|
|
|
/* FIXME */
|
2012-02-15 17:31:37 -06:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
typedef struct {
|
|
|
|
|
const char *name;
|
2013-07-05 16:41:51 +02:00
|
|
|
const char *default_value;
|
2013-08-28 10:38:46 +02:00
|
|
|
} Option;
|
|
|
|
|
|
|
|
|
|
static const Option master_options[] = {
|
2013-07-05 16:41:51 +02:00
|
|
|
{ "mode", "balance-rr" },
|
|
|
|
|
{ "arp_interval", "0" },
|
|
|
|
|
{ "miimon", "0" },
|
|
|
|
|
|
|
|
|
|
{ "ad_select", "stable" },
|
|
|
|
|
{ "arp_validate", "none" },
|
|
|
|
|
{ "downdelay", "0" },
|
|
|
|
|
{ "fail_over_mac", "none" },
|
|
|
|
|
{ "lacp_rate", "slow" },
|
|
|
|
|
{ "min_links", "0" },
|
|
|
|
|
{ "num_grat_arp", "1" },
|
|
|
|
|
{ "num_unsol_na", "1" },
|
|
|
|
|
{ "primary", "" },
|
|
|
|
|
{ "primary_reselect", "always" },
|
|
|
|
|
{ "resend_igmp", "1" },
|
|
|
|
|
{ "updelay", "0" },
|
|
|
|
|
{ "use_carrier", "1" },
|
|
|
|
|
{ "xmit_hash_policy", "layer2" },
|
|
|
|
|
{ NULL, NULL }
|
|
|
|
|
};
|
|
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
static gboolean
|
|
|
|
|
option_valid_for_nm_setting (NMSettingBond *s_bond, const Option *option)
|
|
|
|
|
{
|
|
|
|
|
const char **valid_opts = nm_setting_bond_get_valid_options (s_bond);
|
|
|
|
|
|
|
|
|
|
for (; *valid_opts; valid_opts++)
|
|
|
|
|
if (!strcmp (option->name, *valid_opts))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-05 16:41:51 +02:00
|
|
|
static void
|
2013-08-28 10:38:46 +02:00
|
|
|
remove_bonding_entries (NMDevice *device, const char *option)
|
2013-07-05 16:41:51 +02:00
|
|
|
{
|
2013-08-28 10:38:46 +02:00
|
|
|
int ifindex = nm_device_get_ifindex (device);
|
|
|
|
|
const char *ifname = nm_device_get_iface (device);
|
|
|
|
|
gs_free char *value = nm_platform_master_get_option (ifindex, option);
|
|
|
|
|
char **entries, **entry;
|
2013-07-05 16:41:51 +02:00
|
|
|
char cmd[20];
|
|
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
g_return_if_fail (value);
|
2013-07-05 16:41:51 +02:00
|
|
|
|
|
|
|
|
entries = g_strsplit (value, " ", -1);
|
2013-08-28 10:38:46 +02:00
|
|
|
for (entry = entries; *entry; entry++) {
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (*entry));
|
|
|
|
|
if (!nm_platform_master_set_option (ifindex, option, cmd))
|
2013-07-05 16:41:51 +02:00
|
|
|
nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'",
|
2013-08-28 10:38:46 +02:00
|
|
|
ifname, *entry, option);
|
2013-07-05 16:41:51 +02:00
|
|
|
}
|
|
|
|
|
g_strfreev (entries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2013-08-28 10:38:46 +02:00
|
|
|
apply_bonding_config (NMDevice *device, NMSettingBond *s_bond)
|
2013-07-05 16:41:51 +02:00
|
|
|
{
|
2013-08-28 10:38:46 +02:00
|
|
|
int ifindex = nm_device_get_ifindex (device);
|
|
|
|
|
const char *ifname = nm_device_get_iface (device);
|
|
|
|
|
static const Option *option;
|
|
|
|
|
const char *value;
|
2013-07-05 16:41:51 +02:00
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
g_return_val_if_fail (ifindex, FALSE);
|
2013-07-05 16:41:51 +02:00
|
|
|
|
|
|
|
|
/* Remove old slaves and arp_ip_targets */
|
2013-08-28 10:38:46 +02:00
|
|
|
remove_bonding_entries (device, "arp_ip_target");
|
|
|
|
|
remove_bonding_entries (device, "slaves");
|
2013-07-05 16:41:51 +02:00
|
|
|
|
|
|
|
|
/* Apply config/defaults */
|
2013-08-28 10:38:46 +02:00
|
|
|
for (option = master_options; option->name; option++) {
|
|
|
|
|
gs_free char *old_value = NULL;
|
|
|
|
|
char *space;
|
|
|
|
|
|
|
|
|
|
value = NULL;
|
|
|
|
|
if (option_valid_for_nm_setting (s_bond, option))
|
|
|
|
|
value = nm_setting_bond_get_option_by_name (s_bond, option->name);
|
2013-07-05 16:41:51 +02:00
|
|
|
if (!value)
|
2013-08-28 10:38:46 +02:00
|
|
|
value = option->default_value;
|
|
|
|
|
|
|
|
|
|
old_value = nm_platform_master_get_option (ifindex, option->name);
|
|
|
|
|
/* FIXME: This could be handled in nm-platform. */
|
|
|
|
|
space = strchr (old_value, ' ');
|
|
|
|
|
if (space)
|
|
|
|
|
*space = '\0';
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (value, old_value)) {
|
|
|
|
|
if (!nm_platform_master_set_option (ifindex, option->name, value))
|
|
|
|
|
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
|
|
|
|
"'%s' to '%s'", ifname, option->name, value);
|
2013-07-05 16:41:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handle arp_ip_target */
|
|
|
|
|
value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target");
|
|
|
|
|
if (value) {
|
2013-08-28 10:38:46 +02:00
|
|
|
char **addresses, **address;
|
2013-07-05 16:41:51 +02:00
|
|
|
|
|
|
|
|
addresses = g_strsplit (value, ",", -1);
|
2013-08-28 10:38:46 +02:00
|
|
|
for (address = addresses; *address; address++) {
|
|
|
|
|
char cmd[20];
|
|
|
|
|
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "+%s", g_strstrip (*address));
|
|
|
|
|
if (!nm_platform_master_set_option (ifindex, "arp_ip_target", cmd)){
|
2013-07-05 16:41:51 +02:00
|
|
|
nm_log_warn (LOGD_HW, "(%s): failed to add arp_ip_target '%s'",
|
2013-08-28 10:38:46 +02:00
|
|
|
ifname, *address);
|
2013-07-05 16:41:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_strfreev (addresses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 12:39:57 -06:00
|
|
|
static NMActStageReturn
|
2012-09-27 12:12:15 -04:00
|
|
|
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
2012-02-29 12:39:57 -06:00
|
|
|
{
|
|
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingBond *s_bond;
|
|
|
|
|
gboolean no_firmware = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
|
|
|
|
|
|
|
|
|
ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason);
|
|
|
|
|
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
|
|
|
|
connection = nm_device_get_connection (dev);
|
|
|
|
|
g_assert (connection);
|
|
|
|
|
s_bond = nm_connection_get_setting_bond (connection);
|
|
|
|
|
g_assert (s_bond);
|
|
|
|
|
|
|
|
|
|
/* Interface must be down to set bond options */
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_take_down (dev, TRUE);
|
2012-02-29 12:39:57 -06:00
|
|
|
|
2013-08-28 10:38:46 +02:00
|
|
|
if (!apply_bonding_config (dev, s_bond))
|
2012-02-29 12:39:57 -06:00
|
|
|
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
|
|
|
|
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_bring_up (dev, TRUE, &no_firmware);
|
2012-02-29 12:39:57 -06:00
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-28 18:35:30 -06:00
|
|
|
static gboolean
|
2012-11-04 17:51:34 -06:00
|
|
|
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
2012-02-28 18:35:30 -06:00
|
|
|
{
|
|
|
|
|
gboolean success, no_firmware = FALSE;
|
2012-11-14 14:05:30 -06:00
|
|
|
const char *iface = nm_device_get_ip_iface (device);
|
|
|
|
|
const char *slave_iface = nm_device_get_ip_iface (slave);
|
2012-02-28 18:35:30 -06:00
|
|
|
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_take_down (slave, TRUE);
|
2012-02-28 18:35:30 -06:00
|
|
|
|
2013-01-21 15:12:24 +01:00
|
|
|
success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device),
|
|
|
|
|
nm_device_get_ip_ifindex (slave));
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_bring_up (slave, TRUE, &no_firmware);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2012-02-28 18:35:30 -06:00
|
|
|
if (success) {
|
2012-11-14 14:05:30 -06:00
|
|
|
nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface);
|
2012-10-17 16:10:03 -04:00
|
|
|
g_object_notify (G_OBJECT (device), "slaves");
|
2012-02-28 18:35:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
release_slave (NMDevice *device, NMDevice *slave)
|
|
|
|
|
{
|
2013-01-21 14:33:40 -06:00
|
|
|
gboolean success, no_firmware = FALSE;
|
2012-02-28 18:35:30 -06:00
|
|
|
|
2013-01-21 15:12:24 +01:00
|
|
|
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
|
|
|
|
nm_device_get_ip_ifindex (slave));
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
nm_log_info (LOGD_BOND, "(%s): released bond slave %s (success %d)",
|
|
|
|
|
nm_device_get_ip_iface (device),
|
|
|
|
|
nm_device_get_ip_iface (slave),
|
|
|
|
|
success);
|
2012-10-17 16:10:03 -04:00
|
|
|
g_object_notify (G_OBJECT (device), "slaves");
|
2013-01-21 14:33:40 -06:00
|
|
|
|
|
|
|
|
/* Kernel bonding code "closes" the slave 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 slave.
|
|
|
|
|
*/
|
2013-06-13 15:13:58 -05:00
|
|
|
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
2013-01-21 14:33:40 -06:00
|
|
|
nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.",
|
|
|
|
|
nm_device_get_iface (slave));
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-28 18:35:30 -06:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
2012-02-15 17:31:37 -06:00
|
|
|
NMDevice *
|
2013-09-03 14:23:16 -04:00
|
|
|
nm_device_bond_new (NMPlatformLink *platform_device)
|
2012-02-15 17:31:37 -06:00
|
|
|
{
|
2013-09-03 14:23:16 -04:00
|
|
|
g_return_val_if_fail (platform_device != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
|
|
|
|
|
NM_DEVICE_PLATFORM_DEVICE, platform_device,
|
|
|
|
|
NM_DEVICE_DRIVER, "bonding",
|
|
|
|
|
NM_DEVICE_TYPE_DESC, "Bond",
|
|
|
|
|
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
|
|
|
|
|
NM_DEVICE_IS_MASTER, TRUE,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_device_bond_new_for_connection (NMConnection *connection)
|
|
|
|
|
{
|
|
|
|
|
const char *iface;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (connection != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
iface = nm_connection_get_virtual_iface_name (connection);
|
2012-02-15 17:31:37 -06:00
|
|
|
g_return_val_if_fail (iface != NULL, NULL);
|
|
|
|
|
|
2013-09-03 14:23:16 -04:00
|
|
|
if ( !nm_platform_bond_add (iface)
|
|
|
|
|
&& nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
|
|
|
|
|
nm_log_warn (LOGD_DEVICE | LOGD_BOND, "(%s): failed to create bonding master interface for '%s': %s",
|
|
|
|
|
iface, nm_connection_get_id (connection),
|
|
|
|
|
nm_platform_get_error_msg ());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 17:31:37 -06:00
|
|
|
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
|
|
|
|
|
NM_DEVICE_IFACE, iface,
|
|
|
|
|
NM_DEVICE_DRIVER, "bonding",
|
|
|
|
|
NM_DEVICE_TYPE_DESC, "Bond",
|
|
|
|
|
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
|
2013-01-24 17:47:59 -06:00
|
|
|
NM_DEVICE_IS_MASTER, TRUE,
|
2012-02-15 17:31:37 -06:00
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
constructed (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
G_OBJECT_CLASS (nm_device_bond_parent_class)->constructed (object);
|
|
|
|
|
|
2012-10-31 17:31:38 +01:00
|
|
|
nm_log_dbg (LOGD_HW | LOGD_BOND, "(%s): kernel ifindex %d",
|
2012-02-15 17:31:37 -06:00
|
|
|
nm_device_get_iface (NM_DEVICE (object)),
|
|
|
|
|
nm_device_get_ifindex (NM_DEVICE (object)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_bond_init (NMDeviceBond * self)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_property (GObject *object, guint prop_id,
|
|
|
|
|
GValue *value, GParamSpec *pspec)
|
|
|
|
|
{
|
2012-10-17 16:10:03 -04:00
|
|
|
GPtrArray *slaves;
|
2012-11-14 14:05:30 -06:00
|
|
|
GSList *list, *iter;
|
2012-02-15 17:31:37 -06:00
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
|
break;
|
2012-10-17 16:10:03 -04:00
|
|
|
case PROP_SLAVES:
|
|
|
|
|
slaves = g_ptr_array_new ();
|
2012-11-14 14:05:30 -06:00
|
|
|
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);
|
2012-10-17 16:10:03 -04:00
|
|
|
g_value_take_boxed (value, slaves);
|
|
|
|
|
break;
|
2012-02-15 17:31:37 -06:00
|
|
|
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_bond_class_init (NMDeviceBondClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate));
|
|
|
|
|
|
|
|
|
|
/* virtual methods */
|
|
|
|
|
object_class->constructed = constructed;
|
|
|
|
|
object_class->get_property = get_property;
|
|
|
|
|
object_class->set_property = set_property;
|
|
|
|
|
|
2012-09-27 12:12:15 -04:00
|
|
|
parent_class->get_generic_capabilities = get_generic_capabilities;
|
2013-01-21 18:16:32 -06:00
|
|
|
parent_class->is_available = is_available;
|
2012-09-27 12:12:15 -04:00
|
|
|
parent_class->check_connection_compatible = check_connection_compatible;
|
|
|
|
|
parent_class->complete_connection = complete_connection;
|
2012-02-15 17:31:37 -06:00
|
|
|
|
2013-03-06 14:58:03 -05:00
|
|
|
parent_class->match_l2_config = match_l2_config;
|
2012-02-15 17:31:37 -06:00
|
|
|
|
2012-09-27 12:12:15 -04:00
|
|
|
parent_class->act_stage1_prepare = act_stage1_prepare;
|
2012-02-28 18:35:30 -06:00
|
|
|
parent_class->enslave_slave = enslave_slave;
|
|
|
|
|
parent_class->release_slave = release_slave;
|
|
|
|
|
|
2012-02-15 17:31:37 -06:00
|
|
|
/* properties */
|
2012-10-17 16:10:03 -04:00
|
|
|
g_object_class_install_property
|
|
|
|
|
(object_class, PROP_SLAVES,
|
|
|
|
|
g_param_spec_boxed (NM_DEVICE_BOND_SLAVES,
|
|
|
|
|
"Slaves",
|
|
|
|
|
"Slaves",
|
|
|
|
|
DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
|
|
|
|
|
G_PARAM_READABLE));
|
|
|
|
|
|
2013-05-07 12:18:41 -04:00
|
|
|
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
&dbus_glib_nm_device_bond_object_info);
|
2012-02-15 17:31:37 -06:00
|
|
|
|
|
|
|
|
dbus_g_error_domain_register (NM_BOND_ERROR, NULL, NM_TYPE_BOND_ERROR);
|
|
|
|
|
}
|