mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-04 20:00:32 +01:00
core: generalize waiting for IP config until slaves are ready
Instead of duplicating the code in bridge and bond, move the logic to the base class and key it off whether or not the device is a master.
This commit is contained in:
parent
8ed4b5109a
commit
479163db59
4 changed files with 101 additions and 246 deletions
|
|
@ -46,8 +46,6 @@ G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE_WIRED)
|
|||
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
gboolean ip4_waiting;
|
||||
gboolean ip6_waiting;
|
||||
guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX];
|
||||
gsize hw_addr_len;
|
||||
} NMDeviceBondPrivate;
|
||||
|
|
@ -82,20 +80,6 @@ nm_bond_error_quark (void)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
device_state_changed (NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
|
||||
|
||||
if (new_state <= NM_DEVICE_STATE_DISCONNECTED || new_state > NM_DEVICE_STATE_ACTIVATED) {
|
||||
priv->ip4_waiting = FALSE;
|
||||
priv->ip6_waiting = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
|
||||
{
|
||||
|
|
@ -330,9 +314,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
NM_DEVICE_BOND_GET_PRIVATE (dev)->ip4_waiting = FALSE;
|
||||
NM_DEVICE_BOND_GET_PRIVATE (dev)->ip6_waiting = FALSE;
|
||||
|
||||
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);
|
||||
|
|
@ -354,7 +335,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
static gboolean
|
||||
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
|
||||
gboolean success, no_firmware = FALSE;
|
||||
const char *iface = nm_device_get_ip_iface (device);
|
||||
const char *slave_iface = nm_device_get_ip_iface (slave);
|
||||
|
|
@ -371,19 +351,6 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
|||
if (success) {
|
||||
nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface);
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
|
||||
/* If waiting for a slave to continue with IP config, start now */
|
||||
if (priv->ip4_waiting) {
|
||||
nm_log_info (LOGD_BOND | LOGD_IP4, "(%s): retrying IPv4 config with first slave", iface);
|
||||
priv->ip4_waiting = FALSE;
|
||||
nm_device_activate_stage3_ip4_start (device);
|
||||
}
|
||||
|
||||
if (priv->ip6_waiting) {
|
||||
nm_log_info (LOGD_BOND | LOGD_IP6, "(%s): retrying IPv6 config with first slave", iface);
|
||||
priv->ip6_waiting = FALSE;
|
||||
nm_device_activate_stage3_ip6_start (device);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
@ -416,92 +383,6 @@ release_slave (NMDevice *device, NMDevice *slave)
|
|||
return success;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip4_config_start (NMDevice *device,
|
||||
NMIP4Config **out_config,
|
||||
NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
const char *method = NULL;
|
||||
GSList *slaves;
|
||||
|
||||
priv->ip4_waiting = FALSE;
|
||||
|
||||
slaves = nm_device_master_get_slaves (device);
|
||||
if (slaves == NULL) {
|
||||
connection = nm_device_get_connection (device);
|
||||
g_assert (connection);
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (s_ip4)
|
||||
method = nm_setting_ip4_config_get_method (s_ip4);
|
||||
|
||||
if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0)
|
||||
priv->ip4_waiting = TRUE;
|
||||
}
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (priv->ip4_waiting) {
|
||||
ret = NM_ACT_STAGE_RETURN_WAIT;
|
||||
nm_log_info (LOGD_BOND | LOGD_IP4, "(%s): IPv4 config waiting until slaves are present",
|
||||
nm_device_get_ip_iface (device));
|
||||
} else {
|
||||
/* We have slaves; proceed with normal IPv4 configuration */
|
||||
ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage3_ip4_config_start (device, out_config, reason);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip6_config_start (NMDevice *device,
|
||||
NMIP6Config **out_config,
|
||||
NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingIP6Config *s_ip6;
|
||||
const char *method = NULL;
|
||||
GSList *slaves;
|
||||
|
||||
priv->ip6_waiting = FALSE;
|
||||
|
||||
slaves = nm_device_master_get_slaves (device);
|
||||
if (slaves == NULL) {
|
||||
connection = nm_device_get_connection (device);
|
||||
g_assert (connection);
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
if (s_ip6)
|
||||
method = nm_setting_ip6_config_get_method (s_ip6);
|
||||
|
||||
/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
|
||||
* to complete addressing. SLAAC and DHCP obviously need a peer to
|
||||
* provide a prefix, while Link-Local must perform DAD on the local link.
|
||||
*/
|
||||
if ( !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
||||
|| !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)
|
||||
|| !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
|
||||
priv->ip6_waiting = TRUE;
|
||||
}
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (priv->ip6_waiting) {
|
||||
ret = NM_ACT_STAGE_RETURN_WAIT;
|
||||
nm_log_info (LOGD_BOND | LOGD_IP6, "(%s): IPv6 config waiting until slaves are present",
|
||||
nm_device_get_ip_iface (device));
|
||||
} else {
|
||||
/* We have slaves; proceed with normal IPv6 configuration */
|
||||
ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage3_ip6_config_start (device, out_config, reason);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMDevice *
|
||||
|
|
@ -603,13 +484,9 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||
parent_class->connection_match_config = connection_match_config;
|
||||
|
||||
parent_class->act_stage1_prepare = act_stage1_prepare;
|
||||
parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
|
||||
parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
|
||||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
parent_class->state_changed = device_state_changed;
|
||||
|
||||
wired_class->carrier_action = carrier_action;
|
||||
|
||||
/* properties */
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE_WIRED)
|
|||
#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
gboolean ip4_waiting;
|
||||
gboolean ip6_waiting;
|
||||
guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX];
|
||||
gsize hw_addr_len;
|
||||
} NMDeviceBridgePrivate;
|
||||
|
|
@ -82,20 +80,6 @@ nm_bridge_error_quark (void)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
device_state_changed (NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason)
|
||||
{
|
||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
|
||||
|
||||
if (new_state <= NM_DEVICE_STATE_DISCONNECTED || new_state > NM_DEVICE_STATE_ACTIVATED) {
|
||||
priv->ip4_waiting = FALSE;
|
||||
priv->ip6_waiting = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
|
||||
{
|
||||
|
|
@ -384,9 +368,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
NM_DEVICE_BRIDGE_GET_PRIVATE (dev)->ip4_waiting = FALSE;
|
||||
NM_DEVICE_BRIDGE_GET_PRIVATE (dev)->ip6_waiting = FALSE;
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
||||
connection = nm_device_get_connection (dev);
|
||||
|
|
@ -411,7 +392,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
static gboolean
|
||||
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
||||
{
|
||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
|
||||
gboolean success;
|
||||
NMSettingBridgePort *s_port;
|
||||
const char *iface = nm_device_get_ip_iface (device);
|
||||
|
|
@ -436,19 +416,6 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
|||
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
||||
|
||||
/* If waiting for a slave to continue with IP config, start now */
|
||||
if (priv->ip4_waiting) {
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP4, "(%s): retrying IPv4 config with first slave", iface);
|
||||
priv->ip4_waiting = FALSE;
|
||||
nm_device_activate_stage3_ip4_start (device);
|
||||
}
|
||||
|
||||
if (priv->ip6_waiting) {
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP6, "(%s): retrying IPv6 config with first slave", iface);
|
||||
priv->ip6_waiting = FALSE;
|
||||
nm_device_activate_stage3_ip6_start (device);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -469,92 +436,6 @@ release_slave (NMDevice *device, NMDevice *slave)
|
|||
return success;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip4_config_start (NMDevice *device,
|
||||
NMIP4Config **out_config,
|
||||
NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
const char *method = NULL;
|
||||
GSList *slaves;
|
||||
|
||||
priv->ip4_waiting = FALSE;
|
||||
|
||||
slaves = nm_device_master_get_slaves (device);
|
||||
if (slaves == NULL) {
|
||||
connection = nm_device_get_connection (device);
|
||||
g_assert (connection);
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (s_ip4)
|
||||
method = nm_setting_ip4_config_get_method (s_ip4);
|
||||
|
||||
if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0)
|
||||
priv->ip4_waiting = TRUE;
|
||||
}
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (priv->ip4_waiting) {
|
||||
ret = NM_ACT_STAGE_RETURN_WAIT;
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP4, "(%s): IPv4 config waiting until slaves are present",
|
||||
nm_device_get_ip_iface (device));
|
||||
} else {
|
||||
/* We have slaves; proceed with normal IPv4 configuration */
|
||||
ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage3_ip4_config_start (device, out_config, reason);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip6_config_start (NMDevice *device,
|
||||
NMIP6Config **out_config,
|
||||
NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMConnection *connection;
|
||||
NMSettingIP6Config *s_ip6;
|
||||
const char *method = NULL;
|
||||
GSList *slaves;
|
||||
|
||||
priv->ip6_waiting = FALSE;
|
||||
|
||||
slaves = nm_device_master_get_slaves (device);
|
||||
if (slaves == NULL) {
|
||||
connection = nm_device_get_connection (device);
|
||||
g_assert (connection);
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
if (s_ip6)
|
||||
method = nm_setting_ip6_config_get_method (s_ip6);
|
||||
|
||||
/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
|
||||
* to complete addressing. SLAAC and DHCP obviously need a peer to
|
||||
* provide a prefix, while Link-Local must perform DAD on the local link.
|
||||
*/
|
||||
if ( !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
||||
|| !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)
|
||||
|| !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
|
||||
priv->ip6_waiting = TRUE;
|
||||
}
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (priv->ip6_waiting) {
|
||||
ret = NM_ACT_STAGE_RETURN_WAIT;
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP6, "(%s): IPv6 config waiting until slaves are present",
|
||||
nm_device_get_ip_iface (device));
|
||||
} else {
|
||||
/* We have slaves; proceed with normal IPv6 configuration */
|
||||
ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage3_ip6_config_start (device, out_config, reason);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMDevice *
|
||||
|
|
@ -656,13 +537,9 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
|||
parent_class->connection_match_config = connection_match_config;
|
||||
|
||||
parent_class->act_stage1_prepare = act_stage1_prepare;
|
||||
parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
|
||||
parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
|
||||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
parent_class->state_changed = device_state_changed;
|
||||
|
||||
wired_class->carrier_action = carrier_action;
|
||||
|
||||
/* properties */
|
||||
|
|
|
|||
|
|
@ -859,6 +859,18 @@ nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connectio
|
|||
if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
|
||||
NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
|
||||
|
||||
/* Restart IP configuration if we're waiting for slaves. Do this
|
||||
* after updating the hardware address as IP config may need the
|
||||
* new address.
|
||||
*/
|
||||
if (success) {
|
||||
if (NM_DEVICE_GET_PRIVATE (dev)->ip4_state == IP_WAIT)
|
||||
nm_device_activate_stage3_ip4_start (dev);
|
||||
|
||||
if (NM_DEVICE_GET_PRIVATE (dev)->ip6_state == IP_WAIT)
|
||||
nm_device_activate_stage3_ip6_start (dev);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -2124,6 +2136,35 @@ shared4_new_config (NMDevice *self, NMDeviceStateReason *reason)
|
|||
|
||||
/*********************************************/
|
||||
|
||||
static gboolean
|
||||
have_any_ready_slaves (NMDevice *device, const GSList *slaves)
|
||||
{
|
||||
const GSList *iter;
|
||||
|
||||
/* Any enslaved slave is "ready" in the generic case as it's
|
||||
* at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2
|
||||
* properties set up.
|
||||
*/
|
||||
for (iter = slaves; iter; iter = g_slist_next (iter)) {
|
||||
if (nm_device_get_enslaved (iter->data))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_requires_slaves (NMConnection *connection)
|
||||
{
|
||||
NMSettingIP4Config *s_ip4;
|
||||
const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (s_ip4)
|
||||
method = nm_setting_ip4_config_get_method (s_ip4);
|
||||
|
||||
return g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip4_config_start (NMDevice *self,
|
||||
NMIP4Config **out_config,
|
||||
|
|
@ -2134,12 +2175,30 @@ act_stage3_ip4_config_start (NMDevice *self,
|
|||
NMSettingIP4Config *s_ip4;
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
||||
GSList *slaves;
|
||||
gboolean ready_slaves;
|
||||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
connection = nm_device_get_connection (self);
|
||||
g_assert (connection);
|
||||
|
||||
if (priv->is_master && ip4_requires_slaves (connection)) {
|
||||
/* If the master has no ready slaves, and depends on slaves for
|
||||
* a successful IPv4 attempt, then postpone IPv4 addressing.
|
||||
*/
|
||||
slaves = nm_device_master_get_slaves (self);
|
||||
ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves);
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (ready_slaves == FALSE) {
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP4,
|
||||
"(%s): IPv4 config waiting until slaves are ready",
|
||||
nm_device_get_ip_iface (self));
|
||||
return NM_ACT_STAGE_RETURN_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we did not receive IP4 configuration information, default to DHCP */
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (s_ip4)
|
||||
|
|
@ -2670,6 +2729,25 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_requires_slaves (NMConnection *connection)
|
||||
{
|
||||
NMSettingIP6Config *s_ip6;
|
||||
const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
if (s_ip6)
|
||||
method = nm_setting_ip6_config_get_method (s_ip6);
|
||||
|
||||
/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
|
||||
* to complete addressing. SLAAC and DHCP obviously need a peer to
|
||||
* provide a prefix, while Link-Local must perform DAD on the local link.
|
||||
*/
|
||||
return g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
||||
|| g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0
|
||||
|| g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip6_config_start (NMDevice *self,
|
||||
NMIP6Config **out_config,
|
||||
|
|
@ -2683,6 +2761,8 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
int conf_use_tempaddr;
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
const char *ip6_privacy_str = "0\n";
|
||||
GSList *slaves;
|
||||
gboolean ready_slaves;
|
||||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
|
|
@ -2691,6 +2771,22 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
|
||||
ip_iface = nm_device_get_ip_iface (self);
|
||||
|
||||
if (priv->is_master && ip6_requires_slaves (connection)) {
|
||||
/* If the master has no ready slaves, and depends on slaves for
|
||||
* a successful IPv6 attempt, then postpone IPv6 addressing.
|
||||
*/
|
||||
slaves = nm_device_master_get_slaves (self);
|
||||
ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves);
|
||||
g_slist_free (slaves);
|
||||
|
||||
if (ready_slaves == FALSE) {
|
||||
nm_log_info (LOGD_DEVICE | LOGD_IP6,
|
||||
"(%s): IPv6 config waiting until slaves are ready",
|
||||
ip_iface);
|
||||
return NM_ACT_STAGE_RETURN_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
update_accept_ra_save (self);
|
||||
update_ip6_privacy_save (self);
|
||||
|
||||
|
|
@ -4464,6 +4560,8 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
klass->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
|
||||
klass->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
|
||||
klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
|
||||
klass->have_any_ready_slaves = have_any_ready_slaves;
|
||||
|
||||
klass->check_connection_available = check_connection_available;
|
||||
klass->hw_is_up = hw_is_up;
|
||||
klass->hw_bring_up = hw_bring_up;
|
||||
|
|
|
|||
|
|
@ -188,6 +188,9 @@ typedef struct {
|
|||
|
||||
gboolean (* release_slave) (NMDevice *self,
|
||||
NMDevice *slave);
|
||||
|
||||
gboolean (* have_any_ready_slaves) (NMDevice *self,
|
||||
const GSList *slaves);
|
||||
} NMDeviceClass;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue