iPXE
Macros | 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.

Macros

#define MIN_TIMEOUT   7
 

Functions

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

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.

Macro Definition Documentation

◆ MIN_TIMEOUT

#define MIN_TIMEOUT   7

Definition at line 50 of file retry.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

◆ LIST_HEAD()

static LIST_HEAD ( timers  )
static

List of running timers.

◆ start_timer_fixed()

void start_timer_fixed ( struct retry_timer timer,
unsigned long  timeout 
)

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 65 of file retry.c.

65  {
66 
67  /* Add to list of running timers (if applicable) */
68  if ( ! timer->running ) {
69  list_add ( &timer->list, &timers );
70  ref_get ( timer->refcnt );
71  timer->running = 1;
72  }
73 
74  /* Record start time */
75  timer->start = currticks();
76 
77  /* Record timeout */
78  timer->timeout = timeout;
79 
80  DBGC2 ( timer, "Timer %p started at time %ld (expires at %ld)\n",
81  timer, timer->start, ( timer->start + timer->timeout ) );
82 }
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:70
A timer.
Definition: timer.h:29
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:93
#define DBGC2(...)
Definition: compiler.h:522
void timeout(int)
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:43

References currticks(), DBGC2, list_add, ref_get, and timeout().

Referenced by bnxt_er_task(), bnxt_er_task_timer(), bnxt_process_er_event(), cgem_expired(), cgem_open(), dhcp_defer(), eapol_eap_rx(), eapol_expired(), efi_watchdog_expired(), exanic_expired(), exanic_open(), fc_link_err(), fc_link_expired(), fc_xchg_rx(), fc_xchg_tx(), fcoe_expired(), fragment_reassemble(), gve_open(), gve_watchdog(), http_transfer_complete(), http_watchdog(), ipair_rx_pair_error(), iphone_expired(), ipv6conf_expired(), neighbour_tx_queue(), netdev_link_block(), peerblk_open(), peerblk_raw_open(), peerblk_raw_rx(), peerblk_retrieval_open(), 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().

◆ start_timer()

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 94 of file retry.c.

94  {
95  unsigned long timeout = timer->timeout;
96  unsigned long min;
97 
98  /* Calculate minimum timeout */
99  min = ( timer->min ? timer->min : DEFAULT_MIN_TIMEOUT );
100  if ( min < MIN_TIMEOUT )
101  min = MIN_TIMEOUT;
102 
103  /* Ensure timeout is at least the minimum */
104  if ( timeout < min )
105  timeout = min;
106 
107  /* Start timer with this timeout */
109 }
#define min(x, y)
Definition: ath.h:36
A timer.
Definition: timer.h:29
#define DEFAULT_MIN_TIMEOUT
Default minimum timeout value (in ticks)
Definition: retry.h:16
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:65
#define MIN_TIMEOUT
Definition: retry.c:50
void timeout(int)

References DEFAULT_MIN_TIMEOUT, min, MIN_TIMEOUT, start_timer_fixed(), 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().

◆ stop_timer()

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 118 of file retry.c.

118  {
119  unsigned long old_timeout = timer->timeout;
120  unsigned long now = currticks();
121  unsigned long runtime;
122 
123  /* If timer was already stopped, do nothing */
124  if ( ! timer->running )
125  return;
126 
127  list_del ( &timer->list );
128  runtime = ( now - timer->start );
129  timer->running = 0;
130  DBGC2 ( timer, "Timer %p stopped at time %ld (ran for %ld)\n",
131  timer, now, runtime );
132 
133  /* Update timer. Variables are:
134  *
135  * r = round-trip time estimate (i.e. runtime)
136  * t = timeout value (i.e. timer->timeout)
137  * s = smoothed round-trip time
138  *
139  * By choice, we set t = 4s, i.e. allow for four times the
140  * normal round-trip time to pass before retransmitting.
141  *
142  * We want to smooth according to s := ( 7 s + r ) / 8
143  *
144  * Since we don't actually store s, this reduces to
145  * t := ( 7 t / 8 ) + ( r / 2 )
146  *
147  */
148  if ( timer->count ) {
149  timer->count--;
150  } else {
151  timer->timeout -= ( timer->timeout >> 3 );
152  timer->timeout += ( runtime >> 1 );
153  if ( timer->timeout != old_timeout ) {
154  DBGC ( timer, "Timer %p timeout updated to %ld\n",
155  timer, timer->timeout );
156  }
157  }
158 
159  ref_put ( timer->refcnt );
160 }
#define DBGC(...)
Definition: compiler.h:505
A timer.
Definition: timer.h:29
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
#define DBGC2(...)
Definition: compiler.h:522
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:43
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107

