NetworkManager/clients/tui/nmt-page-bond.c
Thomas Haller e4839accf5 all: replace non-leading tabs with spaces
We commonly only allow tabs at the beginning of a line, not
afterwards. The reason for this style is so that the code
looks formated right with tabstop=4 and tabstop=8.
2018-02-07 13:32:04 +01:00

459 lines
16 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2013 Red Hat, Inc.
*/
/**
* SECTION:nmt-page-bond
* @short_description: The editor page for Bond connections
*
* Note that this is fairly different from most of the other editor
* pages, because #NMSettingBond doesn't have properties, so we
* can't just use #GBinding.
*/
#include "nm-default.h"
#include "nmt-page-bond.h"
#include "nmt-mac-entry.h"
#include "nmt-address-list.h"
#include "nmt-slave-list.h"
G_DEFINE_TYPE (NmtPageBond, nmt_page_bond, NMT_TYPE_EDITOR_PAGE_DEVICE)
#define NMT_PAGE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_PAGE_BOND, NmtPageBondPrivate))
typedef enum {
NMT_PAGE_BOND_MONITORING_UNKNOWN = -1,
NMT_PAGE_BOND_MONITORING_MII = 0,
NMT_PAGE_BOND_MONITORING_ARP = 1,
} NmtPageBondMonitoringMode;
typedef struct {
NmtSlaveList *slaves;
NmtNewtPopup *mode;
NmtNewtEntry *primary;
NmtNewtPopup *monitoring;
NmtNewtEntry *miimon;
NmtNewtEntry *updelay;
NmtNewtEntry *downdelay;
NmtNewtEntry *arp_interval;
NmtAddressList *arp_ip_target;
NmtPageBondMonitoringMode monitoring_mode;
NMSettingBond *s_bond;
GType slave_type;
gboolean updating;
} NmtPageBondPrivate;
NmtEditorPage *
nmt_page_bond_new (NMConnection *conn,
NmtDeviceEntry *deventry)
{
return g_object_new (NMT_TYPE_PAGE_BOND,
"connection", conn,
"device-entry", deventry,
NULL);
}
static void
nmt_page_bond_init (NmtPageBond *bond)
{
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_UNKNOWN;
priv->slave_type = G_TYPE_NONE;
}
static NmtNewtPopupEntry bond_mode[] = {
{ N_("Round-robin"), "balance-rr" },
{ N_("Active Backup"), "active-backup" },
{ N_("XOR"), "balance-xor" },
{ N_("Broadcast"), "broadcast" },
{ N_("802.3ad"), "802.3ad" },
{ N_("Adaptive Transmit Load Balancing (tlb)"), "balance-tlb" },
{ N_("Adaptive Load Balancing (alb)"), "balance-alb" },
{ NULL, NULL }
};
/* NB: the ordering/numbering here corresponds to NmtPageBondMonitoringMode */
static NmtNewtPopupEntry bond_monitoring[] = {
{ N_("MII (recommended)"), "mii" },
{ N_("ARP"), "arp" },
{ NULL, NULL }
};
static void
bond_options_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NMSettingBond *s_bond = NM_SETTING_BOND (object);
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
const char *val;
char **ips;
if (priv->updating)
return;
priv->updating = TRUE;
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
nmt_newt_popup_set_active_id (priv->mode, val);
if (!strcmp (val, "active-backup")) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
nmt_newt_entry_set_text (priv->primary, val);
} else
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_UNKNOWN) {
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
if (val && strcmp (val, "0") != 0)
priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_ARP;
else
priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_MII;
}
nmt_newt_popup_set_active (priv->monitoring, priv->monitoring_mode);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
nmt_newt_entry_set_text (priv->miimon, val);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
nmt_newt_entry_set_text (priv->updelay, val);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
nmt_newt_entry_set_text (priv->downdelay, val);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
nmt_newt_entry_set_text (priv->arp_interval, val);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
ips = g_strsplit (val, ",", -1);
g_object_set (G_OBJECT (priv->arp_ip_target),
"strings", ips,
NULL);
g_strfreev (ips);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
}
priv->updating = FALSE;
}
static void
slaves_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
GPtrArray *slaves;
g_object_get (object, "connections", &slaves, NULL);
if (slaves->len == 0) {
if (priv->slave_type == G_TYPE_NONE)
return;
priv->slave_type = G_TYPE_NONE;
} else {
NMConnection *slave = slaves->pdata[0];
if (priv->slave_type != G_TYPE_NONE)
return;
if (nm_connection_is_type (slave, NM_SETTING_INFINIBAND_SETTING_NAME))
priv->slave_type = NM_TYPE_SETTING_INFINIBAND;
else
priv->slave_type = NM_TYPE_SETTING_WIRED;
}
if (priv->slave_type == NM_TYPE_SETTING_INFINIBAND) {
nmt_newt_popup_set_active_id (priv->mode, "active-backup");
nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->mode), FALSE);
} else
nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->mode), TRUE);
}
#define WIDGET_CHANGED_FUNC(widget, func, option) \
static void \
widget ## _widget_changed (GObject *object, \
GParamSpec *pspec, \
gpointer user_data) \
{ \
NmtPageBond *bond = NMT_PAGE_BOND (user_data); \
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond); \
\
if (priv->updating) \
return; \
\
priv->updating = TRUE; \
nm_setting_bond_add_option (priv->s_bond, option, func (priv->widget)); \
priv->updating = FALSE; \
}
WIDGET_CHANGED_FUNC (primary, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_PRIMARY)
WIDGET_CHANGED_FUNC (miimon, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_MIIMON)
WIDGET_CHANGED_FUNC (updelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_UPDELAY)
WIDGET_CHANGED_FUNC (downdelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_DOWNDELAY)
WIDGET_CHANGED_FUNC (arp_interval, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_ARP_INTERVAL)
static void
mode_widget_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
const char *mode;
if (priv->updating)
return;
mode = nmt_newt_popup_get_active_id (priv->mode);
priv->updating = TRUE;
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_MODE, mode);
priv->updating = FALSE;
if (!strcmp (mode, "balance-tlb") || !strcmp (mode, "balance-alb")) {
nmt_newt_popup_set_active (priv->monitoring, NMT_PAGE_BOND_MONITORING_MII);
nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->monitoring), FALSE);
} else
nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->monitoring), TRUE);
if (!strcmp (mode, "active-backup")) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY,
nmt_newt_entry_get_text (priv->primary));
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
nm_setting_bond_remove_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
}
}
static void
monitoring_widget_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
if (priv->updating)
return;
priv->monitoring_mode = nmt_newt_popup_get_active (priv->monitoring);
if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
} else {
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
}
}
static void
arp_ip_target_widget_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NmtPageBond *bond = NMT_PAGE_BOND (user_data);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
char **ips, *target;
if (priv->updating)
return;
g_object_get (G_OBJECT (priv->arp_ip_target),
"strings", &ips,
NULL);
target = g_strjoinv (",", ips);
priv->updating = TRUE;
nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, target);
priv->updating = FALSE;
g_free (target);
g_strfreev (ips);
}
static gboolean
bond_connection_type_filter (GType connection_type,
gpointer user_data)
{
NmtPageBond *bond = user_data;
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
if ( priv->slave_type != NM_TYPE_SETTING_WIRED
&& connection_type == NM_TYPE_SETTING_INFINIBAND)
return TRUE;
if ( priv->slave_type != NM_TYPE_SETTING_INFINIBAND
&& connection_type == NM_TYPE_SETTING_WIRED)
return TRUE;
return FALSE;
}
static void
nmt_page_bond_constructed (GObject *object)
{
NmtPageBond *bond = NMT_PAGE_BOND (object);
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
NmtEditorSection *section;
NmtEditorGrid *grid;
NMSettingWired *s_wired;
NMSettingBond *s_bond;
NmtNewtWidget *widget, *label;
NMConnection *conn;
conn = nmt_editor_page_get_connection (NMT_EDITOR_PAGE (bond));
s_bond = nm_connection_get_setting_bond (conn);
if (!s_bond) {
nm_connection_add_setting (conn, nm_setting_bond_new ());
s_bond = nm_connection_get_setting_bond (conn);
}
priv->s_bond = s_bond;
s_wired = nm_connection_get_setting_wired (conn);
if (!s_wired) {
nm_connection_add_setting (conn, nm_setting_wired_new ());
s_wired = nm_connection_get_setting_wired (conn);
}
section = nmt_editor_section_new (_("BOND"), NULL, TRUE);
grid = nmt_editor_section_get_body (section);
widget = nmt_newt_separator_new ();
nmt_editor_grid_append (grid, _("Slaves"), widget, NULL);
nmt_editor_grid_set_row_flags (grid, widget, NMT_EDITOR_GRID_ROW_LABEL_ALIGN_LEFT);
widget = nmt_slave_list_new (conn, bond_connection_type_filter, bond);
g_signal_connect (widget, "notify::connections",
G_CALLBACK (slaves_changed), bond);
nmt_editor_grid_append (grid, NULL, widget, NULL);
priv->slaves = NMT_SLAVE_LIST (widget);
widget = nmt_newt_popup_new (bond_mode);
g_signal_connect (widget, "notify::active-id",
G_CALLBACK (mode_widget_changed), bond);
nmt_editor_grid_append (grid, _("Mode"), widget, NULL);
priv->mode = NMT_NEWT_POPUP (widget);
widget = nmt_newt_entry_new (40, 0);
g_signal_connect (widget, "notify::text",
G_CALLBACK (primary_widget_changed), bond);
nmt_editor_grid_append (grid, _("Primary"), widget, NULL);
priv->primary = NMT_NEWT_ENTRY (widget);
widget = nmt_newt_popup_new (bond_monitoring);
g_signal_connect (widget, "notify::active",
G_CALLBACK (monitoring_widget_changed), bond);
nmt_editor_grid_append (grid, _("Link monitoring"), widget, NULL);
priv->monitoring = NMT_NEWT_POPUP (widget);
widget = nmt_newt_entry_numeric_new (10, 0, G_MAXINT);
g_signal_connect (widget, "notify::text",
G_CALLBACK (miimon_widget_changed), bond);
label = nmt_newt_label_new (C_("milliseconds", "ms"));
nmt_editor_grid_append (grid, _("Monitoring frequency"), widget, label);
priv->miimon = NMT_NEWT_ENTRY (widget);
widget = nmt_newt_entry_numeric_new (10, 0, G_MAXINT);
g_signal_connect (widget, "notify::text",
G_CALLBACK (updelay_widget_changed), bond);
label = nmt_newt_label_new (C_("milliseconds", "ms"));
nmt_editor_grid_append (grid, _("Link up delay"), widget, label);
priv->updelay = NMT_NEWT_ENTRY (widget);
widget = nmt_newt_entry_numeric_new (10, 0, G_MAXINT);
g_signal_connect (widget, "notify::text",
G_CALLBACK (downdelay_widget_changed), bond);
label = nmt_newt_label_new (C_("milliseconds", "ms"));
nmt_editor_grid_append (grid, _("Link down delay"), widget, label);
priv->downdelay = NMT_NEWT_ENTRY (widget);
widget = nmt_newt_entry_numeric_new (10, 0, G_MAXINT);
g_signal_connect (widget, "notify::text",
G_CALLBACK (arp_interval_widget_changed), bond);
label = nmt_newt_label_new (C_("milliseconds", "ms"));
nmt_editor_grid_append (grid, _("Monitoring frequency"), widget, label);
priv->arp_interval = NMT_NEWT_ENTRY (widget);
widget = nmt_address_list_new (NMT_ADDRESS_LIST_IP4);
g_signal_connect (widget, "notify::strings",
G_CALLBACK (arp_ip_target_widget_changed), bond);
nmt_editor_grid_append (grid, _("ARP targets"), widget, NULL);
priv->arp_ip_target = NMT_ADDRESS_LIST (widget);
widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
g_object_bind_property (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget, "mac-address",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
nmt_editor_grid_append (grid, _("Cloned MAC address"), widget, NULL);
g_signal_connect (s_bond, "notify::" NM_SETTING_BOND_OPTIONS,
G_CALLBACK (bond_options_changed), bond);
bond_options_changed (G_OBJECT (s_bond), NULL, bond);
slaves_changed (G_OBJECT (priv->slaves), NULL, bond);
nmt_editor_page_add_section (NMT_EDITOR_PAGE (bond), section);
G_OBJECT_CLASS (nmt_page_bond_parent_class)->constructed (object);
}
static void
nmt_page_bond_saved (NmtEditorPage *editor_page)
{
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (editor_page);
nmt_edit_connection_list_recommit (NMT_EDIT_CONNECTION_LIST (priv->slaves));
}
static void
nmt_page_bond_class_init (NmtPageBondClass *bond_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (bond_class);
NmtEditorPageClass *editor_page_class = NMT_EDITOR_PAGE_CLASS (bond_class);
g_type_class_add_private (bond_class, sizeof (NmtPageBondPrivate));
object_class->constructed = nmt_page_bond_constructed;
editor_page_class->saved = nmt_page_bond_saved;
}