|
@@ -391,6 +391,25 @@ static size_t tcp_xmit_win ( struct tcp_connection *tcp ) {
|
391
|
391
|
return len;
|
392
|
392
|
}
|
393
|
393
|
|
|
394
|
+/**
|
|
395
|
+ * Check data-transfer flow control window
|
|
396
|
+ *
|
|
397
|
+ * @v tcp TCP connection
|
|
398
|
+ * @ret len Length of window
|
|
399
|
+ */
|
|
400
|
+static size_t tcp_xfer_window ( struct tcp_connection *tcp ) {
|
|
401
|
+
|
|
402
|
+ /* Not ready if data queue is non-empty. This imposes a limit
|
|
403
|
+ * of only one unACKed packet in the TX queue at any time; we
|
|
404
|
+ * do this to conserve memory usage.
|
|
405
|
+ */
|
|
406
|
+ if ( ! list_empty ( &tcp->tx_queue ) )
|
|
407
|
+ return 0;
|
|
408
|
+
|
|
409
|
+ /* Return TCP window length */
|
|
410
|
+ return tcp_xmit_win ( tcp );
|
|
411
|
+}
|
|
412
|
+
|
394
|
413
|
/**
|
395
|
414
|
* Process TCP transmit queue
|
396
|
415
|
*
|
|
@@ -1084,6 +1103,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1084
|
1103
|
unsigned int flags;
|
1085
|
1104
|
size_t len;
|
1086
|
1105
|
uint32_t seq_len;
|
|
1106
|
+ size_t old_xfer_window;
|
1087
|
1107
|
int rc;
|
1088
|
1108
|
|
1089
|
1109
|
/* Sanity check packet */
|
|
@@ -1145,6 +1165,9 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1145
|
1165
|
goto discard;
|
1146
|
1166
|
}
|
1147
|
1167
|
|
|
1168
|
+ /* Record old data-transfer window */
|
|
1169
|
+ old_xfer_window = tcp_xfer_window ( tcp );
|
|
1170
|
+
|
1148
|
1171
|
/* Handle ACK, if present */
|
1149
|
1172
|
if ( flags & TCP_ACK ) {
|
1150
|
1173
|
if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
|
|
@@ -1191,6 +1214,10 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1191
|
1214
|
start_timer_fixed ( &tcp->wait, ( 2 * TCP_MSL ) );
|
1192
|
1215
|
}
|
1193
|
1216
|
|
|
1217
|
+ /* Notify application if window has changed */
|
|
1218
|
+ if ( tcp_xfer_window ( tcp ) != old_xfer_window )
|
|
1219
|
+ xfer_window_changed ( &tcp->xfer );
|
|
1220
|
+
|
1194
|
1221
|
return 0;
|
1195
|
1222
|
|
1196
|
1223
|
discard:
|
|
@@ -1256,25 +1283,6 @@ static void tcp_xfer_close ( struct tcp_connection *tcp, int rc ) {
|
1256
|
1283
|
tcp_xmit ( tcp );
|
1257
|
1284
|
}
|
1258
|
1285
|
|
1259
|
|
-/**
|
1260
|
|
- * Check flow control window
|
1261
|
|
- *
|
1262
|
|
- * @v tcp TCP connection
|
1263
|
|
- * @ret len Length of window
|
1264
|
|
- */
|
1265
|
|
-static size_t tcp_xfer_window ( struct tcp_connection *tcp ) {
|
1266
|
|
-
|
1267
|
|
- /* Not ready if data queue is non-empty. This imposes a limit
|
1268
|
|
- * of only one unACKed packet in the TX queue at any time; we
|
1269
|
|
- * do this to conserve memory usage.
|
1270
|
|
- */
|
1271
|
|
- if ( ! list_empty ( &tcp->tx_queue ) )
|
1272
|
|
- return 0;
|
1273
|
|
-
|
1274
|
|
- /* Return TCP window length */
|
1275
|
|
- return tcp_xmit_win ( tcp );
|
1276
|
|
-}
|
1277
|
|
-
|
1278
|
1286
|
/**
|
1279
|
1287
|
* Deliver datagram as I/O buffer
|
1280
|
1288
|
*
|