mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 20:40:21 +01:00
core: move slave handling to device subclasses
Let the master control how the slave gets enslaved and released since that's dependent on the virtual interface type of the master.
This commit is contained in:
parent
58227d0136
commit
9146d4e8c6
7 changed files with 278 additions and 140 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include "nm-device-private.h"
|
||||
#include "nm-netlink-monitor.h"
|
||||
#include "nm-enum-types.h"
|
||||
#include "nm-system.h"
|
||||
|
||||
#include "nm-device-bond-glue.h"
|
||||
|
||||
|
|
@ -44,7 +45,8 @@ G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE_WIRED)
|
|||
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
int dummy;
|
||||
gboolean disposed;
|
||||
GSList *slaves;
|
||||
} NMDeviceBondPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -291,6 +293,122 @@ connection_match_config (NMDevice *self, const GSList *connections)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
slave_state_changed (NMDevice *slave,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND (user_data);
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): slave %s state change %d -> %d",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
nm_device_get_iface (slave),
|
||||
old_state,
|
||||
new_state);
|
||||
|
||||
if ( old_state > NM_DEVICE_STATE_DISCONNECTED
|
||||
&& new_state <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
/* Slave is no longer available or managed; can't use it */
|
||||
nm_device_release_slave (NM_DEVICE (self), slave);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NMDevice *slave;
|
||||
guint state_id;
|
||||
} SlaveInfo;
|
||||
|
||||
static SlaveInfo *
|
||||
find_slave_info_by_device (NMDeviceBond *self, NMDevice *slave)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
|
||||
for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
|
||||
if (((SlaveInfo *) iter->data)->slave == slave)
|
||||
return iter->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
free_slave_info (SlaveInfo *sinfo)
|
||||
{
|
||||
g_return_if_fail (sinfo != NULL);
|
||||
g_return_if_fail (sinfo->slave != NULL);
|
||||
|
||||
g_signal_handler_disconnect (sinfo->slave, sinfo->state_id);
|
||||
g_object_unref (sinfo->slave);
|
||||
memset (sinfo, 0, sizeof (*sinfo));
|
||||
g_free (sinfo);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave (NMDevice *device, NMDevice *slave)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND (device);
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
||||
gboolean success, no_firmware = FALSE;
|
||||
|
||||
if (find_slave_info_by_device (self, slave))
|
||||
return TRUE;
|
||||
|
||||
nm_device_hw_take_down (slave, TRUE);
|
||||
|
||||
success = nm_system_iface_enslave (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_ifindex (slave),
|
||||
nm_device_get_ip_iface (slave));
|
||||
if (success) {
|
||||
SlaveInfo *sinfo;
|
||||
|
||||
sinfo = g_malloc0 (sizeof (*slave));
|
||||
sinfo->slave = g_object_ref (slave);
|
||||
sinfo->state_id = g_signal_connect (slave,
|
||||
"state-changed",
|
||||
(GCallback) slave_state_changed,
|
||||
self);
|
||||
priv->slaves = g_slist_append (priv->slaves, sinfo);
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): enslaved bond slave %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
|
||||
nm_device_hw_bring_up (slave, TRUE, &no_firmware);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
release_slave (NMDevice *device, NMDevice *slave)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND (device);
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
||||
gboolean success;
|
||||
SlaveInfo *sinfo;
|
||||
|
||||
sinfo = find_slave_info_by_device (self, slave);
|
||||
if (!sinfo)
|
||||
return FALSE;
|
||||
|
||||
success = nm_system_iface_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_ifindex (slave),
|
||||
nm_device_get_ip_iface (slave));
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): released bond slave %s (success %d)",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave),
|
||||
success);
|
||||
priv->slaves = g_slist_remove (priv->slaves, sinfo);
|
||||
free_slave_info (sinfo);
|
||||
return success;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMDevice *
|
||||
nm_device_bond_new (const char *udi, const char *iface)
|
||||
{
|
||||
|
|
@ -353,6 +471,24 @@ set_property (GObject *object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND (object);
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
|
||||
if (priv->disposed) {
|
||||
G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object);
|
||||
return;
|
||||
}
|
||||
priv->disposed = TRUE;
|
||||
|
||||
for (iter = priv->slaves; iter; iter = g_slist_next (iter))
|
||||
release_slave (NM_DEVICE (self), ((SlaveInfo *) iter->data)->slave);
|
||||
g_slist_free (priv->slaves);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_device_bond_class_init (NMDeviceBondClass *klass)
|
||||
{
|
||||
|
|
@ -365,6 +501,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||
object_class->constructed = constructed;
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
object_class->dispose = dispose;
|
||||
|
||||
parent_class->get_generic_capabilities = real_get_generic_capabilities;
|
||||
parent_class->update_hw_address = real_update_hw_address;
|
||||
|
|
@ -375,6 +512,9 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||
parent_class->spec_match_list = spec_match_list;
|
||||
parent_class->connection_match_config = connection_match_config;
|
||||
|
||||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
/* properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_HW_ADDRESS,
|
||||
|
|
|
|||
|
|
@ -1055,16 +1055,19 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
req = nm_device_get_act_request (NM_DEVICE (self));
|
||||
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||
req = nm_device_get_act_request (NM_DEVICE (self));
|
||||
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
s_wired = NM_SETTING_WIRED (device_get_setting (dev, NM_TYPE_SETTING_WIRED));
|
||||
g_assert (s_wired);
|
||||
s_wired = NM_SETTING_WIRED (device_get_setting (dev, NM_TYPE_SETTING_WIRED));
|
||||
g_assert (s_wired);
|
||||
|
||||
/* Set device MAC address if the connection wants to change it */
|
||||
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
|
||||
if (cloned_mac && (cloned_mac->len == ETH_ALEN))
|
||||
_set_hw_addr (self, (const guint8 *) cloned_mac->data, "set");
|
||||
/* Set device MAC address if the connection wants to change it */
|
||||
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
|
||||
if (cloned_mac && (cloned_mac->len == ETH_ALEN))
|
||||
_set_hw_addr (self, (const guint8 *) cloned_mac->data, "set");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
return NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
129
src/nm-device.c
129
src/nm-device.c
|
|
@ -617,6 +617,51 @@ nm_device_set_master (NMDevice *self, NMDevice *master)
|
|||
g_object_notify (G_OBJECT (priv->act_request), NM_ACTIVE_CONNECTION_MASTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_enslave_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 enslaves @slave.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
||||
* other devices.
|
||||
*/
|
||||
gboolean
|
||||
nm_device_enslave_slave (NMDevice *dev, NMDevice *slave)
|
||||
{
|
||||
g_return_val_if_fail (dev != NULL, FALSE);
|
||||
g_return_val_if_fail (slave != NULL, FALSE);
|
||||
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
|
||||
if (NM_DEVICE_GET_CLASS (dev)->enslave_slave)
|
||||
return NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_release_slave:
|
||||
* @dev: the master device
|
||||
* @slave: the slave device to release
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, 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.
|
||||
*/
|
||||
gboolean
|
||||
nm_device_release_slave (NMDevice *dev, NMDevice *slave)
|
||||
{
|
||||
g_return_val_if_fail (dev != NULL, FALSE);
|
||||
g_return_val_if_fail (slave != NULL, FALSE);
|
||||
|
||||
if (NM_DEVICE_GET_CLASS (dev)->release_slave)
|
||||
return NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* nm_device_get_act_request
|
||||
*
|
||||
|
|
@ -914,68 +959,26 @@ ip6_method_matches (NMConnection *connection, const char *match)
|
|||
static NMActStageReturn
|
||||
real_act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
|
||||
{
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
NMActRequest *req;
|
||||
NMActiveConnection *master_ac;
|
||||
NMDevice *master;
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
||||
static gboolean
|
||||
handle_slave_activation (NMDevice *slave, NMDevice *master)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
req = nm_device_get_act_request (self);
|
||||
g_assert (req);
|
||||
|
||||
connection = nm_device_get_connection (slave);
|
||||
g_assert (connection);
|
||||
/* If the interface is going to be a slave, let the master enslave it here */
|
||||
master_ac = nm_act_request_get_dependency (req);
|
||||
if (master_ac && NM_IS_ACT_REQUEST (master_ac)) {
|
||||
/* FIXME: handle VPNs here too */
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
|
||||
if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) {
|
||||
/*
|
||||
* Bonding
|
||||
*
|
||||
* Kernel expects slaves to be down while the enslaving is
|
||||
* taking place.
|
||||
*/
|
||||
nm_device_hw_take_down (slave, TRUE);
|
||||
|
||||
if (!nm_system_iface_enslave (slave, master))
|
||||
return FALSE;
|
||||
|
||||
nm_device_hw_bring_up (slave, TRUE, NULL);
|
||||
} else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_VLAN_SETTING_NAME)) {
|
||||
/* NOP */
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): Unable to enslave. Unknown slave type '%s'",
|
||||
nm_device_get_iface (slave), nm_setting_connection_get_slave_type (s_con));
|
||||
|
||||
/* Abort activation */
|
||||
return FALSE;
|
||||
master = NM_DEVICE (nm_act_request_get_device (NM_ACT_REQUEST (master_ac)));
|
||||
g_assert (master);
|
||||
if (!nm_device_enslave_slave (master, self))
|
||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
|
||||
nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) enslaved to %s",
|
||||
nm_device_get_iface (slave),
|
||||
nm_device_get_iface (master));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_slave_deactivation (NMDevice *slave, NMDevice *master)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
|
||||
connection = nm_device_get_connection (slave);
|
||||
g_assert (connection);
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
|
||||
if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) {
|
||||
nm_system_iface_release (slave, master);
|
||||
nm_log_info (LOGD_DEVICE, "Device %s released from master %s",
|
||||
nm_device_get_iface (slave), nm_device_get_iface (master));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -992,7 +995,6 @@ nm_device_activate_stage1_device_prepare (gpointer user_data)
|
|||
const char *iface;
|
||||
NMActStageReturn ret;
|
||||
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
|
||||
NMDevice *master;
|
||||
|
||||
/* Clear the activation source ID now that this stage has run */
|
||||
activation_source_clear (self, FALSE, 0);
|
||||
|
|
@ -1008,13 +1010,6 @@ nm_device_activate_stage1_device_prepare (gpointer user_data)
|
|||
nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
||||
|
||||
if ((master = nm_device_get_master (self))) {
|
||||
if (!handle_slave_activation (self, master)) {
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason);
|
||||
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
|
||||
goto out;
|
||||
|
|
@ -3071,7 +3066,6 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
||||
NMDevice *master;
|
||||
NMConnection *connection = NULL;
|
||||
NMSettingConnection *s_con = NULL;
|
||||
gboolean tried_ipv6 = FALSE;
|
||||
|
|
@ -3141,9 +3135,6 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|||
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
||||
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
||||
|
||||
if ((master = nm_device_get_master (self)))
|
||||
handle_slave_deactivation (self, master);
|
||||
|
||||
/* Tear down an existing activation request */
|
||||
clear_act_request (self);
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,12 @@ typedef struct {
|
|||
const guint8 *other_hwaddr,
|
||||
guint other_hwaddr_len,
|
||||
gboolean fail_if_no_hwaddr);
|
||||
|
||||
gboolean (* enslave_slave) (NMDevice *self,
|
||||
NMDevice *slave);
|
||||
|
||||
gboolean (* release_slave) (NMDevice *self,
|
||||
NMDevice *slave);
|
||||
} NMDeviceClass;
|
||||
|
||||
|
||||
|
|
@ -189,6 +195,9 @@ NMDevice * nm_device_get_master (NMDevice *self);
|
|||
const char *nm_device_get_master_path (NMDevice *self);
|
||||
void nm_device_set_master (NMDevice *self, NMDevice *master);
|
||||
|
||||
gboolean nm_device_enslave_slave (NMDevice *dev, NMDevice *slave);
|
||||
gboolean nm_device_release_slave (NMDevice *dev, NMDevice *slave);
|
||||
|
||||
NMActRequest * nm_device_get_act_request (NMDevice *dev);
|
||||
NMConnection * nm_device_get_connection (NMDevice *dev);
|
||||
|
||||
|
|
|
|||
106
src/nm-system.c
106
src/nm-system.c
|
|
@ -1309,7 +1309,7 @@ nm_system_add_bonding_master (const char *iface)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
nm_system_iface_compat_enslave (NMDevice *slave, const char *master_name)
|
||||
nm_system_iface_compat_enslave (const char *master_iface, const char *slave_iface)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
|
|
@ -1323,20 +1323,16 @@ nm_system_iface_compat_enslave (NMDevice *slave, const char *master_name)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
strncpy (ifr.ifr_name, master_name, IFNAMSIZ);
|
||||
strncpy (ifr.ifr_slave, nm_device_get_iface (slave), IFNAMSIZ);
|
||||
strncpy (ifr.ifr_name, master_iface, IFNAMSIZ);
|
||||
strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ);
|
||||
|
||||
if (ioctl (fd, SIOCBONDENSLAVE, &ifr) < 0 &&
|
||||
ioctl (fd, BOND_ENSLAVE_OLD, &ifr) < 0) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)",
|
||||
master_name, nm_device_get_iface (slave),
|
||||
errno, strerror (errno));
|
||||
goto errout;
|
||||
}
|
||||
master_iface, slave_iface, errno, strerror (errno));
|
||||
} else
|
||||
ret = TRUE;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
errout:
|
||||
close (fd);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1344,58 +1340,56 @@ errout:
|
|||
|
||||
/**
|
||||
* nm_system_iface_enslave:
|
||||
* @slave: Slave device
|
||||
* @master: Master device
|
||||
* @master_ifindex: master device interface index
|
||||
* @master_iface: master device interface name
|
||||
* @slave_ifindex: slave device interface index
|
||||
* @slave_iface: slave device interface name
|
||||
*
|
||||
* Enslaves the 'slave' to 'master. This function targets implementing a
|
||||
* generic interface to attaching all kinds of slaves to masters. Currently
|
||||
* only bonding is properly supported due to the backwards compatibility
|
||||
* function being bonding specific.
|
||||
*
|
||||
* The slave device needs to be down as a prerequirement.
|
||||
* The slave device needs to be down as a prerequisite.
|
||||
*
|
||||
* Returns: %TRUE on success, or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
nm_system_iface_enslave (NMDevice *slave, NMDevice *master)
|
||||
nm_system_iface_enslave (gint master_ifindex,
|
||||
const char *master_iface,
|
||||
gint slave_ifindex,
|
||||
const char *slave_iface)
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
const char *master_name;
|
||||
int err, master_ifindex, slave_ifindex;
|
||||
int err;
|
||||
|
||||
master_name = nm_device_get_iface (master);
|
||||
if (!master_name)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (master_ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (master_iface != NULL, FALSE);
|
||||
g_return_val_if_fail (slave_ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (slave_iface != NULL, FALSE);
|
||||
|
||||
sock = nm_netlink_get_default_handle ();
|
||||
|
||||
master_ifindex = nm_netlink_iface_to_index (master_name);
|
||||
g_assert (master_ifindex > 0);
|
||||
|
||||
if (!(nm_system_iface_get_flags (master_ifindex) & IFF_MASTER)) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): interface is not a master", master_name);
|
||||
nm_log_err (LOGD_DEVICE, "(%s): interface is not a master", master_iface);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
slave_ifindex = nm_device_get_ifindex (slave);
|
||||
g_assert (slave_ifindex > 0);
|
||||
|
||||
g_assert (!nm_system_iface_is_up (slave_ifindex));
|
||||
|
||||
if (nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): %s is already a slave",
|
||||
master_name, nm_device_get_iface (slave));
|
||||
master_iface, slave_iface);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = rtnl_link_bond_enslave_ifindex (sock, master_ifindex, slave_ifindex);
|
||||
if (err == -NLE_OPNOTSUPP)
|
||||
return nm_system_iface_compat_enslave (slave, master_name);
|
||||
return nm_system_iface_compat_enslave (master_iface, slave_iface);
|
||||
|
||||
if (err < 0) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)",
|
||||
master_name, nm_device_get_iface (slave),
|
||||
err, nl_geterror (err));
|
||||
master_iface, slave_iface, err, nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1403,7 +1397,7 @@ nm_system_iface_enslave (NMDevice *slave, NMDevice *master)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
nm_system_iface_compat_release (NMDevice *device, const char *master_name)
|
||||
nm_system_iface_compat_release (const char *master_iface, const char *slave_iface)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
|
|
@ -1417,29 +1411,26 @@ nm_system_iface_compat_release (NMDevice *device, const char *master_name)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
strncpy (ifr.ifr_name, master_name, IFNAMSIZ);
|
||||
strncpy (ifr.ifr_slave, nm_device_get_iface (device), IFNAMSIZ);
|
||||
strncpy (ifr.ifr_name, master_iface, IFNAMSIZ);
|
||||
strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ);
|
||||
|
||||
if (ioctl (fd, SIOCBONDRELEASE, &ifr) < 0 &&
|
||||
ioctl (fd, BOND_RELEASE_OLD, &ifr) < 0) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)",
|
||||
master_name, nm_device_get_iface (device),
|
||||
errno, strerror (errno));
|
||||
goto errout;
|
||||
}
|
||||
master_iface, slave_iface, errno, strerror (errno));
|
||||
} else
|
||||
ret = TRUE;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
errout:
|
||||
close (fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_system_iface_release:
|
||||
* @slave: Slave device
|
||||
* @maser: Master device
|
||||
* @master_ifindex: master device interface index
|
||||
* @master_iface: master device interface name
|
||||
* @slave_ifindex: slave device interface index
|
||||
* @slave_iface: slave device interface name
|
||||
*
|
||||
* Releases the 'slave' which is attached to 'master. This function targets
|
||||
* implementing a generic interface to releasing all kinds of slaves. Currently
|
||||
|
|
@ -1449,37 +1440,34 @@ errout:
|
|||
* Returns: %TRUE on success, or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
nm_system_iface_release (NMDevice *slave, NMDevice *master)
|
||||
nm_system_iface_release (gint master_ifindex,
|
||||
const char *master_iface,
|
||||
gint slave_ifindex,
|
||||
const char *slave_iface)
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
const char *master_name;
|
||||
int err, slave_ifindex;
|
||||
int err;
|
||||
|
||||
master_name = nm_device_get_iface (master);
|
||||
if (!master_name)
|
||||
return TRUE;
|
||||
g_return_val_if_fail (master_ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (master_iface != NULL, FALSE);
|
||||
g_return_val_if_fail (slave_ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (slave_iface != NULL, FALSE);
|
||||
|
||||
sock = nm_netlink_get_default_handle ();
|
||||
|
||||
slave_ifindex = nm_device_get_ifindex (slave);
|
||||
g_assert (slave_ifindex > 0);
|
||||
|
||||
/* Only release if this is actually a slave */
|
||||
if (!(nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE))
|
||||
goto out;
|
||||
return TRUE;
|
||||
|
||||
err = rtnl_link_bond_release_ifindex (sock, slave_ifindex);
|
||||
if (err == -NLE_OPNOTSUPP)
|
||||
return nm_system_iface_compat_release (slave, master_name);
|
||||
|
||||
if (err < 0) {
|
||||
return nm_system_iface_compat_release (master_iface, slave_iface);
|
||||
else if (err < 0) {
|
||||
nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)",
|
||||
master_name, nm_device_get_iface (slave),
|
||||
err, nl_geterror (err));
|
||||
master_iface, slave_iface, err, nl_geterror (err));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,15 @@ gboolean nm_system_iface_set_mac (int ifindex, const struct eth
|
|||
|
||||
gboolean nm_system_apply_bonding_config (NMSettingBond *s_bond);
|
||||
gboolean nm_system_add_bonding_master (const char *iface);
|
||||
gboolean nm_system_iface_enslave (NMDevice *slave, NMDevice *master);
|
||||
gboolean nm_system_iface_release (NMDevice *slave, NMDevice *master);
|
||||
|
||||
gboolean nm_system_iface_enslave (gint master_ifindex,
|
||||
const char *master_iface,
|
||||
gint slave_ifindex,
|
||||
const char *slave_iface);
|
||||
gboolean nm_system_iface_release (gint master_ifindex,
|
||||
const char *master_iface,
|
||||
gint slave_ifindex,
|
||||
const char *slave_iface);
|
||||
|
||||
enum {
|
||||
NM_IFACE_TYPE_UNSPEC = 0,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue