From 1e67c7ac0b63021ef6a7b669645a0da29f3ed1b9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 16 Jan 2017 10:20:26 +0100 Subject: device: reset previous MTU when device disconnects When you have a connection with "ethernet.mtu=0 (auto)", the MTU is not set during activation. That means, the effective MTU depends on the previous MTU configuration of the device. Which in turn, depends on the previously active connection, as we don't reset the MTU on deactivation. Restore the previous MTU on deactivation iff NetworkManager changed the MTU during device activation. --- src/devices/nm-device.c | 63 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 638b9d8320..3d4a96368a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -307,6 +307,9 @@ typedef struct _NMDevicePrivate { gulong ignore_carrier_id; guint32 mtu; guint32 ip6_mtu; + guint32 mtu_initial; + guint32 ip6_mtu_initial; + bool up; /* IFF_UP */ /* Generic DHCP stuff */ @@ -2570,6 +2573,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) /* Balanced by a thaw in nm_device_realize_finish() */ g_object_freeze_notify (G_OBJECT (self)); + priv->mtu_initial = 0; + priv->ip6_mtu_initial = 0; priv->ip6_mtu = 0; if (priv->mtu) { priv->mtu = 0; @@ -6599,6 +6604,10 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) guint32 ip6_mtu, ip6_mtu_orig; guint32 mtu_desired, mtu_desired_orig; guint32 mtu_plat; + struct { + gboolean initialized; + guint32 value; + } ip6_mtu_sysctl; int ifindex; char sbuf[64], sbuf1[64], sbuf2[64]; @@ -6658,23 +6667,41 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) } } - _LOGT (LOGD_DEVICE, "mtu: device-mtu: %u%s, ipv6-mtu: %u%s", + _LOGT (LOGD_DEVICE, "mtu: device-mtu: %u%s, ipv6-mtu: %u%s, ifindex: %d", (guint) mtu_desired, mtu_desired == mtu_desired_orig ? "" : nm_sprintf_buf (sbuf1, " (was %u)", (guint) mtu_desired_orig), (guint) ip6_mtu, - ip6_mtu == ip6_mtu_orig ? "" : nm_sprintf_buf (sbuf2, " (was %u)", (guint) ip6_mtu_orig)); - - if (mtu_desired) { - if (mtu_desired != mtu_plat) + ip6_mtu == ip6_mtu_orig ? "" : nm_sprintf_buf (sbuf2, " (was %u)", (guint) ip6_mtu_orig), + ifindex); + + ip6_mtu_sysctl.initialized = FALSE; +#define _IP6_MTU_SYS() \ + ({ \ + if (!ip6_mtu_sysctl.initialized) { \ + ip6_mtu_sysctl.value = nm_device_ipv6_sysctl_get_uint32 (self, "mtu", 0); \ + ip6_mtu_sysctl.initialized = TRUE; \ + } \ + ip6_mtu_sysctl.value; \ + }) + if ( (mtu_desired && mtu_desired != mtu_plat) + || (ip6_mtu && ip6_mtu != _IP6_MTU_SYS ())) { + + if (!priv->mtu_initial && !priv->ip6_mtu_initial) { + /* before touching any of the MTU paramters, record the + * original setting to restore on deactivation. */ + priv->mtu_initial = mtu_plat; + priv->ip6_mtu_initial = _IP6_MTU_SYS (); + } + + if (mtu_desired && mtu_desired != mtu_plat) nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, mtu_desired); - } - if (ip6_mtu) { - if (ip6_mtu != nm_device_ipv6_sysctl_get_uint32 (self, "mtu", 0)) { + if (ip6_mtu && ip6_mtu != _IP6_MTU_SYS ()) { nm_device_ipv6_sysctl_set (self, "mtu", nm_sprintf_buf (sbuf, "%u", (unsigned) ip6_mtu)); } } +#undef _IP6_MTU_SYS } static void @@ -11428,6 +11455,26 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean NM_DEVICE_GET_CLASS (self)->deactivate_reset_hw_addr (self); } + if (priv->mtu_initial || priv->ip6_mtu_initial) { + ifindex = nm_device_get_ip_ifindex (self); + + if ( ifindex > 0 + && cleanup_type == CLEANUP_TYPE_DECONFIGURE) { + _LOGT (LOGD_DEVICE, "mtu: reset device-mtu: %u, ipv6-mtu: %u, ifindex: %d", + (guint) priv->mtu_initial, (guint) priv->ip6_mtu_initial, ifindex); + if (priv->mtu_initial) + nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, priv->mtu_initial); + if (priv->ip6_mtu_initial) { + char sbuf[64]; + + nm_device_ipv6_sysctl_set (self, "mtu", + nm_sprintf_buf (sbuf, "%u", (unsigned) priv->ip6_mtu_initial)); + } + } + priv->mtu_initial = 0; + priv->ip6_mtu_initial = 0; + } + _cleanup_generic_post (self, cleanup_type); } -- cgit v1.2.3