[ipxe-devel] [PATCH] [netdevice] Make MTU configurable, obey DHCP option 26

Dan Callaghan dcallagh at redhat.com
Wed Nov 16 01:21:46 UTC 2016


iPXE is already assuming a conservative MTU in the TCP transmission code
path (tcp_xmit_win() is using TCP_PATH_MTU, which is calculated assuming
a network-layer MTU of 1280).

However, MTU is also used to determine the TCP Maximum Segment Size.
Currently tcpip_mtu() is assuming the network layer can receive full
length packets (1500 in the case of IPv4 over Ethernet). In some
scenarios this is not a valid assumption, for example when the network
is Ethernet encapsulated in something else. This is common in OpenStack
virtualised networks.

In those cases the administrator may need to configure a lower MTU than
the default, either explicitly or using DHCP option 26.

Signed-off-by: Dan Callaghan <dcallagh at redhat.com>
---
 src/include/ipxe/dhcp.h      |  3 +++
 src/include/ipxe/netdevice.h |  1 +
 src/include/ipxe/settings.h  |  2 ++
 src/net/netdev_settings.c    |  6 ++++++
 src/net/netdevice.c          | 22 ++++++++++++++++++++++
 src/net/tcpip.c              |  3 +--
 src/net/udp/dhcp.c           |  6 +++---
 7 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h
index b699b31..189468a 100644
--- a/src/include/ipxe/dhcp.h
+++ b/src/include/ipxe/dhcp.h
@@ -83,6 +83,9 @@ struct dhcp_packet;
 /** Root path */
 #define DHCP_ROOT_PATH 17
 
+/** MTU */
+#define DHCP_MTU 26
+
 /** Vendor encapsulated options */
 #define DHCP_VENDOR_ENCAP 43
 
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index a1d207f..4fb45c7 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -680,6 +680,7 @@ netdev_rx_frozen ( struct net_device *netdev ) {
 	return ( netdev->state & NETDEV_RX_FROZEN );
 }
 
+extern size_t netdev_mtu ( struct net_device *netdev );
 extern void netdev_rx_freeze ( struct net_device *netdev );
 extern void netdev_rx_unfreeze ( struct net_device *netdev );
 extern void netdev_link_err ( struct net_device *netdev, int rc );
diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h
index 341fc3c..2d8f241 100644
--- a/src/include/ipxe/settings.h
+++ b/src/include/ipxe/settings.h
@@ -466,6 +466,8 @@ mac_setting __setting ( SETTING_NETDEV, mac );
 extern const struct setting
 busid_setting __setting ( SETTING_NETDEV, busid );
 extern const struct setting
+mtu_setting __setting ( SETTING_NETDEV, mtu );
+extern const struct setting
 user_class_setting __setting ( SETTING_HOST_EXTRA, user-class );
 extern const struct setting
 manufacturer_setting __setting ( SETTING_HOST_EXTRA, manufacturer );
diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c
index 7d893a1..73d1d67 100644
--- a/src/net/netdev_settings.c
+++ b/src/net/netdev_settings.c
@@ -70,6 +70,12 @@ const struct setting ifname_setting __setting ( SETTING_NETDEV, ifname ) = {
 	.description = "Interface name",
 	.type = &setting_type_string,
 };
+const struct setting mtu_setting __setting ( SETTING_NETDEV, mtu ) = {
+	.name = "mtu",
+	.description = "Network-layer Maximum Transmission Unit (MTU)",
+	.type = &setting_type_uint16,
+	.tag = DHCP_MTU,
+};
 
 /**
  * Store MAC address setting
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 9df2119..8e6e7f8 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -127,6 +127,28 @@ static void netdev_notify ( struct net_device *netdev ) {
 }
 
 /**
+ * Returns the network-layer Maximum Transmission Unit
+ *
+ * This is configurable at runtime with the "mtu" setting, either explicitly or
+ * through DHCP option 26. Otherwise uses the value determined by the driver
+ * (if any) or the protocol default.
+ *
+ * @v			Network device
+ * @ret 		Computed network-layer MTU
+ */
+size_t netdev_mtu ( struct net_device *netdev ) {
+	unsigned long mtu;
+
+	/* Use MTU from settings if one is set */
+	if ( fetch_uint_setting ( netdev_settings ( netdev ), &mtu_setting,
+				  &mtu ) >= 0 )
+		return mtu;
+
+	/* Use default */
+	return ( netdev->max_pkt_len - netdev->ll_protocol->ll_header_len );
+}
+
+/**
  * Freeze network device receive queue processing
  *
  * @v netdev		Network device
diff --git a/src/net/tcpip.c b/src/net/tcpip.c
index c9e4ee7..9c439a5 100644
--- a/src/net/tcpip.c
+++ b/src/net/tcpip.c
@@ -144,8 +144,7 @@ size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest ) {
 		return 0;
 
 	/* Calculate MTU */
-	mtu = ( netdev->max_pkt_len - netdev->ll_protocol->ll_header_len -
-		tcpip_net->header_len );
+	mtu = ( netdev_mtu ( netdev ) - tcpip_net->header_len );
 
 	return mtu;
 }
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index b9c1fd9..95f8082 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -91,9 +91,9 @@ static uint8_t dhcp_request_options_data[] = {
 	DHCP_PARAMETER_REQUEST_LIST,
 	DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
 		      DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
-		      DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
-		      DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
-		      DHCP_DOMAIN_SEARCH,
+		      DHCP_ROOT_PATH, DHCP_MTU, DHCP_VENDOR_ENCAP,
+		      DHCP_VENDOR_CLASS_ID, DHCP_TFTP_SERVER_NAME,
+		      DHCP_BOOTFILE_NAME, DHCP_DOMAIN_SEARCH,
 		      128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
 		      DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
 	DHCP_END
-- 
2.7.4




More information about the ipxe-devel mailing list