From: krw Date: Mon, 1 Feb 2021 01:42:20 +0000 (+0000) Subject: Switch dispatch loop to ppoll() and protocol timeouts to struct timespec. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fa4dce490f2e9112f8deb5bdbb77e8e309868ea6;p=openbsd Switch dispatch loop to ppoll() and protocol timeouts to struct timespec. Reduces spurious packet transmissions in situations with short timings. Suggestions millert@, further suggestions & ok cheloha@ --- diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index b96441322c2..023af04e3b6 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.290 2020/12/10 18:35:32 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.291 2021/02/01 01:42:20 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer @@ -135,7 +135,7 @@ struct interface_info { struct dhcp_packet sent_packet; int sent_packet_length; uint32_t xid; - time_t timeout; + struct timespec timeout; time_t expiry, rebind; void (*timeout_func)(struct interface_info *); uint16_t secs; diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 93c024989ee..a32c5e4b37c 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.166 2019/11/19 14:35:08 krw Exp $ */ +/* $OpenBSD: dispatch.c,v 1.167 2021/02/01 01:42:21 krw Exp $ */ /* * Copyright 2004 Henning Brauer @@ -84,9 +84,10 @@ void dispatch(struct interface_info *ifi, int routefd) { struct pollfd fds[3]; + struct timespec timeout; + struct timespec *ts; void (*func)(struct interface_info *); - time_t cur_time, howlong; - int nfds, to_msec; + int nfds; while (quit == 0 || quit == RESTART) { if (quit == RESTART) { @@ -99,26 +100,18 @@ dispatch(struct interface_info *ifi, int routefd) ifi->state = S_PREBOOT; state_preboot(ifi); } - if (ifi->timeout_func != NULL) { - time(&cur_time); - if (ifi->timeout <= cur_time) { + if (timespecisset(&ifi->timeout)) { + clock_gettime(CLOCK_REALTIME, &timeout); + if (timespeccmp(&timeout, &ifi->timeout, >=)) { func = ifi->timeout_func; cancel_timeout(ifi); (*(func))(ifi); continue; } - /* - * Figure timeout in milliseconds, and check for - * potential overflow, so we can cram into an - * int for poll, while not polling with a - * negative timeout and blocking indefinitely. - */ - howlong = ifi->timeout - cur_time; - if (howlong > INT_MAX / 1000) - howlong = INT_MAX / 1000; - to_msec = howlong * 1000; + timespecsub(&ifi->timeout, &timeout, &timeout); + ts = &timeout; } else - to_msec = -1; + ts = NULL; /* * Set up the descriptors to be polled. @@ -135,7 +128,7 @@ dispatch(struct interface_info *ifi, int routefd) if (unpriv_ibuf->w.queued) fds[2].events |= POLLOUT; - nfds = poll(fds, 3, to_msec); + nfds = ppoll(fds, 3, ts, NULL); if (nfds == -1) { if (errno == EINTR) continue; @@ -307,15 +300,18 @@ void set_timeout(struct interface_info *ifi, time_t secs, void (*where)(struct interface_info *)) { - time(&ifi->timeout); - if (secs > 0) - ifi->timeout += secs; + struct timespec cur_time; + + clock_gettime(CLOCK_REALTIME, &cur_time); + timespecclear(&ifi->timeout); + ifi->timeout.tv_sec = secs; + timespecadd(&ifi->timeout, &cur_time, &ifi->timeout); ifi->timeout_func = where; } void cancel_timeout(struct interface_info *ifi) { - ifi->timeout = 0; + timespecclear(&ifi->timeout); ifi->timeout_func = NULL; }