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
 	struct retry_timer link_block;
397
 	struct retry_timer link_block;
398
 	/** Maximum packet length
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
 	size_t max_pkt_len;
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
 	/** TX packet queue */
410
 	/** TX packet queue */
404
 	struct list_head tx_queue;
411
 	struct list_head tx_queue;
405
 	/** Deferred TX packet queue */
412
 	/** Deferred TX packet queue */

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

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

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

393
 	struct net_device *netdev;
393
 	struct net_device *netdev;
394
 	struct settings *settings;
394
 	struct settings *settings;
395
 	struct ll_protocol *ll_protocol;
395
 	struct ll_protocol *ll_protocol;
396
-	size_t old_max_pkt_len;
396
+	size_t max_mtu;
397
+	size_t old_mtu;
397
 	size_t mtu;
398
 	size_t mtu;
398
 	int rc;
399
 	int rc;
399
 
400
 
410
 		if ( ! mtu )
411
 		if ( ! mtu )
411
 			continue;
412
 			continue;
412
 
413
 
413
-		/* Update maximum packet length */
414
+		/* Limit MTU to maximum supported by hardware */
414
 		ll_protocol = netdev->ll_protocol;
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
 			DBGC ( netdev, "NETDEV %s MTU is %zd\n",
427
 			DBGC ( netdev, "NETDEV %s MTU is %zd\n",
419
 			       netdev->name, mtu );
428
 			       netdev->name, mtu );
420
 		}
429
 		}
421
 
430
 
422
 		/* Close and reopen network device if MTU has increased */
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
 			netdev_close ( netdev );
433
 			netdev_close ( netdev );
426
 			if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
434
 			if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
427
 				DBGC ( netdev, "NETDEV %s could not reopen: "
435
 				DBGC ( netdev, "NETDEV %s could not reopen: "

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

663
 		ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
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
 	/* Reject network devices that are already available via a
672
 	/* Reject network devices that are already available via a
667
 	 * different hardware device.
673
 	 * different hardware device.
668
 	 */
674
 	 */

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

144
 		return 0;
144
 		return 0;
145
 
145
 
146
 	/* Calculate MTU */
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
 	return mtu;
149
 	return mtu;
151
 }
150
 }

Loading…
Cancel
Save