core: rework master/slave handling
This commit is contained in:
@@ -62,8 +62,7 @@ typedef struct {
|
|||||||
gulong user_uid;
|
gulong user_uid;
|
||||||
char *dbus_sender;
|
char *dbus_sender;
|
||||||
|
|
||||||
NMActiveConnection *dep;
|
NMDevice *master;
|
||||||
guint dep_state_id;
|
|
||||||
|
|
||||||
gboolean shared;
|
gboolean shared;
|
||||||
GSList *share_rules;
|
GSList *share_rules;
|
||||||
@@ -75,13 +74,6 @@ enum {
|
|||||||
PROP_MASTER = 2000,
|
PROP_MASTER = 2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
DEP_RESULT,
|
|
||||||
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -229,31 +221,10 @@ nm_act_request_get_assumed (NMActRequest *req)
|
|||||||
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
|
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
NMActiveConnection *
|
GObject *
|
||||||
nm_act_request_get_dependency (NMActRequest *req)
|
nm_act_request_get_master (NMActRequest *req)
|
||||||
{
|
{
|
||||||
return NM_ACT_REQUEST_GET_PRIVATE (req)->dep;
|
return (GObject *) NM_ACT_REQUEST_GET_PRIVATE (req)->master;
|
||||||
}
|
|
||||||
|
|
||||||
static NMActRequestDependencyResult
|
|
||||||
ac_state_to_dep_result (NMActiveConnection *ac)
|
|
||||||
{
|
|
||||||
NMActiveConnectionState state = nm_active_connection_get_state (ac);
|
|
||||||
|
|
||||||
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
|
|
||||||
return NM_ACT_REQUEST_DEP_RESULT_WAIT;
|
|
||||||
else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
|
|
||||||
return NM_ACT_REQUEST_DEP_RESULT_READY;
|
|
||||||
|
|
||||||
return NM_ACT_REQUEST_DEP_RESULT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NMActRequestDependencyResult
|
|
||||||
nm_act_request_get_dependency_result (NMActRequest *req)
|
|
||||||
{
|
|
||||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req);
|
|
||||||
|
|
||||||
return priv->dep ? ac_state_to_dep_result (priv->dep) : NM_ACT_REQUEST_DEP_RESULT_READY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
@@ -411,39 +382,6 @@ device_state_changed (NMDevice *device,
|
|||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
||||||
static void
|
|
||||||
dep_gone (NMActRequest *self, GObject *ignored)
|
|
||||||
{
|
|
||||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
|
||||||
|
|
||||||
g_warn_if_fail (G_OBJECT (priv->dep) == ignored);
|
|
||||||
|
|
||||||
/* Dependent connection is gone; clean up and fail */
|
|
||||||
priv->dep = NULL;
|
|
||||||
priv->dep_state_id = 0;
|
|
||||||
g_signal_emit (self, signals[DEP_RESULT], 0, NM_ACT_REQUEST_DEP_RESULT_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dep_state_changed (NMActiveConnection *dep,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
NMActRequest *self)
|
|
||||||
{
|
|
||||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
|
||||||
NMActRequestDependencyResult result;
|
|
||||||
|
|
||||||
g_warn_if_fail (priv->dep == dep);
|
|
||||||
|
|
||||||
result = ac_state_to_dep_result (priv->dep);
|
|
||||||
if (result == NM_ACT_REQUEST_DEP_RESULT_FAILED) {
|
|
||||||
g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, self);
|
|
||||||
g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
|
|
||||||
priv->dep = NULL;
|
|
||||||
priv->dep_state_id = 0;
|
|
||||||
}
|
|
||||||
g_signal_emit (self, signals[DEP_RESULT], 0, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_act_request_new:
|
* nm_act_request_new:
|
||||||
*
|
*
|
||||||
@@ -458,9 +396,9 @@ dep_state_changed (NMActiveConnection *dep,
|
|||||||
* @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
|
* @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
|
||||||
* existing connection made before this instance of NM started
|
* existing connection made before this instance of NM started
|
||||||
* @device: the device/interface to configure according to @connection
|
* @device: the device/interface to configure according to @connection
|
||||||
* @dependency: if the activation depends on another device (ie, VLAN slave,
|
* @master: if the activation depends on another device (ie, bond or bridge
|
||||||
* bond slave, etc) pass the #NMActiveConnection that this activation request
|
* master to which this device will be enslaved) pass the #NMDevice that this
|
||||||
* should wait for before proceeding
|
* activation request be enslaved to
|
||||||
*
|
*
|
||||||
* Begins activation of @device using the given @connection and other details.
|
* Begins activation of @device using the given @connection and other details.
|
||||||
*
|
*
|
||||||
@@ -474,7 +412,7 @@ nm_act_request_new (NMConnection *connection,
|
|||||||
const char *dbus_sender,
|
const char *dbus_sender,
|
||||||
gboolean assumed,
|
gboolean assumed,
|
||||||
gpointer *device,
|
gpointer *device,
|
||||||
NMActiveConnection *dependency)
|
gpointer *master)
|
||||||
{
|
{
|
||||||
GObject *object;
|
GObject *object;
|
||||||
NMActRequestPrivate *priv;
|
NMActRequestPrivate *priv;
|
||||||
@@ -500,14 +438,11 @@ nm_act_request_new (NMConnection *connection,
|
|||||||
priv->user_requested = user_requested;
|
priv->user_requested = user_requested;
|
||||||
priv->dbus_sender = g_strdup (dbus_sender);
|
priv->dbus_sender = g_strdup (dbus_sender);
|
||||||
priv->assumed = assumed;
|
priv->assumed = assumed;
|
||||||
|
if (master) {
|
||||||
|
g_assert (NM_IS_DEVICE (master));
|
||||||
|
g_assert (NM_DEVICE (master) != NM_DEVICE (device));
|
||||||
|
|
||||||
if (dependency) {
|
priv->master = g_object_ref (master);
|
||||||
priv->dep = dependency;
|
|
||||||
g_object_weak_ref (G_OBJECT (dependency), (GWeakNotify) dep_gone, object);
|
|
||||||
priv->dep_state_id = g_signal_connect (dependency,
|
|
||||||
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
|
||||||
G_CALLBACK (dep_state_changed),
|
|
||||||
object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object),
|
if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object),
|
||||||
@@ -530,16 +465,10 @@ get_property (GObject *object, guint prop_id,
|
|||||||
GValue *value, GParamSpec *pspec)
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
|
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
|
||||||
NMDevice *master;
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_MASTER:
|
case PROP_MASTER:
|
||||||
if (priv->dep && NM_IS_ACT_REQUEST (priv->dep)) {
|
g_value_set_boxed (value, priv->master ? nm_device_get_path (priv->master) : "/");
|
||||||
master = NM_DEVICE (nm_act_request_get_device (NM_ACT_REQUEST (priv->dep)));
|
|
||||||
g_assert (master);
|
|
||||||
g_value_set_boxed (value, nm_device_get_path (master));
|
|
||||||
} else
|
|
||||||
g_value_set_boxed (value, "/");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
@@ -580,12 +509,7 @@ dispose (GObject *object)
|
|||||||
|
|
||||||
g_free (priv->dbus_sender);
|
g_free (priv->dbus_sender);
|
||||||
|
|
||||||
if (priv->dep) {
|
g_clear_object (&priv->master);
|
||||||
g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, object);
|
|
||||||
g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
|
|
||||||
priv->dep = NULL;
|
|
||||||
priv->dep_state_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
|
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@@ -611,13 +535,5 @@ nm_act_request_class_init (NMActRequestClass *req_class)
|
|||||||
object_class->finalize = finalize;
|
object_class->finalize = finalize;
|
||||||
|
|
||||||
g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER);
|
g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER);
|
||||||
|
|
||||||
signals[DEP_RESULT] =
|
|
||||||
g_signal_new (NM_ACT_REQUEST_DEPENDENCY_RESULT,
|
|
||||||
G_OBJECT_CLASS_TYPE (object_class),
|
|
||||||
G_SIGNAL_RUN_FIRST,
|
|
||||||
0, NULL, NULL,
|
|
||||||
g_cclosure_marshal_VOID__UINT,
|
|
||||||
G_TYPE_NONE, 1, G_TYPE_UINT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,15 +34,6 @@
|
|||||||
#define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACT_REQUEST))
|
#define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACT_REQUEST))
|
||||||
#define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass))
|
#define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass))
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NM_ACT_REQUEST_DEP_RESULT_UNKNOWN,
|
|
||||||
NM_ACT_REQUEST_DEP_RESULT_WAIT,
|
|
||||||
NM_ACT_REQUEST_DEP_RESULT_READY,
|
|
||||||
NM_ACT_REQUEST_DEP_RESULT_FAILED,
|
|
||||||
} NMActRequestDependencyResult;
|
|
||||||
|
|
||||||
#define NM_ACT_REQUEST_DEPENDENCY_RESULT "dependency-result"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
} NMActRequest;
|
} NMActRequest;
|
||||||
@@ -52,8 +43,6 @@ typedef struct {
|
|||||||
|
|
||||||
/* Signals */
|
/* Signals */
|
||||||
void (*properties_changed) (NMActRequest *req, GHashTable *properties);
|
void (*properties_changed) (NMActRequest *req, GHashTable *properties);
|
||||||
|
|
||||||
void (*dependency_result) (NMActRequest *req, NMActRequestDependencyResult result);
|
|
||||||
} NMActRequestClass;
|
} NMActRequestClass;
|
||||||
|
|
||||||
GType nm_act_request_get_type (void);
|
GType nm_act_request_get_type (void);
|
||||||
@@ -65,7 +54,7 @@ NMActRequest *nm_act_request_new (NMConnection *connection,
|
|||||||
const char *dbus_sender,
|
const char *dbus_sender,
|
||||||
gboolean assumed,
|
gboolean assumed,
|
||||||
gpointer *device, /* An NMDevice */
|
gpointer *device, /* An NMDevice */
|
||||||
NMActiveConnection *dependency);
|
gpointer *master); /* An NMDevice */
|
||||||
|
|
||||||
NMConnection *nm_act_request_get_connection (NMActRequest *req);
|
NMConnection *nm_act_request_get_connection (NMActRequest *req);
|
||||||
|
|
||||||
@@ -87,9 +76,7 @@ GObject * nm_act_request_get_device (NMActRequest *req);
|
|||||||
|
|
||||||
gboolean nm_act_request_get_assumed (NMActRequest *req);
|
gboolean nm_act_request_get_assumed (NMActRequest *req);
|
||||||
|
|
||||||
NMActiveConnection * nm_act_request_get_dependency (NMActRequest *req);
|
GObject * nm_act_request_get_master (NMActRequest *req);
|
||||||
|
|
||||||
NMActRequestDependencyResult nm_act_request_get_dependency_result (NMActRequest *req);
|
|
||||||
|
|
||||||
/* Secrets handling */
|
/* Secrets handling */
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE_WIRED)
|
|||||||
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GSList *slaves;
|
gboolean unused;
|
||||||
} NMDeviceBondPrivate;
|
} NMDeviceBondPrivate;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -321,118 +321,43 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_BOND, "(%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
|
static gboolean
|
||||||
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
||||||
{
|
{
|
||||||
NMDeviceBond *self = NM_DEVICE_BOND (device);
|
|
||||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
|
||||||
gboolean success, no_firmware = FALSE;
|
gboolean success, no_firmware = FALSE;
|
||||||
|
const char *iface = nm_device_get_ip_iface (device);
|
||||||
if (find_slave_info_by_device (self, slave))
|
const char *slave_iface = nm_device_get_ip_iface (slave);
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
nm_device_hw_take_down (slave, TRUE);
|
nm_device_hw_take_down (slave, TRUE);
|
||||||
|
|
||||||
success = nm_system_bond_enslave (nm_device_get_ip_ifindex (device),
|
success = nm_system_bond_enslave (nm_device_get_ip_ifindex (device),
|
||||||
nm_device_get_ip_iface (device),
|
iface,
|
||||||
nm_device_get_ip_ifindex (slave),
|
nm_device_get_ip_ifindex (slave),
|
||||||
nm_device_get_ip_iface (slave));
|
slave_iface);
|
||||||
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_BOND, "(%s): enslaved bond slave %s",
|
|
||||||
nm_device_get_ip_iface (device),
|
|
||||||
nm_device_get_ip_iface (slave));
|
|
||||||
g_object_notify (G_OBJECT (device), "slaves");
|
|
||||||
}
|
|
||||||
|
|
||||||
nm_device_hw_bring_up (slave, TRUE, &no_firmware);
|
nm_device_hw_bring_up (slave, TRUE, &no_firmware);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface);
|
||||||
|
g_object_notify (G_OBJECT (device), "slaves");
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
release_slave (NMDevice *device, NMDevice *slave)
|
release_slave (NMDevice *device, NMDevice *slave)
|
||||||
{
|
{
|
||||||
NMDeviceBond *self = NM_DEVICE_BOND (device);
|
|
||||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
|
||||||
gboolean success;
|
gboolean success;
|
||||||
SlaveInfo *sinfo;
|
|
||||||
|
|
||||||
sinfo = find_slave_info_by_device (self, slave);
|
|
||||||
if (!sinfo)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
success = nm_system_bond_release (nm_device_get_ip_ifindex (device),
|
success = nm_system_bond_release (nm_device_get_ip_ifindex (device),
|
||||||
nm_device_get_ip_iface (device),
|
nm_device_get_ip_iface (device),
|
||||||
nm_device_get_ip_ifindex (slave),
|
nm_device_get_ip_ifindex (slave),
|
||||||
nm_device_get_ip_iface (slave));
|
nm_device_get_ip_iface (slave));
|
||||||
nm_log_dbg (LOGD_BOND, "(%s): released bond slave %s (success %d)",
|
nm_log_info (LOGD_BOND, "(%s): released bond slave %s (success %d)",
|
||||||
nm_device_get_ip_iface (device),
|
nm_device_get_ip_iface (device),
|
||||||
nm_device_get_ip_iface (slave),
|
nm_device_get_ip_iface (slave),
|
||||||
success);
|
success);
|
||||||
priv->slaves = g_slist_remove (priv->slaves, sinfo);
|
|
||||||
free_slave_info (sinfo);
|
|
||||||
g_object_notify (G_OBJECT (device), "slaves");
|
g_object_notify (G_OBJECT (device), "slaves");
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -473,12 +398,9 @@ static void
|
|||||||
get_property (GObject *object, guint prop_id,
|
get_property (GObject *object, guint prop_id,
|
||||||
GValue *value, GParamSpec *pspec)
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
NMDeviceBond *self = NM_DEVICE_BOND (object);
|
|
||||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (self);
|
|
||||||
const guint8 *current_addr;
|
const guint8 *current_addr;
|
||||||
GPtrArray *slaves;
|
GPtrArray *slaves;
|
||||||
GSList *iter;
|
GSList *list, *iter;
|
||||||
SlaveInfo *info;
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_HW_ADDRESS:
|
case PROP_HW_ADDRESS:
|
||||||
@@ -490,10 +412,10 @@ get_property (GObject *object, guint prop_id,
|
|||||||
break;
|
break;
|
||||||
case PROP_SLAVES:
|
case PROP_SLAVES:
|
||||||
slaves = g_ptr_array_new ();
|
slaves = g_ptr_array_new ();
|
||||||
for (iter = priv->slaves; iter; iter = iter->next) {
|
list = nm_device_master_get_slaves (NM_DEVICE (object));
|
||||||
info = iter->data;
|
for (iter = list; iter; iter = iter->next)
|
||||||
g_ptr_array_add (slaves, g_strdup (nm_device_get_path (info->slave)));
|
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);
|
g_value_take_boxed (value, slaves);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -513,21 +435,6 @@ 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;
|
|
||||||
|
|
||||||
for (iter = priv->slaves; iter; iter = g_slist_next (iter))
|
|
||||||
release_slave (NM_DEVICE (self), ((SlaveInfo *) iter->data)->slave);
|
|
||||||
g_slist_free (priv->slaves);
|
|
||||||
priv->slaves = NULL;
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nm_device_bond_class_init (NMDeviceBondClass *klass)
|
nm_device_bond_class_init (NMDeviceBondClass *klass)
|
||||||
{
|
{
|
||||||
@@ -540,7 +447,6 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||||||
object_class->constructed = constructed;
|
object_class->constructed = constructed;
|
||||||
object_class->get_property = get_property;
|
object_class->get_property = get_property;
|
||||||
object_class->set_property = set_property;
|
object_class->set_property = set_property;
|
||||||
object_class->dispose = dispose;
|
|
||||||
|
|
||||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
parent_class->update_hw_address = update_hw_address;
|
parent_class->update_hw_address = update_hw_address;
|
||||||
|
@@ -46,7 +46,7 @@ G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE_WIRED)
|
|||||||
#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
|
#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GSList *slaves;
|
gboolean unused;
|
||||||
} NMDeviceBridgePrivate;
|
} NMDeviceBridgePrivate;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -384,125 +384,48 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
slave_state_changed (NMDevice *slave,
|
|
||||||
NMDeviceState new_state,
|
|
||||||
NMDeviceState old_state,
|
|
||||||
NMDeviceStateReason reason,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE (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 (NMDeviceBridge *self, NMDevice *slave)
|
|
||||||
{
|
|
||||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_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
|
static gboolean
|
||||||
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
||||||
{
|
{
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
|
|
||||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (self);
|
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
NMSettingBridgePort *s_port;
|
||||||
if (find_slave_info_by_device (self, slave))
|
const char *iface = nm_device_get_ip_iface (device);
|
||||||
return TRUE;
|
const char *slave_iface = nm_device_get_ip_iface (slave);
|
||||||
|
|
||||||
success = nm_system_bridge_attach (nm_device_get_ip_ifindex (device),
|
success = nm_system_bridge_attach (nm_device_get_ip_ifindex (device),
|
||||||
nm_device_get_ip_iface (device),
|
iface,
|
||||||
nm_device_get_ip_ifindex (slave),
|
nm_device_get_ip_ifindex (slave),
|
||||||
nm_device_get_ip_iface (slave));
|
slave_iface);
|
||||||
if (success) {
|
if (!success)
|
||||||
SlaveInfo *sinfo;
|
return FALSE;
|
||||||
NMSettingBridgePort *s_port;
|
|
||||||
const char *slave_iface = nm_device_get_ip_iface (slave);
|
|
||||||
|
|
||||||
sinfo = g_malloc0 (sizeof (*slave));
|
/* Set port properties */
|
||||||
sinfo->slave = g_object_ref (slave);
|
s_port = nm_connection_get_setting_bridge_port (connection);
|
||||||
sinfo->state_id = g_signal_connect (slave,
|
if (s_port) {
|
||||||
"state-changed",
|
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY, "priority", TRUE, FALSE);
|
||||||
(GCallback) slave_state_changed,
|
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST, "path_cost", TRUE, FALSE);
|
||||||
self);
|
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", FALSE, FALSE);
|
||||||
priv->slaves = g_slist_append (priv->slaves, sinfo);
|
|
||||||
|
|
||||||
nm_log_dbg (LOGD_DEVICE, "(%s): attached bridge component %s",
|
|
||||||
nm_device_get_ip_iface (device),
|
|
||||||
nm_device_get_ip_iface (slave));
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
|
||||||
|
|
||||||
/* Set port properties */
|
|
||||||
s_port = nm_connection_get_setting_bridge_port (connection);
|
|
||||||
if (s_port) {
|
|
||||||
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY, "priority", TRUE, FALSE);
|
|
||||||
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST, "path_cost", TRUE, FALSE);
|
|
||||||
set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", FALSE, FALSE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
nm_log_info (LOGD_DEVICE, "(%s): attached bridge port %s", iface, slave_iface);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
release_slave (NMDevice *device, NMDevice *slave)
|
release_slave (NMDevice *device, NMDevice *slave)
|
||||||
{
|
{
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
|
|
||||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (self);
|
|
||||||
gboolean success;
|
gboolean success;
|
||||||
SlaveInfo *sinfo;
|
|
||||||
|
|
||||||
sinfo = find_slave_info_by_device (self, slave);
|
|
||||||
if (!sinfo)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
success = nm_system_bridge_detach (nm_device_get_ip_ifindex (device),
|
success = nm_system_bridge_detach (nm_device_get_ip_ifindex (device),
|
||||||
nm_device_get_ip_iface (device),
|
nm_device_get_ip_iface (device),
|
||||||
nm_device_get_ip_ifindex (slave),
|
nm_device_get_ip_ifindex (slave),
|
||||||
nm_device_get_ip_iface (slave));
|
nm_device_get_ip_iface (slave));
|
||||||
nm_log_dbg (LOGD_DEVICE, "(%s): detached bridge component %s (success %d)",
|
nm_log_info (LOGD_DEVICE, "(%s): detached bridge port %s (success %d)",
|
||||||
nm_device_get_ip_iface (device),
|
nm_device_get_ip_iface (device),
|
||||||
nm_device_get_ip_iface (slave),
|
nm_device_get_ip_iface (slave),
|
||||||
success);
|
success);
|
||||||
priv->slaves = g_slist_remove (priv->slaves, sinfo);
|
|
||||||
free_slave_info (sinfo);
|
|
||||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -543,12 +466,9 @@ static void
|
|||||||
get_property (GObject *object, guint prop_id,
|
get_property (GObject *object, guint prop_id,
|
||||||
GValue *value, GParamSpec *pspec)
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE (object);
|
|
||||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (self);
|
|
||||||
const guint8 *current_addr;
|
const guint8 *current_addr;
|
||||||
GPtrArray *slaves;
|
GPtrArray *slaves;
|
||||||
GSList *iter;
|
GSList *list, *iter;
|
||||||
SlaveInfo *info;
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_HW_ADDRESS:
|
case PROP_HW_ADDRESS:
|
||||||
@@ -560,10 +480,10 @@ get_property (GObject *object, guint prop_id,
|
|||||||
break;
|
break;
|
||||||
case PROP_SLAVES:
|
case PROP_SLAVES:
|
||||||
slaves = g_ptr_array_new ();
|
slaves = g_ptr_array_new ();
|
||||||
for (iter = priv->slaves; iter; iter = iter->next) {
|
list = nm_device_master_get_slaves (NM_DEVICE (object));
|
||||||
info = iter->data;
|
for (iter = list; iter; iter = iter->next)
|
||||||
g_ptr_array_add (slaves, g_strdup (nm_device_get_path (info->slave)));
|
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);
|
g_value_take_boxed (value, slaves);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -583,21 +503,6 @@ set_property (GObject *object, guint prop_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dispose (GObject *object)
|
|
||||||
{
|
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE (object);
|
|
||||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (self);
|
|
||||||
GSList *iter;
|
|
||||||
|
|
||||||
for (iter = priv->slaves; iter; iter = g_slist_next (iter))
|
|
||||||
release_slave (NM_DEVICE (self), ((SlaveInfo *) iter->data)->slave);
|
|
||||||
g_slist_free (priv->slaves);
|
|
||||||
priv->slaves = NULL;
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_device_bridge_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
||||||
{
|
{
|
||||||
@@ -610,7 +515,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
|||||||
object_class->constructed = constructed;
|
object_class->constructed = constructed;
|
||||||
object_class->get_property = get_property;
|
object_class->get_property = get_property;
|
||||||
object_class->set_property = set_property;
|
object_class->set_property = set_property;
|
||||||
object_class->dispose = dispose;
|
|
||||||
|
|
||||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
parent_class->update_hw_address = update_hw_address;
|
parent_class->update_hw_address = update_hw_address;
|
||||||
|
439
src/nm-device.c
439
src/nm-device.c
@@ -149,6 +149,12 @@ typedef struct {
|
|||||||
guint id;
|
guint id;
|
||||||
} QueuedState;
|
} QueuedState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMDevice *slave;
|
||||||
|
gboolean enslaved;
|
||||||
|
guint watch_id;
|
||||||
|
} SlaveInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gboolean disposed;
|
gboolean disposed;
|
||||||
gboolean initialized;
|
gboolean initialized;
|
||||||
@@ -181,8 +187,6 @@ typedef struct {
|
|||||||
gpointer act_source_func;
|
gpointer act_source_func;
|
||||||
guint act_source6_id;
|
guint act_source6_id;
|
||||||
gpointer act_source6_func;
|
gpointer act_source6_func;
|
||||||
guint act_dep_result_id;
|
|
||||||
guint act_dep_timeout_id;
|
|
||||||
gulong secrets_updated_id;
|
gulong secrets_updated_id;
|
||||||
gulong secrets_failed_id;
|
gulong secrets_failed_id;
|
||||||
|
|
||||||
@@ -241,8 +245,12 @@ typedef struct {
|
|||||||
/* allow autoconnect feature */
|
/* allow autoconnect feature */
|
||||||
gboolean autoconnect;
|
gboolean autoconnect;
|
||||||
|
|
||||||
/* master interface for bridge, bond, vlan, etc */
|
/* master interface for bridge/bond slave */
|
||||||
NMDevice * master;
|
NMDevice * master;
|
||||||
|
gboolean enslaved;
|
||||||
|
|
||||||
|
/* list of SlaveInfo for bond/bridge master */
|
||||||
|
GSList * slaves;
|
||||||
|
|
||||||
NMConnectionProvider *con_provider;
|
NMConnectionProvider *con_provider;
|
||||||
|
|
||||||
@@ -281,6 +289,8 @@ static void cp_connections_loaded (NMConnectionProvider *cp, NMConnection *conne
|
|||||||
static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
|
static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
|
||||||
static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
|
static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data);
|
||||||
|
|
||||||
|
static const char *state_to_string (NMDeviceState state);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nm_device_init (NMDevice *self)
|
nm_device_init (NMDevice *self)
|
||||||
{
|
{
|
||||||
@@ -762,6 +772,30 @@ nm_device_get_connection_provider (NMDevice *device)
|
|||||||
return NM_DEVICE_GET_PRIVATE (device)->con_provider;
|
return NM_DEVICE_GET_PRIVATE (device)->con_provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SlaveInfo *
|
||||||
|
find_slave_info (NMDevice *self, NMDevice *slave)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
SlaveInfo *info;
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
|
for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
|
||||||
|
info = iter->data;
|
||||||
|
if (info->slave == slave)
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_slave_info (SlaveInfo *info)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (info->slave, info->watch_id);
|
||||||
|
g_clear_object (&info->slave);
|
||||||
|
memset (info, 0, sizeof (*info));
|
||||||
|
g_free (info);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_device_enslave_slave:
|
* nm_device_enslave_slave:
|
||||||
* @dev: the master device
|
* @dev: the master device
|
||||||
@@ -774,22 +808,35 @@ nm_device_get_connection_provider (NMDevice *device)
|
|||||||
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
||||||
* other devices.
|
* other devices.
|
||||||
*/
|
*/
|
||||||
gboolean
|
static gboolean
|
||||||
nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection)
|
nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection)
|
||||||
{
|
{
|
||||||
|
SlaveInfo *info;
|
||||||
|
gboolean success = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (dev != NULL, FALSE);
|
g_return_val_if_fail (dev != NULL, FALSE);
|
||||||
g_return_val_if_fail (slave != 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);
|
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||||
|
g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
|
||||||
|
|
||||||
if (NM_DEVICE_GET_CLASS (dev)->enslave_slave)
|
info = find_slave_info (dev, slave);
|
||||||
return NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection);
|
if (!info)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
g_warn_if_fail (info->enslaved == FALSE);
|
||||||
|
success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection);
|
||||||
|
if (success) {
|
||||||
|
info->enslaved = TRUE;
|
||||||
|
nm_device_slave_notify_enslaved (info->slave, TRUE, FALSE);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_device_release_slave:
|
* nm_device_release_one_slave:
|
||||||
* @dev: the master device
|
* @dev: the master device
|
||||||
* @slave: the slave device to release
|
* @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)
|
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
|
||||||
* then this function releases the previously enslaved @slave.
|
* then this function releases the previously enslaved @slave.
|
||||||
@@ -797,15 +844,197 @@ nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connectio
|
|||||||
* Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
|
* Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
|
||||||
* other devices, or if @slave was never enslaved.
|
* other devices, or if @slave was never enslaved.
|
||||||
*/
|
*/
|
||||||
gboolean
|
static gboolean
|
||||||
nm_device_release_slave (NMDevice *dev, NMDevice *slave)
|
nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean failed)
|
||||||
{
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||||
|
SlaveInfo *info;
|
||||||
|
gboolean success = FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail (slave != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->release_slave != NULL, FALSE);
|
||||||
|
|
||||||
|
info = find_slave_info (dev, slave);
|
||||||
|
if (!info)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (info->enslaved) {
|
||||||
|
success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
|
||||||
|
g_warn_if_fail (success);
|
||||||
|
}
|
||||||
|
nm_device_slave_notify_enslaved (info->slave, FALSE, failed);
|
||||||
|
|
||||||
|
priv->slaves = g_slist_remove (priv->slaves, info);
|
||||||
|
free_slave_info (info);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slave_state_changed (NMDevice *slave,
|
||||||
|
NMDeviceState slave_new_state,
|
||||||
|
NMDeviceState slave_old_state,
|
||||||
|
NMDeviceStateReason reason,
|
||||||
|
NMDevice *self)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
gboolean release = FALSE;
|
||||||
|
|
||||||
|
nm_log_dbg (LOGD_DEVICE, "(%s): slave %s state change %d (%s) -> %d (%s)",
|
||||||
|
nm_device_get_iface (self),
|
||||||
|
nm_device_get_iface (slave),
|
||||||
|
slave_old_state,
|
||||||
|
state_to_string (slave_old_state),
|
||||||
|
slave_new_state,
|
||||||
|
state_to_string (slave_new_state));
|
||||||
|
|
||||||
|
g_assert (priv->state > NM_DEVICE_STATE_DISCONNECTED);
|
||||||
|
g_assert (priv->state <= NM_DEVICE_STATE_ACTIVATED);
|
||||||
|
|
||||||
|
/* Don't try to enslave slaves until the master is ready */
|
||||||
|
if (priv->state < NM_DEVICE_STATE_CONFIG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG)
|
||||||
|
nm_device_enslave_slave (self, slave, nm_device_get_connection (slave));
|
||||||
|
else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED)
|
||||||
|
release = TRUE;
|
||||||
|
else if ( slave_new_state <= NM_DEVICE_STATE_DISCONNECTED
|
||||||
|
&& slave_old_state > NM_DEVICE_STATE_DISCONNECTED) {
|
||||||
|
/* Catch failures due to unavailable or unmanaged */
|
||||||
|
release = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (release) {
|
||||||
|
nm_device_release_one_slave (self, slave, FALSE);
|
||||||
|
if (priv->slaves == NULL) {
|
||||||
|
/* FIXME: all slaves gone; do something? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_device_master_add_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.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE on failure
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_device_master_add_slave (NMDevice *dev, NMDevice *slave)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||||
|
SlaveInfo *info;
|
||||||
|
|
||||||
g_return_val_if_fail (dev != NULL, FALSE);
|
g_return_val_if_fail (dev != NULL, FALSE);
|
||||||
g_return_val_if_fail (slave != 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);
|
||||||
|
g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
|
||||||
|
|
||||||
if (NM_DEVICE_GET_CLASS (dev)->release_slave)
|
if (!find_slave_info (dev, slave)) {
|
||||||
return NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
|
info = g_malloc0 (sizeof (SlaveInfo));
|
||||||
return FALSE;
|
info->slave = g_object_ref (slave);
|
||||||
|
info->watch_id = g_signal_connect (slave, "state-changed",
|
||||||
|
G_CALLBACK (slave_state_changed), dev);
|
||||||
|
priv->slaves = g_slist_prepend (priv->slaves, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_device_master_get_slaves:
|
||||||
|
* @dev: the master device
|
||||||
|
*
|
||||||
|
* Returns: any slaves of which @device is the master. Caller owns returned list.
|
||||||
|
*/
|
||||||
|
GSList *
|
||||||
|
nm_device_master_get_slaves (NMDevice *dev)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||||
|
GSList *slaves = NULL, *iter;
|
||||||
|
|
||||||
|
for (iter = priv->slaves; iter; iter = g_slist_next (iter))
|
||||||
|
slaves = g_slist_prepend (slaves, ((SlaveInfo *) iter->data)->slave);
|
||||||
|
|
||||||
|
return slaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release all slaves */
|
||||||
|
static void
|
||||||
|
nm_device_master_release_slaves (NMDevice *self, gboolean failed)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
|
for (iter = priv->slaves; iter; iter = g_slist_next (iter))
|
||||||
|
nm_device_release_one_slave (self, ((SlaveInfo *) iter->data)->slave, failed);
|
||||||
|
g_slist_free (priv->slaves);
|
||||||
|
priv->slaves = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_device_slave_notify_enslaved:
|
||||||
|
* @dev: the slave device
|
||||||
|
* @enslaved: %TRUE if the device is now enslaved, %FALSE if released
|
||||||
|
* @master_failed: if released, indicates whether the release was unexpected,
|
||||||
|
* ie the master device failed.
|
||||||
|
*
|
||||||
|
* Notifies a slave that it has been enslaved or released. If released, provides
|
||||||
|
* information on whether the release was expected or not, and thus whether the
|
||||||
|
* slave should fail it's activation or gracefully deactivate.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nm_device_slave_notify_enslaved (NMDevice *dev,
|
||||||
|
gboolean enslaved,
|
||||||
|
gboolean master_failed)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||||
|
NMConnection *connection = nm_device_get_connection (dev);
|
||||||
|
|
||||||
|
g_assert (priv->master);
|
||||||
|
|
||||||
|
if (enslaved) {
|
||||||
|
g_warn_if_fail (priv->enslaved == FALSE);
|
||||||
|
g_warn_if_fail (priv->state == NM_DEVICE_STATE_IP_CONFIG);
|
||||||
|
|
||||||
|
nm_log_info (LOGD_DEVICE,
|
||||||
|
"Activation (%s) connection '%s' enslaved, continuing activation",
|
||||||
|
nm_device_get_iface (dev),
|
||||||
|
nm_connection_get_id (connection));
|
||||||
|
|
||||||
|
/* Now that we're enslaved, proceed with activation. Remember, slaves
|
||||||
|
* don't have any IP configuration, so they skip directly to SECONDARIES.
|
||||||
|
*/
|
||||||
|
priv->enslaved = TRUE;
|
||||||
|
priv->ip4_state = IP_DONE;
|
||||||
|
priv->ip6_state = IP_DONE;
|
||||||
|
nm_device_queue_state (dev, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
|
||||||
|
} else {
|
||||||
|
NMDeviceState new_state = NM_DEVICE_STATE_DISCONNECTED;
|
||||||
|
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
|
||||||
|
|
||||||
|
if (master_failed) {
|
||||||
|
new_state = NM_DEVICE_STATE_FAILED;
|
||||||
|
reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED;
|
||||||
|
|
||||||
|
nm_log_warn (LOGD_DEVICE,
|
||||||
|
"Activation (%s) connection '%s' master failed",
|
||||||
|
nm_device_get_iface (dev),
|
||||||
|
nm_connection_get_id (connection));
|
||||||
|
} else {
|
||||||
|
nm_log_dbg (LOGD_DEVICE,
|
||||||
|
"Activation (%s) connection '%s' master deactivated",
|
||||||
|
nm_device_get_iface (dev),
|
||||||
|
nm_connection_get_id (connection));
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_device_queue_state (dev, new_state, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1097,26 +1326,7 @@ ip6_method_matches (NMConnection *connection, const char *match)
|
|||||||
static NMActStageReturn
|
static NMActStageReturn
|
||||||
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
|
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
|
||||||
{
|
{
|
||||||
NMActRequest *req;
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||||
NMActiveConnection *master_ac;
|
|
||||||
NMDevice *master;
|
|
||||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
|
||||||
|
|
||||||
req = nm_device_get_act_request (self);
|
|
||||||
g_assert (req);
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
master = NM_DEVICE (nm_act_request_get_device (NM_ACT_REQUEST (master_ac)));
|
|
||||||
g_assert (master);
|
|
||||||
if (!nm_device_enslave_slave (master, self, nm_act_request_get_connection (req)))
|
|
||||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1137,11 +1347,6 @@ nm_device_activate_stage1_device_prepare (gpointer user_data)
|
|||||||
/* Clear the activation source ID now that this stage has run */
|
/* Clear the activation source ID now that this stage has run */
|
||||||
activation_source_clear (self, FALSE, 0);
|
activation_source_clear (self, FALSE, 0);
|
||||||
|
|
||||||
if (priv->act_dep_timeout_id) {
|
|
||||||
g_source_remove (priv->act_dep_timeout_id);
|
|
||||||
priv->act_dep_timeout_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->ip4_state = priv->ip6_state = IP_NONE;
|
priv->ip4_state = priv->ip6_state = IP_NONE;
|
||||||
|
|
||||||
iface = nm_device_get_iface (self);
|
iface = nm_device_get_iface (self);
|
||||||
@@ -1190,6 +1395,17 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
|
|||||||
static NMActStageReturn
|
static NMActStageReturn
|
||||||
act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
|
act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
|
||||||
{
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
|
/* If we have slaves that aren't yet enslaved, do that now */
|
||||||
|
for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
|
||||||
|
SlaveInfo *info = iter->data;
|
||||||
|
|
||||||
|
if (nm_device_get_state (info->slave) == NM_DEVICE_STATE_IP_CONFIG)
|
||||||
|
nm_device_enslave_slave (dev, info->slave, nm_device_get_connection (info->slave));
|
||||||
|
}
|
||||||
|
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -2451,6 +2667,7 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||||||
NMIP4Config *ip4_config = NULL;
|
NMIP4Config *ip4_config = NULL;
|
||||||
NMIP6Config *ip6_config = NULL;
|
NMIP6Config *ip6_config = NULL;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
NMDevice *master;
|
||||||
|
|
||||||
/* Clear the activation source ID now that this stage has run */
|
/* Clear the activation source ID now that this stage has run */
|
||||||
activation_source_clear (self, FALSE, 0);
|
activation_source_clear (self, FALSE, 0);
|
||||||
@@ -2466,6 +2683,26 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||||||
|
|
||||||
priv->ip4_state = priv->ip6_state = IP_CONF;
|
priv->ip4_state = priv->ip6_state = IP_CONF;
|
||||||
|
|
||||||
|
/* If the device is a slave, then we don't do any IP configuration but we
|
||||||
|
* use the IP config stage to indicate to the master we're ready for
|
||||||
|
* enslavement. Either the master has already enslaved us, in which case
|
||||||
|
* our state transition to SECONDARIES is already queued courtesy of
|
||||||
|
* nm_device_slave_notify_enslaved(), or the master is still activating,
|
||||||
|
* in which case we postpone activation here until the master enslaves us,
|
||||||
|
* which calls nm_device_slave_notify_enslaved().
|
||||||
|
*/
|
||||||
|
master = (NMDevice *) nm_act_request_get_master (priv->act_request);
|
||||||
|
if (master) {
|
||||||
|
if (priv->enslaved == FALSE) {
|
||||||
|
nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on master '%s'",
|
||||||
|
nm_device_get_iface (self),
|
||||||
|
nm_connection_get_id (nm_device_get_connection (self)),
|
||||||
|
nm_device_get_iface (master));
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IPv4 */
|
||||||
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason);
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason);
|
||||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||||
g_assert (ip4_config);
|
g_assert (ip4_config);
|
||||||
@@ -2480,6 +2717,7 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||||||
} else
|
} else
|
||||||
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
|
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
|
||||||
|
|
||||||
|
/* IPv6 */
|
||||||
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason);
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason);
|
||||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||||
g_assert (ip6_config);
|
g_assert (ip6_config);
|
||||||
@@ -2496,16 +2734,6 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);
|
nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);
|
||||||
|
|
||||||
/* Handle interfaces (bond slaves, etc) that won't have any IP config; they
|
|
||||||
* need to move to SECONDARIES.
|
|
||||||
*/
|
|
||||||
if (priv->ip4_state == IP_DONE && priv->ip6_state == IP_DONE) {
|
|
||||||
/* FIXME: call layer2 stuff to set MTU? */
|
|
||||||
|
|
||||||
nm_device_state_changed (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3250,15 +3478,6 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|||||||
activation_source_clear (self, TRUE, AF_INET);
|
activation_source_clear (self, TRUE, AF_INET);
|
||||||
activation_source_clear (self, TRUE, AF_INET6);
|
activation_source_clear (self, TRUE, AF_INET6);
|
||||||
|
|
||||||
if (priv->act_dep_result_id) {
|
|
||||||
g_source_remove (priv->act_dep_result_id);
|
|
||||||
priv->act_dep_result_id = 0;
|
|
||||||
}
|
|
||||||
if (priv->act_dep_timeout_id) {
|
|
||||||
g_source_remove (priv->act_dep_timeout_id);
|
|
||||||
priv->act_dep_timeout_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear any queued transitions */
|
/* Clear any queued transitions */
|
||||||
nm_device_queued_state_clear (self);
|
nm_device_queued_state_clear (self);
|
||||||
|
|
||||||
@@ -3284,6 +3503,13 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|||||||
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
||||||
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
||||||
|
|
||||||
|
/* master: release slaves */
|
||||||
|
g_clear_object (&priv->master);
|
||||||
|
nm_device_master_release_slaves (self, FALSE);
|
||||||
|
|
||||||
|
/* slave: mark no longer enslaved */
|
||||||
|
priv->enslaved = FALSE;
|
||||||
|
|
||||||
/* Tear down an existing activation request */
|
/* Tear down an existing activation request */
|
||||||
clear_act_request (self);
|
clear_act_request (self);
|
||||||
|
|
||||||
@@ -3353,61 +3579,6 @@ impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
act_dep_timeout_cb (gpointer user_data)
|
|
||||||
{
|
|
||||||
NMDevice *self = NM_DEVICE (user_data);
|
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
||||||
NMConnection *connection;
|
|
||||||
|
|
||||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request));
|
|
||||||
nm_log_warn (LOGD_DEVICE,
|
|
||||||
"Activation (%s) connection '%s' dependency timed out",
|
|
||||||
nm_device_get_iface (self),
|
|
||||||
nm_connection_get_id (connection));
|
|
||||||
|
|
||||||
nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
act_dep_result_cb (NMActRequest *req,
|
|
||||||
NMActRequestDependencyResult result,
|
|
||||||
NMDevice *self)
|
|
||||||
{
|
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
||||||
NMConnection *connection;
|
|
||||||
|
|
||||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request));
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_FAILED:
|
|
||||||
g_source_remove (priv->act_dep_result_id);
|
|
||||||
priv->act_dep_result_id = 0;
|
|
||||||
|
|
||||||
nm_log_warn (LOGD_DEVICE,
|
|
||||||
"Activation (%s) connection '%s' dependency failed",
|
|
||||||
nm_device_get_iface (self),
|
|
||||||
nm_connection_get_id (connection));
|
|
||||||
nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
|
|
||||||
break;
|
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_READY:
|
|
||||||
g_warn_if_fail (priv->state == NM_DEVICE_STATE_PREPARE);
|
|
||||||
if (priv->state == NM_DEVICE_STATE_PREPARE) {
|
|
||||||
nm_log_info (LOGD_DEVICE,
|
|
||||||
"Activation (%s) connection '%s' dependency ready, continuing activation",
|
|
||||||
nm_device_get_iface (self),
|
|
||||||
nm_connection_get_id (connection));
|
|
||||||
nm_device_activate_schedule_stage1_device_prepare (self);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_WAIT:
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_device_activate (NMDevice *self, NMActRequest *req)
|
nm_device_activate (NMDevice *self, NMActRequest *req)
|
||||||
{
|
{
|
||||||
@@ -3441,8 +3612,7 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
|
|||||||
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
||||||
nm_device_activate_schedule_stage3_ip_config_start (self);
|
nm_device_activate_schedule_stage3_ip_config_start (self);
|
||||||
} else {
|
} else {
|
||||||
NMActiveConnection *dep_ac;
|
NMDevice *master;
|
||||||
NMConnection *dep_con;
|
|
||||||
|
|
||||||
/* HACK: update the state a bit early to avoid a race between the
|
/* HACK: update the state a bit early to avoid a race between the
|
||||||
* scheduled stage1 handler and nm_policy_device_change_check() thinking
|
* scheduled stage1 handler and nm_policy_device_change_check() thinking
|
||||||
@@ -3452,33 +3622,17 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
|
|||||||
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
||||||
|
|
||||||
/* Handle any dependencies this connection might have */
|
/* Handle any dependencies this connection might have */
|
||||||
switch (nm_act_request_get_dependency_result (priv->act_request)) {
|
master = (NMDevice *) nm_act_request_get_master (req);
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_FAILED:
|
if (master) {
|
||||||
nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
|
/* Master should at least already be activating */
|
||||||
break;
|
g_assert (nm_device_get_state (master) > NM_DEVICE_STATE_DISCONNECTED);
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_WAIT:
|
|
||||||
dep_ac = nm_act_request_get_dependency (priv->act_request);
|
|
||||||
g_assert (dep_ac);
|
|
||||||
dep_con = nm_active_connection_get_connection (dep_ac);
|
|
||||||
g_assert (dep_con);
|
|
||||||
nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on dependency '%s'",
|
|
||||||
nm_device_get_iface (self),
|
|
||||||
nm_connection_get_id (connection),
|
|
||||||
nm_connection_get_id (dep_con));
|
|
||||||
|
|
||||||
priv->act_dep_result_id = g_signal_connect (priv->act_request,
|
g_assert (priv->master == NULL);
|
||||||
NM_ACT_REQUEST_DEPENDENCY_RESULT,
|
priv->master = g_object_ref (master);
|
||||||
G_CALLBACK (act_dep_result_cb),
|
nm_device_master_add_slave (master, self);
|
||||||
self);
|
|
||||||
priv->act_dep_timeout_id = g_timeout_add_seconds (60, act_dep_timeout_cb, self);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_warn_if_reached ();
|
|
||||||
/* fall through */
|
|
||||||
case NM_ACT_REQUEST_DEP_RESULT_READY:
|
|
||||||
nm_device_activate_schedule_stage1_device_prepare (self);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nm_device_activate_schedule_stage1_device_prepare (self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3821,6 +3975,8 @@ dispose (GObject *object)
|
|||||||
addrconf6_cleanup (self);
|
addrconf6_cleanup (self);
|
||||||
dnsmasq_cleanup (self);
|
dnsmasq_cleanup (self);
|
||||||
|
|
||||||
|
g_warn_if_fail (priv->slaves == NULL);
|
||||||
|
|
||||||
/* Take the device itself down and clear its IPv4 configuration */
|
/* Take the device itself down and clear its IPv4 configuration */
|
||||||
if (priv->managed && take_down) {
|
if (priv->managed && take_down) {
|
||||||
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
||||||
@@ -4668,6 +4824,9 @@ nm_device_state_changed (NMDevice *device,
|
|||||||
nm_device_get_iface (device),
|
nm_device_get_iface (device),
|
||||||
nm_connection_get_id (connection));
|
nm_connection_get_id (connection));
|
||||||
|
|
||||||
|
/* Notify any slaves of the unexpected failure */
|
||||||
|
nm_device_master_release_slaves (device, TRUE);
|
||||||
|
|
||||||
/* If the connection doesn't yet have a timestamp, set it to zero so that
|
/* If the connection doesn't yet have a timestamp, set it to zero so that
|
||||||
* we can distinguish between connections we've tried to activate and have
|
* we can distinguish between connections we've tried to activate and have
|
||||||
* failed (zero timestamp), connections that succeeded (non-zero timestamp),
|
* failed (zero timestamp), connections that succeeded (non-zero timestamp),
|
||||||
|
@@ -217,8 +217,14 @@ NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *dev);
|
|||||||
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
|
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
|
||||||
NMIP6Config * nm_device_get_ip6_config (NMDevice *dev);
|
NMIP6Config * nm_device_get_ip6_config (NMDevice *dev);
|
||||||
|
|
||||||
gboolean nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection);
|
/* Master */
|
||||||
gboolean nm_device_release_slave (NMDevice *dev, NMDevice *slave);
|
gboolean nm_device_master_add_slave (NMDevice *dev, NMDevice *slave);
|
||||||
|
GSList * nm_device_master_get_slaves (NMDevice *dev);
|
||||||
|
|
||||||
|
/* Slave */
|
||||||
|
void nm_device_slave_notify_enslaved (NMDevice *dev,
|
||||||
|
gboolean enslaved,
|
||||||
|
gboolean master_failed);
|
||||||
|
|
||||||
NMActRequest * nm_device_get_act_request (NMDevice *dev);
|
NMActRequest * nm_device_get_act_request (NMDevice *dev);
|
||||||
NMConnection * nm_device_get_connection (NMDevice *dev);
|
NMConnection * nm_device_get_connection (NMDevice *dev);
|
||||||
|
@@ -2289,6 +2289,7 @@ internal_activate_device (NMManager *manager,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
NMActRequest *req;
|
NMActRequest *req;
|
||||||
|
NMDevice *master_device = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
||||||
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
||||||
@@ -2307,6 +2308,9 @@ internal_activate_device (NMManager *manager,
|
|||||||
NM_DEVICE_STATE_REASON_NONE);
|
NM_DEVICE_STATE_REASON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (master)
|
||||||
|
master_device = (NMDevice *) nm_act_request_get_device (NM_ACT_REQUEST (master));
|
||||||
|
|
||||||
req = nm_act_request_new (connection,
|
req = nm_act_request_new (connection,
|
||||||
specific_object,
|
specific_object,
|
||||||
user_requested,
|
user_requested,
|
||||||
@@ -2314,7 +2318,7 @@ internal_activate_device (NMManager *manager,
|
|||||||
dbus_sender,
|
dbus_sender,
|
||||||
assumed,
|
assumed,
|
||||||
(gpointer) device,
|
(gpointer) device,
|
||||||
master);
|
(gpointer) master_device);
|
||||||
nm_device_activate (device, req);
|
nm_device_activate (device, req);
|
||||||
g_object_unref (req);
|
g_object_unref (req);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user