Blame SOURCES/1003-keep-mtu-after-parent-change-rh1751079

4e1021
From 738b3feab24500406fc685ddddbe99975088d253 Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Wed, 18 Sep 2019 10:54:13 +0200
4e1021
Subject: [PATCH 1/6] device: reset ip6_mtu on cleanup
4e1021
4e1021
ip6_mtu contains the MTU received through IPv6 autoconfiguration; it
4e1021
should be reset when the connection is deactivated.
4e1021
4e1021
https://bugzilla.redhat.com/show_bug.cgi?id=1753128
4e1021
(cherry picked from commit 353c7c95c1c664c024c4267e67ed2d4b57b44437)
4e1021
(cherry picked from commit f35783c3fba244fea926528bc6d0a2ba4d1c44ad)
4e1021
---
4e1021
 src/devices/nm-device.c | 1 +
4e1021
 1 file changed, 1 insertion(+)
4e1021
4e1021
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
4e1021
index f07c4f09a..66bbf0a84 100644
4e1021
--- a/src/devices/nm-device.c
4e1021
+++ b/src/devices/nm-device.c
4e1021
@@ -14781,6 +14781,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
4e1021
 	}
4e1021
 
4e1021
 	priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
4e1021
+	priv->ip6_mtu = 0;
4e1021
 	if (priv->mtu_initial || priv->ip6_mtu_initial) {
4e1021
 		ifindex = nm_device_get_ip_ifindex (self);
4e1021
 
4e1021
-- 
4e1021
2.21.0
4e1021
4e1021
From eac2aaa09ac60383d928831a257c6e0713e3fb38 Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Wed, 11 Sep 2019 10:57:07 +0200
4e1021
Subject: [PATCH 2/6] device: expand comment on MTU selection
4e1021
4e1021
(cherry picked from commit 6455a4e52852a936ae34e6596a2d309a44fb8fcc)
4e1021
(cherry picked from commit 37720d856a1cbaf2bff31a080756ccaff247319b)
4e1021
---
4e1021
 src/devices/nm-device.c | 18 +++++++++++++++---
4e1021
 1 file changed, 15 insertions(+), 3 deletions(-)
4e1021
4e1021
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
4e1021
index 66bbf0a84..52fe17771 100644
4e1021
--- a/src/devices/nm-device.c
4e1021
+++ b/src/devices/nm-device.c
4e1021
@@ -9324,9 +9324,21 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
4e1021
 	{
4e1021
 		guint32 mtu = 0;
4e1021
 
4e1021
-		/* preferably, get the MTU from explicit user-configuration.
4e1021
-		 * Only if that fails, look at the current @config (which contains
4e1021
-		 * MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */
4e1021
+		/* We take the MTU from various sources: (in order of increasing
4e1021
+		 * priority) parent link, IP configuration (which contains the
4e1021
+		 * MTU from DHCP/PPP), connection profile.
4e1021
+		 *
4e1021
+		 * We could just compare it with the platform MTU and apply it
4e1021
+		 * when different, but this would revert at random times manual
4e1021
+		 * changes done by the user with the MTU from the connection.
4e1021
+		 *
4e1021
+		 * Instead, we remember the source of the currently configured
4e1021
+		 * MTU and apply the new one only when the new source has a
4e1021
+		 * higher priority, so that we don't set a MTU from same source
4e1021
+		 * multiple times. An exception to this is for the PARENT
4e1021
+		 * source, since we need to keep tracking the parent MTU when it
4e1021
+		 * changes.
4e1021
+		 */
4e1021
 
4e1021
 		if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
4e1021
 			mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source);
4e1021
-- 
4e1021
2.21.0
4e1021
4e1021
From 0f64ecf35508654437ca82eb1d6a4c0e489a5017 Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Thu, 12 Sep 2019 17:29:49 +0200
4e1021
Subject: [PATCH 3/6] device: introduce generic function to inherit MTU from
4e1021
 parent
4e1021
4e1021
Introduce a generic function to set a MTU based on parent's one. Also
4e1021
define a device-specific @mtu_parent_delta value that specifies the
4e1021
difference from parent MTU that should be set by default. For VLAN it
4e1021
is zero but other interface types (for example MACsec) require a
4e1021
positive value due to encapsulation overhead.
4e1021
4e1021
(cherry picked from commit 5cf57f452233b1211fcff7c8cf689d9d5cb48092)
4e1021
(cherry picked from commit 73597864bb0a229ce33d9072a3f73f96443f1fe7)
4e1021
---
4e1021
 src/devices/nm-device-private.h |  3 +++
4e1021
 src/devices/nm-device-vlan.c    | 23 ++---------------------
4e1021
 src/devices/nm-device.c         | 27 +++++++++++++++++++++++++++
4e1021
 src/devices/nm-device.h         |  4 ++++
4e1021
 4 files changed, 36 insertions(+), 21 deletions(-)
4e1021
4e1021
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
4e1021
index 0a414af96..3caa82ee1 100644
4e1021
--- a/src/devices/nm-device-private.h
4e1021
+++ b/src/devices/nm-device-private.h
4e1021
@@ -176,6 +176,9 @@ guint32 nm_device_get_configured_mtu_from_connection (NMDevice *device,
4e1021
 
4e1021
 guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source);
4e1021
 
4e1021
+guint32 nm_device_get_configured_mtu_wired_parent (NMDevice *self,
4e1021
+                                                   NMDeviceMtuSource *out_source);
4e1021
+
4e1021
 void nm_device_commit_mtu (NMDevice *self);
4e1021
 
4e1021
 /*****************************************************************************/
4e1021
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
4e1021
index 0467a6e45..f8f6a5976 100644
4e1021
--- a/src/devices/nm-device-vlan.c
4e1021
+++ b/src/devices/nm-device-vlan.c
4e1021
@@ -523,26 +523,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
4e1021
 	return ret;
4e1021
 }
