|
@@ -301,6 +301,27 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) {
|
301
|
301
|
***************************************************************************
|
302
|
302
|
*/
|
303
|
303
|
|
|
304
|
+/**
|
|
305
|
+ * Calculate transmission window
|
|
306
|
+ *
|
|
307
|
+ * @v tcp TCP connection
|
|
308
|
+ * @ret len Maximum length that can be sent in a single packet
|
|
309
|
+ */
|
|
310
|
+static size_t tcp_xmit_win ( struct tcp_connection *tcp ) {
|
|
311
|
+ size_t len;
|
|
312
|
+
|
|
313
|
+ /* Not ready if we're not in a suitable connection state */
|
|
314
|
+ if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
|
|
315
|
+ return 0;
|
|
316
|
+
|
|
317
|
+ /* Length is the minimum of the receiver's window and the path MTU */
|
|
318
|
+ len = tcp->snd_win;
|
|
319
|
+ if ( len > TCP_PATH_MTU )
|
|
320
|
+ len = TCP_PATH_MTU;
|
|
321
|
+
|
|
322
|
+ return len;
|
|
323
|
+}
|
|
324
|
+
|
304
|
325
|
/**
|
305
|
326
|
* Process TCP transmit queue
|
306
|
327
|
*
|
|
@@ -363,8 +384,8 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
363
|
384
|
unsigned int flags;
|
364
|
385
|
size_t len = 0;
|
365
|
386
|
size_t seq_len;
|
366
|
|
- size_t app_window;
|
367
|
|
- size_t window;
|
|
387
|
+ size_t app_win;
|
|
388
|
+ size_t rcv_win;
|
368
|
389
|
int rc;
|
369
|
390
|
|
370
|
391
|
/* If retransmission timer is already running, do nothing */
|
|
@@ -375,7 +396,8 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
375
|
396
|
* lengths that we wish to transmit.
|
376
|
397
|
*/
|
377
|
398
|
if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
|
378
|
|
- len = tcp_process_queue ( tcp, tcp->snd_win, NULL, 0 );
|
|
399
|
+ len = tcp_process_queue ( tcp, tcp_xmit_win ( tcp ),
|
|
400
|
+ NULL, 0 );
|
379
|
401
|
}
|
380
|
402
|
seq_len = len;
|
381
|
403
|
flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
|
|
@@ -410,13 +432,13 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
410
|
432
|
tcp_process_queue ( tcp, len, iobuf, 0 );
|
411
|
433
|
|
412
|
434
|
/* Estimate window size */
|
413
|
|
- window = ( ( freemem * 3 ) / 4 );
|
414
|
|
- if ( window > TCP_MAX_WINDOW_SIZE )
|
415
|
|
- window = TCP_MAX_WINDOW_SIZE;
|
416
|
|
- app_window = xfer_window ( &tcp->xfer );
|
417
|
|
- if ( window > app_window )
|
418
|
|
- window = app_window;
|
419
|
|
- window &= ~0x03; /* Keep everything dword-aligned */
|
|
435
|
+ rcv_win = ( ( freemem * 3 ) / 4 );
|
|
436
|
+ if ( rcv_win > TCP_MAX_WINDOW_SIZE )
|
|
437
|
+ rcv_win = TCP_MAX_WINDOW_SIZE;
|
|
438
|
+ app_win = xfer_window ( &tcp->xfer );
|
|
439
|
+ if ( rcv_win > app_win )
|
|
440
|
+ rcv_win = app_win;
|
|
441
|
+ rcv_win &= ~0x03; /* Keep everything dword-aligned */
|
420
|
442
|
|
421
|
443
|
/* Fill up the TCP header */
|
422
|
444
|
payload = iobuf->data;
|
|
@@ -434,7 +456,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
434
|
456
|
tcphdr->ack = htonl ( tcp->rcv_ack );
|
435
|
457
|
tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
|
436
|
458
|
tcphdr->flags = flags;
|
437
|
|
- tcphdr->win = htons ( window );
|
|
459
|
+ tcphdr->win = htons ( rcv_win );
|
438
|
460
|
tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
|
439
|
461
|
|
440
|
462
|
/* Dump header */
|
|
@@ -910,10 +932,6 @@ static size_t tcp_xfer_window ( struct xfer_interface *xfer ) {
|
910
|
932
|
struct tcp_connection *tcp =
|
911
|
933
|
container_of ( xfer, struct tcp_connection, xfer );
|
912
|
934
|
|
913
|
|
- /* Not ready if we're not in a suitable connection state */
|
914
|
|
- if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
|
915
|
|
- return 0;
|
916
|
|
-
|
917
|
935
|
/* Not ready if data queue is non-empty. This imposes a limit
|
918
|
936
|
* of only one unACKed packet in the TX queue at any time; we
|
919
|
937
|
* do this to conserve memory usage.
|
|
@@ -922,7 +940,7 @@ static size_t tcp_xfer_window ( struct xfer_interface *xfer ) {
|
922
|
940
|
return 0;
|
923
|
941
|
|
924
|
942
|
/* Return TCP window length */
|
925
|
|
- return tcp->snd_win;
|
|
943
|
+ return tcp_xmit_win ( tcp );
|
926
|
944
|
}
|
927
|
945
|
|
928
|
946
|
/**
|