diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 72ec29a121..7a9f14c24b 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9692,6 +9692,17 @@ _set_mtu (NMDevice *self, guint32 mtu) } } +static gboolean +set_platform_mtu (NMDevice *self, guint32 mtu) +{ + int r; + + r = nm_platform_link_set_mtu (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + mtu); + return (r != -NME_PL_CANT_SET_MTU); +} + static void _commit_mtu (NMDevice *self, const NMIP4Config *config) { @@ -9851,10 +9862,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) } if (mtu_desired && mtu_desired != mtu_plat) { - int r; - - r = nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, mtu_desired); - if (r == -NME_PL_CANT_SET_MTU) { + if (!NM_DEVICE_GET_CLASS (self)->set_platform_mtu (self, mtu_desired)) { anticipated_failure = TRUE; success = FALSE; _LOGW (LOGD_DEVICE, "mtu: failure to set MTU. %s", @@ -17631,6 +17639,7 @@ nm_device_class_init (NMDeviceClass *klass) klass->parent_changed_notify = parent_changed_notify; klass->can_reapply_change = can_reapply_change; klass->reapply_connection = reapply_connection; + klass->set_platform_mtu = set_platform_mtu; obj_properties[PROP_UDI] = g_param_spec_string (NM_DEVICE_UDI, "", "", diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 8c6c856e81..0161592652 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -444,6 +444,8 @@ typedef struct _NMDeviceClass { gboolean (* can_update_from_platform_link) (NMDevice *self, const NMPlatformLink *plink); + gboolean (* set_platform_mtu) (NMDevice *self, guint32 mtu); + /* Controls, whether to call act_stage2_config() callback also for assuming * a device or for external activations. In this case, act_stage2_config() must * take care not to touch the device's configuration. */ diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index 2868dee093..951b578892 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -121,6 +121,43 @@ _is_internal_interface (NMDevice *device) return nm_streq (nm_setting_ovs_interface_get_interface_type (s_ovs_iface), "internal"); } +static void +set_platform_mtu_cb (GError *error, gpointer user_data) +{ + NMDevice *device = user_data; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); + + if ( error + && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + _LOGW (LOGD_DEVICE, "could not change mtu of '%s': %s", + nm_device_get_iface (device), error->message); + } + + g_object_unref (device); +} + +static gboolean +set_platform_mtu (NMDevice *device, guint32 mtu) +{ + /* + * If the MTU is not set in ovsdb, Open vSwitch will change + * the MTU of an internal interface to match the minimum of + * the other interfaces in the bridge. + */ + /* FIXME(shutdown): the function should become cancellable so + * that it doesn't need to hold a reference to the device, and + * it can be stopped during shutdown. + */ + if (_is_internal_interface (device)) { + nm_ovsdb_set_interface_mtu (nm_ovsdb_get (), + nm_device_get_ip_iface (device), + mtu, set_platform_mtu_cb, + g_object_ref (device)); + } + + return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->set_platform_mtu (device, mtu); +} + static NMActStageReturn act_stage3_ip_config_start (NMDevice *device, int addr_family, @@ -351,4 +388,6 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) device_class->link_changed = link_changed; device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; device_class->can_unmanaged_external_down = can_unmanaged_external_down; + device_class->set_platform_mtu = set_platform_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; }