core: wait with "startup complete" for both IPv4 and IPv6 dynamic configuration

In case of DHCP4, DHCP6 and/or SLAAC, delay "startup complete" until
both IPv4 and IPv6 are ready. This especially has an effect on
nm-online/NetworkManager-wait-online.service, which blocks until
configuration of both IPv4 and IPv6 is ready.

We queue a pending_action when automatic configuration starts and
remove it again, when we receive an address. Before, "startup complete"
was reached when either one of the two IP protocols was configured.

https://bugzilla.redhat.com/show_bug.cgi?id=1086906

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller
2014-04-14 17:57:56 +02:00
parent a16faa3985
commit 516d66210f
2 changed files with 34 additions and 1 deletions

View File

@@ -35,7 +35,12 @@ is a utility to find out whether we are online. It is done by asking
NetworkManager about its status. When run, \fInm\-online\fP waits until
NetworkManager reports an active connection, or specified timeout expires. On
exit, the returned status code should be checked (see the return codes bellow).
.P
By default NetworkManager waits for IPv4 dynamic addressing to complete but does
not wait for the "auto" IPv6 dynamic addressing. To wait for IPv6 addressing to
complete, either (1) change the network connection's IPv6 "may-fail" setting to "no",
and/or (2) change the IPv6 addressing method to "manual" or "dhcp", to indicate that
IPv6 connectivity is expected.
.SH OPTIONS
.TP
.B \-t, \-\-timeout <timeout_value>

View File

@@ -156,6 +156,10 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMDevice, nm_device, G_TYPE_OBJECT,
#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
#define PENDING_ACTION_DHCP4 "dhcp4"
#define PENDING_ACTION_DHCP6 "dhcp6"
#define PENDING_ACTION_AUTOCONF6 "autoconf6"
typedef enum {
IP_NONE = 0,
IP_WAIT,
@@ -2815,6 +2819,8 @@ dhcp4_start (NMDevice *self,
G_CALLBACK (dhcp4_timeout),
self);
nm_device_add_pending_action (self, PENDING_ACTION_DHCP4, TRUE);
/* DHCP devices will be notified by the DHCP manager when stuff happens */
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -3200,6 +3206,7 @@ dhcp6_start (NMDevice *self,
guint32 dhcp_opt,
NMDeviceStateReason *reason)
{
NMSettingIP6Config *s_ip6;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
GByteArray *tmp = NULL;
@@ -3248,6 +3255,11 @@ dhcp6_start (NMDevice *self,
G_CALLBACK (dhcp6_timeout),
self);
s_ip6 = nm_connection_get_setting_ip6_config (connection);
if (!nm_setting_ip6_config_get_may_fail (s_ip6) ||
!strcmp (nm_setting_ip6_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_DHCP))
nm_device_add_pending_action (self, PENDING_ACTION_DHCP6, TRUE);
/* DHCP devices will be notified by the DHCP manager when stuff happens */
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else {
@@ -3614,6 +3626,9 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
priv->rdisc_use_tempaddr = use_tempaddr;
print_support_extended_ifa_flags (use_tempaddr);
if (!nm_setting_ip6_config_get_may_fail (nm_connection_get_setting_ip6_config (connection)))
nm_device_add_pending_action (self, PENDING_ACTION_AUTOCONF6, TRUE);
/* ensure link local is ready... */
ret = linklocal6_start (self);
if (ret == NM_ACT_STAGE_RETURN_SUCCESS)
@@ -3657,6 +3672,8 @@ addrconf6_cleanup (NMDevice *self)
priv->rdisc_config_changed_sigid = 0;
}
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
g_clear_object (&priv->ac_ip6_config);
g_clear_object (&priv->rdisc);
}
@@ -4489,6 +4506,9 @@ nm_device_activate_ip4_config_commit (gpointer user_data)
/* Enter the IP_CHECK state if this is the first method to complete */
priv->ip4_state = IP_DONE;
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
@@ -4564,6 +4584,10 @@ nm_device_activate_ip6_config_commit (gpointer user_data)
if (ip6_config_merge_and_apply (self, TRUE, &reason)) {
/* Enter the IP_CHECK state if this is the first method to complete */
priv->ip6_state = IP_DONE;
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
} else {
@@ -4649,6 +4673,8 @@ dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
priv->dhcp4_timeout_sigid = 0;
}
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
if (stop)
nm_dhcp_client_stop (priv->dhcp4_client, release);
@@ -4686,6 +4712,8 @@ dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
priv->dhcp6_timeout_sigid = 0;
}
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
if (stop)
nm_dhcp_client_stop (priv->dhcp6_client, release);