diff options
-rw-r--r-- | src/devices/nm-device-bridge.c | 7 | ||||
-rw-r--r-- | src/devices/nm-device.c | 16 | ||||
-rw-r--r-- | src/devices/nm-device.h | 11 |
3 files changed, 34 insertions, 0 deletions
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index d9dbd5e356..48dcec1b1d 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -1103,6 +1103,12 @@ create_and_realize(NMDevice * device, to_sysfs_group_address_sys(nm_setting_bridge_get_group_address(s_bridge), &props.group_addr); + /* If mtu != 0, we set the MTU of the new bridge at creation time. However, kernel will still + * automatically adjust the MTU of the bridge based on the minimum of the slave's MTU. + * We don't want this automatism as the user asked for a fixed MTU. + * + * To workaround this behavior of kernel, we will later toggle the MTU twice. See + * NMDeviceClass.mtu_force_set. */ r = nm_platform_link_bridge_add(nm_device_get_platform(device), iface, hwaddr ? mac_address : NULL, @@ -1159,6 +1165,7 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_BRIDGE); device_class->is_master = TRUE; + device_class->mtu_force_set = TRUE; device_class->get_generic_capabilities = get_generic_capabilities; device_class->check_connection_compatible = check_connection_compatible; device_class->check_connection_available = check_connection_available; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f979251f89..63178a63c5 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -661,6 +661,8 @@ typedef struct _NMDevicePrivate { guint64 tx_bytes; guint64 rx_bytes; } stats; + + bool mtu_force_set_done : 1; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -10419,6 +10421,18 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) } } + if (mtu_desired && NM_DEVICE_GET_CLASS(self)->mtu_force_set && !priv->mtu_force_set_done) { + priv->mtu_force_set_done = TRUE; + + if (mtu_desired == mtu_plat) { + mtu_plat--; + if (NM_DEVICE_GET_CLASS(self)->set_platform_mtu(self, mtu_desired - 1)) { + _LOGD(LOGD_DEVICE, "mtu: force-set MTU to %u", mtu_desired - 1); + } else + _LOGW(LOGD_DEVICE, "mtu: failure to force-set MTU to %u", mtu_desired - 1); + } + } + _LOGT(LOGD_DEVICE, "mtu: device-mtu: %u%s, ipv6-mtu: %u%s, ifindex: %d", (guint) mtu_desired, @@ -15644,6 +15658,8 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) priv->linklocal6_dad_counter = 0; + priv->mtu_force_set_done = FALSE; + /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 008b69324b..d29a6a1506 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -232,6 +232,17 @@ typedef struct _NMDeviceClass { * type (NMDeviceClass), not the actual device instance. */ bool is_master : 1; + /* Force setting the MTU actually means first setting the MTU + * to (desired_MTU-1) and then setting the desired_MTU + * so that kernel actually applies the MTU, otherwise + * kernel will ignore the request if the link's MTU is the + * same as the desired one. + * + * This is just a workaround made for bridges (ATM) that employ + * a auto-MTU adjust mechanism if no MTU is manually set. + */ + bool mtu_force_set : 1; + void (*state_changed)(NMDevice * device, NMDeviceState new_state, NMDeviceState old_state, |