diff options
author | Thomas Haller <thaller@redhat.com> | 2017-01-16 10:20:26 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-01-16 17:29:44 +0100 |
commit | 1e67c7ac0b63021ef6a7b669645a0da29f3ed1b9 (patch) | |
tree | 6f7c772c334c1ad8a8385d8de62695f942804bbd | |
parent | b5fcbdf5940d2b9e353fca393af694c02b466d0a (diff) |
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.
-rw-r--r-- | src/devices/nm-device.c | 63 |
1 files 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); } |