Use an RFC2131-compliant exponential backoff delay.

This commit is contained in:
Nicholas J. Kain 2011-06-30 03:27:57 -04:00
parent 339804856b
commit 3a81f1ea6c
2 changed files with 28 additions and 27 deletions

View File

@ -23,9 +23,6 @@
#include <stdint.h> #include <stdint.h>
#define NUMPACKETS 3 /* number of packets to send before delay */
#define RETRY_DELAY 30 /* time in seconds to delay after sending NUMPACKETS */
enum { enum {
LM_NONE = 0, LM_NONE = 0,
LM_KERNEL, LM_KERNEL,

View File

@ -47,15 +47,24 @@ dhcp_state_t dhcp_states[] = {
{ 0, 0, 0, 0}, // NUM_STATES { 0, 0, 0, 0}, // NUM_STATES
}; };
static int delay_timeout(int numpackets)
{
int to = 64;
char tot[] = { 4, 8, 16, 32, 64 };
if (numpackets < sizeof tot)
to = tot[numpackets];
return to;
}
// Triggered after a DHCP lease request packet has been sent and no reply has // Triggered after a DHCP lease request packet has been sent and no reply has
// been received within the response wait time. If we've not exceeded the // been received within the response wait time. If we've not exceeded the
// maximum number of request retransmits, then send another packet and wait // maximum number of request retransmits, then send another packet and wait
// again. Otherwise, return to the DHCP initialization state. // again. Otherwise, return to the DHCP initialization state.
static void requesting_timeout(struct client_state_t *cs) static void requesting_timeout(struct client_state_t *cs)
{ {
if (cs->packetNum < NUMPACKETS) { if (cs->packetNum < 5) {
send_selecting(cs->xid, cs->serverAddr, cs->requestedIP); send_selecting(cs->xid, cs->serverAddr, cs->requestedIP);
cs->timeout = ((cs->packetNum == NUMPACKETS - 1) ? 10 : 2) * 1000; cs->timeout = delay_timeout(cs->packetNum);
cs->packetNum++; cs->packetNum++;
} else { } else {
cs->dhcpState = DS_SELECTING; cs->dhcpState = DS_SELECTING;
@ -151,8 +160,10 @@ static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
memcpy(&cs->lease, temp, 4); memcpy(&cs->lease, temp, 4);
cs->lease = ntohl(cs->lease); cs->lease = ntohl(cs->lease);
cs->lease &= 0x0fffffff; cs->lease &= 0x0fffffff;
if (cs->lease < RETRY_DELAY) if (cs->lease < 60) {
cs->lease = RETRY_DELAY; log_warning("Server sent lease of <1m. Forcing lease to 1m.");
cs->lease = 60;
}
} }
// Always use RFC2131 'default' values. It's not worth validating // Always use RFC2131 'default' values. It's not worth validating
// the remote server values, if they even exist, for sanity. // the remote server values, if they even exist, for sanity.
@ -202,35 +213,28 @@ static void selecting_packet(struct client_state_t *cs, struct dhcpmsg *packet,
} }
} }
#define DELAY_SEC (((RETRY_DELAY - (RETRY_DELAY / NUMPACKETS)) / NUMPACKETS) + 1)
// Triggered after a DHCP discover packet has been sent and no reply has // Triggered after a DHCP discover packet has been sent and no reply has
// been received within the response wait time. If we've not exceeded the // been received within the response wait time. If we've not exceeded the
// maximum number of discover retransmits, then send another packet and wait // maximum number of discover retransmits, then send another packet and wait
// again. Otherwise, background or fail. // again. Otherwise, background or fail.
static void selecting_timeout(struct client_state_t *cs) static void selecting_timeout(struct client_state_t *cs)
{ {
if (cs->packetNum < NUMPACKETS) { if (cs->packetNum == 0)
if (cs->packetNum == 0) cs->xid = libc_random_u32();
cs->xid = libc_random_u32(); send_discover(cs->xid, cs->requestedIP);
send_discover(cs->xid, cs->requestedIP); cs->timeout = delay_timeout(cs->packetNum);
cs->timeout = DELAY_SEC * (cs->packetNum + 1) * 1000; cs->packetNum++;
cs->packetNum++; if (cs->init && cs->packetNum >= 2) {
} else { if (client_config.background_if_no_lease) {
if (cs->init) { log_line("No lease, going to background.");
if (client_config.background_if_no_lease) { cs->init = 0;
log_line("No lease, going to background."); background(cs);
cs->init = 0; } else if (client_config.abort_if_no_lease) {
background(cs); log_line("No lease, failing.");
} else if (client_config.abort_if_no_lease) { exit(EXIT_FAILURE);
log_line("No lease, failing.");
exit(EXIT_FAILURE);
}
} }
cs->packetNum = 0;
cs->timeout = RETRY_DELAY * 1000;
} }
} }
#undef DELAY_SEC
static void anfrelease(struct client_state_t *cs) static void anfrelease(struct client_state_t *cs)
{ {