Browse Source

Towards an RFC2988-compliant timer.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
c3a4f3c5da
2 changed files with 41 additions and 18 deletions
  1. 2
    0
      src/include/gpxe/retry.h
  2. 39
    18
      src/net/retry.c

+ 2
- 0
src/include/gpxe/retry.h View File

17
 	unsigned long timeout;
17
 	unsigned long timeout;
18
 	/** Start time (in ticks) */
18
 	/** Start time (in ticks) */
19
 	unsigned long start;
19
 	unsigned long start;
20
+	/** Retry count */
21
+	unsigned int count;
20
 	/** Timer expired callback
22
 	/** Timer expired callback
21
 	 *
23
 	 *
22
 	 * @v timer	Retry timer
24
 	 * @v timer	Retry timer

+ 39
- 18
src/net/retry.c View File

29
  *
29
  *
30
  * A retry timer is a binary exponential backoff timer.  It can be
30
  * A retry timer is a binary exponential backoff timer.  It can be
31
  * used to build automatic retransmission into network protocols.
31
  * used to build automatic retransmission into network protocols.
32
+ *
33
+ * This implementation of the timer is designed to satisfy RFC 2988
34
+ * and therefore be usable as a TCP retransmission timer.
35
+ *
36
+ * 
32
  */
37
  */
33
 
38
 
34
 /** Default timeout value */
39
 /** Default timeout value */
94
 	 * t := ( 7 t / 8 ) + ( r / 2 )
99
 	 * t := ( 7 t / 8 ) + ( r / 2 )
95
 	 *
100
 	 *
96
 	 */
101
 	 */
97
-	timer->timeout -= ( timer->timeout >> 3 );
98
-	timer->timeout += ( runtime >> 1 );
99
-	if ( timer->timeout != old_timeout ) {
100
-		DBG ( "Timer updated to %dms\n",
101
-		      ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
102
+	if ( timer->count ) {
103
+		timer->count--;
104
+	} else {
105
+		timer->timeout -= ( timer->timeout >> 3 );
106
+		timer->timeout += ( runtime >> 1 );
107
+		if ( timer->timeout != old_timeout ) {
108
+			DBG ( "Timer updated to %dms\n",
109
+			      ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
110
+		}
102
 	}
111
 	}
103
 }
112
 }
104
 
113
 
114
+/**
115
+ * Handle expired timer
116
+ *
117
+ * @v timer		Retry timer
118
+ */
119
+static void timer_expired ( struct retry_timer *timer ) {
120
+	int fail;
121
+
122
+	/* Stop timer without performing RTT calculations */
123
+	list_del ( &timer->list );
124
+	timer->count++;
125
+
126
+	/* Back off the timeout value */
127
+	timer->timeout <<= 1;
128
+	if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
129
+		timer->timeout = MAX_TIMEOUT;
130
+	DBG ( "Timer backed off to %dms\n",
131
+	      ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
132
+
133
+	/* Call expiry callback */
134
+	timer->expired ( timer, fail );	
135
+}
136
+
105
 /**
137
 /**
106
  * Single-step the retry timer list
138
  * Single-step the retry timer list
107
  *
139
  *
112
 	struct retry_timer *tmp;
144
 	struct retry_timer *tmp;
113
 	unsigned long now = currticks();
145
 	unsigned long now = currticks();
114
 	unsigned long used;
146
 	unsigned long used;
115
-	int fail;
116
 
147
 
117
 	list_for_each_entry_safe ( timer, tmp, &timers, list ) {
148
 	list_for_each_entry_safe ( timer, tmp, &timers, list ) {
118
 		used = ( now - timer->start );
149
 		used = ( now - timer->start );
119
-		if ( used >= timer->timeout ) {
120
-			/* Stop timer without performing RTT calculations */
121
-			list_del ( &timer->list );
122
-			/* Back off the timeout value */
123
-			timer->timeout <<= 1;
124
-			if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
125
-				timer->timeout = MAX_TIMEOUT;
126
-			DBG ( "Timer backed off to %dms\n",
127
-			      ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
128
-			/* Call expiry callback */
129
-			timer->expired ( timer, fail );
130
-		}
150
+		if ( used >= timer->timeout )
151
+			timer_expired ( timer );
131
 	}
152
 	}
132
 
153
 
133
 	schedule ( process );
154
 	schedule ( process );

Loading…
Cancel
Save