|
Packit Service |
5ffa24 |
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
Packit Service |
5ffa24 |
/*
|
|
Packit Service |
5ffa24 |
* Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us>
|
|
Packit Service |
5ffa24 |
* Copyright (C) 2018 Red Hat, Inc.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include "nm-default.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include "nm-device-team.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include <sys/types.h>
|
|
Packit Service |
5ffa24 |
#include <unistd.h>
|
|
Packit Service |
5ffa24 |
#include <signal.h>
|
|
Packit Service |
5ffa24 |
#include <sys/wait.h>
|
|
Packit Service |
5ffa24 |
#include <teamdctl.h>
|
|
Packit Service |
5ffa24 |
#include <stdlib.h>
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#include "nm-glib-aux/nm-jansson.h"
|
|
Packit Service |
5ffa24 |
#include "NetworkManagerUtils.h"
|
|
Packit Service |
5ffa24 |
#include "devices/nm-device-private.h"
|
|
Packit Service |
5ffa24 |
#include "platform/nm-platform.h"
|
|
Packit Service |
5ffa24 |
#include "nm-config.h"
|
|
Packit Service |
5ffa24 |
#include "nm-core-internal.h"
|
|
Packit Service |
5ffa24 |
#include "nm-dbus-manager.h"
|
|
Packit Service |
5ffa24 |
#include "nm-ip4-config.h"
|
|
Packit Service |
5ffa24 |
#include "nm-std-aux/nm-dbus-compat.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#define _NMLOG_DEVICE_TYPE NMDeviceTeam
|
|
Packit Service |
5ffa24 |
#include "devices/nm-device-logging.h"
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceTeam, PROP_CONFIG, );
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
typedef struct {
|
|
Packit Service |
5ffa24 |
struct teamdctl * tdc;
|
|
Packit Service |
5ffa24 |
char * config;
|
|
Packit Service |
5ffa24 |
GPid teamd_pid;
|
|
Packit Service |
5ffa24 |
guint teamd_process_watch;
|
|
Packit Service |
5ffa24 |
guint teamd_timeout;
|
|
Packit Service |
5ffa24 |
guint teamd_read_timeout;
|
|
Packit Service |
5ffa24 |
guint teamd_dbus_watch;
|
|
Packit Service |
5ffa24 |
bool kill_in_progress : 1;
|
|
Packit Service |
5ffa24 |
GFileMonitor * usock_monitor;
|
|
Packit Service |
5ffa24 |
NMDeviceStageState stage1_state : 3;
|
|
Packit Service |
5ffa24 |
} NMDeviceTeamPrivate;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
struct _NMDeviceTeam {
|
|
Packit Service |
5ffa24 |
NMDevice parent;
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate _priv;
|
|
Packit Service |
5ffa24 |
};
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
struct _NMDeviceTeamClass {
|
|
Packit Service |
5ffa24 |
NMDeviceClass parent;
|
|
Packit Service |
5ffa24 |
};
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
G_DEFINE_TYPE(NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE)
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
#define NM_DEVICE_TEAM_GET_PRIVATE(self) \
|
|
Packit Service |
5ffa24 |
_NM_GET_PRIVATE(self, NMDeviceTeam, NM_IS_DEVICE_TEAM, NMDevice)
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean teamd_start(NMDeviceTeam *self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static NMDeviceCapabilities
|
|
Packit Service |
5ffa24 |
get_generic_capabilities(NMDevice *device)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
complete_connection(NMDevice * device,
|
|
Packit Service |
5ffa24 |
NMConnection * connection,
|
|
Packit Service |
5ffa24 |
const char * specific_object,
|
|
Packit Service |
5ffa24 |
NMConnection *const *existing_connections,
|
|
Packit Service |
5ffa24 |
GError ** error)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMSettingTeam *s_team;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_utils_complete_generic(nm_device_get_platform(device),
|
|
Packit Service |
5ffa24 |
connection,
|
|
Packit Service |
5ffa24 |
NM_SETTING_TEAM_SETTING_NAME,
|
|
Packit Service |
5ffa24 |
existing_connections,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
_("Team connection"),
|
|
Packit Service |
5ffa24 |
"team",
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
TRUE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
s_team = nm_connection_get_setting_team(connection);
|
|
Packit Service |
5ffa24 |
if (!s_team) {
|
|
Packit Service |
5ffa24 |
s_team = (NMSettingTeam *) nm_setting_team_new();
|
|
Packit Service |
5ffa24 |
nm_connection_add_setting(connection, NM_SETTING(s_team));
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
ensure_teamd_connection(NMDevice *device)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
int err;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->tdc)
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->tdc = teamdctl_alloc();
|
|
Packit Service |
5ffa24 |
g_assert(priv->tdc);
|
|
Packit Service |
5ffa24 |
err = teamdctl_connect(priv->tdc, nm_device_get_iface(device), NULL, NULL);
|
|
Packit Service |
5ffa24 |
if (err != 0) {
|
|
Packit Service |
5ffa24 |
_LOGE(LOGD_TEAM, "failed to connect to teamd (err=%d)", err);
|
|
Packit Service |
5ffa24 |
teamdctl_free(priv->tdc);
|
|
Packit Service |
5ffa24 |
priv->tdc = NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return !!priv->tdc;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static const char *
|
|
Packit Service |
5ffa24 |
_get_config(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
return nm_str_not_empty(NM_DEVICE_TEAM_GET_PRIVATE(self)->config);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
teamd_read_config(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
const char * config = NULL;
|
|
Packit Service |
5ffa24 |
int err;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->tdc) {
|
|
Packit Service |
5ffa24 |
err = teamdctl_config_actual_get_raw_direct(priv->tdc, (char **) &config);
|
|
Packit Service |
5ffa24 |
if (err)
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
if (!config) {
|
|
Packit Service |
5ffa24 |
/* set "" to distinguish an empty result from no config at all. */
|
|
Packit Service |
5ffa24 |
config = "";
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!nm_streq0(config, priv->config)) {
|
|
Packit Service |
5ffa24 |
g_free(priv->config);
|
|
Packit Service |
5ffa24 |
priv->config = g_strdup(config);
|
|
Packit Service |
5ffa24 |
_notify(self, PROP_CONFIG);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
teamd_read_timeout_cb(gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = user_data;
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->teamd_read_timeout = 0;
|
|
Packit Service |
5ffa24 |
teamd_read_config(self);
|
|
Packit Service |
5ffa24 |
return G_SOURCE_REMOVE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
update_connection(NMDevice *device, NMConnection *connection)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMSettingTeam * s_team = nm_connection_get_setting_team(connection);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
struct teamdctl * tdc = priv->tdc;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!s_team) {
|
|
Packit Service |
5ffa24 |
s_team = (NMSettingTeam *) nm_setting_team_new();
|
|
Packit Service |
5ffa24 |
nm_connection_add_setting(connection, (NMSetting *) s_team);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Read the configuration only if not already set */
|
|
Packit Service |
5ffa24 |
if (!priv->config && ensure_teamd_connection(device))
|
|
Packit Service |
5ffa24 |
teamd_read_config(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Restore previous tdc state */
|
|
Packit Service |
5ffa24 |
if (priv->tdc && !tdc) {
|
|
Packit Service |
5ffa24 |
teamdctl_disconnect(priv->tdc);
|
|
Packit Service |
5ffa24 |
teamdctl_free(priv->tdc);
|
|
Packit Service |
5ffa24 |
priv->tdc = NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_set(G_OBJECT(s_team), NM_SETTING_TEAM_CONFIG, _get_config(self), NULL);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
master_update_slave_connection(NMDevice * self,
|
|
Packit Service |
5ffa24 |
NMDevice * slave,
|
|
Packit Service |
5ffa24 |
NMConnection *connection,
|
|
Packit Service |
5ffa24 |
GError ** error)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMSettingTeamPort *s_port;
|
|
Packit Service |
5ffa24 |
char * port_config = NULL;
|
|
Packit Service |
5ffa24 |
int err = 0;
|
|
Packit Service |
5ffa24 |
struct teamdctl * tdc;
|
|
Packit Service |
5ffa24 |
const char * team_port_config = NULL;
|
|
Packit Service |
5ffa24 |
const char * iface = nm_device_get_iface(self);
|
|
Packit Service |
5ffa24 |
const char * iface_slave = nm_device_get_iface(slave);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
tdc = teamdctl_alloc();
|
|
Packit Service |
5ffa24 |
if (!tdc) {
|
|
Packit Service |
5ffa24 |
g_set_error(error,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR_FAILED,
|
|
Packit Service |
5ffa24 |
"update slave connection for slave '%s' failed to connect to teamd for master "
|
|
Packit Service |
5ffa24 |
"%s (out of memory?)",
|
|
Packit Service |
5ffa24 |
iface_slave,
|
|
Packit Service |
5ffa24 |
iface);
|
|
Packit Service |
5ffa24 |
g_return_val_if_reached(FALSE);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
err = teamdctl_connect(tdc, iface, NULL, NULL);
|
|
Packit Service |
5ffa24 |
if (err) {
|
|
Packit Service |
5ffa24 |
teamdctl_free(tdc);
|
|
Packit Service |
5ffa24 |
g_set_error(error,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR_FAILED,
|
|
Packit Service |
5ffa24 |
"update slave connection for slave '%s' failed to connect to teamd for master "
|
|
Packit Service |
5ffa24 |
"%s (err=%d)",
|
|
Packit Service |
5ffa24 |
iface_slave,
|
|
Packit Service |
5ffa24 |
iface,
|
|
Packit Service |
5ffa24 |
err);
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
err = teamdctl_port_config_get_raw_direct(tdc, iface_slave, (char **) &team_port_config);
|
|
Packit Service |
5ffa24 |
port_config = g_strdup(team_port_config);
|
|
Packit Service |
5ffa24 |
teamdctl_disconnect(tdc);
|
|
Packit Service |
5ffa24 |
teamdctl_free(tdc);
|
|
Packit Service |
5ffa24 |
if (err) {
|
|
Packit Service |
5ffa24 |
g_set_error(error,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR_FAILED,
|
|
Packit Service |
5ffa24 |
"update slave connection for slave '%s' failed to get configuration from teamd "
|
|
Packit Service |
5ffa24 |
"master %s (err=%d)",
|
|
Packit Service |
5ffa24 |
iface_slave,
|
|
Packit Service |
5ffa24 |
iface,
|
|
Packit Service |
5ffa24 |
err);
|
|
Packit Service |
5ffa24 |
g_free(port_config);
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
s_port = nm_connection_get_setting_team_port(connection);
|
|
Packit Service |
5ffa24 |
if (!s_port) {
|
|
Packit Service |
5ffa24 |
s_port = (NMSettingTeamPort *) nm_setting_team_port_new();
|
|
Packit Service |
5ffa24 |
nm_connection_add_setting(connection, NM_SETTING(s_port));
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_set(G_OBJECT(s_port), NM_SETTING_TEAM_PORT_CONFIG, port_config, NULL);
|
|
Packit Service |
5ffa24 |
g_free(port_config);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_set(nm_connection_get_setting_connection(connection),
|
|
Packit Service |
5ffa24 |
NM_SETTING_CONNECTION_MASTER,
|
|
Packit Service |
5ffa24 |
iface,
|
|
Packit Service |
5ffa24 |
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
Packit Service |
5ffa24 |
NM_SETTING_TEAM_SETTING_NAME,
|
|
Packit Service |
5ffa24 |
NULL);
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_kill_cb(pid_t pid, gboolean success, int child_status, void *user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
gs_unref_object NMDeviceTeam *self = user_data;
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate * priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->kill_in_progress = FALSE;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_device_get_state(NM_DEVICE(self)) != NM_DEVICE_STATE_PREPARE) {
|
|
Packit Service |
5ffa24 |
_LOGT(LOGD_TEAM, "kill terminated");
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGT(LOGD_TEAM, "kill terminated, starting teamd...");
|
|
Packit Service |
5ffa24 |
if (!teamd_start(self)) {
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(NM_DEVICE(self),
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_cleanup(NMDeviceTeam *self, gboolean free_tdc)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_clear_g_source(&priv->teamd_process_watch);
|
|
Packit Service |
5ffa24 |
nm_clear_g_source(&priv->teamd_timeout);
|
|
Packit Service |
5ffa24 |
nm_clear_g_source(&priv->teamd_read_timeout);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->teamd_pid > 0) {
|
|
Packit Service |
5ffa24 |
priv->kill_in_progress = TRUE;
|
|
Packit Service |
5ffa24 |
nm_utils_kill_child_async(priv->teamd_pid,
|
|
Packit Service |
5ffa24 |
SIGTERM,
|
|
Packit Service |
5ffa24 |
LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"teamd",
|
|
Packit Service |
5ffa24 |
2000,
|
|
Packit Service |
5ffa24 |
teamd_kill_cb,
|
|
Packit Service |
5ffa24 |
g_object_ref(self));
|
|
Packit Service |
5ffa24 |
priv->teamd_pid = 0;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->tdc && free_tdc) {
|
|
Packit Service |
5ffa24 |
teamdctl_disconnect(priv->tdc);
|
|
Packit Service |
5ffa24 |
teamdctl_free(priv->tdc);
|
|
Packit Service |
5ffa24 |
priv->tdc = NULL;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
teamd_timeout_cb(gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(user_data);
|
|
Packit Service |
5ffa24 |
NMDevice * device = NM_DEVICE(self);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_val_if_fail(priv->teamd_timeout, FALSE);
|
|
Packit Service |
5ffa24 |
priv->teamd_timeout = 0;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->teamd_pid && !priv->tdc) {
|
|
Packit Service |
5ffa24 |
/* Timed out launching our own teamd process */
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "teamd timed out");
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_warn_if_fail(nm_device_is_activating(device));
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(device,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
} else {
|
|
Packit Service |
5ffa24 |
/* Read again the configuration after the timeout since it might
|
|
Packit Service |
5ffa24 |
* have changed.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
if (!teamd_read_config(self)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "failed to read teamd configuration");
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(device,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return G_SOURCE_REMOVE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_ready(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
NMDevice * device = NM_DEVICE(self);
|
|
Packit Service |
5ffa24 |
gboolean success;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->kill_in_progress) {
|
|
Packit Service |
5ffa24 |
/* If we are currently killing teamd, we are not
|
|
Packit Service |
5ffa24 |
* interested in knowing when it becomes ready. */
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_device_queue_recheck_assume(device);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Grab a teamd control handle even if we aren't going to use it
|
|
Packit Service |
5ffa24 |
* immediately. But if we are, and grabbing it failed, fail the
|
|
Packit Service |
5ffa24 |
* device activation.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
success = ensure_teamd_connection(device);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_device_get_state(device) != NM_DEVICE_STATE_PREPARE
|
|
Packit Service |
5ffa24 |
|| priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING)
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (success)
|
|
Packit Service |
5ffa24 |
success = teamd_read_config(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!success) {
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(device,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED;
|
|
Packit Service |
5ffa24 |
nm_device_activate_schedule_stage1_device_prepare(device, FALSE);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_gone(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDevice * device = NM_DEVICE(self);
|
|
Packit Service |
5ffa24 |
NMDeviceState state;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
state = nm_device_get_state(device);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Attempt to respawn teamd */
|
|
Packit Service |
5ffa24 |
if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_ACTIVATED) {
|
|
Packit Service |
5ffa24 |
if (!teamd_start(self)) {
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(device,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_dbus_appeared(GDBusConnection *connection,
|
|
Packit Service |
5ffa24 |
const char * name,
|
|
Packit Service |
5ffa24 |
const char * name_owner,
|
|
Packit Service |
5ffa24 |
gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(user_data);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(priv->teamd_dbus_watch);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "teamd appeared on D-Bus");
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* If another teamd grabbed the bus name while our teamd was starting,
|
|
Packit Service |
5ffa24 |
* just ignore the death of our teamd and run with the existing one.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
if (priv->teamd_process_watch) {
|
|
Packit Service |
5ffa24 |
gs_unref_variant GVariant *ret = NULL;
|
|
Packit Service |
5ffa24 |
guint32 pid;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
ret = g_dbus_connection_call_sync(connection,
|
|
Packit Service |
5ffa24 |
DBUS_SERVICE_DBUS,
|
|
Packit Service |
5ffa24 |
DBUS_PATH_DBUS,
|
|
Packit Service |
5ffa24 |
DBUS_INTERFACE_DBUS,
|
|
Packit Service |
5ffa24 |
"GetConnectionUnixProcessID",
|
|
Packit Service |
5ffa24 |
g_variant_new("(s)", name_owner),
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
|
Packit Service |
5ffa24 |
2000,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
NULL);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (ret) {
|
|
Packit Service |
5ffa24 |
g_variant_get(ret, "(u)", &pid;;
|
|
Packit Service |
5ffa24 |
if (pid != priv->teamd_pid)
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, FALSE);
|
|
Packit Service |
5ffa24 |
} else {
|
|
Packit Service |
5ffa24 |
/* The process that registered on the bus died. If it's
|
|
Packit Service |
5ffa24 |
* the teamd instance we just started, ignore the event
|
|
Packit Service |
5ffa24 |
* as we already detect the failure through the process
|
|
Packit Service |
5ffa24 |
* watch. If it's a previous instance that got killed,
|
|
Packit Service |
5ffa24 |
* also ignore that as our new instance will register
|
|
Packit Service |
5ffa24 |
* again. */
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "failed to determine D-Bus name owner, ignoring");
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_ready(self);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_dbus_vanished(GDBusConnection *dbus_connection, const char *name, gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(user_data);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(priv->teamd_dbus_watch);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!priv->tdc) {
|
|
Packit Service |
5ffa24 |
/* g_bus_watch_name will always raise an initial signal, to indicate whether the
|
|
Packit Service |
5ffa24 |
* name exists/not exists initially. Do not take this as a failure if it hadn't
|
|
Packit Service |
5ffa24 |
* previously appeared.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "teamd not on D-Bus (ignored)");
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "teamd vanished from D-Bus");
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_gone(self);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
monitor_changed_cb(GFileMonitor * monitor,
|
|
Packit Service |
5ffa24 |
GFile * file,
|
|
Packit Service |
5ffa24 |
GFile * other_file,
|
|
Packit Service |
5ffa24 |
GFileMonitorEvent event_type,
|
|
Packit Service |
5ffa24 |
gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam *self = NM_DEVICE_TEAM(user_data);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
switch (event_type) {
|
|
Packit Service |
5ffa24 |
case G_FILE_MONITOR_EVENT_CREATED:
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "file %s was created", g_file_get_path(file));
|
|
Packit Service |
5ffa24 |
teamd_ready(self);
|
|
Packit Service |
5ffa24 |
break;
|
|
Packit Service |
5ffa24 |
case G_FILE_MONITOR_EVENT_DELETED:
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "file %s was deleted", g_file_get_path(file));
|
|
Packit Service |
5ffa24 |
teamd_gone(self);
|
|
Packit Service |
5ffa24 |
break;
|
|
Packit Service |
5ffa24 |
default:;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_process_watch_cb(GPid pid, int status, gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(user_data);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
NMDevice * device = NM_DEVICE(self);
|
|
Packit Service |
5ffa24 |
NMDeviceState state = nm_device_get_state(device);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_return_if_fail(priv->teamd_process_watch);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "teamd %lld died with status %d", (long long) pid, status);
|
|
Packit Service |
5ffa24 |
priv->teamd_pid = 0;
|
|
Packit Service |
5ffa24 |
priv->teamd_process_watch = 0;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* If teamd quit within 5 seconds of starting, it's probably hosed
|
|
Packit Service |
5ffa24 |
* and will just die again, so fail the activation.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
if (priv->teamd_timeout && (state >= NM_DEVICE_STATE_PREPARE)
|
|
Packit Service |
5ffa24 |
&& (state <= NM_DEVICE_STATE_ACTIVATED)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"teamd process %lld quit unexpectedly; failing activation",
|
|
Packit Service |
5ffa24 |
(long long) pid);
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
nm_device_state_changed(device,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_FAILED,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
teamd_child_setup(gpointer user_data)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_utils_setpgid(NULL);
|
|
Packit Service |
5ffa24 |
signal(SIGPIPE, SIG_IGN);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static const char **
|
|
Packit Service |
5ffa24 |
teamd_env(void)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
const char **env = g_new0(const char *, 2);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_config_get_is_debug(nm_config_get()))
|
|
Packit Service |
5ffa24 |
env[0] = "TEAM_LOG_OUTPUT=stderr";
|
|
Packit Service |
5ffa24 |
else
|
|
Packit Service |
5ffa24 |
env[0] = "TEAM_LOG_OUTPUT=syslog";
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return env;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
teamd_kill(NMDeviceTeam *self, const char *teamd_binary, GError **error)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
gs_unref_ptrarray GPtrArray *argv = NULL;
|
|
Packit Service |
5ffa24 |
gs_free char * tmp_str = NULL;
|
|
Packit Service |
5ffa24 |
gs_free const char ** envp = NULL;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!teamd_binary) {
|
|
Packit Service |
5ffa24 |
teamd_binary = nm_utils_find_helper("teamd", NULL, error);
|
|
Packit Service |
5ffa24 |
if (!teamd_binary) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "Activation: (team) failed to start teamd: teamd binary not found");
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
argv = g_ptr_array_new();
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) teamd_binary);
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-k");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-t");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) nm_device_get_iface(NM_DEVICE(self)));
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, NULL);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
envp = teamd_env();
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "running: %s", (tmp_str = g_strjoinv(" ", (char **) argv->pdata)));
|
|
Packit Service |
5ffa24 |
return g_spawn_sync("/",
|
|
Packit Service |
5ffa24 |
(char **) argv->pdata,
|
|
Packit Service |
5ffa24 |
(char **) envp,
|
|
Packit Service |
5ffa24 |
0,
|
|
Packit Service |
5ffa24 |
teamd_child_setup,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
error);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
teamd_start(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
const char * iface = nm_device_get_ip_iface(NM_DEVICE(self));
|
|
Packit Service |
5ffa24 |
NMConnection * connection;
|
|
Packit Service |
5ffa24 |
gs_unref_ptrarray GPtrArray *argv = NULL;
|
|
Packit Service |
5ffa24 |
gs_free_error GError * error = NULL;
|
|
Packit Service |
5ffa24 |
gs_free char * tmp_str = NULL;
|
|
Packit Service |
5ffa24 |
const char * teamd_binary;
|
|
Packit Service |
5ffa24 |
const char * config;
|
|
Packit Service |
5ffa24 |
nm_auto_free const char *config_free = NULL;
|
|
Packit Service |
5ffa24 |
NMSettingTeam * s_team;
|
|
Packit Service |
5ffa24 |
gs_free char * cloned_mac = NULL;
|
|
Packit Service |
5ffa24 |
gs_free const char ** envp = NULL;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
connection = nm_device_get_applied_connection(NM_DEVICE(self));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
s_team = nm_connection_get_setting_team(connection);
|
|
Packit Service |
5ffa24 |
if (!s_team)
|
|
Packit Service |
5ffa24 |
g_return_val_if_reached(FALSE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_assert(iface);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_binary = nm_utils_find_helper("teamd", NULL, NULL);
|
|
Packit Service |
5ffa24 |
if (!teamd_binary) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "Activation: (team) failed to start teamd: teamd binary not found");
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->teamd_process_watch || priv->teamd_pid > 0 || priv->tdc) {
|
|
Packit Service |
5ffa24 |
g_warn_if_reached();
|
|
Packit Service |
5ffa24 |
if (!priv->teamd_pid)
|
|
Packit Service |
5ffa24 |
teamd_kill(self, teamd_binary, NULL);
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Start teamd now */
|
|
Packit Service |
5ffa24 |
argv = g_ptr_array_new();
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) teamd_binary);
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-o");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-n");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-U");
|
|
Packit Service |
5ffa24 |
if (priv->teamd_dbus_watch)
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-D");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-N");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-t");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) iface);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
config = nm_setting_team_get_config(s_team);
|
|
Packit Service |
5ffa24 |
if (!nm_device_hw_addr_get_cloned(NM_DEVICE(self),
|
|
Packit Service |
5ffa24 |
connection,
|
|
Packit Service |
5ffa24 |
FALSE,
|
|
Packit Service |
5ffa24 |
&cloned_mac,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
&error)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_DEVICE, "set-hw-addr: %s", error->message);
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (cloned_mac) {
|
|
Packit Service |
5ffa24 |
json_t * json, *hwaddr;
|
|
Packit Service |
5ffa24 |
json_error_t jerror;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Inject the hwaddr property into the JSON configuration.
|
|
Packit Service |
5ffa24 |
* While doing so, detect potential conflicts */
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
json = json_loads(config ?: "{}", JSON_REJECT_DUPLICATES, &jerror);
|
|
Packit Service |
5ffa24 |
g_return_val_if_fail(json, FALSE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
hwaddr = json_object_get(json, "hwaddr");
|
|
Packit Service |
5ffa24 |
if (hwaddr) {
|
|
Packit Service |
5ffa24 |
if (!json_is_string(hwaddr) || !nm_streq0(json_string_value(hwaddr), cloned_mac))
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"set-hw-addr: can't set team cloned-mac-address as the JSON configuration "
|
|
Packit Service |
5ffa24 |
"already contains \"hwaddr\"");
|
|
Packit Service |
5ffa24 |
} else {
|
|
Packit Service |
5ffa24 |
hwaddr = json_string(cloned_mac);
|
|
Packit Service |
5ffa24 |
json_object_set(json, "hwaddr", hwaddr);
|
|
Packit Service |
5ffa24 |
config = config_free =
|
|
Packit Service |
5ffa24 |
json_dumps(json, JSON_INDENT(0) | JSON_ENSURE_ASCII | JSON_SORT_KEYS);
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"set-hw-addr: injected \"hwaddr\" \"%s\" into team configuration",
|
|
Packit Service |
5ffa24 |
cloned_mac);
|
|
Packit Service |
5ffa24 |
json_decref(hwaddr);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
json_decref(json);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (config) {
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-c");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) config);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_logging_enabled(LOGL_DEBUG, LOGD_TEAM))
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, (gpointer) "-gg");
|
|
Packit Service |
5ffa24 |
g_ptr_array_add(argv, NULL);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
envp = teamd_env();
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "running: %s", (tmp_str = g_strjoinv(" ", (char **) argv->pdata)));
|
|
Packit Service |
5ffa24 |
if (!g_spawn_async("/",
|
|
Packit Service |
5ffa24 |
(char **) argv->pdata,
|
|
Packit Service |
5ffa24 |
(char **) envp,
|
|
Packit Service |
5ffa24 |
G_SPAWN_DO_NOT_REAP_CHILD,
|
|
Packit Service |
5ffa24 |
teamd_child_setup,
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
&priv->teamd_pid,
|
|
Packit Service |
5ffa24 |
&error)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "Activation: (team) failed to start teamd: %s", error->message);
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Start a timeout for teamd to appear at D-Bus */
|
|
Packit Service |
5ffa24 |
if (!priv->teamd_timeout)
|
|
Packit Service |
5ffa24 |
priv->teamd_timeout = g_timeout_add_seconds(5, teamd_timeout_cb, self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Monitor the child process so we know when it dies */
|
|
Packit Service |
5ffa24 |
priv->teamd_process_watch = g_child_watch_add(priv->teamd_pid, teamd_process_watch_cb, self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "Activation: (team) started teamd [pid %u]...", (guint) priv->teamd_pid);
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static NMActStageReturn
|
|
Packit Service |
5ffa24 |
act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
gs_free_error GError *error = NULL;
|
|
Packit Service |
5ffa24 |
NMSettingTeam * s_team;
|
|
Packit Service |
5ffa24 |
const char * cfg;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_device_sys_iface_state_is_external(device))
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_device_sys_iface_state_is_external_or_assume(device)) {
|
|
Packit Service |
5ffa24 |
if (ensure_teamd_connection(device))
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
s_team = nm_device_get_applied_setting(device, NM_TYPE_SETTING_TEAM);
|
|
Packit Service |
5ffa24 |
if (!s_team)
|
|
Packit Service |
5ffa24 |
g_return_val_if_reached(NM_ACT_STAGE_RETURN_FAILURE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING)
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED)
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->tdc) {
|
|
Packit Service |
5ffa24 |
/* If the existing teamd config is the same as we're about to use,
|
|
Packit Service |
5ffa24 |
* then we can proceed. If it's not the same, and we have a PID,
|
|
Packit Service |
5ffa24 |
* kill it so we can respawn it with the right config. If we don't
|
|
Packit Service |
5ffa24 |
* have a PID, then we must fail.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
cfg = teamdctl_config_get_raw(priv->tdc);
|
|
Packit Service |
5ffa24 |
if (cfg && nm_streq0(cfg, nm_setting_team_get_config(s_team))) {
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "using existing matching teamd config");
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!priv->teamd_pid) {
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "existing teamd config mismatch; killing existing via teamdctl");
|
|
Packit Service |
5ffa24 |
if (!teamd_kill(self, NULL, &error)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"existing teamd config mismatch; failed to kill existing teamd: %s",
|
|
Packit Service |
5ffa24 |
error->message);
|
|
Packit Service |
5ffa24 |
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_FAILURE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "existing teamd config mismatch; respawning...");
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->kill_in_progress) {
|
|
Packit Service |
5ffa24 |
_LOGT(LOGD_TEAM, "kill in progress, wait before starting teamd");
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!teamd_start(self))
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_FAILURE;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
deactivate(NMDevice *device)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_device_sys_iface_state_is_external(device))
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->teamd_pid || priv->tdc)
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "deactivation: stopping teamd...");
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!priv->teamd_pid)
|
|
Packit Service |
5ffa24 |
teamd_kill(self, NULL, NULL);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
gboolean success = TRUE;
|
|
Packit Service |
5ffa24 |
const char * slave_iface = nm_device_get_ip_iface(slave);
|
|
Packit Service |
5ffa24 |
NMSettingTeamPort * s_team_port;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_device_master_check_slave_physical_port(device, slave, LOGD_TEAM);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (configure) {
|
|
Packit Service |
5ffa24 |
nm_device_take_down(slave, TRUE);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
s_team_port = nm_connection_get_setting_team_port(connection);
|
|
Packit Service |
5ffa24 |
if (s_team_port) {
|
|
Packit Service |
5ffa24 |
const char *config = nm_setting_team_port_get_config(s_team_port);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (config) {
|
|
Packit Service |
5ffa24 |
if (!priv->tdc) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"enslaved team port %s config not changed, not connected to teamd",
|
|
Packit Service |
5ffa24 |
slave_iface);
|
|
Packit Service |
5ffa24 |
} else {
|
|
Packit Service |
5ffa24 |
int err;
|
|
Packit Service |
5ffa24 |
char *sanitized_config;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
sanitized_config = g_strdelimit(g_strdup(config), "\r\n", ' ');
|
|
Packit Service |
5ffa24 |
err = teamdctl_port_config_update_raw(priv->tdc, slave_iface, sanitized_config);
|
|
Packit Service |
5ffa24 |
g_free(sanitized_config);
|
|
Packit Service |
5ffa24 |
if (err != 0) {
|
|
Packit Service |
5ffa24 |
_LOGE(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"failed to update config for port %s (err=%d)",
|
|
Packit Service |
5ffa24 |
slave_iface,
|
|
Packit Service |
5ffa24 |
err);
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
success = nm_platform_link_enslave(nm_device_get_platform(device),
|
|
Packit Service |
5ffa24 |
nm_device_get_ip_ifindex(device),
|
|
Packit Service |
5ffa24 |
nm_device_get_ip_ifindex(slave));
|
|
Packit Service |
5ffa24 |
nm_device_bring_up(slave, TRUE, NULL);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (!success)
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_clear_g_source(&priv->teamd_read_timeout);
|
|
Packit Service |
5ffa24 |
priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "enslaved team port %s", slave_iface);
|
|
Packit Service |
5ffa24 |
} else
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "team port %s was enslaved", slave_iface);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(device);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
gboolean do_release, success;
|
|
Packit Service |
5ffa24 |
NMSettingTeamPort * s_port;
|
|
Packit Service |
5ffa24 |
int ifindex_slave;
|
|
Packit Service |
5ffa24 |
int ifindex;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
do_release = configure;
|
|
Packit Service |
5ffa24 |
if (do_release) {
|
|
Packit Service |
5ffa24 |
ifindex = nm_device_get_ifindex(device);
|
|
Packit Service |
5ffa24 |
if (ifindex <= 0 || !nm_platform_link_get(nm_device_get_platform(device), ifindex))
|
|
Packit Service |
5ffa24 |
do_release = FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
ifindex_slave = nm_device_get_ip_ifindex(slave);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (ifindex_slave <= 0) {
|
|
Packit Service |
5ffa24 |
_LOGD(LOGD_TEAM, "team port %s is already released", nm_device_get_ip_iface(slave));
|
|
Packit Service |
5ffa24 |
} else if (do_release) {
|
|
Packit Service |
5ffa24 |
success = nm_platform_link_release(nm_device_get_platform(device),
|
|
Packit Service |
5ffa24 |
nm_device_get_ip_ifindex(device),
|
|
Packit Service |
5ffa24 |
ifindex_slave);
|
|
Packit Service |
5ffa24 |
if (success)
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "released team port %s", nm_device_get_ip_iface(slave));
|
|
Packit Service |
5ffa24 |
else
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM, "failed to release team port %s", nm_device_get_ip_iface(slave));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Kernel team code "closes" the port when releasing it, (which clears
|
|
Packit Service |
5ffa24 |
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
|
Packit Service |
5ffa24 |
* other state is noticed by the now-released port.
|
|
Packit Service |
5ffa24 |
*/
|
|
Packit Service |
5ffa24 |
if (!nm_device_bring_up(slave, TRUE, NULL)) {
|
|
Packit Service |
5ffa24 |
_LOGW(LOGD_TEAM,
|
|
Packit Service |
5ffa24 |
"released team port %s could not be brought up",
|
|
Packit Service |
5ffa24 |
nm_device_get_ip_iface(slave));
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
nm_clear_g_source(&priv->teamd_read_timeout);
|
|
Packit Service |
5ffa24 |
priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self);
|
|
Packit Service |
5ffa24 |
} else
|
|
Packit Service |
5ffa24 |
_LOGI(LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface(slave));
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* Delete any port configuration we previously set */
|
|
Packit Service |
5ffa24 |
if (configure && priv->tdc
|
|
Packit Service |
5ffa24 |
&& (s_port = nm_device_get_applied_setting(slave, NM_TYPE_SETTING_TEAM_PORT))
|
|
Packit Service |
5ffa24 |
&& (nm_setting_team_port_get_config(s_port)))
|
|
Packit Service |
5ffa24 |
teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(slave), "{}");
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static gboolean
|
|
Packit Service |
5ffa24 |
create_and_realize(NMDevice * device,
|
|
Packit Service |
5ffa24 |
NMConnection * connection,
|
|
Packit Service |
5ffa24 |
NMDevice * parent,
|
|
Packit Service |
5ffa24 |
const NMPlatformLink **out_plink,
|
|
Packit Service |
5ffa24 |
GError ** error)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
const char *iface = nm_device_get_iface(device);
|
|
Packit Service |
5ffa24 |
int r;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
r = nm_platform_link_team_add(nm_device_get_platform(device), iface, out_plink);
|
|
Packit Service |
5ffa24 |
if (r < 0) {
|
|
Packit Service |
5ffa24 |
g_set_error(error,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_ERROR_CREATION_FAILED,
|
|
Packit Service |
5ffa24 |
"Failed to create team master interface '%s' for '%s': %s",
|
|
Packit Service |
5ffa24 |
iface,
|
|
Packit Service |
5ffa24 |
nm_connection_get_id(connection),
|
|
Packit Service |
5ffa24 |
nm_strerror(r));
|
|
Packit Service |
5ffa24 |
return FALSE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
return TRUE;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam *self = NM_DEVICE_TEAM(object);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
switch (prop_id) {
|
|
Packit Service |
5ffa24 |
case PROP_CONFIG:
|
|
Packit Service |
5ffa24 |
g_value_set_string(value, _get_config(self));
|
|
Packit Service |
5ffa24 |
break;
|
|
Packit Service |
5ffa24 |
default:
|
|
Packit Service |
5ffa24 |
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
Packit Service |
5ffa24 |
break;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/*****************************************************************************/
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
nm_device_team_init(NMDeviceTeam *self)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
nm_assert(nm_device_is_master(NM_DEVICE(self)));
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
constructed(GObject *object)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDevice * device = NM_DEVICE(object);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(device);
|
|
Packit Service |
5ffa24 |
gs_free char * tmp_str = NULL;
|
|
Packit Service |
5ffa24 |
gs_unref_object GFile *file = NULL;
|
|
Packit Service |
5ffa24 |
GError * error;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
G_OBJECT_CLASS(nm_device_team_parent_class)->constructed(object);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (nm_dbus_manager_get_dbus_connection(nm_dbus_manager_get())) {
|
|
Packit Service |
5ffa24 |
/* Register D-Bus name watcher */
|
|
Packit Service |
5ffa24 |
tmp_str = g_strdup_printf("org.libteam.teamd.%s", nm_device_get_ip_iface(device));
|
|
Packit Service |
5ffa24 |
priv->teamd_dbus_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
|
|
Packit Service |
5ffa24 |
tmp_str,
|
|
Packit Service |
5ffa24 |
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
Packit Service |
5ffa24 |
teamd_dbus_appeared,
|
|
Packit Service |
5ffa24 |
teamd_dbus_vanished,
|
|
Packit Service |
5ffa24 |
NM_DEVICE(device),
|
|
Packit Service |
5ffa24 |
NULL);
|
|
Packit Service |
5ffa24 |
return;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
/* No D-Bus, watch unix socket */
|
|
Packit Service |
5ffa24 |
tmp_str = g_strdup_printf("/run/teamd/%s.sock", nm_device_get_ip_iface(device));
|
|
Packit Service |
5ffa24 |
file = g_file_new_for_path(tmp_str);
|
|
Packit Service |
5ffa24 |
priv->usock_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, &error);
|
|
Packit Service |
5ffa24 |
if (!priv->usock_monitor) {
|
|
Packit Service |
5ffa24 |
nm_log_warn(LOGD_TEAM, "error monitoring %s: %s", tmp_str, error->message);
|
|
Packit Service |
5ffa24 |
} else {
|
|
Packit Service |
5ffa24 |
g_signal_connect(priv->usock_monitor, "changed", G_CALLBACK(monitor_changed_cb), object);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
NMDevice *
|
|
Packit Service |
5ffa24 |
nm_device_team_new(const char *iface)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
return g_object_new(NM_TYPE_DEVICE_TEAM,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_IFACE,
|
|
Packit Service |
5ffa24 |
iface,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_DRIVER,
|
|
Packit Service |
5ffa24 |
"team",
|
|
Packit Service |
5ffa24 |
NM_DEVICE_TYPE_DESC,
|
|
Packit Service |
5ffa24 |
"Team",
|
|
Packit Service |
5ffa24 |
NM_DEVICE_DEVICE_TYPE,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_TYPE_TEAM,
|
|
Packit Service |
5ffa24 |
NM_DEVICE_LINK_TYPE,
|
|
Packit Service |
5ffa24 |
NM_LINK_TYPE_TEAM,
|
|
Packit Service |
5ffa24 |
NULL);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
dispose(GObject *object)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
NMDeviceTeam * self = NM_DEVICE_TEAM(object);
|
|
Packit Service |
5ffa24 |
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->teamd_dbus_watch) {
|
|
Packit Service |
5ffa24 |
g_bus_unwatch_name(priv->teamd_dbus_watch);
|
|
Packit Service |
5ffa24 |
priv->teamd_dbus_watch = 0;
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
if (priv->usock_monitor) {
|
|
Packit Service |
5ffa24 |
g_signal_handlers_disconnect_by_data(priv->usock_monitor, object);
|
|
Packit Service |
5ffa24 |
g_clear_object(&priv->usock_monitor);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
teamd_cleanup(self, TRUE);
|
|
Packit Service |
5ffa24 |
nm_clear_g_free(&priv->config);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
G_OBJECT_CLASS(nm_device_team_parent_class)->dispose(object);
|
|
Packit Service |
5ffa24 |
}
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static const NMDBusInterfaceInfoExtended interface_info_device_team = {
|
|
Packit Service |
5ffa24 |
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
|
|
Packit Service |
5ffa24 |
NM_DBUS_INTERFACE_DEVICE_TEAM,
|
|
Packit Service |
5ffa24 |
.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ),
|
|
Packit Service |
5ffa24 |
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
|
|
Packit Service |
5ffa24 |
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress",
|
|
Packit Service |
5ffa24 |
"s",
|
|
Packit Service |
5ffa24 |
NM_DEVICE_HW_ADDRESS),
|
|
Packit Service |
5ffa24 |
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", "b", NM_DEVICE_CARRIER),
|
|
Packit Service |
5ffa24 |
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Slaves", "ao", NM_DEVICE_SLAVES),
|
|
Packit Service |
5ffa24 |
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Config",
|
|
Packit Service |
5ffa24 |
"s",
|
|
Packit Service |
5ffa24 |
NM_DEVICE_TEAM_CONFIG), ), ),
|
|
Packit Service |
5ffa24 |
.legacy_property_changed = TRUE,
|
|
Packit Service |
5ffa24 |
};
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
static void
|
|
Packit Service |
5ffa24 |
nm_device_team_class_init(NMDeviceTeamClass *klass)
|
|
Packit Service |
5ffa24 |
{
|
|
Packit Service |
5ffa24 |
GObjectClass * object_class = G_OBJECT_CLASS(klass);
|
|
Packit Service |
5ffa24 |
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
|
|
Packit Service |
5ffa24 |
NMDeviceClass * device_class = NM_DEVICE_CLASS(klass);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
object_class->constructed = constructed;
|
|
Packit Service |
5ffa24 |
object_class->dispose = dispose;
|
|
Packit Service |
5ffa24 |
object_class->get_property = get_property;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_team);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
device_class->connection_type_supported = NM_SETTING_TEAM_SETTING_NAME;
|
|
Packit Service |
5ffa24 |
device_class->connection_type_check_compatible = NM_SETTING_TEAM_SETTING_NAME;
|
|
Packit Service |
5ffa24 |
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_TEAM);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
device_class->is_master = TRUE;
|
|
Packit Service |
5ffa24 |
device_class->create_and_realize = create_and_realize;
|
|
Packit Service |
5ffa24 |
device_class->get_generic_capabilities = get_generic_capabilities;
|
|
Packit Service |
5ffa24 |
device_class->complete_connection = complete_connection;
|
|
Packit Service |
5ffa24 |
device_class->update_connection = update_connection;
|
|
Packit Service |
5ffa24 |
device_class->master_update_slave_connection = master_update_slave_connection;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
device_class->act_stage1_prepare_also_for_external_or_assume = TRUE;
|
|
Packit Service |
5ffa24 |
device_class->act_stage1_prepare = act_stage1_prepare;
|
|
Packit Service |
5ffa24 |
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
|
Packit Service |
5ffa24 |
device_class->deactivate = deactivate;
|
|
Packit Service |
5ffa24 |
device_class->enslave_slave = enslave_slave;
|
|
Packit Service |
5ffa24 |
device_class->release_slave = release_slave;
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
obj_properties[PROP_CONFIG] = g_param_spec_string(NM_DEVICE_TEAM_CONFIG,
|
|
Packit Service |
5ffa24 |
"",
|
|
Packit Service |
5ffa24 |
"",
|
|
Packit Service |
5ffa24 |
NULL,
|
|
Packit Service |
5ffa24 |
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
Packit Service |
5ffa24 |
|
|
Packit Service |
5ffa24 |
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
|
Packit Service |
5ffa24 |
}
|