[ipxe-devel] [PATCH] [netdevice] Make MTU configurable, obey DHCP option 26
Ladi Prosek
lprosek at redhat.com
Mon Nov 21 10:27:41 UTC 2016
On Wed, Nov 16, 2016 at 2:21 AM, Dan Callaghan <dcallagh at redhat.com> wrote:
> 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 );
Is this the only place that consumes max_pkt_len and should be
modified to take the new setting? For example, the two occurrences in
interface/efi/efi_snp.c look like they might be affected. Or if it's
really IP only, would it make more sense for the setting to be
SETTING_IP / SETTING_IP_EXTRA?
Thanks!
Ladi
> 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
>
> _______________________________________________
> ipxe-devel mailing list
> ipxe-devel at lists.ipxe.org
> https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel
More information about the ipxe-devel
mailing list