From bcf11ebeada87d4b744d735976aba2006c7eb2ef Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 1 Sep 2022 11:03:05 +0200 Subject: [PATCH] team: restore port configuration after teamd respawn If teamd crashes, we restore it. That's very nice, but if it really crashed then it left ports attached and the slave connections are not going to fail and the port configuration (e.g. priority or link watcher) in teamd's memory will be gone. This will restore the port configuration when the teamd connection is re-established. This probably also fixes a race where a slave connection would be enslaved (only possible externally and manually?) while we didn't establish a connection to teamd yet. We'll just send the port configuration in once're connected. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1361 (cherry picked from commit f3327835c1c90840315692fb10a624dcc89386f9) --- src/core/devices/team/nm-device-team.c | 56 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 65caec887a..d90b766bdb 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -43,6 +43,7 @@ typedef struct { bool kill_in_progress : 1; GFileMonitor *usock_monitor; NMDeviceStageState stage1_state : 3; + GHashTable *port_configs; } NMDeviceTeamPrivate; struct _NMDeviceTeam { @@ -137,21 +138,45 @@ complete_connection(NMDevice *device, return TRUE; } +static gboolean +_update_port_config(NMDeviceTeam *self, const char *port_iface, const char *sanitized_config) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + int err; + + err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config); + if (err != 0) { + _LOGE(LOGD_TEAM, "failed to update config for port %s (err=%d)", port_iface, err); + return FALSE; + } + + return TRUE; +} + static gboolean ensure_teamd_connection(NMDevice *device) { NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gs_free_error GError *error = NULL; + const char *port_iface; + const char *port_config; + GHashTableIter iter; if (priv->tdc) return TRUE; priv->tdc = _tdc_connect_new(self, nm_device_get_iface(device), &error); - if (!priv->tdc) + if (!priv->tdc) { _LOGE(LOGD_TEAM, "failed to connect to teamd: %s", error->message); + return FALSE; + } - return !!priv->tdc; + g_hash_table_iter_init(&iter, priv->port_configs); + while (g_hash_table_iter_next(&iter, (gpointer *) &port_iface, (gpointer *) &port_config)) + _update_port_config(self, port_iface, port_config); + + return TRUE; } static const char * @@ -843,24 +868,18 @@ attach_port(NMDevice *device, const char *config = nm_setting_team_port_get_config(s_team_port); if (config) { + char *sanitized_config = g_strdup(config); + g_strdelimit(sanitized_config, "\r\n", ' '); + + g_hash_table_insert(priv->port_configs, g_strdup(port_iface), sanitized_config); + if (!priv->tdc) { _LOGW(LOGD_TEAM, "attached team port %s config not changed, not connected to teamd", port_iface); } else { - gs_free char *sanitized_config = NULL; - int err; - - sanitized_config = g_strdup(config); - g_strdelimit(sanitized_config, "\r\n", ' '); - err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config); - if (err != 0) { - _LOGE(LOGD_TEAM, - "failed to update config for port %s (err=%d)", - port_iface, - err); + if (!_update_port_config(self, port_iface, sanitized_config)) return FALSE; - } } } } @@ -929,8 +948,10 @@ detach_port(NMDevice *device, NMDevice *port, gboolean configure) /* Delete any port configuration we previously set */ if (configure && priv->tdc && (s_port = nm_device_get_applied_setting(port, NM_TYPE_SETTING_TEAM_PORT)) - && (nm_setting_team_port_get_config(s_port))) - teamdctl_port_config_update_raw(priv->tdc, port_iface, "{}"); + && (nm_setting_team_port_get_config(s_port))) { + _update_port_config(self, port_iface, "{}"); + g_hash_table_remove(priv->port_configs, port_iface); + } } static gboolean @@ -994,6 +1015,8 @@ constructed(GObject *object) G_OBJECT_CLASS(nm_device_team_parent_class)->constructed(object); + priv->port_configs = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + if (nm_dbus_manager_get_dbus_connection(nm_dbus_manager_get())) { /* Register D-Bus name watcher */ tmp_str = g_strdup_printf("org.libteam.teamd.%s", nm_device_get_ip_iface(device)); @@ -1053,6 +1076,7 @@ dispose(GObject *object) teamd_cleanup(self, TRUE); nm_clear_g_free(&priv->config); + nm_clear_pointer(&priv->port_configs, g_hash_table_destroy); G_OBJECT_CLASS(nm_device_team_parent_class)->dispose(object); }