timeout values now have millisecond precision.

This commit is contained in:
Nicholas J. Kain 2010-12-02 00:15:03 -05:00
parent e37ed0e16b
commit fa98b4c024
2 changed files with 37 additions and 36 deletions

View File

@ -17,13 +17,6 @@
#include "strl.h" #include "strl.h"
#include "io.h" #include "io.h"
static unsigned long long curms()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
}
/* Returns fd of the arp socket, or -1 on failure. */ /* Returns fd of the arp socket, or -1 on failure. */
int arpping(uint32_t test_nip, const uint8_t *safe_mac, uint32_t from_ip, int arpping(uint32_t test_nip, const uint8_t *safe_mac, uint32_t from_ip,
uint8_t *from_mac, const char *interface) uint8_t *from_mac, const char *interface)

View File

@ -68,7 +68,9 @@ static struct epoll_event events[3];
static char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT; static char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT;
static uint32_t requested_ip, server_addr, timeout; static uint32_t requested_ip, server_addr, timeout;
static uint32_t lease, t1, t2, xid, start; static uint32_t lease, t1, t2, xid;
static long long start;
static int dhcp_state, arp_prev_dhcp_state, packet_num, listenFd, listen_mode; static int dhcp_state, arp_prev_dhcp_state, packet_num, listenFd, listen_mode;
enum { enum {
@ -91,6 +93,13 @@ struct client_config_t client_config = {
.arp = "\0", .arp = "\0",
}; };
static unsigned long long curms()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
}
static void epoll_add(int fd) static void epoll_add(int fd)
{ {
struct epoll_event ev; struct epoll_event ev;
@ -224,7 +233,7 @@ static void perform_release(void)
} }
change_listen_mode(LISTEN_NONE); change_listen_mode(LISTEN_NONE);
dhcp_state = RELEASED; dhcp_state = RELEASED;
timeout = 0x7fffffff; timeout = -1;
} }
static void background(void) static void background(void)
@ -257,7 +266,7 @@ static void arp_failed(void)
run_script(NULL, SCRIPT_DECONFIG); run_script(NULL, SCRIPT_DECONFIG);
dhcp_state = INIT_SELECTING; dhcp_state = INIT_SELECTING;
requested_ip = 0; requested_ip = 0;
timeout = time(0); timeout = 0;
packet_num = 0; packet_num = 0;
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
} }
@ -271,14 +280,14 @@ static void arp_success(void)
/* enter bound state */ /* enter bound state */
t1 = lease >> 1; t1 = lease >> 1;
/* little fixed point for n * .875 */ /* little fixed point for n * .875 */
t2 = (lease * 0x7) >> 3; t2 = (lease * 0x7) >> 3;
timeout = t1 * 1000;
start = curms();
temp_addr.s_addr = arp_dhcp_packet.yiaddr; temp_addr.s_addr = arp_dhcp_packet.yiaddr;
log_line("Lease of %s obtained, lease time %ld.", log_line("Lease of %s obtained, lease time %ld.",
inet_ntoa(temp_addr), lease); inet_ntoa(temp_addr), lease);
start = time(0);
timeout = t1 + start;
requested_ip = arp_dhcp_packet.yiaddr; requested_ip = arp_dhcp_packet.yiaddr;
run_script(&arp_dhcp_packet, run_script(&arp_dhcp_packet,
((arp_prev_dhcp_state == RENEWING || ((arp_prev_dhcp_state == RENEWING ||
@ -296,8 +305,6 @@ static void arp_success(void)
/* Handle select timeout dropping to zero */ /* Handle select timeout dropping to zero */
static void handle_timeout(void) static void handle_timeout(void)
{ {
time_t now = time(0);
switch (dhcp_state) { switch (dhcp_state) {
case INIT_SELECTING: case INIT_SELECTING:
if (packet_num < NUMPACKETS) { if (packet_num < NUMPACKETS) {
@ -306,7 +313,7 @@ static void handle_timeout(void)
/* broadcast */ /* broadcast */
send_discover(xid, requested_ip); send_discover(xid, requested_ip);
timeout = now + ((packet_num == NUMPACKETS - 1) ? 4 : 2); timeout = ((packet_num == NUMPACKETS - 1) ? 4 : 2) * 1000;
packet_num++; packet_num++;
} else { } else {
if (client_config.background_if_no_lease) { if (client_config.background_if_no_lease) {
@ -318,7 +325,7 @@ static void handle_timeout(void)
} }
/* wait to try again */ /* wait to try again */
packet_num = 0; packet_num = 0;
timeout = now + RETRY_DELAY; timeout = RETRY_DELAY * 1000;
} }
break; break;
case RENEW_REQUESTED: case RENEW_REQUESTED:
@ -331,14 +338,14 @@ static void handle_timeout(void)
else else
/* broadcast */ /* broadcast */
send_selecting(xid, server_addr, requested_ip); send_selecting(xid, server_addr, requested_ip);
timeout = now + ((packet_num == NUMPACKETS - 1) ? 10 : 2); timeout = ((packet_num == NUMPACKETS - 1) ? 10 : 2) * 1000;
packet_num++; packet_num++;
} else { } else {
/* timed out, go back to init state */ /* timed out, go back to init state */
if (dhcp_state == RENEW_REQUESTED) if (dhcp_state == RENEW_REQUESTED)
run_script(NULL, SCRIPT_DECONFIG); run_script(NULL, SCRIPT_DECONFIG);
dhcp_state = INIT_SELECTING; dhcp_state = INIT_SELECTING;
timeout = now; timeout = 0;
packet_num = 0; packet_num = 0;
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
} }
@ -354,14 +361,14 @@ static void handle_timeout(void)
if ((t2 - t1) <= (lease / 14400 + 1)) { if ((t2 - t1) <= (lease / 14400 + 1)) {
/* timed out, enter rebinding state */ /* timed out, enter rebinding state */
dhcp_state = REBINDING; dhcp_state = REBINDING;
timeout = now + (t2 - t1); timeout = (t2 - t1) * 1000;
log_line("Entering rebinding state."); log_line("Entering rebinding state.");
} else { } else {
/* 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) >> 1) + t1; t1 = ((t2 - t1) >> 1) + t1;
timeout = t1 + start; timeout = (t1 * 1000) - (curms() - start);
} }
break; break;
case REBINDING: case REBINDING:
@ -371,7 +378,7 @@ static void handle_timeout(void)
dhcp_state = INIT_SELECTING; dhcp_state = INIT_SELECTING;
log_line("Lease lost, entering init state."); log_line("Lease lost, entering init state.");
run_script(NULL, SCRIPT_DECONFIG); run_script(NULL, SCRIPT_DECONFIG);
timeout = now; timeout = 0;
packet_num = 0; packet_num = 0;
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
} else { } else {
@ -379,12 +386,12 @@ static void handle_timeout(void)
send_renew(xid, 0, requested_ip); /* broadcast */ send_renew(xid, 0, requested_ip); /* broadcast */
t2 = ((lease - t2) >> 1) + t2; t2 = ((lease - t2) >> 1) + t2;
timeout = t2 + start; timeout = (t2 * 1000) - (curms() - start);
} }
break; break;
case RELEASED: case RELEASED:
/* yah, I know, *you* say it would never happen */ /* yah, I know, *you* say it would never happen */
timeout = 0x7fffffff; timeout = -1;
break; break;
case ARP_CHECK: case ARP_CHECK:
arp_failed(); arp_failed();
@ -460,7 +467,6 @@ static void handle_packet(void)
return; return;
} }
time_t now = time(0);
switch (dhcp_state) { switch (dhcp_state) {
case INIT_SELECTING: case INIT_SELECTING:
/* Must be a DHCPOFFER to one of our xid's */ /* Must be a DHCPOFFER to one of our xid's */
@ -473,7 +479,7 @@ static void handle_packet(void)
/* enter requesting state */ /* enter requesting state */
dhcp_state = REQUESTING; dhcp_state = REQUESTING;
timeout = now; timeout = 0;
packet_num = 0; packet_num = 0;
} else { } else {
log_line("No server ID in message"); log_line("No server ID in message");
@ -509,7 +515,7 @@ static void handle_packet(void)
arpFd = arpping(arp_dhcp_packet.yiaddr, NULL, 0, arpFd = arpping(arp_dhcp_packet.yiaddr, NULL, 0,
client_config.arp, client_config.interface); client_config.arp, client_config.interface);
epoll_add(arpFd); epoll_add(arpFd);
timeout = now + 2; timeout = 2000;
memset(&arpreply, 0, sizeof arpreply); memset(&arpreply, 0, sizeof arpreply);
arpreply_offset = 0; arpreply_offset = 0;
// Can transition to BOUND or INIT_SELECTING. // Can transition to BOUND or INIT_SELECTING.
@ -521,7 +527,7 @@ static void handle_packet(void)
if (dhcp_state != REQUESTING) if (dhcp_state != REQUESTING)
run_script(NULL, SCRIPT_DECONFIG); run_script(NULL, SCRIPT_DECONFIG);
dhcp_state = INIT_SELECTING; dhcp_state = INIT_SELECTING;
timeout = now; timeout = 0;
requested_ip = 0; requested_ip = 0;
packet_num = 0; packet_num = 0;
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
@ -582,22 +588,19 @@ static void signal_dispatch()
static void do_work(void) static void do_work(void)
{ {
int timeoutms; long long last_awake;
int timeout_delta;
epollfd = epoll_create1(0); epollfd = epoll_create1(0);
if (epollfd == -1) if (epollfd == -1)
suicide("epoll_create1 failed"); suicide("epoll_create1 failed");
epoll_add(signalFd); epoll_add(signalFd);
change_listen_mode(LISTEN_RAW); change_listen_mode(LISTEN_RAW);
handle_timeout();
for (;;) { for (;;) {
timeoutms = (timeout - time(0)) * 1000; last_awake = curms();
if (timeoutms <= 0) { int r = epoll_wait(epollfd, events, 3, timeout);
handle_timeout();
continue;
}
int r = epoll_wait(epollfd, events, 3, timeoutms);
if (r == -1) { if (r == -1) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
@ -615,6 +618,11 @@ static void do_work(void)
else else
suicide("epoll_wait: unknown fd"); suicide("epoll_wait: unknown fd");
} }
timeout_delta = curms() - last_awake;
timeout -= timeout_delta;
if (timeout <= 0)
handle_timeout();
} }
} }