summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2022-09-01 11:03:05 +0200
committerLubomir Rintel <lkundrak@v3.sk>2022-09-01 12:39:12 +0200
commitf5d51dba6c43d11fcb801eec948bcb7a52597ec4 (patch)
tree9eba4030b46fe6165acf0cb5c70321340a40ed14
parentfc25da3f5a7d41609ca983793e84871e12b8066c (diff)
team: restore port configuration after teamd respawnteam-restore-ports-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.
-rw-r--r--src/core/devices/team/nm-device-team.c56
1 files 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 {
@@ -138,20 +139,44 @@ complete_connection(NMDevice *device,
}
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;
+ }
+
+ 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 !!priv->tdc;
+ 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);
}