summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/nm-device-bridge.c7
-rw-r--r--src/devices/nm-device.c16
-rw-r--r--src/devices/nm-device.h11
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,