Browse Source

Limit xmit window to one MTU. (Path MTU discovery not yet

implemented; should be done at some point.)
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
edded7546e
2 changed files with 42 additions and 16 deletions
  1. 8
    0
      src/include/gpxe/tcp.h
  2. 34
    16
      src/net/tcp.c

+ 8
- 0
src/include/gpxe/tcp.h View File

237
  */
237
  */
238
 #define TCP_MAX_WINDOW_SIZE	( 65536 - 4 )
238
 #define TCP_MAX_WINDOW_SIZE	( 65536 - 4 )
239
 
239
 
240
+/**
241
+ * Path MTU
242
+ *
243
+ * We really ought to implement Path MTU discovery.  Until we do,
244
+ * anything with a path MTU greater than this may fail.
245
+ */
246
+#define TCP_PATH_MTU 1460
247
+
240
 /**
248
 /**
241
  * Advertised TCP MSS
249
  * Advertised TCP MSS
242
  *
250
  *

+ 34
- 16
src/net/tcp.c View File

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
  * Process TCP transmit queue
326
  * Process TCP transmit queue
306
  *
327
  *
363
 	unsigned int flags;
384
 	unsigned int flags;
364
 	size_t len = 0;
385
 	size_t len = 0;
365
 	size_t seq_len;
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
 	int rc;
389
 	int rc;
369
 
390
 
370
 	/* If retransmission timer is already running, do nothing */
391
 	/* If retransmission timer is already running, do nothing */
375
 	 * lengths that we wish to transmit.
396
 	 * lengths that we wish to transmit.
376
 	 */
397
 	 */
377
 	if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
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
 	seq_len = len;
402
 	seq_len = len;
381
 	flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
403
 	flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
410
 	tcp_process_queue ( tcp, len, iobuf, 0 );
432
 	tcp_process_queue ( tcp, len, iobuf, 0 );
411
 
433
 
412
 	/* Estimate window size */
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
 	/* Fill up the TCP header */
443
 	/* Fill up the TCP header */
422
 	payload = iobuf->data;
444
 	payload = iobuf->data;
434
 	tcphdr->ack = htonl ( tcp->rcv_ack );
456
 	tcphdr->ack = htonl ( tcp->rcv_ack );
435
 	tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
457
 	tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
436
 	tcphdr->flags = flags;
458
 	tcphdr->flags = flags;
437
-	tcphdr->win = htons ( window );
459
+	tcphdr->win = htons ( rcv_win );
438
 	tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
460
 	tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
439
 
461
 
440
 	/* Dump header */
462
 	/* Dump header */
910
 	struct tcp_connection *tcp =
932
 	struct tcp_connection *tcp =
911
 		container_of ( xfer, struct tcp_connection, xfer );
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
 	/* Not ready if data queue is non-empty.  This imposes a limit
935
 	/* Not ready if data queue is non-empty.  This imposes a limit
918
 	 * of only one unACKed packet in the TX queue at any time; we
936
 	 * of only one unACKed packet in the TX queue at any time; we
919
 	 * do this to conserve memory usage.
937
 	 * do this to conserve memory usage.
922
 		return 0;
940
 		return 0;
923
 
941
 
924
 	/* Return TCP window length */
942
 	/* Return TCP window length */
925
-	return tcp->snd_win;
943
+	return tcp_xmit_win ( tcp );
926
 }
944
 }
927
 
945
 
928
 /**
946
 /**

Loading…
Cancel
Save