From 04264be151f323a78dea23e58311c90d9928bd9e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 16 Mar 2020 10:53:06 +0100 Subject: [PATCH] ovs: set the MTU in ovsdb when changing platform MTU of ovs-interface If we change the the MTU of an ovs interface only through netlink, the change could be overridden by ovs-vswitchd at any time when other interfaces change. Set the MTU also in the ovsdb to prevent such changes. Note that if the MTU comes from the connection, we already set the ovsdb MTU at creation time and so this other update becomes useless. But it is needed when changing the MTU at runtime (reapply) or when the MTU comes from a different source (e.g. DHCP). (cherry picked from commit c2a97129453c49f86976b42c29b793a87d9d2e41) (cherry picked from commit e27a59c69e956961efe99f83068b760380b77066) (cherry picked from commit 99ef891db6a561d6b3dcaec9ead2b2158b43ae8d) --- src/devices/nm-device.c | 17 +++++++--- src/devices/nm-device.h | 2 ++ src/devices/ovs/nm-device-ovs-interface.c | 39 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f966ae6f4c..5b7015779c 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9152,6 +9152,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) { @@ -9310,10 +9321,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", @@ -16995,6 +17003,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 0eab3aca19..5a9339d03d 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -462,6 +462,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 9c74ffd1c2..f2919b4881 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -134,6 +134,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, @@ -364,4 +401,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; }