diff options
Diffstat (limited to 'tui/nmt-page-bond.c')
-rw-r--r-- | tui/nmt-page-bond.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/tui/nmt-page-bond.c b/tui/nmt-page-bond.c new file mode 100644 index 000000000..55a6ffeeb --- /dev/null +++ b/tui/nmt-page-bond.c @@ -0,0 +1,436 @@ +/* -*- 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 "config.h" + +#include <glib.h> +#include <glib/gi18n-lib.h> + +#include "nmt-page-bond.h" + +#include "nmt-address-list.h" +#include "nmt-slave-list.h" + +G_DEFINE_TYPE (NmtPageBond, nmt_page_bond, NMT_TYPE_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; + +NmtNewtWidget * +nmt_page_bond_new (NMConnection *conn, + NmtDeviceEntry *deventry) +{ + return g_object_new (NMT_TYPE_PAGE_BOND, + "connection", conn, + "title", _("BOND"), + "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), + "string", 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); + else + nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE); +} + +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); + NmtDeviceEntry *deventry; + NmtPageGrid *grid; + 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; + + deventry = nmt_page_device_get_device_entry (NMT_PAGE_DEVICE (object)); + g_object_bind_property (s_bond, NM_SETTING_BOND_INTERFACE_NAME, + deventry, "interface-name", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + + grid = NMT_PAGE_GRID (bond); + + widget = nmt_newt_separator_new (); + nmt_page_grid_append (grid, _("Slaves"), widget, NULL); + nmt_page_grid_set_row_flags (grid, widget, NMT_PAGE_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_page_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_page_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_page_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_page_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_page_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_page_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_page_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_page_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_page_grid_append (grid, _("ARP targets"), widget, NULL); + priv->arp_ip_target = NMT_ADDRESS_LIST (widget); + + 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); + + G_OBJECT_CLASS (nmt_page_bond_parent_class)->constructed (object); +} + +static void +nmt_page_bond_class_init (NmtPageBondClass *bond_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bond_class); + + g_type_class_add_private (bond_class, sizeof (NmtPageBondPrivate)); + + object_class->constructed = nmt_page_bond_constructed; +} |