device: merge branch 'bg/parent-mtu-rh1723690-part1'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/273
This commit is contained in:
Beniamino Galvani 2019-10-10 15:16:57 +02:00
commit facfc94744
15 changed files with 165 additions and 43 deletions

View file

@ -1329,13 +1329,15 @@ act_stage3_ip_config_start (NMDevice *device,
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
/* MTU only set for plain ethernet */
if (NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->ppp_manager)
return 0;
return nm_device_get_configured_mtu_for_wired (device, out_source);
return nm_device_get_configured_mtu_for_wired (device, out_source, out_force);
}
static void

View file

@ -97,7 +97,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
return nm_device_get_configured_mtu_from_connection (device,
NM_TYPE_SETTING_INFINIBAND,

View file

@ -840,7 +840,9 @@ create_and_realize (NMDevice *device,
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
return nm_device_get_configured_mtu_from_connection (device,
NM_TYPE_SETTING_IP_TUNNEL,

View file

@ -52,6 +52,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacsec,
typedef struct {
NMPlatformLnkMacsec props;
gulong parent_state_id;
gulong parent_mtu_id;
Supplicant supplicant;
guint supplicant_timeout_id;
NMActRequestGetSecretsCallId *macsec_secrets_id;
@ -99,6 +100,17 @@ parent_state_changed (NMDevice *parent,
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
}
static void
parent_mtu_maybe_changed (NMDevice *parent,
GParamSpec *pspec,
gpointer user_data)
{
/* the MTU of a MACsec device is limited by the parent's MTU.
*
* When the parent's MTU changes, try to re-set the MTU. */
nm_device_commit_mtu (user_data);
}
static void
parent_changed_notify (NMDevice *device,
int old_ifindex,
@ -119,12 +131,16 @@ parent_changed_notify (NMDevice *device,
* because NMDevice's dispose() will unset the parent, which in turn calls
* parent_changed_notify(). */
nm_clear_g_signal_handler (old_parent, &priv->parent_state_id);
nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id);
if (new_parent) {
priv->parent_state_id = g_signal_connect (new_parent,
NM_DEVICE_STATE_CHANGED,
G_CALLBACK (parent_state_changed),
device);
priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU,
G_CALLBACK (parent_mtu_maybe_changed), device);
/* Set parent-dependent unmanaged flag */
nm_device_set_unmanaged_by_flags (device,
@ -779,11 +795,15 @@ static void
dispose (GObject *object)
{
NMDeviceMacsec *self = NM_DEVICE_MACSEC (object);
NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
macsec_secrets_cancel (self);
supplicant_interface_release (self);
G_OBJECT_CLASS (nm_device_macsec_parent_class)->dispose (object);
nm_assert (priv->parent_state_id == 0);
nm_assert (priv->parent_mtu_id == 0);
}
static const NMDBusInterfaceInfoExtended interface_info_device_macsec = {
@ -826,6 +846,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
device_class->connection_type_supported = NM_SETTING_MACSEC_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_MACSEC_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACSEC);
device_class->mtu_parent_delta = 32;
device_class->act_stage2_config = act_stage2_config;
device_class->create_and_realize = create_and_realize;
@ -835,7 +856,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass)
device_class->is_available = is_available;
device_class->parent_changed_notify = parent_changed_notify;
device_class->state_changed = device_state_changed;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
obj_properties[PROP_SCI] =
g_param_spec_uint64 (NM_DEVICE_MACSEC_SCI, "", "",

View file

@ -34,6 +34,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacvlan,
typedef struct {
gulong parent_state_id;
gulong parent_mtu_id;
NMPlatformLnkMacvlan props;
} NMDeviceMacvlanPrivate;
@ -120,6 +121,17 @@ parent_state_changed (NMDevice *parent,
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
}
static void
parent_mtu_maybe_changed (NMDevice *parent,
GParamSpec *pspec,
gpointer user_data)
{
/* the MTU of a macvlan/macvtap device is limited by the parent's MTU.
*
* When the parent's MTU changes, try to re-set the MTU. */
nm_device_commit_mtu (user_data);
}
static void
parent_changed_notify (NMDevice *device,
int old_ifindex,
@ -136,12 +148,15 @@ parent_changed_notify (NMDevice *device,
* because NMDevice's dispose() will unset the parent, which in turn calls
* parent_changed_notify(). */
nm_clear_g_signal_handler (old_parent, &priv->parent_state_id);
nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id);
if (new_parent) {
priv->parent_state_id = g_signal_connect (new_parent,
NM_DEVICE_STATE_CHANGED,
G_CALLBACK (parent_state_changed),
device);
priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU,
G_CALLBACK (parent_mtu_maybe_changed), device);
/* Set parent-dependent unmanaged flag */
nm_device_set_unmanaged_by_flags (device,
@ -447,6 +462,17 @@ nm_device_macvlan_init (NMDeviceMacvlan *self)
{
}
static void
dispose (GObject *object)
{
NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object);
G_OBJECT_CLASS (nm_device_macvlan_parent_class)->dispose (object);
nm_assert (priv->parent_state_id == 0);
nm_assert (priv->parent_mtu_id == 0);
}
static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
NM_DBUS_INTERFACE_DEVICE_MACVLAN,
@ -470,6 +496,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->dispose = dispose;
object_class->get_property = get_property;
object_class->set_property = set_property;
@ -478,13 +505,14 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
device_class->connection_type_supported = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP);
device_class->mtu_parent_delta = 0;
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
device_class->is_available = is_available;
device_class->link_changed = link_changed;
device_class->parent_changed_notify = parent_changed_notify;

View file

@ -166,7 +166,11 @@ guint32 nm_device_get_configured_mtu_from_connection (NMDevice *device,
GType setting_type,
NMDeviceMtuSource *out_source);
guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source);
guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force);
guint32 nm_device_get_configured_mtu_wired_parent (NMDevice *self,
NMDeviceMtuSource *out_source,
gboolean *out_force);
void nm_device_commit_mtu (NMDevice *self);

View file

@ -502,26 +502,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static guint32
get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source)
{
guint32 mtu = 0;
int ifindex;
mtu = nm_device_get_configured_mtu_for_wired (self, out_source);
if (*out_source != NM_DEVICE_MTU_SOURCE_NONE)
return mtu;
/* Inherit the MTU from parent device, if any */
ifindex = nm_device_parent_get_ifindex (self);
if (ifindex > 0) {
mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex);
*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
}
return mtu;
}
/*****************************************************************************/
static void
@ -577,6 +557,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
device_class->connection_type_supported = NM_SETTING_VLAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_VLAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VLAN);
device_class->mtu_parent_delta = 0; /* VLANs can have the same MTU of parent */
device_class->create_and_realize = create_and_realize;
device_class->link_changed = link_changed;
@ -584,7 +565,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->get_configured_mtu = get_configured_mtu;
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
device_class->is_available = is_available;
device_class->parent_changed_notify = parent_changed_notify;

View file

@ -1691,7 +1691,7 @@ act_stage3_ip_config_start (NMDevice *device,
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
{
/* When "MTU" for `wg-quick up` is unset, it calls `ip route get` for
* each configured endpoint, to determine the suitable MTU how to reach

View file

@ -9317,13 +9317,59 @@ nm_device_get_configured_mtu_from_connection (NMDevice *self,
}
guint32
nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source)
nm_device_get_configured_mtu_for_wired (NMDevice *self,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
return nm_device_get_configured_mtu_from_connection (self,
NM_TYPE_SETTING_WIRED,
out_source);
}
guint32
nm_device_get_configured_mtu_wired_parent (NMDevice *self,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
guint32 mtu = 0;
guint32 parent_mtu = 0;
int ifindex;
ifindex = nm_device_parent_get_ifindex (self);
if (ifindex > 0) {
parent_mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex);
if (parent_mtu >= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta)
parent_mtu -= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta;
else
parent_mtu = 0;
}
mtu = nm_device_get_configured_mtu_for_wired (self, out_source, NULL);
if (parent_mtu && mtu > parent_mtu) {
/* Trying to set a MTU that is out of range from configuration:
* fall back to the parent MTU and set force flag so that it
* overrides an MTU with higher priority already configured.
*/
*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
*out_force = TRUE;
return parent_mtu;
}
if (*out_source != NM_DEVICE_MTU_SOURCE_NONE) {
nm_assert (mtu > 0);
return mtu;
}
/* Inherit the MTU from parent device, if any */
if (parent_mtu) {
mtu = parent_mtu;
*out_source = NM_DEVICE_MTU_SOURCE_PARENT;
}
return mtu;
}
/*****************************************************************************/
static void
@ -9375,15 +9421,34 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
{
guint32 mtu = 0;
gboolean force = FALSE;
/* preferably, get the MTU from explicit user-configuration.
* Only if that fails, look at the current @config (which contains
* MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */
/* We take the MTU from various sources: (in order of increasing
* priority) parent link, IP configuration (which contains the
* MTU from DHCP/PPP), connection profile.
*
* We could just compare it with the platform MTU and apply it
* when different, but this would revert at random times manual
* changes done by the user with the MTU from the connection.
*
* Instead, we remember the source of the currently configured
* MTU and apply the new one only when the new source has a
* higher priority, so that we don't set a MTU from same source
* multiple times. An exception to this is for the PARENT
* source, since we need to keep tracking the parent MTU when it
* changes.
*
* The subclass can set the @force argument to TRUE to signal that the
* returned MTU should be applied even if it has a lower priority. This
* is useful when the value from a lower source should
* preempt the one from higher ones.
*/
if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source);
mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source, &force);
if ( config
&& !force
&& source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
&& nm_ip4_config_get_mtu (config)) {
mtu = nm_ip4_config_get_mtu (config);
@ -9392,14 +9457,16 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config)
if (mtu != 0) {
_LOGT (LOGD_DEVICE,
"mtu: value %u from source '%s' (%u), current source '%s' (%u)",
"mtu: value %u from source '%s' (%u), current source '%s' (%u)%s",
(guint) mtu,
mtu_source_to_str (source), (guint) source,
mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source);
mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source,
force ? " (forced)" : "");
}
if ( mtu != 0
&& ( source > priv->mtu_source
&& ( force
|| source > priv->mtu_source
|| (priv->mtu_source == NM_DEVICE_MTU_SOURCE_PARENT && source == priv->mtu_source)))
mtu_desired = mtu;
else {
@ -14845,6 +14912,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
}
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
priv->ip6_mtu = 0;
if (priv->mtu_initial || priv->ip6_mtu_initial) {
ifindex = nm_device_get_ip_ifindex (self);

View file

@ -225,6 +225,10 @@ typedef struct _NMDeviceClass {
const NMLinkType *link_types;
/* if the device MTU is set based on parent's one, this specifies
* a delta in the MTU allowed value due the encapsulation overhead */
guint16 mtu_parent_delta;
/* Whether the device type is a master-type. This depends purely on the
* type (NMDeviceClass), not the actual device instance. */
bool is_master:1;
@ -321,7 +325,9 @@ typedef struct _NMDeviceClass {
NMSettingsConnection *sett_conn,
char **specific_object);
guint32 (*get_configured_mtu) (NMDevice *self, NMDeviceMtuSource *out_source);
guint32 (*get_configured_mtu) (NMDevice *self,
NMDeviceMtuSource *out_source,
gboolean *out_force);
/* allow the subclass to overwrite the routing table. This is mainly useful
* to change from partial mode (route-table=0) to full-sync mode (route-table=254). */

View file

@ -1865,7 +1865,9 @@ out:
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
return nm_device_get_configured_mtu_from_connection (device,
NM_TYPE_SETTING_WIRELESS,

View file

@ -604,7 +604,9 @@ deactivate (NMDevice *device)
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
*out_source = NM_DEVICE_MTU_SOURCE_NONE;
return 0;

View file

@ -2895,7 +2895,9 @@ act_stage3_ip_config_start (NMDevice *device,
}
static guint32
get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
get_configured_mtu (NMDevice *device,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
return nm_device_get_configured_mtu_from_connection (device,
NM_TYPE_SETTING_WIRELESS,

View file

@ -910,7 +910,9 @@ nm_modem_stage3_ip6_config_start (NMModem *self,
}
guint32
nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source)
nm_modem_get_configured_mtu (NMDevice *self,
NMDeviceMtuSource *out_source,
gboolean *out_force)
{
NMConnection *connection;
NMSetting *setting;

View file

@ -275,7 +275,7 @@ void nm_modem_emit_ip6_config_result (NMModem *self,
const char *nm_modem_ip_type_to_string (NMModemIPType ip_type);
guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source);
guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force);
void _nm_modem_set_operator_code (NMModem *self, const char *operator_code);
void _nm_modem_set_apn (NMModem *self, const char *apn);