Optimize timeout calculations so that curms() is called fewer times and
the timeout intervals are a bit more exact.
This commit is contained in:
parent
2e328b6913
commit
8c30c82240
30
ndhc/arp.c
30
ndhc/arp.c
@ -524,7 +524,7 @@ static int arp_gen_probe_wait(void)
|
|||||||
return PROBE_MIN + rand() % (PROBE_MAX - PROBE_MIN);
|
return PROBE_MIN + rand() % (PROBE_MAX - PROBE_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arp_defense_timeout(struct client_state_t *cs)
|
static void arp_defense_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
if (pending_def_ts) {
|
if (pending_def_ts) {
|
||||||
log_line("arp: Defending our lease IP.");
|
log_line("arp: Defending our lease IP.");
|
||||||
@ -538,16 +538,15 @@ static void arp_defense_timeout(struct client_state_t *cs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arp_check_timeout(struct client_state_t *cs)
|
static void arp_check_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
arp_defense_timeout(cs);
|
arp_defense_timeout(cs, nowts);
|
||||||
|
|
||||||
if (arpState == AS_GW_CHECK && act_if_arp_gw_failed(cs))
|
if (arpState == AS_GW_CHECK && act_if_arp_gw_failed(cs))
|
||||||
return;
|
return;
|
||||||
long long cms = curms();
|
|
||||||
long long rtts = arp_send_stats[ASEND_GW_PING].ts + ARP_RETRANS_DELAY;
|
long long rtts = arp_send_stats[ASEND_GW_PING].ts + ARP_RETRANS_DELAY;
|
||||||
if (cms < rtts) {
|
if (nowts < rtts) {
|
||||||
cs->timeout = rtts - cms;
|
cs->timeout = rtts - nowts;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log_line(arpState == AS_GW_CHECK ?
|
log_line(arpState == AS_GW_CHECK ?
|
||||||
@ -558,20 +557,19 @@ static void arp_check_timeout(struct client_state_t *cs)
|
|||||||
cs->timeout = ARP_RETRANS_DELAY;
|
cs->timeout = ARP_RETRANS_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arp_collision_timeout(struct client_state_t *cs)
|
static void arp_collision_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
arp_defense_timeout(cs);
|
arp_defense_timeout(cs, nowts);
|
||||||
|
|
||||||
long long cms = curms();
|
if (nowts >= collision_check_init_ts + ANNOUNCE_WAIT ||
|
||||||
if (cms >= collision_check_init_ts + ANNOUNCE_WAIT ||
|
|
||||||
arp_send_stats[ASEND_COLLISION_CHECK].count >= PROBE_NUM) {
|
arp_send_stats[ASEND_COLLISION_CHECK].count >= PROBE_NUM) {
|
||||||
arp_success(cs);
|
arp_success(cs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long long rtts = arp_send_stats[ASEND_COLLISION_CHECK].ts +
|
long long rtts = arp_send_stats[ASEND_COLLISION_CHECK].ts +
|
||||||
probe_wait_time;
|
probe_wait_time;
|
||||||
if (cms < rtts) {
|
if (nowts < rtts) {
|
||||||
cs->timeout = rtts - cms;
|
cs->timeout = rtts - nowts;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log_line("arp: Probing for hosts that may conflict with our lease...");
|
log_line("arp: Probing for hosts that may conflict with our lease...");
|
||||||
@ -659,7 +657,7 @@ static void arp_do_invalid(struct client_state_t *cs)
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*packet_fn)(struct client_state_t *cs);
|
void (*packet_fn)(struct client_state_t *cs);
|
||||||
void (*timeout_fn)(struct client_state_t *cs);
|
void (*timeout_fn)(struct client_state_t *cs, long long nowts);
|
||||||
} arp_state_fn_t;
|
} arp_state_fn_t;
|
||||||
|
|
||||||
static const arp_state_fn_t arp_states[] = {
|
static const arp_state_fn_t arp_states[] = {
|
||||||
@ -691,7 +689,7 @@ void handle_arp_response(struct client_state_t *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
handle_arp_timeout(cs);
|
handle_arp_timeout(cs, curms());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,8 +710,8 @@ void handle_arp_response(struct client_state_t *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform retransmission if necessary.
|
// Perform retransmission if necessary.
|
||||||
void handle_arp_timeout(struct client_state_t *cs)
|
void handle_arp_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
if (arp_states[arpState].timeout_fn)
|
if (arp_states[arpState].timeout_fn)
|
||||||
arp_states[arpState].timeout_fn(cs);
|
arp_states[arpState].timeout_fn(cs, nowts);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,6 @@ int arp_gw_check(struct client_state_t *cs);
|
|||||||
void arp_set_defense_mode(struct client_state_t *cs);
|
void arp_set_defense_mode(struct client_state_t *cs);
|
||||||
void arp_success(struct client_state_t *cs);
|
void arp_success(struct client_state_t *cs);
|
||||||
void handle_arp_response(struct client_state_t *cs);
|
void handle_arp_response(struct client_state_t *cs);
|
||||||
void handle_arp_timeout(struct client_state_t *cs);
|
void handle_arp_timeout(struct client_state_t *cs, long long nowts);
|
||||||
|
|
||||||
#endif /* ARP_H_ */
|
#endif /* ARP_H_ */
|
||||||
|
12
ndhc/ndhc.c
12
ndhc/ndhc.c
@ -161,7 +161,7 @@ static int get_clientid_mac_string(char *str, size_t slen)
|
|||||||
static void do_work(void)
|
static void do_work(void)
|
||||||
{
|
{
|
||||||
struct epoll_event events[3];
|
struct epoll_event events[3];
|
||||||
long long last_awake;
|
long long last_awake, nowts;
|
||||||
int timeout_delta;
|
int timeout_delta;
|
||||||
|
|
||||||
cs.epollFd = epoll_create1(0);
|
cs.epollFd = epoll_create1(0);
|
||||||
@ -170,10 +170,10 @@ static void do_work(void)
|
|||||||
setup_signals(&cs);
|
setup_signals(&cs);
|
||||||
epoll_add(&cs, cs.nlFd);
|
epoll_add(&cs, cs.nlFd);
|
||||||
set_listen_raw(&cs);
|
set_listen_raw(&cs);
|
||||||
timeout_action(&cs);
|
last_awake = curms();
|
||||||
|
timeout_action(&cs, last_awake);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
last_awake = curms();
|
|
||||||
int r = epoll_wait(cs.epollFd, events, 3, cs.timeout);
|
int r = epoll_wait(cs.epollFd, events, 3, cs.timeout);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
@ -195,12 +195,14 @@ static void do_work(void)
|
|||||||
suicide("epoll_wait: unknown fd");
|
suicide("epoll_wait: unknown fd");
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout_delta = curms() - last_awake;
|
nowts = curms();
|
||||||
|
timeout_delta = nowts - last_awake;
|
||||||
cs.timeout -= timeout_delta;
|
cs.timeout -= timeout_delta;
|
||||||
if (cs.timeout <= 0) {
|
if (cs.timeout <= 0) {
|
||||||
cs.timeout = 0;
|
cs.timeout = 0;
|
||||||
timeout_action(&cs);
|
timeout_action(&cs, nowts);
|
||||||
}
|
}
|
||||||
|
last_awake = nowts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
57
ndhc/state.c
57
ndhc/state.c
@ -16,12 +16,12 @@ static void selecting_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
|||||||
uint8_t *message);
|
uint8_t *message);
|
||||||
static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||||
uint8_t *message);
|
uint8_t *message);
|
||||||
static void selecting_timeout(struct client_state_t *cs);
|
static void selecting_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void requesting_timeout(struct client_state_t *cs);
|
static void requesting_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void bound_timeout(struct client_state_t *cs);
|
static void bound_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void renewing_timeout(struct client_state_t *cs);
|
static void renewing_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void rebinding_timeout(struct client_state_t *cs);
|
static void rebinding_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void released_timeout(struct client_state_t *cs);
|
static void released_timeout(struct client_state_t *cs, long long nowts);
|
||||||
static void xmit_release(struct client_state_t *cs);
|
static void xmit_release(struct client_state_t *cs);
|
||||||
static void print_release(struct client_state_t *cs);
|
static void print_release(struct client_state_t *cs);
|
||||||
static void frenew(struct client_state_t *cs);
|
static void frenew(struct client_state_t *cs);
|
||||||
@ -29,7 +29,7 @@ static void frenew(struct client_state_t *cs);
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
void (*packet_fn)(struct client_state_t *cs, struct dhcpmsg *packet,
|
void (*packet_fn)(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||||
uint8_t *message);
|
uint8_t *message);
|
||||||
void (*timeout_fn)(struct client_state_t *cs);
|
void (*timeout_fn)(struct client_state_t *cs, long long nowts);
|
||||||
void (*force_renew_fn)(struct client_state_t *cs);
|
void (*force_renew_fn)(struct client_state_t *cs);
|
||||||
void (*force_release_fn)(struct client_state_t *cs);
|
void (*force_release_fn)(struct client_state_t *cs);
|
||||||
} dhcp_state_t;
|
} dhcp_state_t;
|
||||||
@ -85,7 +85,7 @@ static void set_released(struct client_state_t *cs)
|
|||||||
// 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, long long nowts)
|
||||||
{
|
{
|
||||||
if (num_dhcp_requests < 5) {
|
if (num_dhcp_requests < 5) {
|
||||||
send_selecting(cs);
|
send_selecting(cs);
|
||||||
@ -97,14 +97,17 @@ static void requesting_timeout(struct client_state_t *cs)
|
|||||||
|
|
||||||
// Triggered when the lease has been held for a significant fraction of its
|
// Triggered when the lease has been held for a significant fraction of its
|
||||||
// total time, and it is time to renew the lease so that it is not lost.
|
// total time, and it is time to renew the lease so that it is not lost.
|
||||||
static void bound_timeout(struct client_state_t *cs)
|
static void bound_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
if (curms() < cs->leaseStartTime + cs->renewTime * 1000)
|
long long rnt = cs->leaseStartTime + cs->renewTime * 1000;
|
||||||
|
if (nowts < rnt) {
|
||||||
|
cs->timeout = rnt - nowts;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
cs->dhcpState = DS_RENEWING;
|
cs->dhcpState = DS_RENEWING;
|
||||||
set_listen_cooked(cs);
|
set_listen_cooked(cs);
|
||||||
log_line("Entering renew state.");
|
log_line("Entering renew state.");
|
||||||
renewing_timeout(cs);
|
renewing_timeout(cs, nowts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lease_timedout(struct client_state_t *cs)
|
static void lease_timedout(struct client_state_t *cs)
|
||||||
@ -119,23 +122,22 @@ static void lease_timedout(struct client_state_t *cs)
|
|||||||
// expires. Check to see if the lease is still valid, and if it is, send
|
// expires. Check to see if the lease is still valid, and if it is, send
|
||||||
// a unicast DHCP renew packet. If it is not, then change to the REBINDING
|
// a unicast DHCP renew packet. If it is not, then change to the REBINDING
|
||||||
// state to send broadcast queries.
|
// state to send broadcast queries.
|
||||||
static void renewing_timeout(struct client_state_t *cs)
|
static void renewing_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
long long ct = curms();
|
|
||||||
long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
|
long long rbt = cs->leaseStartTime + cs->rebindTime * 1000;
|
||||||
if (ct < rbt) {
|
if (nowts < rbt) {
|
||||||
long long wt = (rbt - ct) / 2;
|
long long wt = (rbt - nowts) / 2;
|
||||||
if (wt >= 30000)
|
if (wt >= 30000)
|
||||||
send_renew(cs);
|
send_renew(cs);
|
||||||
else
|
else
|
||||||
wt = rbt - ct;
|
wt = rbt - nowts;
|
||||||
cs->timeout = wt;
|
cs->timeout = wt;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long long elt = cs->leaseStartTime + cs->lease * 1000;
|
long long elt = cs->leaseStartTime + cs->lease * 1000;
|
||||||
if (ct < elt) {
|
if (nowts < elt) {
|
||||||
cs->dhcpState = DS_REBINDING;
|
cs->dhcpState = DS_REBINDING;
|
||||||
cs->timeout = (elt - ct) / 2;
|
cs->timeout = (elt - nowts) / 2;
|
||||||
log_line("Entering rebinding state.");
|
log_line("Entering rebinding state.");
|
||||||
} else
|
} else
|
||||||
lease_timedout(cs);
|
lease_timedout(cs);
|
||||||
@ -145,22 +147,21 @@ static void renewing_timeout(struct client_state_t *cs)
|
|||||||
// received within the response wait time. Check to see if the lease is still
|
// received within the response wait time. Check to see if the lease is still
|
||||||
// valid, and if it is, send a broadcast DHCP renew packet. If it is not, then
|
// valid, and if it is, send a broadcast DHCP renew packet. If it is not, then
|
||||||
// change to the SELECTING state to get a new lease.
|
// change to the SELECTING state to get a new lease.
|
||||||
static void rebinding_timeout(struct client_state_t *cs)
|
static void rebinding_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
long long ct = curms();
|
|
||||||
long long elt = cs->leaseStartTime + cs->lease * 1000;
|
long long elt = cs->leaseStartTime + cs->lease * 1000;
|
||||||
if (ct < elt) {
|
if (nowts < elt) {
|
||||||
long long wt = (elt - ct) / 2;
|
long long wt = (elt - nowts) / 2;
|
||||||
if (wt >= 30000)
|
if (wt >= 30000)
|
||||||
send_rebind(cs);
|
send_rebind(cs);
|
||||||
else
|
else
|
||||||
wt = elt - ct;
|
wt = elt - nowts;
|
||||||
cs->timeout = wt;
|
cs->timeout = wt;
|
||||||
} else
|
} else
|
||||||
lease_timedout(cs);
|
lease_timedout(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void released_timeout(struct client_state_t *cs)
|
static void released_timeout(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
cs->timeout = -1;
|
cs->timeout = -1;
|
||||||
}
|
}
|
||||||
@ -233,7 +234,7 @@ static void selecting_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
|||||||
// 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, long long nowts)
|
||||||
{
|
{
|
||||||
if (cs->init && num_dhcp_requests >= 2) {
|
if (cs->init && num_dhcp_requests >= 2) {
|
||||||
if (client_config.background_if_no_lease) {
|
if (client_config.background_if_no_lease) {
|
||||||
@ -315,11 +316,11 @@ void packet_action(struct client_state_t *cs, struct dhcpmsg *packet,
|
|||||||
dhcp_states[cs->dhcpState].packet_fn(cs, packet, message);
|
dhcp_states[cs->dhcpState].packet_fn(cs, packet, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_action(struct client_state_t *cs)
|
void timeout_action(struct client_state_t *cs, long long nowts)
|
||||||
{
|
{
|
||||||
handle_arp_timeout(cs);
|
|
||||||
if (dhcp_states[cs->dhcpState].timeout_fn)
|
if (dhcp_states[cs->dhcpState].timeout_fn)
|
||||||
dhcp_states[cs->dhcpState].timeout_fn(cs);
|
dhcp_states[cs->dhcpState].timeout_fn(cs, nowts);
|
||||||
|
handle_arp_timeout(cs, nowts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void force_renew_action(struct client_state_t *cs)
|
void force_renew_action(struct client_state_t *cs)
|
||||||
|
@ -20,7 +20,7 @@ void reinit_selecting(struct client_state_t *cs, int timeout);
|
|||||||
|
|
||||||
void packet_action(struct client_state_t *cs, struct dhcpmsg *packet,
|
void packet_action(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||||
uint8_t *message);
|
uint8_t *message);
|
||||||
void timeout_action(struct client_state_t *cs);
|
void timeout_action(struct client_state_t *cs, long long nowts);
|
||||||
void force_renew_action(struct client_state_t *cs);
|
void force_renew_action(struct client_state_t *cs);
|
||||||
void force_release_action(struct client_state_t *cs);
|
void force_release_action(struct client_state_t *cs);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user