diff options
author | Francesco Giudici <fgiudici@redhat.com> | 2018-02-20 18:51:42 +0100 |
---|---|---|
committer | Francesco Giudici <fgiudici@redhat.com> | 2018-02-20 18:51:42 +0100 |
commit | bcb37e80931d6e3e09d164f8191c8149b27e5e37 (patch) | |
tree | 66a6670219d2d12e7838feba7462ae36318b6854 | |
parent | 19c22a13b2a43400dabc5956700dbb355b722d25 (diff) | |
parent | b6d2ad3312eea21effbd8d6d5fe32056ccf89cb8 (diff) | |
download | NetworkManager-bcb37e80931d6e3e09d164f8191c8149b27e5e37.tar.gz |
dhcp: merge branch 'fg/dhcp_lease-rh1503587'
https://bugzilla.redhat.com/show_bug.cgi?id=1503587
(cherry picked from commit b9e22ece2d51510c81fa4286a6a26932d93d3e8a)
-rw-r--r-- | src/devices/nm-device.c | 93 |
1 files changed, 65 insertions, 28 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f8651e2e11..eb91dc2571 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3940,21 +3940,24 @@ get_ip_config_may_fail (NMDevice *self, int addr_family) /* * check_ip_state * - * Transition the device from IP_CONFIG to the next state according to the - * outcome of IPv4 and IPv6 configuration. @may_fail indicates that we are - * called just after the initial configuration and thus IPv4/IPv6 are allowed to - * fail if the ipvx.may-fail properties say so, because the IP methods couldn't - * even be started. + * When @full_state_update is TRUE, transition the device from IP_CONFIG to the + * next state according to the outcome of IPv4 and IPv6 configuration. @may_fail + * indicates that we are called just after the initial configuration and thus + * IPv4/IPv6 are allowed to fail if the ipvx.may-fail properties say so, because + * the IP methods couldn't even be started. + * If @full_state_update is FALSE, just check if the connection should be failed + * due to the state of both ip families and the ipvx.may-fail settings. */ static void -check_ip_state (NMDevice *self, gboolean may_fail) +check_ip_state (NMDevice *self, gboolean may_fail, gboolean full_state_update) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean ip4_disabled = FALSE, ip6_ignore = FALSE; NMSettingIPConfig *s_ip4, *s_ip6; NMDeviceState state; - if (nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG) + if ( full_state_update + && nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG) return; /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the @@ -4001,9 +4004,12 @@ check_ip_state (NMDevice *self, gboolean may_fail) state = NM_DEVICE_STATE_FAILED; } - nm_device_state_changed (self, - state, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + if ( full_state_update + || state == NM_DEVICE_STATE_FAILED) { + nm_device_state_changed (self, + state, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } return; } @@ -4016,7 +4022,8 @@ check_ip_state (NMDevice *self, gboolean may_fail) /* If at least a method has completed, proceed with activation */ if ( (priv->ip4_state == IP_DONE && !ip4_disabled) || (priv->ip6_state == IP_DONE && !ip6_ignore)) { - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + if (full_state_update) + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); return; } } @@ -4058,7 +4065,7 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) if (activating) { if (success) - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); else nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); } else @@ -5434,7 +5441,7 @@ nm_device_ip_method_failed (NMDevice *self, _set_ip_state (self, addr_family, IP_FAIL); if (get_ip_config_may_fail (self, addr_family)) - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)); else nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); } @@ -6059,15 +6066,23 @@ dhcp4_fail (NMDevice *self, gboolean timeout) && (timeout || (priv->ip4_state == IP_CONF)) && !priv->dhcp4.was_active) nm_device_activate_schedule_ip4_config_timeout (self); - else if (priv->ip4_state == IP_DONE || priv->dhcp4.was_active) { + else if ( priv->dhcp4.num_tries_left < DHCP_NUM_TRIES_MAX + || priv->ip4_state == IP_DONE + || priv->dhcp4.was_active) { /* Don't fail immediately when the lease expires but try to * restart DHCP for a predefined number of times. */ if (priv->dhcp4.num_tries_left) { priv->dhcp4.num_tries_left--; dhcp_schedule_restart (self, AF_INET, "lease expired"); - } else + } else { nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + /* We failed the ipv4 method but schedule again the retries if the ipv6 method is + * configured, keeping the connection up. + */ + if (nm_device_get_state (self) != NM_DEVICE_STATE_FAILED) + dhcp_schedule_restart (self, AF_INET, "renewal failed"); + } } else g_warn_if_reached (); } @@ -6109,6 +6124,12 @@ dhcp4_state_changed (NMDhcpClient *client, break; } + /* After some failures, we have been able to renew the lease: + * update the ip state + */ + if (priv->ip4_state == IP_FAIL) + _set_ip_state (self, AF_INET, IP_CONF); + g_free (priv->dhcp4.pac_url); priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad")); nm_device_set_proxy_config (self, priv->dhcp4.pac_url); @@ -6778,13 +6799,15 @@ static void dhcp6_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean is_dhcp_managed; _LOGD (LOGD_DHCP6, "DHCPv6 failed: timeout %d, num tries left %u", timeout, priv->dhcp6.num_tries_left); + is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED); dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) { + if (is_dhcp_managed || priv->dhcp6.num_tries_left < DHCP_NUM_TRIES_MAX) { /* Don't fail if there are static addresses configured on * the device, instead retry after some time. */ @@ -6799,15 +6822,23 @@ dhcp6_fail (NMDevice *self, gboolean timeout) && (timeout || (priv->ip6_state == IP_CONF)) && !priv->dhcp6.was_active) nm_device_activate_schedule_ip6_config_timeout (self); - else if (priv->ip6_state == IP_DONE || priv->dhcp6.was_active) { + else if ( priv->dhcp6.num_tries_left < DHCP_NUM_TRIES_MAX + || priv->ip6_state == IP_DONE + || priv->dhcp6.was_active) { /* Don't fail immediately when the lease expires but try to * restart DHCP for a predefined number of times. */ if (priv->dhcp6.num_tries_left) { priv->dhcp6.num_tries_left--; dhcp_schedule_restart (self, AF_INET6, "lease expired"); - } else + } else { nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + /* We failed the ipv6 method but schedule again the retries if the ipv4 method is + * configured, keeping the connection up. + */ + if (nm_device_get_state (self) != NM_DEVICE_STATE_FAILED) + dhcp_schedule_restart (self, AF_INET6, "renewal failed"); + } } else g_warn_if_reached (); } else { @@ -6874,6 +6905,12 @@ dhcp6_state_changed (NMDhcpClient *client, } } + /* After long time we have been able to renew the lease: + * update the ip state + */ + if (priv->ip6_state == IP_FAIL) + _set_ip_state (self, AF_INET6, IP_CONF); + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; if (priv->ip6_state == IP_CONF) { @@ -8163,7 +8200,7 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) if (nm_device_sys_iface_state_is_external (self)) { _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); return TRUE; } @@ -8176,7 +8213,7 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) g_object_unref (ip4_config); } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; @@ -8210,7 +8247,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) if (nm_device_sys_iface_state_is_external (self)) { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); return TRUE; } @@ -8227,7 +8264,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) nm_device_activate_schedule_ip6_config_result (self); } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; @@ -8277,7 +8314,7 @@ activate_stage3_ip_config_start (NMDevice *self) /* Proxy */ nm_device_set_proxy_config (self, NULL); - check_ip_state (self, TRUE); + check_ip_state (self, TRUE, TRUE); } static void @@ -8416,7 +8453,7 @@ activate_stage4_ip4_config_timeout (NMDevice *self) _set_ip_state (self, AF_INET, IP_FAIL); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } /* @@ -8472,7 +8509,7 @@ activate_stage4_ip6_config_timeout (NMDevice *self) _set_ip_state (self, AF_INET6, IP_FAIL); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } /* @@ -8720,7 +8757,7 @@ activate_stage5_ip4_config_result (NMDevice *self) /* Enter the IP_CHECK state if this is the first method to complete */ _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } void @@ -8875,7 +8912,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); } else { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } } } else { @@ -11378,7 +11415,7 @@ queued_ip6_config_change (gpointer user_data) _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); g_clear_object (&priv->dad6_ip6_config); _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); if (priv->rt6_temporary_not_available) nm_device_activate_schedule_ip6_config_result (self); } |