Quellcode durchsuchen

Towards an RFC2988-compliant timer.

tags/v0.9.3
Michael Brown vor 18 Jahren
Ursprung
Commit
c3a4f3c5da
2 geänderte Dateien mit 41 neuen und 18 gelöschten Zeilen
  1. 2
    0
      src/include/gpxe/retry.h
  2. 39
    18
      src/net/retry.c

+ 2
- 0
src/include/gpxe/retry.h Datei anzeigen

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

+ 39
- 18
src/net/retry.c Datei anzeigen

@@ -29,6 +29,11 @@
29 29
  *
30 30
  * A retry timer is a binary exponential backoff timer.  It can be
31 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 39
 /** Default timeout value */
@@ -94,14 +99,41 @@ void stop_timer ( struct retry_timer *timer ) {
94 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 138
  * Single-step the retry timer list
107 139
  *
@@ -112,22 +144,11 @@ static void retry_step ( struct process *process ) {
112 144
 	struct retry_timer *tmp;
113 145
 	unsigned long now = currticks();
114 146
 	unsigned long used;
115
-	int fail;
116 147
 
117 148
 	list_for_each_entry_safe ( timer, tmp, &timers, list ) {
118 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 154
 	schedule ( process );

Laden…
Abbrechen
Speichern