Browse Source

[tcp] Calculate correct MSS from peer address

iPXE currently advertises a fixed MSS of 1460, which is correct only
for IPv4 over Ethernet.  For IPv6 over Ethernet, the value should be
1440 (allowing for the larger IPv6 header).  For non-Ethernet link
layers, the value should reflect the MTU of the underlying network
device.

Use tcpip_mtu() to calculate the transport-layer MTU associated with
the peer address, and calculate the MSS to allow for an optionless TCP
header as per RFC 6691.

As a side benefit, we can now fail a connection immediately with a
meaningful error message if we have no route to the destination
address.

Reported-by: Anton D. Kachalov <mouse@yandex-team.ru>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
e191298a1d
2 changed files with 14 additions and 11 deletions
  1. 0
    10
      src/include/ipxe/tcp.h
  2. 14
    1
      src/net/tcp.c

+ 0
- 10
src/include/ipxe/tcp.h View File

330
 #define TCP_PATH_MTU							\
330
 #define TCP_PATH_MTU							\
331
 	( 1280 - 40 /* IPv6 */ - 20 /* TCP */ - 12 /* TCP timestamp */ )
331
 	( 1280 - 40 /* IPv6 */ - 20 /* TCP */ - 12 /* TCP timestamp */ )
332
 
332
 
333
-/**
334
- * Advertised TCP MSS
335
- *
336
- * We currently hardcode this to a reasonable value and hope that the
337
- * sender uses path MTU discovery.  The alternative is breaking the
338
- * abstraction layer so that we can find out the MTU from the IP layer
339
- * (which would have to find out from the net device layer).
340
- */
341
-#define TCP_MSS 1460
342
-
343
 /** TCP maximum segment lifetime
333
 /** TCP maximum segment lifetime
344
  *
334
  *
345
  * Currently set to 2 minutes, as per RFC 793.
335
  * Currently set to 2 minutes, as per RFC 793.

+ 14
- 1
src/net/tcp.c View File

43
 	struct sockaddr_tcpip peer;
43
 	struct sockaddr_tcpip peer;
44
 	/** Local port */
44
 	/** Local port */
45
 	unsigned int local_port;
45
 	unsigned int local_port;
46
+	/** Maximum segment size */
47
+	size_t mss;
46
 
48
 
47
 	/** Current TCP state */
49
 	/** Current TCP state */
48
 	unsigned int tcp_state;
50
 	unsigned int tcp_state;
250
 	struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
252
 	struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
251
 	struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
253
 	struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
252
 	struct tcp_connection *tcp;
254
 	struct tcp_connection *tcp;
255
+	size_t mtu;
253
 	int port;
256
 	int port;
254
 	int rc;
257
 	int rc;
255
 
258
 
271
 	INIT_LIST_HEAD ( &tcp->rx_queue );
274
 	INIT_LIST_HEAD ( &tcp->rx_queue );
272
 	memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
275
 	memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
273
 
276
 
277
+	/* Calculate MSS */
278
+	mtu = tcpip_mtu ( &tcp->peer );
279
+	if ( ! mtu ) {
280
+		DBGC ( tcp, "TCP %p has no route to %s\n",
281
+		       tcp, sock_ntoa ( peer ) );
282
+		rc = -ENETUNREACH;
283
+		goto err;
284
+	}
285
+	tcp->mss = ( mtu - sizeof ( struct tcp_header ) );
286
+
274
 	/* Bind to local port */
287
 	/* Bind to local port */
275
 	port = tcpip_bind ( st_local, tcp_port_available );
288
 	port = tcpip_bind ( st_local, tcp_port_available );
276
 	if ( port < 0 ) {
289
 	if ( port < 0 ) {
552
 		mssopt = iob_push ( iobuf, sizeof ( *mssopt ) );
565
 		mssopt = iob_push ( iobuf, sizeof ( *mssopt ) );
553
 		mssopt->kind = TCP_OPTION_MSS;
566
 		mssopt->kind = TCP_OPTION_MSS;
554
 		mssopt->length = sizeof ( *mssopt );
567
 		mssopt->length = sizeof ( *mssopt );
555
-		mssopt->mss = htons ( TCP_MSS );
568
+		mssopt->mss = htons ( tcp->mss );
556
 		wsopt = iob_push ( iobuf, sizeof ( *wsopt ) );
569
 		wsopt = iob_push ( iobuf, sizeof ( *wsopt ) );
557
 		wsopt->nop = TCP_OPTION_NOP;
570
 		wsopt->nop = TCP_OPTION_NOP;
558
 		wsopt->wsopt.kind = TCP_OPTION_WS;
571
 		wsopt->wsopt.kind = TCP_OPTION_WS;

Loading…
Cancel
Save