]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[retry] Rewrite unrelicensable portions of retry.c
authorMichael Brown <mcb30@ipxe.org>
Thu, 5 Mar 2015 11:04:47 +0000 (11:04 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 5 Mar 2015 11:06:03 +0000 (11:06 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/retry.h
src/net/neighbour.c
src/net/retry.c
src/net/udp/dhcp.c

index c514822b2940a12390e959ecb9a686705cf8a0d6..76d45fbd0144730dc8c7225b9a003254a477cbde 100644 (file)
@@ -7,14 +7,14 @@
  *
  */
 
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <ipxe/list.h>
 
-/** Default timeout value */
+/** Default minimum timeout value (in ticks) */
 #define DEFAULT_MIN_TIMEOUT ( TICKS_PER_SEC / 4 )
 
-/** Limit after which the timeout will be deemed permanent */
+/** Default maximum timeout value (in ticks) */
 #define DEFAULT_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
 
 /** A retry timer */
@@ -25,16 +25,18 @@ struct retry_timer {
        unsigned int running;
        /** Timeout value (in ticks) */
        unsigned long timeout;
-       /** Minimum timeout value (in ticks)
+       /** Minimum timeout value (in ticks), or zero to use default
         *
-        * A value of zero means "use default timeout."
+        * The timeout will never be reduced below this value.
         */
-       unsigned long min_timeout;
-       /** Maximum timeout value before failure (in ticks)
+       unsigned long min;
+       /** Maximum timeout value (in ticks), or zero to use default
         *
-        * A value of zero means "use default timeout."
+        * The timeout will be deemed permanent (according to the
+        * failure indicator passed to expired()) when it exceeds this
+        * value.
         */
-       unsigned long max_timeout;
+       unsigned long max;
        /** Start time (in ticks) */
        unsigned long start;
        /** Retry count */
@@ -46,7 +48,7 @@ struct retry_timer {
         *
         * The timer will already be stopped when this method is
         * called.  The failure indicator will be True if the retry
-        * timeout has already exceeded @c MAX_TIMEOUT.
+        * timeout has already exceeded @c max_timeout.
         */
        void ( * expired ) ( struct retry_timer *timer, int over );
        /** Reference counter
@@ -109,4 +111,18 @@ timer_running ( struct retry_timer *timer ) {
        return ( timer->running );
 }
 
+/**
+ * Set minimum and maximum timeouts
+ *
+ * @v timer            Retry timer
+ * @v min              Minimum timeout (in ticks), or zero to use default
+ * @v max              Maximum timeout (in ticks), or zero to use default
+ */
+static inline __attribute__ (( always_inline )) void
+set_timer_limits ( struct retry_timer *timer, unsigned long min,
+                  unsigned long max ) {
+       timer->min = min;
+       timer->max = max;
+}
+
 #endif /* _IPXE_RETRY_H */
index d39618571b4d3c00e148a7b5708e275af324c751..f70896a1956152ce72a18d5ac43d59ed9dd45ffb 100644 (file)
@@ -95,8 +95,8 @@ static struct neighbour * neighbour_create ( struct net_device *netdev,
        memcpy ( neighbour->net_dest, net_dest,
                 net_protocol->net_addr_len );
        timer_init ( &neighbour->timer, neighbour_expired, &neighbour->refcnt );
-       neighbour->timer.min_timeout = NEIGHBOUR_MIN_TIMEOUT;
-       neighbour->timer.max_timeout = NEIGHBOUR_MAX_TIMEOUT;
+       set_timer_limits ( &neighbour->timer, NEIGHBOUR_MIN_TIMEOUT,
+                          NEIGHBOUR_MAX_TIMEOUT );
        INIT_LIST_HEAD ( &neighbour->tx_queue );
 
        /* Transfer ownership to cache */
index 8f210bdcc45d512da87b3689861df33dcb2b6f78..035b324e4d3a80f90a52cb3bb5277958872ce5ab 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
  */
 
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stddef.h>
 #include <ipxe/timer.h>
@@ -35,7 +39,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
  *
  * This implementation of the timer is designed to satisfy RFC 2988
  * and therefore be usable as a TCP retransmission timer.
- *
  * 
  */
 
@@ -49,47 +52,59 @@ FILE_LICENCE ( GPL2_OR_LATER );
 static LIST_HEAD ( timers );
 
 /**
- * Start timer
+ * Start timer with a specified timeout
  *
  * @v timer            Retry timer
+ * @v timeout          Timeout, in ticks
  *
- * This starts the timer running with the current timeout value.  If
+ * This starts the timer running with the specified timeout value.  If
  * stop_timer() is not called before the timer expires, the timer will
  * be stopped and the timer's callback function will be called.
  */
-void start_timer ( struct retry_timer *timer ) {
+void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
+
+       /* Add to list of running timers (if applicable) */
        if ( ! timer->running ) {
                list_add ( &timer->list, &timers );
                ref_get ( timer->refcnt );
+               timer->running = 1;
        }
+
+       /* Record start time */
        timer->start = currticks();
-       timer->running = 1;
-
-       /* 0 means "use default timeout" */
-       if ( timer->min_timeout == 0 )
-               timer->min_timeout = DEFAULT_MIN_TIMEOUT;
-       /* We must never be less than MIN_TIMEOUT under any circumstances */
-       if ( timer->min_timeout < MIN_TIMEOUT )
-               timer->min_timeout = MIN_TIMEOUT;
-       /* Honor user-specified minimum timeout */
-       if ( timer->timeout < timer->min_timeout )
-               timer->timeout = timer->min_timeout;
+
+       /* Record timeout */
+       timer->timeout = timeout;
 
        DBG2 ( "Timer %p started at time %ld (expires at %ld)\n",
               timer, timer->start, ( timer->start + timer->timeout ) );
 }
 
 /**
- * Start timer with a specified fixed timeout
+ * Start timer
  *
  * @v timer            Retry timer
- * @v timeout          Timeout, in ticks
+ *
+ * This starts the timer running with the current timeout value
+ * (rounded up to the minimum timeout value).  If stop_timer() is not
+ * called before the timer expires, the timer will be stopped and the
+ * timer's callback function will be called.
  */
-void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
-       start_timer ( timer );
-       timer->timeout = timeout;
-       DBG2 ( "Timer %p expiry time changed to %ld\n",
-              timer, ( timer->start + timer->timeout ) );
+void start_timer ( struct retry_timer *timer ) {
+       unsigned long timeout = timer->timeout;
+       unsigned long min;
+
+       /* Calculate minimum timeout */
+       min = ( timer->min ? timer->min : DEFAULT_MIN_TIMEOUT );
+       if ( min < MIN_TIMEOUT )
+               min = MIN_TIMEOUT;
+
+       /* Ensure timeout is at least the minimum */
+       if ( timeout < min )
+               timeout = min;
+
+       /* Start timer with this timeout */
+       start_timer_fixed ( timer, timeout );
 }
 
 /**
@@ -150,6 +165,7 @@ void stop_timer ( struct retry_timer *timer ) {
  */
 static void timer_expired ( struct retry_timer *timer ) {
        struct refcnt *refcnt = timer->refcnt;
+       unsigned long max = ( timer->max ? timer->max : DEFAULT_MAX_TIMEOUT );
        int fail;
 
        /* Stop timer without performing RTT calculations */
@@ -162,10 +178,8 @@ static void timer_expired ( struct retry_timer *timer ) {
 
        /* Back off the timeout value */
        timer->timeout <<= 1;
-       if ( timer->max_timeout == 0 ) /* 0 means "use default timeout" */
-               timer->max_timeout = DEFAULT_MAX_TIMEOUT;
-       if ( ( fail = ( timer->timeout > timer->max_timeout ) ) )
-               timer->timeout = timer->max_timeout;
+       if ( ( fail = ( timer->timeout > max ) ) )
+               timer->timeout = max;
        DBG ( "Timer %p timeout backed off to %ld\n",
              timer, timer->timeout );
 
index 2e75ac8156fd250b06454d453fcfd84430f9d933..8fe2774fdc202a43ed383d45e5d90afbcc7491dc 100644 (file)
@@ -278,8 +278,9 @@ static void dhcp_set_state ( struct dhcp_session *dhcp,
        dhcp->state = state;
        dhcp->start = currticks();
        stop_timer ( &dhcp->timer );
-       dhcp->timer.min_timeout = state->min_timeout_sec * TICKS_PER_SEC;
-       dhcp->timer.max_timeout = state->max_timeout_sec * TICKS_PER_SEC;
+       set_timer_limits ( &dhcp->timer,
+                          ( state->min_timeout_sec * TICKS_PER_SEC ),
+                          ( state->max_timeout_sec * TICKS_PER_SEC ) );
        start_timer_nodelay ( &dhcp->timer );
 }