summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
authorMichael Brown2017-01-25 15:48:24 +0100
committerMichael Brown2017-01-25 15:55:09 +0100
commit70fc25ad6e71a99b5802eb92b95c26407acbe990 (patch)
treeb5b399a427584f7a78258601fa3d645b3a7ae16d /src/net
parent[interface] Unplug interface before calling intf_close() in intf_shutdown() (diff)
downloadipxe-70fc25ad6e71a99b5802eb92b95c26407acbe990.tar.gz
ipxe-70fc25ad6e71a99b5802eb92b95c26407acbe990.tar.xz
ipxe-70fc25ad6e71a99b5802eb92b95c26407acbe990.zip
[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>
Diffstat (limited to 'src/net')
-rw-r--r--src/net/infiniband/xsigo.c1
-rw-r--r--src/net/netdev_settings.c22
-rw-r--r--src/net/netdevice.c6
-rw-r--r--src/net/tcpip.c3
4 files changed, 23 insertions, 9 deletions
diff --git a/src/net/infiniband/xsigo.c b/src/net/infiniband/xsigo.c
index 91b7b71f..0ee753c3 100644
--- a/src/net/infiniband/xsigo.c
+++ b/src/net/infiniband/xsigo.c
@@ -323,6 +323,7 @@ static int xve_update_mtu ( struct xsigo_nic *xve, struct eoib_device *eoib,
* not the EoIB header.
*/
netdev->max_pkt_len = ( mtu + sizeof ( struct ethhdr ) );
+ netdev->mtu = mtu;
DBGC ( xve, "XVE %s has MTU %zd\n", xve->name, mtu );
return 0;
diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c
index 67a45bed..c54288d4 100644
--- a/src/net/netdev_settings.c
+++ b/src/net/netdev_settings.c
@@ -393,7 +393,8 @@ static int apply_netdev_settings ( void ) {
struct net_device *netdev;
struct settings *settings;
struct ll_protocol *ll_protocol;
- size_t old_max_pkt_len;
+ size_t max_mtu;
+ size_t old_mtu;
size_t mtu;
int rc;
@@ -410,18 +411,25 @@ static int apply_netdev_settings ( void ) {
if ( ! mtu )
continue;
- /* Update maximum packet length */
+ /* Limit MTU to maximum supported by hardware */
ll_protocol = netdev->ll_protocol;
- old_max_pkt_len = netdev->max_pkt_len;
- netdev->max_pkt_len = ( mtu + ll_protocol->ll_header_len );
- if ( netdev->max_pkt_len != old_max_pkt_len ) {
+ max_mtu = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
+ if ( mtu > max_mtu ) {
+ DBGC ( netdev, "NETDEV %s cannot support MTU %zd (max "
+ "%zd)\n", netdev->name, mtu, max_mtu );
+ mtu = max_mtu;
+ }
+
+ /* Update maximum packet length */
+ old_mtu = netdev->mtu;
+ netdev->mtu = mtu;
+ if ( mtu != old_mtu ) {
DBGC ( netdev, "NETDEV %s MTU is %zd\n",
netdev->name, mtu );
}
/* Close and reopen network device if MTU has increased */
- if ( netdev_is_open ( netdev ) &&
- ( netdev->max_pkt_len > old_max_pkt_len ) ) {
+ if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
netdev_close ( netdev );
if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
DBGC ( netdev, "NETDEV %s could not reopen: "
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 9df21196..41ece77f 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -663,6 +663,12 @@ int register_netdev ( struct net_device *netdev ) {
ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
}
+ /* Set MTU, if not already set */
+ if ( ! netdev->mtu ) {
+ netdev->mtu = ( netdev->max_pkt_len -
+ ll_protocol->ll_header_len );
+ }
+
/* Reject network devices that are already available via a
* different hardware device.
*/
diff --git a/src/net/tcpip.c b/src/net/tcpip.c
index c9e4ee78..cc7d0200 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 - tcpip_net->header_len );
return mtu;
}