diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2020-01-07 12:02:55 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2020-01-09 09:04:08 +0100 |
commit | 218782a9a3c326f5c8cc3ea40dc0cd039060b188 (patch) | |
tree | 765de82115bf3ac48f8a52283f87e85f77cd5ca7 | |
parent | 4bcdc3c1ebe3e2e8a967ff067ecb2a8cbfc2f6ab (diff) | |
download | NetworkManager-218782a9a3c326f5c8cc3ea40dc0cd039060b188.tar.gz |
n-dhcp4: restart the transaction after a NAK
It is not enough to set the INIT state after a NAK; a timeout
(ns_deferred) must be set so that it is added to the event fd. The
client retries immediately the first time, so that in the successful
case it gets an address quickly. To avoid flooding the network in case
of servers always replying with NAKs, next attempts are done with
intervals from 2 seconds to 5 minutes using exponential backoff. See
also systemd commit [1].
[1] https://github.com/systemd/systemd/commit/1d1a3e0afb85478cda43670b8ed92a6db6c83f3e
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/325
-rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-probe.c | 10 | ||||
-rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-private.h | 1 |
2 files changed, 7 insertions, 4 deletions
diff --git a/shared/n-dhcp4/src/n-dhcp4-c-probe.c b/shared/n-dhcp4/src/n-dhcp4-c-probe.c index 4fb7d3892a..82a089ee5f 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-probe.c @@ -946,7 +946,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I n_dhcp4_client_lease_unref(probe->current_lease); probe->current_lease = n_dhcp4_client_lease_ref(lease); probe->state = N_DHCP4_CLIENT_PROBE_STATE_BOUND; - + probe->ns_nak_restart_delay = 0; break; case N_DHCP4_CLIENT_PROBE_STATE_REQUESTING: @@ -969,7 +969,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I node->event.granted.lease = n_dhcp4_client_lease_ref(lease); probe->current_lease = n_dhcp4_client_lease_ref(lease); probe->state = N_DHCP4_CLIENT_PROBE_STATE_GRANTED; - + probe->ns_nak_restart_delay = 0; break; case N_DHCP4_CLIENT_PROBE_STATE_INIT: @@ -1004,9 +1004,11 @@ static int n_dhcp4_client_probe_transition_nak(NDhcp4ClientProbe *probe) { return r; probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT; - + probe->ns_deferred = n_dhcp4_gettime(CLOCK_BOOTTIME) + probe->ns_nak_restart_delay; + probe->ns_nak_restart_delay = c_clamp(probe->ns_nak_restart_delay * 2, + UINT64_C(1000000000 * 2), + UINT64_C(1000000000 * 300)); break; - case N_DHCP4_CLIENT_PROBE_STATE_SELECTING: case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT: case N_DHCP4_CLIENT_PROBE_STATE_INIT: diff --git a/shared/n-dhcp4/src/n-dhcp4-private.h b/shared/n-dhcp4/src/n-dhcp4-private.h index fcfb0f35b8..c092ae8fc3 100644 --- a/shared/n-dhcp4/src/n-dhcp4-private.h +++ b/shared/n-dhcp4/src/n-dhcp4-private.h @@ -352,6 +352,7 @@ struct NDhcp4ClientProbe { unsigned int state; /* current probe state */ uint64_t ns_deferred; /* timeout for deferred action */ uint64_t ns_reinit; + uint64_t ns_nak_restart_delay; /* restart delay after a nak */ NDhcp4ClientLease *current_lease; /* current lease */ NDhcp4CConnection connection; /* client connection wrapper */ |