Browse Source

[netdevice] Limit MTU by hardware maximum frame length

Separate out the concept of "hardware maximum supported frame length"
and "configured link MTU", and limit the latter according to the
former.

In networks where the DHCP-supplied link MTU is inconsistent with the
hardware or driver capabilities (e.g. a network using jumbo frames),
this will result in iPXE advertising a TCP MSS consistent with a size
that can actually be received.

Note that the term "MTU" is typically used to refer to the maximum
length excluding the link-layer headers; we adopt this usage.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
70fc25ad6e
5 changed files with 31 additions and 10 deletions
  1. 8
    1
      src/include/ipxe/netdevice.h
  2. 1
    0
      src/net/infiniband/xsigo.c
  3. 15
    7
      src/net/netdev_settings.c
  4. 6
    0
      src/net/netdevice.c
  5. 1
    2
      src/net/tcpip.c

+ 8
- 1
src/include/ipxe/netdevice.h View File

@@ -397,9 +397,16 @@ struct net_device {
397 397
 	struct retry_timer link_block;
398 398
 	/** Maximum packet length
399 399
 	 *
400
-	 * This length includes any link-layer headers.
400
+	 * This is the maximum packet length (including any link-layer
401
+	 * headers) supported by the hardware.
401 402
 	 */
402 403
 	size_t max_pkt_len;
404
+	/** Maximum transmission unit length
405
+	 *
406
+	 * This is the maximum transmission unit length (excluding any
407
+	 * link-layer headers) configured for the link.
408
+	 */
409
+	size_t mtu;
403 410
 	/** TX packet queue */
404 411
 	struct list_head tx_queue;
405 412
 	/** Deferred TX packet queue */

+ 1
- 0
src/net/infiniband/xsigo.c View File

@@ -323,6 +323,7 @@ static int xve_update_mtu ( struct xsigo_nic *xve, struct eoib_device *eoib,
323 323
 	 * not the EoIB header.
324 324
 	 */
325 325
 	netdev->max_pkt_len = ( mtu + sizeof ( struct ethhdr ) );
326
+	netdev->mtu = mtu;
326 327
 	DBGC ( xve, "XVE %s has MTU %zd\n", xve->name, mtu );
327 328
 
328 329
 	return 0;

+ 15
- 7
src/net/netdev_settings.c View File

@@ -393,7 +393,8 @@ static int apply_netdev_settings ( void ) {
393 393
 	struct net_device *netdev;
394 394
 	struct settings *settings;
395 395
 	struct ll_protocol *ll_protocol;
396
-	size_t old_max_pkt_len;
396
+	size_t max_mtu;
397
+	size_t old_mtu;
397 398
 	size_t mtu;
398 399
 	int rc;
399 400
 
@@ -410,18 +411,25 @@ static int apply_netdev_settings ( void ) {
410 411
 		if ( ! mtu )
411 412
 			continue;
412 413
 
413
-		/* Update maximum packet length */
414
+		/* Limit MTU to maximum supported by hardware */
414 415
 		ll_protocol = netdev->ll_protocol;
415
-		old_max_pkt_len = netdev->max_pkt_len;
416
-		netdev->max_pkt_len = ( mtu + ll_protocol->ll_header_len );
417
-		if ( netdev->max_pkt_len != old_max_pkt_len ) {
416
+		max_mtu = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
417
+		if ( mtu > max_mtu ) {
418
+			DBGC ( netdev, "NETDEV %s cannot support MTU %zd (max "
419
+			       "%zd)\n", netdev->name, mtu, max_mtu );
420
+			mtu = max_mtu;
421
+		}
422
+
423
+		/* Update maximum packet length */
424
+		old_mtu = netdev->mtu;
425
+		netdev->mtu = mtu;
426
+		if ( mtu != old_mtu ) {
418 427
 			DBGC ( netdev, "NETDEV %s MTU is %zd\n",
419 428
 			       netdev->name, mtu );
420 429
 		}
421 430
 
422 431
 		/* Close and reopen network device if MTU has increased */
423
-		if ( netdev_is_open ( netdev ) &&
424
-		     ( netdev->max_pkt_len > old_max_pkt_len ) ) {
432
+		if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
425 433
 			netdev_close ( netdev );
426 434
 			if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
427 435
 				DBGC ( netdev, "NETDEV %s could not reopen: "

+ 6
- 0
src/net/netdevice.c View File

@@ -663,6 +663,12 @@ int register_netdev ( struct net_device *netdev ) {
663 663
 		ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
664 664
 	}
665 665
 
666
+	/* Set MTU, if not already set */
667
+	if ( ! netdev->mtu ) {
668
+		netdev->mtu = ( netdev->max_pkt_len -
669
+				ll_protocol->ll_header_len );
670
+	}
671
+
666 672
 	/* Reject network devices that are already available via a
667 673
 	 * different hardware device.
668 674
 	 */

+ 1
- 2
src/net/tcpip.c View File

@@ -144,8 +144,7 @@ size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest ) {
144 144
 		return 0;
145 145
 
146 146
 	/* Calculate MTU */
147
-	mtu = ( netdev->max_pkt_len - netdev->ll_protocol->ll_header_len -
148
-		tcpip_net->header_len );
147
+	mtu = ( netdev->mtu - tcpip_net->header_len );
149 148
 
150 149
 	return mtu;
151 150
 }

Loading…
Cancel
Save