Kaynağa Gözat

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 yıl önce
ebeveyn
işleme
edded7546e
2 değiştirilmiş dosya ile 42 ekleme ve 16 silme
  1. 8
    0
      src/include/gpxe/tcp.h
  2. 34
    16
      src/net/tcp.c

+ 8
- 0
src/include/gpxe/tcp.h Dosyayı Görüntüle

@@ -237,6 +237,14 @@ struct tcp_mss_option {
237 237
  */
238 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 249
  * Advertised TCP MSS
242 250
  *

+ 34
- 16
src/net/tcp.c Dosyayı Görüntüle

@@ -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
 /**

Loading…
İptal
Kaydet