iPXE
Defines | Functions
retry.c File Reference

Retry timers. More...

#include <stddef.h>
#include <ipxe/timer.h>
#include <ipxe/list.h>
#include <ipxe/process.h>
#include <ipxe/init.h>
#include <ipxe/retry.h>

Go to the source code of this file.

Defines

#define MIN_TIMEOUT   7

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static LIST_HEAD (timers)
 List of running timers.
void start_timer_fixed (struct retry_timer *timer, unsigned long timeout)
 Start timer with a specified timeout.
void start_timer (struct retry_timer *timer)
 Start timer.
void stop_timer (struct retry_timer *timer)
 Stop timer.
static void timer_expired (struct retry_timer *timer)
 Handle expired timer.
void retry_poll (void)
 Poll the retry timer list.
static void retry_step (struct process *process __unused)
 Single-step the retry timer list.
 PERMANENT_PROCESS (retry_process, retry_step)
 Retry timer process.

Detailed Description

Retry timers.

A retry timer is a binary exponential backoff timer. It can be used to build automatic retransmission into network protocols.

This implementation of the timer is designed to satisfy RFC 2988 and therefore be usable as a TCP retransmission timer.

Definition in file retry.c.


Define Documentation

#define MIN_TIMEOUT   7

Definition at line 49 of file retry.c.

Referenced by start_timer().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( timers  ) [static]

List of running timers.

void start_timer_fixed ( struct retry_timer timer,
unsigned long  timeout 
) [read]

Start timer with a specified timeout.

Parameters:
timerRetry timer
timeoutTimeout, in ticks

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.

Definition at line 64 of file retry.c.

References currticks(), DBGC2, retry_timer::list, list_add, ref_get, retry_timer::refcnt, retry_timer::running, retry_timer::start, retry_timer::timeout, and timeout().

Referenced by dhcp_discovery_expired(), efi_watchdog_expired(), exanic_expired(), exanic_open(), fc_link_err(), fc_link_expired(), fc_xchg_rx(), fc_xchg_tx(), fcoe_expired(), fragment_reassemble(), http_transfer_complete(), netdev_link_block(), peerblk_expired(), peerblk_open(), peerblk_raw_rx(), peerblk_retrieval_rx(), peerdisc_expired(), pinger_expired(), pool_add(), sandev_command(), slam_mc_socket_deliver(), slam_open(), start_timer(), start_timer_nodelay(), tcp_keepalive_expired(), tcp_rx(), tcp_rx_ack(), xcm_keepalive(), xcm_reopen(), xsigo_discover(), xsigo_ib_open(), and xsigo_xcm_complete().

                                                                            {

        /* 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();

        /* Record timeout */
        timer->timeout = timeout;

        DBGC2 ( timer, "Timer %p started at time %ld (expires at %ld)\n",
                timer, timer->start, ( timer->start + timer->timeout ) );
}
void start_timer ( struct retry_timer timer)

Start timer.

Parameters:
timerRetry timer

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.

Definition at line 93 of file retry.c.

References DEFAULT_MIN_TIMEOUT, retry_timer::min, min, MIN_TIMEOUT, start_timer_fixed(), retry_timer::timeout, and timeout().

Referenced by aoecmd_tx(), dhcp_tx(), dhcpv6_timer_expired(), dns_send_packet(), ib_mi_timer_expired(), ipv6conf_expired(), neighbour_expired(), ntp_expired(), slam_master_timer_expired(), slam_slave_timer_expired(), slam_socket_deliver(), tcp_xmit_sack(), tftp_send_packet(), xcm_close(), and xcm_reopen().

                                               {
        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 );
}
void stop_timer ( struct retry_timer timer)

Stop timer.

Parameters:
timerRetry timer

This stops the timer and updates the timer's timeout value.

Definition at line 117 of file retry.c.

References retry_timer::count, currticks(), DBGC, DBGC2, retry_timer::list, list_del, ref_put, retry_timer::refcnt, retry_timer::running, retry_timer::start, and retry_timer::timeout.

