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-02 12:51:25 +0200
commitf3327835c1c90840315692fb10a624dcc89386f9 (patch)
tree84db9d7a95bd446c62e9229496a87863a86a74b0
parent38251ad59f41ea2b5ec66febeb82948e15f10dbb (diff)
downloadNetworkManager-f3327835c1c90840315692fb10a624dcc89386f9.tar.gz
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
-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);
}