4e1021
 
4e1021
-static guint32
4e1021
-get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source)
4e1021
-{
4e1021
-	guint32 mtu = 0;
4e1021
-	int ifindex;
4e1021
-
4e1021
-	mtu = nm_device_get_configured_mtu_for_wired (self, out_source);
4e1021
-	if (*out_source != NM_DEVICE_MTU_SOURCE_NONE)
4e1021
-		return mtu;
4e1021
-
4e1021
-	/* Inherit the MTU from parent device, if any */
4e1021
-	ifindex = nm_device_parent_get_ifindex (self);
4e1021
-	if (ifindex > 0) {
4e1021
-		mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex);
4e1021
-		*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
4e1021
-	}
4e1021
-
4e1021
-	return mtu;
4e1021
-}
4e1021
-
4e1021
 /*****************************************************************************/
4e1021
 
4e1021
 static void
4e1021
@@ -598,13 +578,14 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
4e1021
 	device_class->connection_type_supported = NM_SETTING_VLAN_SETTING_NAME;
4e1021
 	device_class->connection_type_check_compatible = NM_SETTING_VLAN_SETTING_NAME;
4e1021
 	device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VLAN);
4e1021
+	device_class->mtu_parent_delta = 0; /* VLANs can have the same MTU of parent */
4e1021
 
4e1021
 	device_class->create_and_realize = create_and_realize;
4e1021
 	device_class->link_changed = link_changed;
4e1021
 	device_class->unrealize_notify = unrealize_notify;
4e1021
 	device_class->get_generic_capabilities = get_generic_capabilities;
4e1021
 	device_class->act_stage1_prepare = act_stage1_prepare;
4e1021
-	device_class->get_configured_mtu = get_configured_mtu;
4e1021
+	device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
4e1021
 	device_class->is_available = is_available;
4e1021
 	device_class->parent_changed_notify = parent_changed_notify;
4e1021
 
4e1021
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
4e1021
index 52fe17771..570f57146 100644
4e1021
--- a/src/devices/nm-device.c
4e1021
+++ b/src/devices/nm-device.c
4e1021
@@ -9272,6 +9272,33 @@ nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_s
4e1021
 	                                                     out_source);
4e1021
 }
4e1021
 
4e1021
+guint32
4e1021
+nm_device_get_configured_mtu_wired_parent (NMDevice *self,
4e1021
+                                           NMDeviceMtuSource *out_source)
4e1021
+{
4e1021
+	guint32 mtu = 0;
4e1021
+	int ifindex;
4e1021
+
4e1021
+	mtu = nm_device_get_configured_mtu_for_wired (self, out_source);
4e1021
+	if (*out_source != NM_DEVICE_MTU_SOURCE_NONE) {
4e1021
+		nm_assert (mtu > 0);
4e1021
+		return mtu;
4e1021
+	}
4e1021
+
4e1021
+	/* Inherit the MTU from parent device, if any */
4e1021
+	ifindex = nm_device_parent_get_ifindex (self);
4e1021
+	if (ifindex > 0) {
4e1021
+		mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex);
4e1021
+		if (mtu >= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta) {
4e1021
+			mtu -= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta;
4e1021
+			*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
4e1021
+		} else
4e1021
+			mtu = 0;
4e1021
+	}
4e1021
+
4e1021
+	return mtu;
4e1021
+}
4e1021
+
4e1021
 /*****************************************************************************/