Referenced by aoecmd_close(), dhcp_finished(), dhcp_set_state(), dhcpv6_finished(), dns_done(), dns_xfer_deliver(), efi_watchdog_stop(), exanic_close(), fc_link_stop(), fc_link_up(), fc_xchg_close(), fcoe_close(), fcoe_expired(), fcoe_reset(), fragment_reassemble(), free_netdev(), http_close(), ib_destroy_madx(), ipv6conf_done(), ipv6conf_rx_router_advertisement(), neighbour_destroy(), neighbour_discovered(), netdev_link_err(), netdev_link_unblock(), ntp_close(), peerblk_reset(), peerblk_retrieval_close(), peerdisc_destroy(), pinger_close(), pool_del(), sandev_command_close(), slam_finished(), slam_mc_socket_deliver(), slam_socket_deliver(), tcp_close(), tcp_rx(), tcp_rx_ack(), tftp_done(), tftp_send_packet(), xcm_close(), xcm_destroy(), xcm_reopen(), xsigo_ib_notify(), and xsigo_ib_remove().

                                              {
        unsigned long old_timeout = timer->timeout;
        unsigned long now = currticks();
        unsigned long runtime;

        /* If timer was already stopped, do nothing */
        if ( ! timer->running )
                return;

        list_del ( &timer->list );
        runtime = ( now - timer->start );
        timer->running = 0;
        DBGC2 ( timer, "Timer %p stopped at time %ld (ran for %ld)\n",
                timer, now, runtime );

        /* Update timer.  Variables are:
         *
         *   r = round-trip time estimate (i.e. runtime)
         *   t = timeout value (i.e. timer->timeout)
         *   s = smoothed round-trip time
         *
         * By choice, we set t = 4s, i.e. allow for four times the
         * normal round-trip time to pass before retransmitting.
         *
         * We want to smooth according to s := ( 7 s + r ) / 8
         *
         * Since we don't actually store s, this reduces to
         * t := ( 7 t / 8 ) + ( r / 2 )
         *
         */
        if ( timer->count ) {
                timer->count--;
        } else {
                timer->timeout -= ( timer->timeout >> 3 );
                timer->timeout += ( runtime >> 1 );
                if ( timer->timeout != old_timeout ) {
                        DBGC ( timer, "Timer %p timeout updated to %ld\n",
                               timer, timer->timeout );
                }
        }

        ref_put ( timer->refcnt );
}
static void timer_expired ( struct retry_timer timer) [static]

Handle expired timer.

Parameters:
timerRetry timer

Definition at line 166 of file retry.c.

References assert, retry_timer::count, currticks(), DBGC, DBGC2, DEFAULT_MAX_TIMEOUT, retry_timer::expired, retry_timer::list, list_del, retry_timer::max, max, ref_put, retry_timer::refcnt, retry_timer::running, and retry_timer::timeout.

Referenced by retry_poll().

                                                        {
        struct refcnt *refcnt = timer->refcnt;
        unsigned long max = ( timer->max ? timer->max : DEFAULT_MAX_TIMEOUT );
        int fail;

        /* Stop timer without performing RTT calculations */
        DBGC2 ( timer, "Timer %p stopped at time %ld on expiry\n",
                timer, currticks() );
        assert ( timer->running );
        list_del ( &timer->list );
        timer->running = 0;
        timer->count++;

        /* Back off the timeout value */
        timer->timeout <<= 1;
        if ( ( fail = ( timer->timeout > max ) ) )
                timer->timeout = max;
        DBGC ( timer, "Timer %p timeout backed off to %ld\n",
               timer, timer->timeout );

        /* Call expiry callback */
        timer->expired ( timer, fail );
        /* If refcnt is NULL, then timer may already have been freed */

        ref_put ( refcnt );
}
void retry_poll ( void  )

Poll the retry timer list.

Definition at line 197 of file retry.c.

References currticks(), retry_timer::list, list_for_each_entry, retry_timer::start, retry_timer::timeout, timer, and timer_expired().

Referenced by eoib_poll(), ipoib_poll(), and retry_step().

                         {
        struct retry_timer *timer;
        unsigned long now = currticks();
        unsigned long used;

        /* Process at most one timer expiry.  We cannot process
         * multiple expiries in one pass, because one timer expiring
         * may end up triggering another timer's deletion from the
         * list.
         */
        list_for_each_entry ( timer, &timers, list ) {
                used = ( now - timer->start );
                if ( used >= timer->timeout ) {
                        timer_expired ( timer );
                        break;
                }
        }
}
static void retry_step ( struct process *process  __unused) [static]

Single-step the retry timer list.

Parameters:
processRetry timer process

Definition at line 221 of file retry.c.

References retry_poll().

                                                            {
        retry_poll();
}
PERMANENT_PROCESS ( retry_process  ,
retry_step   
)

Retry timer process.