summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-01-16 10:20:26 +0100
committerThomas Haller <thaller@redhat.com>2017-01-16 17:29:44 +0100
commit1e67c7ac0b63021ef6a7b669645a0da29f3ed1b9 (patch)
tree6f7c772c334c1ad8a8385d8de62695f942804bbd
parentb5fcbdf5940d2b9e353fca393af694c02b466d0a (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.c63
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);
}