device: rework mtu priority handling
If commit_mtu() is called multiple times and dev->get_configured_mtu() returns @is_user_config=FALSE, only the first call changes the MTU. So, for example, when the parent MTU of a VLAN changes, we apply the new MTU only the first time. Rework the handling of MTU in NMDevice, and store the source of the configured MTU. When commit_mtu() is called again, we ask the subclass a MTU to configure and apply it only if the source has higher priority, or when the parent MTU changed.
This commit is contained in:
@@ -545,8 +545,10 @@ get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source)
|
|||||||
|
|
||||||
/* Inherit the MTU from parent device, if any */
|
/* Inherit the MTU from parent device, if any */
|
||||||
ifindex = nm_device_parent_get_ifindex (self);
|
ifindex = nm_device_parent_get_ifindex (self);
|
||||||
if (ifindex > 0)
|
if (ifindex > 0) {
|
||||||
mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex);
|
mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex);
|
||||||
|
*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
|
||||||
|
}
|
||||||
|
|
||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
@@ -349,8 +349,9 @@ typedef struct _NMDevicePrivate {
|
|||||||
gulong config_changed_id;
|
gulong config_changed_id;
|
||||||
guint32 mtu;
|
guint32 mtu;
|
||||||
guint32 ip6_mtu;
|
guint32 ip6_mtu;
|
||||||
guint32 mtu_initial;
|
guint32 mtu_initial;
|
||||||
guint32 ip6_mtu_initial;
|
guint32 ip6_mtu_initial;
|
||||||
|
NMDeviceMtuSource mtu_source;
|
||||||
|
|
||||||
guint32 v4_route_table;
|
guint32 v4_route_table;
|
||||||
guint32 v6_route_table;
|
guint32 v6_route_table;
|
||||||
@@ -366,8 +367,6 @@ typedef struct _NMDevicePrivate {
|
|||||||
bool carrier:1;
|
bool carrier:1;
|
||||||
bool ignore_carrier:1;
|
bool ignore_carrier:1;
|
||||||
|
|
||||||
bool mtu_initialized:1;
|
|
||||||
|
|
||||||
bool up:1; /* IFF_UP */
|
bool up:1; /* IFF_UP */
|
||||||
|
|
||||||
bool v4_commit_first_time:1;
|
bool v4_commit_first_time:1;
|
||||||
@@ -735,6 +734,14 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_device_state_reason_to_str, NMDeviceStateReason,
|
|||||||
#define reason_to_string(reason) \
|
#define reason_to_string(reason) \
|
||||||
NM_UTILS_LOOKUP_STR (nm_device_state_reason_to_str, reason)
|
NM_UTILS_LOOKUP_STR (nm_device_state_reason_to_str, reason)
|
||||||
|
|
||||||
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (mtu_source_to_str, NMDeviceMtuSource,
|
||||||
|
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_MTU_SOURCE_NONE, "none"),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_MTU_SOURCE_PARENT, "parent"),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_MTU_SOURCE_IP_CONFIG, "ip-config"),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_MTU_SOURCE_CONNECTION, "connection"),
|
||||||
|
);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMSettings *
|
NMSettings *
|
||||||
@@ -4001,7 +4008,7 @@ realize_start_setup (NMDevice *self,
|
|||||||
/* Balanced by a thaw in nm_device_realize_finish() */
|
/* Balanced by a thaw in nm_device_realize_finish() */
|
||||||
g_object_freeze_notify (G_OBJECT (self));
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
priv->mtu_initialized = FALSE;
|
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||||
priv->mtu_initial = 0;
|
priv->mtu_initial = 0;
|
||||||
priv->ip6_mtu_initial = 0;
|
priv->ip6_mtu_initial = 0;
|
||||||
priv->ip6_mtu = 0;
|
priv->ip6_mtu = 0;
|
||||||
@@ -8459,6 +8466,7 @@ static void
|
|||||||
_commit_mtu (NMDevice *self, const NMIP4Config *config)
|
_commit_mtu (NMDevice *self, const NMIP4Config *config)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||||
guint32 ip6_mtu, ip6_mtu_orig;
|
guint32 ip6_mtu, ip6_mtu_orig;
|
||||||
guint32 mtu_desired, mtu_desired_orig;
|
guint32 mtu_desired, mtu_desired_orig;
|
||||||
guint32 mtu_plat;
|
guint32 mtu_plat;
|
||||||
@@ -8468,6 +8476,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
} ip6_mtu_sysctl = { 0, };
|
} ip6_mtu_sysctl = { 0, };
|
||||||
int ifindex;
|
int ifindex;
|
||||||
char sbuf[64], sbuf1[64], sbuf2[64];
|
char sbuf[64], sbuf1[64], sbuf2[64];
|
||||||
|
gboolean success = TRUE;
|
||||||
|
|
||||||
ifindex = nm_device_get_ip_ifindex (self);
|
ifindex = nm_device_get_ip_ifindex (self);
|
||||||
if (ifindex <= 0)
|
if (ifindex <= 0)
|
||||||
@@ -8481,7 +8490,6 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
NMDeviceMtuSource mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
|
||||||
guint32 mtu = 0;
|
guint32 mtu = 0;
|
||||||
|
|
||||||
/* preferably, get the MTU from explict user-configuration.
|
/* preferably, get the MTU from explict user-configuration.
|
||||||
@@ -8489,23 +8497,30 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
* MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */
|
* MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */
|
||||||
|
|
||||||
if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
|
if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
|
||||||
mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &mtu_source);
|
mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source);
|
||||||
|
|
||||||
if (mtu_source == NM_DEVICE_MTU_SOURCE_CONNECTION)
|
if ( config
|
||||||
|
&& source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
|
||||||
|
&& nm_ip4_config_get_mtu (config)) {
|
||||||
|
mtu = nm_ip4_config_get_mtu (config);
|
||||||
|
source = NM_DEVICE_MTU_SOURCE_IP_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtu != 0) {
|
||||||
|
_LOGT (LOGD_DEVICE,
|
||||||
|
"mtu: value %u from source '%s' (%u), current source '%s' (%u)",
|
||||||
|
(guint) mtu,
|
||||||
|
mtu_source_to_str (source), (guint) source,
|
||||||
|
mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mtu != 0
|
||||||
|
&& ( source > priv->mtu_source
|
||||||
|
|| (priv->mtu_source == NM_DEVICE_MTU_SOURCE_PARENT && source == priv->mtu_source)))
|
||||||
mtu_desired = mtu;
|
mtu_desired = mtu;
|
||||||
else {
|
else {
|
||||||
if (config)
|
mtu_desired = 0;
|
||||||
mtu_desired = nm_ip4_config_get_mtu (config);
|
source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||||
else
|
|
||||||
mtu_desired = 0;
|
|
||||||
if (!mtu_desired && !priv->mtu_initialized) {
|
|
||||||
/* there is no MTU specified, and this is the first commit of the MTU.
|
|
||||||
* Reset a per-device MTU default, as returned from get_configured_mtu().
|
|
||||||
*
|
|
||||||
* The device might choose not to return a default MTU via get_configured_mtu()
|
|
||||||
* to suppress this behavior. */
|
|
||||||
mtu_desired = mtu;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8527,7 +8542,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ip6_mtu = priv->ip6_mtu;
|
ip6_mtu = priv->ip6_mtu;
|
||||||
if (!ip6_mtu && !priv->mtu_initialized) {
|
if (!ip6_mtu && priv->mtu_source == NM_DEVICE_MTU_SOURCE_NONE) {
|
||||||
/* initially, if the IPv6 MTU is not specified, grow it as large as the
|
/* initially, if the IPv6 MTU is not specified, grow it as large as the
|
||||||
* link MTU @mtu_desired. Only exception is, if @mtu_desired is so small
|
* link MTU @mtu_desired. Only exception is, if @mtu_desired is so small
|
||||||
* to disable IPv6. */
|
* to disable IPv6. */
|
||||||
@@ -8535,8 +8550,6 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
ip6_mtu = mtu_desired;
|
ip6_mtu = mtu_desired;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->mtu_initialized = TRUE;
|
|
||||||
|
|
||||||
if (!ip6_mtu && !mtu_desired)
|
if (!ip6_mtu && !mtu_desired)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -8588,6 +8601,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
if (mtu_desired && mtu_desired != mtu_plat) {
|
if (mtu_desired && mtu_desired != mtu_plat) {
|
||||||
if (nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, mtu_desired) == NM_PLATFORM_ERROR_CANT_SET_MTU) {
|
if (nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, mtu_desired) == NM_PLATFORM_ERROR_CANT_SET_MTU) {
|
||||||
anticipated_failure = TRUE;
|
anticipated_failure = TRUE;
|
||||||
|
success = FALSE;
|
||||||
_LOGW (LOGD_DEVICE, "mtu: failure to set MTU. %s",
|
_LOGW (LOGD_DEVICE, "mtu: failure to set MTU. %s",
|
||||||
NM_IS_DEVICE_VLAN (self)
|
NM_IS_DEVICE_VLAN (self)
|
||||||
? "Is the parent's MTU size large enough?"
|
? "Is the parent's MTU size large enough?"
|
||||||
@@ -8609,10 +8623,15 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
|
|||||||
anticipated_failure && errsv == EINVAL
|
anticipated_failure && errsv == EINVAL
|
||||||
? ": Is the underlying MTU value successfully set?"
|
? ": Is the underlying MTU value successfully set?"
|
||||||
: "");
|
: "");
|
||||||
|
success = FALSE;
|
||||||
}
|
}
|
||||||
priv->carrier_wait_until_ms = nm_utils_get_monotonic_timestamp_ms () + CARRIER_WAIT_TIME_AFTER_MTU_MS;
|
priv->carrier_wait_until_ms = nm_utils_get_monotonic_timestamp_ms () + CARRIER_WAIT_TIME_AFTER_MTU_MS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success && source != NM_DEVICE_MTU_SOURCE_NONE)
|
||||||
|
priv->mtu_source = source;
|
||||||
|
|
||||||
#undef _IP6_MTU_SYS
|
#undef _IP6_MTU_SYS
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13651,7 +13670,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
|||||||
NM_DEVICE_GET_CLASS (self)->deactivate_reset_hw_addr (self);
|
NM_DEVICE_GET_CLASS (self)->deactivate_reset_hw_addr (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->mtu_initialized = FALSE;
|
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||||
if (priv->mtu_initial || priv->ip6_mtu_initial) {
|
if (priv->mtu_initial || priv->ip6_mtu_initial) {
|
||||||
ifindex = nm_device_get_ip_ifindex (self);
|
ifindex = nm_device_get_ip_ifindex (self);
|
||||||
|
|
||||||
|
@@ -46,6 +46,8 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NM_DEVICE_MTU_SOURCE_NONE,
|
NM_DEVICE_MTU_SOURCE_NONE,
|
||||||
|
NM_DEVICE_MTU_SOURCE_PARENT,
|
||||||
|
NM_DEVICE_MTU_SOURCE_IP_CONFIG,
|
||||||
NM_DEVICE_MTU_SOURCE_CONNECTION,
|
NM_DEVICE_MTU_SOURCE_CONNECTION,
|
||||||
} NMDeviceMtuSource;
|
} NMDeviceMtuSource;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user