4e1021
 
4e1021
 static void
4e1021
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
4e1021
index ae6aab392..32efbd3de 100644
4e1021
--- a/src/devices/nm-device.h
4e1021
+++ b/src/devices/nm-device.h
4e1021
@@ -239,6 +239,10 @@ typedef struct _NMDeviceClass {
4e1021
 
4e1021
 	const NMLinkType *link_types;
4e1021
 
4e1021
+	/* if the device MTU is set based on parent's one, this specifies
4e1021
+	 * a delta in the MTU allowed value due the encapsulation overhead */
4e1021
+	guint16 mtu_parent_delta;
4e1021
+
4e1021
 	/* Whether the device type is a master-type. This depends purely on the
4e1021
 	 * type (NMDeviceClass), not the actual device instance. */
4e1021
 	bool is_master:1;
4e1021
-- 
4e1021
2.21.0
4e1021
4e1021
From 0f5e91d45a9e8fd61bbe18b077d346ec0402eb70 Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Thu, 12 Sep 2019 17:33:49 +0200
4e1021
Subject: [PATCH 4/6] macsec: update MTU according to parent's one
4e1021
4e1021
A MACsec connection doesn't have an ordering dependency with its
4e1021
parent connection and so it's possible that the parent gets activated
4e1021
later and sets a greater MTU than the original one.
4e1021
4e1021
It is reasonable and useful to keep the MACsec MTU configured by
4e1021
default as the maximum allowed by the parent interface, that is the
4e1021
parent MTU minus the encapsulation overhead (32). The user can of
4e1021
course override this by setting an explicit value in the
4e1021
connection. We already do something similar for VLANs.
4e1021
4e1021
https://bugzilla.redhat.com/show_bug.cgi?id=1723690
4e1021
(cherry picked from commit 438a0a9ad5287a82b1872c9783cc8fa4b548d49e)
4e1021
(cherry picked from commit c58ce8945def15192bd9d70ef039fd71e846fdcf)
4e1021
---
4e1021
 src/devices/nm-device-macsec.c | 23 ++++++++++++++++++++++-
4e1021
 1 file changed, 22 insertions(+), 1 deletion(-)
4e1021
4e1021
diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c
4e1021
index e3e3a895b..13798f5e7 100644
4e1021
--- a/src/devices/nm-device-macsec.c
4e1021
+++ b/src/devices/nm-device-macsec.c
4e1021
@@ -66,6 +66,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacsec,
4e1021
 typedef struct {
4e1021
 	NMPlatformLnkMacsec props;
4e1021
 	gulong parent_state_id;
4e1021
+	gulong parent_mtu_id;
4e1021
 	Supplicant supplicant;
4e1021
 	guint supplicant_timeout_id;
4e1021
 	NMActRequestGetSecretsCallId *macsec_secrets_id;
4e1021
@@ -113,6 +114,17 @@ parent_state_changed (NMDevice *parent,
4e1021
 	nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
4e1021
 }
4e1021
 
4e1021
+static void
4e1021
+parent_mtu_maybe_changed (NMDevice *parent,
4e1021
+                          GParamSpec *pspec,
4e1021
+                          gpointer user_data)
4e1021
+{
4e1021
+	/* the MTU of a MACsec device is limited by the parent's MTU.
4e1021
+	 *
4e1021
+	 * When the parent's MTU changes, try to re-set the MTU. */
4e1021
+	nm_device_commit_mtu (user_data);
4e1021
+}
4e1021
+
4e1021
 static void
4e1021
 parent_changed_notify (NMDevice *device,
4e1021
                        int old_ifindex,
4e1021
@@ -133,12 +145,16 @@ parent_changed_notify (NMDevice *device,
4e1021
 	 *  because NMDevice's dispose() will unset the parent, which in turn calls
4e1021
 	 *  parent_changed_notify(). */
4e1021
 	nm_clear_g_signal_handler (old_parent, &priv->parent_state_id);
4e1021
+	nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id);
4e1021
 
4e1021
 	if (new_parent) {
4e1021
 		priv->parent_state_id = g_signal_connect (new_parent,
4e1021
 		                                          NM_DEVICE_STATE_CHANGED,
4e1021
 		                                          G_CALLBACK (parent_state_changed),
4e1021
 		                                          device);
4e1021
+		priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU,
4e1021
+		                                        G_CALLBACK (parent_mtu_maybe_changed), device);
4e1021
+
4e1021
 
4e1021
 		/* Set parent-dependent unmanaged flag */
4e1021
 		nm_device_set_unmanaged_by_flags (device,
4e1021
@@ -791,11 +807,15 @@ static void
4e1021
 dispose (GObject *object)
4e1021
 {
4e1021
 	NMDeviceMacsec *self = NM_DEVICE_MACSEC (object);
4e1021
+	NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
4e1021
 
4e1021
 	macsec_secrets_cancel (self);
4e1021
 	supplicant_interface_release (self);
4e1021
 
4e1021
 	G_OBJECT_CLASS (nm_device_macsec_parent_class)->dispose (object);
4e1021
+
4e1021
+	nm_assert (priv->parent_state_id == 0);
4e1021
+	nm_assert (priv->parent_mtu_id == 0);
4e1021
 }
4e1021
 
4e1021
 static const NMDBusInterfaceInfoExtended interface_info_device_macsec = {
4e1021
@@ -838,6 +858,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
4e1021
 	device_class->connection_type_supported = NM_SETTING_MACSEC_SETTING_NAME;
4e1021
 	device_class->connection_type_check_compatible = NM_SETTING_MACSEC_SETTING_NAME;
4e1021
 	device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACSEC);
4e1021
+	device_class->mtu_parent_delta = 32;
4e1021
 
4e1021
 	device_class->act_stage2_config = act_stage2_config;
4e1021
 	device_class->create_and_realize = create_and_realize;
4e1021
@@ -847,7 +868,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
4e1021
 	device_class->is_available = is_available;
4e1021
 	device_class->parent_changed_notify = parent_changed_notify;
4e1021
 	device_class->state_changed = device_state_changed;
4e1021
-	device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
4e1021
+	device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
4e1021
 
4e1021
 	obj_properties[PROP_SCI] =
4e1021
 	    g_param_spec_uint64 (NM_DEVICE_MACSEC_SCI, "", "",
4e1021
-- 
4e1021
2.21.0
4e1021
4e1021
From 2bbe0e352b9f6f0bc417f6c5a8c376ee750272cb Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Fri, 13 Sep 2019 11:40:51 +0200
4e1021
Subject: [PATCH 5/6] macvlan: update MTU according to parent's one
4e1021
4e1021
(cherry picked from commit 4875745bc09c2f535cd28c13ea864cffbce37b0a)
4e1021
(cherry picked from commit 9133ba90033188ae5a11ab0897a2640d1c6c33bd)
4e1021
---
4e1021
 src/devices/nm-device-macvlan.c | 30 +++++++++++++++++++++++++++++-
4e1021
 1 file changed, 29 insertions(+), 1 deletion(-)
4e1021
4e1021
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
4e1021
index 709f98dab..260231215 100644
4e1021
--- a/src/devices/nm-device-macvlan.c
4e1021
+++ b/src/devices/nm-device-macvlan.c
4e1021
@@ -48,6 +48,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacvlan,
4e1021
 
4e1021
 typedef struct {
4e1021
 	gulong parent_state_id;
4e1021
+	gulong parent_mtu_id;
4e1021
 	NMPlatformLnkMacvlan props;
4e1021
 } NMDeviceMacvlanPrivate;
4e1021
 
4e1021
@@ -134,6 +135,17 @@ parent_state_changed (NMDevice *parent,
4e1021
 	nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
4e1021
 }
4e1021
 
4e1021
+static void
4e1021
+parent_mtu_maybe_changed (NMDevice *parent,
4e1021
+                          GParamSpec *pspec,
4e1021
+                          gpointer user_data)
4e1021
+{
4e1021
+	/* the MTU of a macvlan/macvtap device is limited by the parent's MTU.
4e1021
+	 *
4e1021
+	 * When the parent's MTU changes, try to re-set the MTU. */
4e1021
+	nm_device_commit_mtu (user_data);
4e1021
+}
4e1021
+
4e1021
 static void
4e1021
 parent_changed_notify (NMDevice *device,
4e1021
                        int old_ifindex,
4e1021
@@ -150,12 +162,15 @@ parent_changed_notify (NMDevice *device,
4e1021
 	 *  because NMDevice's dispose() will unset the parent, which in turn calls
4e1021
 	 *  parent_changed_notify(). */
4e1021
 	nm_clear_g_signal_handler (old_parent, &priv->parent_state_id);
4e1021
+	nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id);
4e1021
 
4e1021
 	if (new_parent) {
4e1021
 		priv->parent_state_id = g_signal_connect (new_parent,
4e1021
 		                                          NM_DEVICE_STATE_CHANGED,
4e1021
 		                                          G_CALLBACK (parent_state_changed),
4e1021
 		                                          device);
4e1021
+		priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU,
4e1021
+		                                        G_CALLBACK (parent_mtu_maybe_changed), device);
4e1021
 
4e1021
 		/* Set parent-dependent unmanaged flag */
4e1021
 		nm_device_set_unmanaged_by_flags (device,
4e1021
@@ -475,6 +490,17 @@ nm_device_macvlan_init (NMDeviceMacvlan *self)
4e1021
 {
4e1021
 }
4e1021
 
4e1021
+static void
4e1021
+dispose (GObject *object)
4e1021
+{
4e1021
+	NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object);
4e1021
+
4e1021
+	G_OBJECT_CLASS (nm_device_macvlan_parent_class)->dispose (object);
4e1021
+
4e1021
+	nm_assert (priv->parent_state_id == 0);
4e1021
+	nm_assert (priv->parent_mtu_id == 0);
4e1021
+}
4e1021
+
4e1021
 static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = {
4e1021
 	.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
4e1021
 		NM_DBUS_INTERFACE_DEVICE_MACVLAN,
4e1021
@@ -498,6 +524,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
4e1021
 	NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
4e1021
 	NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
4e1021
 
4e1021
+	object_class->dispose = dispose;
4e1021
 	object_class->get_property = get_property;
4e1021
 	object_class->set_property = set_property;
4e1021
 
4e1021
@@ -506,13 +533,14 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
4e1021
 	device_class->connection_type_supported = NM_SETTING_MACVLAN_SETTING_NAME;
4e1021
 	device_class->connection_type_check_compatible = NM_SETTING_MACVLAN_SETTING_NAME;
4e1021
 	device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP);
4e1021
+	device_class->mtu_parent_delta = 0;
4e1021
 
4e1021
 	device_class->act_stage1_prepare = act_stage1_prepare;
4e1021
 	device_class->check_connection_compatible = check_connection_compatible;
4e1021
 	device_class->complete_connection = complete_connection;
4e1021
 	device_class->create_and_realize = create_and_realize;
4e1021
 	device_class->get_generic_capabilities = get_generic_capabilities;
4e1021
-	device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
4e1021
+	device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
4e1021
 	device_class->is_available = is_available;
4e1021
 	device_class->link_changed = link_changed;
4e1021
 	device_class->parent_changed_notify = parent_changed_notify;
4e1021
-- 
4e1021
2.21.0
4e1021
4e1021
From 5544b621a3e8aa8e547cdaf2bfeaa208a0d89349 Mon Sep 17 00:00:00 2001
4e1021
From: Beniamino Galvani <bgalvani@redhat.com>
4e1021
Date: Wed, 11 Sep 2019 10:57:07 +0200
4e1021
Subject: [PATCH 6/6] device: fix setting MTU from connection when limited by
4e1021
 parent
4e1021
4e1021
We try to set only one time the MTU from the connection to not
4e1021
interfere with manual user changes.
4e1021
4e1021
If at some point the parent interface changes temporarily MTU to a
4e1021
lower value (for example, because the connection was reactivated), the
4e1021
kernel will also lower the MTU on child interface and we will not
4e1021
update it ever again.
4e1021
4e1021
Add a workaround to this. If we detect that the MTU we want to set
4e1021
from connection is higher that the allowed one, go into a state where
4e1021
we follow the parent MTU until it is possible to set again the desired
4e1021
MTU. This is a bit ugly, but I can't think of any nicer way to do it.
4e1021
4e1021
https://bugzilla.redhat.com/show_bug.cgi?id=1751079
4e1021
(cherry picked from commit ec28f5b343816d6696f6a4994efcfa919b6f02b2)
4e1021
(cherry picked from commit 49857ed279323e8b25d4120644add660f5816acb)
4e1021
---
4e1021
 src/devices/nm-device-ethernet.c      |  6 ++-
4e1021
 src/devices/nm-device-infiniband.c    |  4 +-
4e1021
 src/devices/nm-device-ip-tunnel.c     |  4 +-
4e1021
 src/devices/nm-device-private.h       |  5 ++-
4e1021
 src/devices/nm-device-wireguard.c     |  2 +-
4e1021
 src/devices/nm-device.c               | 58 ++++++++++++++++++++-------
4e1021
 src/devices/nm-device.h               |  4 +-
4e1021
 src/devices/wifi/nm-device-iwd.c      |  4 +-
4e1021
 src/devices/wifi/nm-device-wifi-p2p.c |  4 +-
4e1021
 src/devices/wifi/nm-device-wifi.c     |  4 +-
4e1021
 src/devices/wwan/nm-modem.c           |  4 +-
4e1021
 src/devices/wwan/nm-modem.h           |  2 +-
4e1021
 12 files changed, 73 insertions(+), 28 deletions(-)
4e1021
4e1021
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
4e1021
index 3e84847ed..6e01b0934 100644
4e1021
--- a/src/devices/nm-device-ethernet.c
4e1021
+++ b/src/devices/nm-device-ethernet.c
4e1021
@@ -1335,13 +1335,15 @@ act_stage3_ip_config_start (NMDevice *device,
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	/* MTU only set for plain ethernet */
4e1021
 	if (NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->ppp_manager)
4e1021
 		return 0;
4e1021
 
4e1021
-	return nm_device_get_configured_mtu_for_wired (device, out_source);
4e1021
+	return nm_device_get_configured_mtu_for_wired (device, out_source, out_force);
4e1021
 }
4e1021
 
4e1021
 static void
4e1021
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
4e1021
index 89db2af29..e39329a9c 100644
4e1021
--- a/src/devices/nm-device-infiniband.c
4e1021
+++ b/src/devices/nm-device-infiniband.c
4e1021
@@ -116,7 +116,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	return nm_device_get_configured_mtu_from_connection (device,
4e1021
 	                                                     NM_TYPE_SETTING_INFINIBAND,
4e1021
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
4e1021
index ede4487e3..f070dd5f9 100644
4e1021
--- a/src/devices/nm-device-ip-tunnel.c
4e1021
+++ b/src/devices/nm-device-ip-tunnel.c
4e1021
@@ -854,7 +854,9 @@ create_and_realize (NMDevice *device,
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	return nm_device_get_configured_mtu_from_connection (device,
4e1021
 	                                                     NM_TYPE_SETTING_IP_TUNNEL,
4e1021
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
4e1021
index 3caa82ee1..83feb130e 100644
4e1021
--- a/src/devices/nm-device-private.h
4e1021
+++ b/src/devices/nm-device-private.h
4e1021
@@ -174,10 +174,11 @@ guint32 nm_device_get_configured_mtu_from_connection (NMDevice *device,
4e1021
                                                       GType setting_type,
4e1021
                                                       NMDeviceMtuSource *out_source);
4e1021
 
4e1021
-guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source);
4e1021
+guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force);
4e1021
 
4e1021
 guint32 nm_device_get_configured_mtu_wired_parent (NMDevice *self,
4e1021
-                                                   NMDeviceMtuSource *out_source);
4e1021
+                                                   NMDeviceMtuSource *out_source,
4e1021
+                                                   gboolean *out_force);
4e1021
 
4e1021
 void nm_device_commit_mtu (NMDevice *self);
4e1021
 
4e1021
diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c
4e1021
index e3b8e8b4c..5d640b622 100644
4e1021
--- a/src/devices/nm-device-wireguard.c
4e1021
+++ b/src/devices/nm-device-wireguard.c
4e1021
@@ -1714,7 +1714,7 @@ act_stage3_ip_config_start (NMDevice *device,
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
4e1021
 {
4e1021
 	/* When "MTU" for `wg-quick up` is unset, it calls `ip route get` for
4e1021
 	 * each configured endpoint, to determine the suitable MTU how to reach
4e1021
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
4e1021
index 570f57146..0da8049bd 100644
4e1021
--- a/src/devices/nm-device.c
4e1021
+++ b/src/devices/nm-device.c
4e1021
@@ -9265,7 +9265,9 @@ nm_device_get_configured_mtu_from_connection (NMDevice *self,
4e1021
 }
4e1021
 
4e1021
 guint32
4e1021
-nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source)
4e1021
+nm_device_get_configured_mtu_for_wired (NMDevice *self,
4e1021
+                                        NMDeviceMtuSource *out_source,
4e1021
+                                        gboolean *out_force)
4e1021
 {
4e1021
 	return nm_device_get_configured_mtu_from_connection (self,
4e1021
 	                                                     NM_TYPE_SETTING_WIRED,
4e1021
@@ -9274,26 +9276,43 @@ nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_s
4e1021
 
4e1021
 guint32
4e1021
 nm_device_get_configured_mtu_wired_parent (NMDevice *self,
4e1021
-                                           NMDeviceMtuSource *out_source)
4e1021
+                                           NMDeviceMtuSource *out_source,
4e1021
+                                           gboolean *out_force)
4e1021
 {
4e1021
 	guint32 mtu = 0;
4e1021
+	guint32 parent_mtu = 0;
4e1021
 	int ifindex;
4e1021
 
4e1021
-	mtu = nm_device_get_configured_mtu_for_wired (self, out_source);
4e1021
+	ifindex = nm_device_parent_get_ifindex (self);
4e1021
+	if (ifindex > 0) {
4e1021
+		parent_mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex);
4e1021
+		if (parent_mtu >= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta)
4e1021
+			parent_mtu -= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta;
4e1021
+		else
4e1021
+			parent_mtu = 0;
4e1021
+	}
4e1021
+
4e1021
+	mtu = nm_device_get_configured_mtu_for_wired (self, out_source, NULL);
4e1021
+
4e1021
+	if (parent_mtu && mtu > parent_mtu) {
4e1021
+		/* Trying to set a MTU that is out of range from configuration:
4e1021
+		 * fall back to the parent MTU and set force flag so that it
4e1021
+		 * overrides an MTU with higher priority already configured.
4e1021
+		 */
4e1021
+		 *out_source = NM_DEVICE_MTU_SOURCE_PARENT;
4e1021
+		 *out_force = TRUE;
4e1021
+		 return parent_mtu;
4e1021
+	}
4e1021
+
4e1021
 	if (*out_source != NM_DEVICE_MTU_SOURCE_NONE) {
4e1021
 		nm_assert (mtu > 0);
4e1021
 		return mtu;
4e1021
 	}
4e1021
 
4e1021
 	/* Inherit the MTU from parent device, if any */
4e1021
-	ifindex = nm_device_parent_get_ifindex (self);
4e1021
-	if (ifindex > 0) {
4e1021
-		mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex);
4e1021
-		if (mtu >= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta) {
4e1021
-			mtu -= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta;
4e1021
-			*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
4e1021
-		} else
4e1021
-			mtu = 0;
4e1021
+	if (parent_mtu) {
4e1021
+		mtu = parent_mtu;
4e1021
+		*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
4e1021
 	}
4e1021
 
4e1021
 	return mtu;
4e1021
@@ -9350,6 +9369,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
4e1021
 
4e1021
 	{
4e1021
 		guint32 mtu = 0;
4e1021
+		gboolean force = FALSE;
4e1021
 
4e1021
 		/* We take the MTU from various sources: (in order of increasing
4e1021
 		 * priority) parent link, IP configuration (which contains the
4e1021
@@ -9365,12 +9385,18 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
4e1021
 		 * multiple times. An exception to this is for the PARENT
4e1021
 		 * source, since we need to keep tracking the parent MTU when it
4e1021
 		 * changes.
4e1021
+		 *
4e1021
+		 * The subclass can set the @force argument to TRUE to signal that the
4e1021
+		 * returned MTU should be applied even if it has a lower priority. This
4e1021
+		 * is useful when the value from a lower source should
4e1021
+		 * preempt the one from higher ones.
4e1021
 		 */
4e1021
 
4e1021
 		if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
4e1021
-			mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source);
4e1021
+			mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source, &force);
4e1021
 
4e1021
 		if (   config
4e1021
+		    && !force
4e1021
 		    && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
4e1021
 		    && nm_ip4_config_get_mtu (config)) {
4e1021
 			mtu = nm_ip4_config_get_mtu (config);
4e1021
@@ -9379,14 +9405,16 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
4e1021
 
4e1021
 		if (mtu != 0) {
4e1021
 			_LOGT (LOGD_DEVICE,
4e1021
-			       "mtu: value %u from source '%s' (%u), current source '%s' (%u)",
4e1021
+			       "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s",
4e1021
 			       (guint) mtu,
4e1021
 			       mtu_source_to_str (source), (guint) source,
4e1021
-			       mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source);
4e1021
+			       mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source,
4e1021
+			       force ? " (forced)" : "");
4e1021
 		}
4e1021
 
4e1021
 		if (   mtu != 0
4e1021
-		    && (   source > priv->mtu_source
4e1021
+		    && (   force
4e1021
+		        || source > priv->mtu_source
4e1021
 		        || (priv->mtu_source == NM_DEVICE_MTU_SOURCE_PARENT && source == priv->mtu_source)))
4e1021
 			mtu_desired = mtu;
4e1021
 		else {
4e1021
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
4e1021
index 32efbd3de..412a57a0a 100644
4e1021
--- a/src/devices/nm-device.h
4e1021
+++ b/src/devices/nm-device.h
4e1021
@@ -339,7 +339,9 @@ typedef struct _NMDeviceClass {
4e1021
 	                                  NMSettingsConnection *sett_conn,
4e1021
 	                                  char **specific_object);
4e1021
 
4e1021
-	guint32     (*get_configured_mtu) (NMDevice *self, NMDeviceMtuSource *out_source);
4e1021
+	guint32     (*get_configured_mtu) (NMDevice *self,
4e1021
+	                                   NMDeviceMtuSource *out_source,
4e1021
+	                                   gboolean *out_force);
4e1021
 
4e1021
 	/* allow the subclass to overwrite the routing table. This is mainly useful
4e1021
 	 * to change from partial mode (route-table=0) to full-sync mode (route-table=254). */
4e1021
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
4e1021
index 9cfe5f70a..82b69ccfb 100644
4e1021
--- a/src/devices/wifi/nm-device-iwd.c
4e1021
+++ b/src/devices/wifi/nm-device-iwd.c
4e1021
@@ -1881,7 +1881,9 @@ out:
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	return nm_device_get_configured_mtu_from_connection (device,
4e1021
 	                                                     NM_TYPE_SETTING_WIRELESS,
4e1021
diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/devices/wifi/nm-device-wifi-p2p.c
4e1021
index c5826e24a..fcd1630cb 100644
4e1021
--- a/src/devices/wifi/nm-device-wifi-p2p.c
4e1021
+++ b/src/devices/wifi/nm-device-wifi-p2p.c
4e1021
@@ -629,7 +629,9 @@ deactivate (NMDevice *device)
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	*out_source = NM_DEVICE_MTU_SOURCE_NONE;
4e1021
 	return 0;
4e1021
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
4e1021
index 2ffba47a2..5cffb260a 100644
4e1021
--- a/src/devices/wifi/nm-device-wifi.c
4e1021
+++ b/src/devices/wifi/nm-device-wifi.c
4e1021
@@ -2969,7 +2969,9 @@ act_stage3_ip_config_start (NMDevice *device,
4e1021
 }
4e1021
 
4e1021
 static guint32
4e1021
-get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
4e1021
+get_configured_mtu (NMDevice *device,
4e1021
+                    NMDeviceMtuSource *out_source,
4e1021
+                    gboolean *out_force)
4e1021
 {
4e1021
 	return nm_device_get_configured_mtu_from_connection (device,
4e1021
 	                                                     NM_TYPE_SETTING_WIRELESS,
4e1021
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
4e1021
index 617096a76..fb2316d51 100644
4e1021
--- a/src/devices/wwan/nm-modem.c
4e1021
+++ b/src/devices/wwan/nm-modem.c
4e1021
@@ -875,7 +875,9 @@ nm_modem_stage3_ip6_config_start (NMModem *self,
4e1021
 }
4e1021
 
4e1021
 guint32
4e1021
-nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source)
4e1021
+nm_modem_get_configured_mtu (NMDevice *self,
4e1021
+                             NMDeviceMtuSource *out_source,
4e1021
+                             gboolean *out_force)
4e1021
 {
4e1021
 	NMConnection *connection;
4e1021
 	NMSetting *setting;
4e1021
diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h
4e1021
index f5b386e8b..fccb4fec4 100644
4e1021
--- a/src/devices/wwan/nm-modem.h
4e1021
+++ b/src/devices/wwan/nm-modem.h
4e1021
@@ -287,7 +287,7 @@ void nm_modem_emit_ip6_config_result (NMModem *self,
4e1021
 
4e1021
 const char *nm_modem_ip_type_to_string (NMModemIPType ip_type);
4e1021
 
4e1021
-guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source);
4e1021
+guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force);
4e1021
 
4e1021
 void _nm_modem_set_operator_code (NMModem *self, const char *operator_code);
4e1021
 void _nm_modem_set_apn           (NMModem *self, const char *apn);
4e1021
-- 
4e1021
2.21.0
4e1021