udhcpc: simplify renewal of the lease

This commit is contained in:
Denis Vlasenko
2008-05-21 07:03:03 +00:00
parent b23429198e
commit 19903f0d44

View File

@@ -143,10 +143,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
uint32_t xid = 0; uint32_t xid = 0;
uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */ uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */
int packet_num; int packet_num;
/* t1, t2... what a wonderful names... */ unsigned already_waited_sec;
unsigned t1 = t1; /* for gcc */
unsigned t2 = t2;
unsigned timestamp_got_lease = timestamp_got_lease;
unsigned opt; unsigned opt;
int max_fd; int max_fd;
int retval; int retval;
@@ -337,6 +334,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
packet_num = 0; packet_num = 0;
already_waited_sec = 0;
/* Main event loop. select() waits on signal pipe and possibly /* Main event loop. select() waits on signal pipe and possibly
* on sockfd. * on sockfd.
@@ -353,7 +351,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
} }
max_fd = udhcp_sp_fd_set(&rfds, sockfd); max_fd = udhcp_sp_fd_set(&rfds, sockfd);
tv.tv_sec = timeout; tv.tv_sec = timeout - already_waited_sec;
tv.tv_usec = 0; tv.tv_usec = 0;
retval = 0; /* If we already timed out, fall through, else... */ retval = 0; /* If we already timed out, fall through, else... */
if (tv.tv_sec > 0) { if (tv.tv_sec > 0) {
@@ -373,6 +371,9 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
* resend discover/renew/whatever * resend discover/renew/whatever
*/ */
if (retval == 0) { if (retval == 0) {
/* We will restart wait afresh in any case */
already_waited_sec = 0;
switch (state) { switch (state) {
case INIT_SELECTING: case INIT_SELECTING:
if (packet_num < discover_retries) { if (packet_num < discover_retries) {
@@ -420,33 +421,29 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
packet_num = 0; packet_num = 0;
continue; continue;
case BOUND: case BOUND:
/* Lease is starting to run out, time to enter renewing state */ /* Half of the lease passed, time to enter renewing state */
change_listen_mode(LISTEN_KERNEL); change_listen_mode(LISTEN_KERNEL);
DEBUG("Entering renew state"); DEBUG("Entering renew state");
state = RENEWING; state = RENEWING;
/* fall right through */ /* fall right through */
case RENEWING: case RENEWING:
/* Either set a new T1, or enter REBINDING state */ if (timeout > 60) {
if ((t2 - t1) > (lease_seconds / (4*60*60) + 1)) {
/* send a request packet */ /* send a request packet */
send_renew(xid, server_addr, requested_ip); /* unicast */ send_renew(xid, server_addr, requested_ip); /* unicast */
t1 += (t2 - t1) / 2; timeout >>= 1;
timeout = t1 - ((unsigned)monotonic_sec() - timestamp_got_lease);
continue; continue;
} }
/* Timed out, enter rebinding state */ /* Timed out, enter rebinding state */
DEBUG("Entering rebinding state"); DEBUG("Entering rebinding state");
state = REBINDING; state = REBINDING;
timeout = (t2 - t1);
continue; continue;
case REBINDING: case REBINDING:
/* Lease is *really* about to run out, /* Lease is *really* about to run out,
* try to find DHCP server using broadcast */ * try to find DHCP server using broadcast */
if ((lease_seconds - t2) > (lease_seconds / (4*60*60) + 1)) { if (timeout > 0) {
/* send a request packet */ /* send a request packet */
send_renew(xid, 0, requested_ip); /* broadcast */ send_renew(xid, 0, requested_ip); /* broadcast */
t2 += (lease_seconds - t2) / 2; timeout >>= 1;
timeout = t2 - ((unsigned)monotonic_sec() - timestamp_got_lease);
continue; continue;
} }
/* Timed out, enter init state */ /* Timed out, enter init state */
@@ -454,7 +451,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
state = INIT_SELECTING; state = INIT_SELECTING;
timeout = 0; /*timeout = 0; - already is */
packet_num = 0; packet_num = 0;
continue; continue;
/* case RELEASED: */ /* case RELEASED: */
@@ -477,7 +474,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
/* If this packet will turn out to be unrelated/bogus, /* If this packet will turn out to be unrelated/bogus,
* we will go back and wait for next one. * we will go back and wait for next one.
* Be sure timeout is properly decreased. */ * Be sure timeout is properly decreased. */
timeout -= (unsigned)monotonic_sec() - timestamp_before_wait; already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
if (len == -1) { /* error is severe, reopen socket */ if (len == -1) { /* error is severe, reopen socket */
DEBUG("error on read, %s, reopening socket", strerror(errno)); DEBUG("error on read, %s, reopening socket", strerror(errno));
@@ -523,6 +520,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
state = REQUESTING; state = REQUESTING;
timeout = 0; timeout = 0;
packet_num = 0; packet_num = 0;
already_waited_sec = 0;
} }
continue; continue;
case RENEW_REQUESTED: case RENEW_REQUESTED:
@@ -538,6 +536,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
/* can be misaligned, thus memcpy */ /* can be misaligned, thus memcpy */
memcpy(&lease_seconds, temp, 4); memcpy(&lease_seconds, temp, 4);
lease_seconds = ntohl(lease_seconds); lease_seconds = ntohl(lease_seconds);
lease_seconds &= 0x0fffffff; /* paranoia: must not be negative */
} }
#if ENABLE_FEATURE_UDHCPC_ARPING #if ENABLE_FEATURE_UDHCPC_ARPING
if (opt & OPT_a) { if (opt & OPT_a) {
@@ -557,20 +556,16 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
requested_ip = 0; requested_ip = 0;
timeout = tryagain_timeout; timeout = tryagain_timeout;
packet_num = 0; packet_num = 0;
already_waited_sec = 0;
continue; /* back to main loop */ continue; /* back to main loop */
} }
} }
#endif #endif
/* enter bound state */ /* enter bound state */
t1 = lease_seconds / 2; timeout = lease_seconds / 2;
/* little fixed point for n * .875 */
t2 = (lease_seconds * 7) >> 3;
temp_addr.s_addr = packet.yiaddr; temp_addr.s_addr = packet.yiaddr;
bb_info_msg("Lease of %s obtained, lease time %u", bb_info_msg("Lease of %s obtained, lease time %u",
inet_ntoa(temp_addr), (unsigned)lease_seconds); inet_ntoa(temp_addr), (unsigned)lease_seconds);
timestamp_got_lease = monotonic_sec();
timeout = t1;
requested_ip = packet.yiaddr; requested_ip = packet.yiaddr;
udhcp_run_script(&packet, udhcp_run_script(&packet,
((state == RENEWING || state == REBINDING) ? "renew" : "bound")); ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
@@ -585,6 +580,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
if (!client_config.foreground) if (!client_config.foreground)
client_background(); client_background();
already_waited_sec = 0;
continue; /* back to main loop */ continue; /* back to main loop */
} }
if (*message == DHCPNAK) { if (*message == DHCPNAK) {
@@ -599,6 +595,7 @@ int udhcpc_main(int argc ATTRIBUTE_UNUSED, char **argv)
requested_ip = 0; requested_ip = 0;
timeout = 0; timeout = 0;
packet_num = 0; packet_num = 0;
already_waited_sec = 0;
} }
continue; continue;
/* case BOUND, RELEASED: - ignore all packets */ /* case BOUND, RELEASED: - ignore all packets */