References currticks(), DBGC, DBGC2, list_del, and ref_put.

Referenced by aoecmd_close(), bnxt_close(), bnxt_er_task(), bnxt_er_wait_timer(), bnxt_process_er_event(), cgem_close(), dhcp_finished(), dhcp_set_state(), dhcpv6_finished(), dns_done(), dns_xfer_deliver(), eapol_eap_rx(), eapol_notify(), efi_watchdog_stop(), exanic_close(), fc_link_stop(), fc_link_up(), fc_xchg_close(), fcoe_close(), fcoe_expired(), fcoe_reset(), fragment_reassemble(), gve_close(), http_close(), http_transfer_complete(), ib_destroy_madx(), ipair_close(), iphone_close(), ipv6conf_done(), ipv6conf_rx_router_advertisement(), neighbour_destroy(), neighbour_tx_queue(), netdev_close(), 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().

◆ timer_expired()

static void timer_expired ( struct retry_timer timer)
static

Handle expired timer.

Parameters
timerRetry timer

Definition at line 167 of file retry.c.

167  {
168  struct refcnt *refcnt = timer->refcnt;
169  unsigned long max = ( timer->max ? timer->max : DEFAULT_MAX_TIMEOUT );
170  int fail;
171 
172  /* Stop timer without performing RTT calculations */
173  DBGC2 ( timer, "Timer %p stopped at time %ld on expiry\n",
174  timer, currticks() );
175  assert ( timer->running );
176  list_del ( &timer->list );
177  timer->running = 0;
178  timer->count++;
179 
180  /* Back off the timeout value */
181  timer->timeout <<= 1;
182  if ( ( fail = ( timer->timeout > max ) ) )
183  timer->timeout = max;
184  DBGC ( timer, "Timer %p timeout backed off to %ld\n",
185  timer, timer->timeout );
186 
187  /* Call expiry callback */
188  timer->expired ( timer, fail );
189  /* If refcnt is NULL, then timer may already have been freed */
190 
191  ref_put ( refcnt );
192 }
#define max(x, y)
Definition: ath.h:41
#define DBGC(...)
Definition: compiler.h:505
A reference counter.
Definition: refcnt.h:27
A timer.
Definition: timer.h:29
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define DEFAULT_MAX_TIMEOUT
Default maximum timeout value (in ticks)
Definition: retry.h:19
#define DBGC2(...)
Definition: compiler.h:522
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:43
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107

References assert(), currticks(), DBGC, DBGC2, DEFAULT_MAX_TIMEOUT, list_del, max, and ref_put.

Referenced by retry_poll().

◆ retry_poll()

void retry_poll ( void  )

Poll the retry timer list.

Definition at line 198 of file retry.c.

198  {
199  struct retry_timer *timer;
200  unsigned long now = currticks();
201  unsigned long used;
202 
203  /* Process at most one timer expiry. We cannot process
204  * multiple expiries in one pass, because one timer expiring
205  * may end up triggering another timer's deletion from the
206  * list.
207  */
208  list_for_each_entry ( timer, &timers, list ) {
209  used = ( now - timer->start );
210  if ( used >= timer->timeout ) {
211  timer_expired ( timer );
212  break;
213  }
214  }
215 }
struct list_head list
List of active timers.
Definition: retry.h:24
A retry timer.
Definition: retry.h:22
A timer.
Definition: timer.h:29
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
static struct timer * timer
Current timer.
Definition: timer.c:36
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:43
static void timer_expired(struct retry_timer *timer)
Handle expired timer.
Definition: retry.c:167

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

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

◆ retry_step()

static void retry_step ( struct process *process  __unused)
static

Single-step the retry timer list.

Parameters
processRetry timer process

Definition at line 222 of file retry.c.

222  {
223  retry_poll();
224 }
void retry_poll(void)
Poll the retry timer list.
Definition: retry.c:198

References retry_poll().

◆ PERMANENT_PROCESS()

PERMANENT_PROCESS ( retry_process  ,
retry_step   
)

Retry timer process.