mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-06 18:40:31 +01:00
bridge: 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
dcecc41327
commit
445e8755bc
1 changed files with 115 additions and 1 deletions
|
|
@ -46,7 +46,8 @@ G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE_WIRED)
|
|||
#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
|
||||
|
||||
typedef struct {
|
||||
gboolean unused;
|
||||
gboolean ip4_waiting;
|
||||
gboolean ip6_waiting;
|
||||
} NMDeviceBridgePrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -85,10 +86,17 @@ device_state_changed (NMDevice *device,
|
|||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason)
|
||||
{
|
||||
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_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
|
||||
|
|
@ -363,6 +371,9 @@ 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);
|
||||
|
|
@ -387,6 +398,7 @@ 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);
|
||||
|
|
@ -410,6 +422,20 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
|
|||
nm_log_info (LOGD_DEVICE, "(%s): attached bridge port %s", iface, slave_iface);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -430,6 +456,92 @@ 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 *
|
||||
|
|
@ -527,6 +639,8 @@ 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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue