diff options
author | Antonio Cardace <acardace@redhat.com> | 2020-10-21 18:57:18 +0200 |
---|---|---|
committer | Antonio Cardace <acardace@redhat.com> | 2020-11-02 17:23:22 +0100 |
commit | e23798a5e5e8d7eb615f0e8b305fc20b8b645c66 (patch) | |
tree | 5a3056f826f821e34c960c4db4e1c72b2feed09e | |
parent | 516c6236183b361eccf3e0693616b48c680d0f7b (diff) | |
download | NetworkManager-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.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, |