diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h index b699b31f..23f16aaa 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 +/** Maximum transmission unit */ +#define DHCP_MTU 26 + /** Vendor encapsulated options */ #define DHCP_VENDOR_ENCAP 43 diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 7d893a12..67a45bed 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 = "MTU", + .type = &setting_type_int16, + .tag = DHCP_MTU, +}; /** * Store MAC address setting @@ -377,3 +383,58 @@ static void netdev_redirect_settings_init ( void ) { struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = { .initialise = netdev_redirect_settings_init, }; + +/** + * Apply network device settings + * + * @ret rc Return status code + */ +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 mtu; + int rc; + + /* Process settings for each network device */ + for_each_netdev ( netdev ) { + + /* Get network device settings */ + settings = netdev_settings ( netdev ); + + /* Get MTU */ + mtu = fetch_uintz_setting ( settings, &mtu_setting ); + + /* Do nothing unless MTU is specified */ + if ( ! mtu ) + continue; + + /* Update maximum packet length */ + 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 ) { + 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 ) ) { + netdev_close ( netdev ); + if ( ( rc = netdev_open ( netdev ) ) != 0 ) { + DBGC ( netdev, "NETDEV %s could not reopen: " + "%s\n", netdev->name, strerror ( rc ) ); + return rc; + } + } + } + + return 0; +} + +/** Network device settings applicator */ +struct settings_applicator netdev_applicator __settings_applicator = { + .apply = apply_netdev_settings, +}; diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index b9c1fd90..95f80821 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