summaryrefslogtreecommitdiffstats
path: root/src/net/netdev_settings.c
diff options
context:
space:
mode:
authorMichael Brown2017-01-23 18:47:28 +0100
committerMichael Brown2017-01-23 18:47:28 +0100
commit16aed6e5ce808615df95c7767b4dd8793c398d93 (patch)
tree18d3b12c515078ea904e5db21940fecf34084097 /src/net/netdev_settings.c
parent[virtio] Use host-specified MTU when available (diff)
downloadipxe-16aed6e5ce808615df95c7767b4dd8793c398d93.tar.gz
ipxe-16aed6e5ce808615df95c7767b4dd8793c398d93.tar.xz
ipxe-16aed6e5ce808615df95c7767b4dd8793c398d93.zip
[netdevice] Allow MTU to be changed at runtime
Provide a settings applicator to modify netdev->max_pkt_len in response to changes to the "mtu" setting (DHCP option 26). Note that as with MAC address changes, drivers are permitted to completely ignore any changes in the MTU value. The net result will be that iPXE effectively uses the smaller of either the hardware default MTU or the software configured MTU. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/netdev_settings.c')
-rw-r--r--src/net/netdev_settings.c61
1 files changed, 61 insertions, 0 deletions
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,
+};