summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cardace <acardace@redhat.com>2020-10-21 18:57:18 +0200
committerAntonio Cardace <acardace@redhat.com>2020-11-02 17:23:22 +0100
commite23798a5e5e8d7eb615f0e8b305fc20b8b645c66 (patch)
tree5a3056f826f821e34c960c4db4e1c72b2feed09e
parent516c6236183b361eccf3e0693616b48c680d0f7b (diff)
downloadNetworkManager-e23798a5e5e8d7eb615f0e8b305fc20b8b645c66.tar.gz
bridge: force (hack)-set of the MTU when explicitly set in the profileac/bridge_mtu_autoadjust
Kernel does a auto-mtu adjusting process whenever a port is added/removed from the bridge, this can cause issues when NM wants to explicitly set an MTU which is equal to the bridge default one (1500) because if later a port is added with a different MTU the kernel will assign the bridge that port's MTU resulting in the bridge runtime configuration differing from the bridge's NM connection profile. What we can do is to always apply the MTU manually for the bridge (if explicitly set by the profile), after doing so the kernel won't modify the MTU anymore, which is what we want, problem is that kernel won't actually apply the MTU to the netdev if it's not actually changing so we first apply it to MTU-1 and then to the desired value. https://bugzilla.redhat.com/show_bug.cgi?id=1778590 Signed-off-by: Antonio Cardace <acardace@redhat.com>
-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,