mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-03 00:00:14 +01:00
bond: allow independent IPv4 and IPv6 configuration with no slaves
When no slave is present, dynamic IP configuration (DHCPv4, DHCPv6, IPv6 autoconf) cannot proceed. But static and link-local configuration can. So if IPv4 requires DHCP but IPv6 is static, it makes no sense to block IPv6 configuration from proceeding just because DHCPv4 cannot.
This commit is contained in:
parent
54f9a670f7
commit
dcecc41327
1 changed files with 114 additions and 1 deletions
|
|
@ -46,7 +46,8 @@ G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE_WIRED)
|
|||
#define NM_BOND_ERROR (nm_bond_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
gboolean unused;
|
||||
gboolean ip4_waiting;
|
||||
gboolean ip6_waiting;
|
||||
} NMDeviceBondPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -85,10 +86,17 @@ device_state_changed (NMDevice *device,
|
|||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason)
|
||||
{
|
||||
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
|
||||
|
||||
if (new_state == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
/* Use NM_DEVICE_STATE_REASON_CARRIER to make sure num retries is reset */
|
||||
nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
}
|
||||
|
||||
if (new_state <= NM_DEVICE_STATE_DISCONNECTED || new_state > NM_DEVICE_STATE_ACTIVATED) {
|
||||
priv->ip4_waiting = FALSE;
|
||||
priv->ip6_waiting = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -303,6 +311,9 @@ 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);
|
||||
|
|
@ -324,6 +335,7 @@ 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);
|
||||
|
|
@ -340,6 +352,19 @@ 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;
|
||||
|
|
@ -362,6 +387,92 @@ 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 *
|
||||
|
|
@ -458,6 +569,8 @@ 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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue