static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, const GSList *existing_connections, GError **error) { NMSettingBond *s_bond, *tmp; guint32 i = 0; char *name; const GSList *iter; gboolean found; nm_utils_complete_generic (connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, _("Bond connection %d"), NULL, TRUE); s_bond = nm_connection_get_setting_bond (connection); if (!s_bond) { s_bond = (NMSettingBond *) nm_setting_bond_new (); nm_connection_add_setting (connection, NM_SETTING (s_bond)); } /* Grab the first name that doesn't exist in either our connections * or a device on the system. */ while (i < 500 && !nm_setting_bond_get_interface_name (s_bond)) { name = g_strdup_printf ("bond%u", i); /* check interface names */ if (!nm_platform_link_exists (name)) { /* check existing bond connections */ for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { NMConnection *candidate = iter->data; tmp = nm_connection_get_setting_bond (candidate); if (tmp && nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) { if (g_strcmp0 (nm_setting_bond_get_interface_name (tmp), name) == 0) { found = TRUE; break; } } } if (!found) g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, name, NULL); } g_free (name); i++; } return TRUE; }
void bond_connection_new (GtkWindow *parent, const char *detail, NMRemoteSettings *settings, PageNewConnectionResultFunc result_func, gpointer user_data) { NMConnection *connection; int bond_num, max_bond_num, num; GSList *connections, *iter; NMConnection *conn2; NMSettingBond *s_bond; const char *iface; char *my_iface; connection = ce_page_new_connection (_("Bond connection %d"), NM_SETTING_BOND_SETTING_NAME, TRUE, settings, user_data); nm_connection_add_setting (connection, nm_setting_bond_new ()); /* Find an available interface name */ bond_num = max_bond_num = 0; connections = nm_remote_settings_list_connections (settings); for (iter = connections; iter; iter = iter->next) { conn2 = iter->data; if (!nm_connection_is_type (conn2, NM_SETTING_BOND_SETTING_NAME)) continue; s_bond = nm_connection_get_setting_bond (conn2); if (!s_bond) continue; iface = nm_setting_bond_get_interface_name (s_bond); if (!iface || strncmp (iface, "bond", 4) != 0 || !g_ascii_isdigit (iface[4])) continue; num = atoi (iface + 4); if (num > max_bond_num) max_bond_num = num; if (num == bond_num) bond_num = max_bond_num + 1; } g_slist_free (connections); my_iface = g_strdup_printf ("bond%d", bond_num); s_bond = nm_connection_get_setting_bond (connection); g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, my_iface, NULL); g_free (my_iface); (*result_func) (connection, FALSE, NULL, user_data); }
static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, const GSList *existing_connections, GError **error) { NMSettingBond *s_bond; nm_utils_complete_generic (NM_PLATFORM_GET, connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, NULL, _("Bond connection"), "bond", TRUE); s_bond = nm_connection_get_setting_bond (connection); if (!s_bond) { s_bond = (NMSettingBond *) nm_setting_bond_new (); nm_connection_add_setting (connection, NM_SETTING (s_bond)); } return TRUE; }
static void update_connection (NMDevice *device, NMConnection *connection) { NMSettingBond *s_bond = nm_connection_get_setting_bond (connection); int ifindex = nm_device_get_ifindex (device); const char **options; if (!s_bond) { s_bond = (NMSettingBond *) nm_setting_bond_new (); nm_connection_add_setting (connection, (NMSetting *) s_bond); } /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options (s_bond); while (options && *options) { gs_free char *value = nm_platform_sysctl_master_get_option (nm_device_get_platform(device), ifindex, *options); const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); if (value && !ignore_if_zero (*options, value) && (g_strcmp0 (value, defvalue) != 0)) { /* Replace " " with "," for arp_ip_targets from the kernel */ if (strcmp (*options, "arp_ip_target") == 0) { char *p = value; while (p && *p) { if (*p == ' ') *p = ','; p++; } } nm_setting_bond_add_option (s_bond, *options, value); } options++; } }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { const char *iface; NMSettingBond *s_bond; if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection, error)) return FALSE; s_bond = nm_connection_get_setting_bond (connection); if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) { g_set_error (error, NM_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND, "The connection was not a bond connection."); return FALSE; } /* Bond connections must specify the virtual interface name */ iface = nm_connection_get_virtual_iface_name (connection); if (!iface || strcmp (nm_device_get_iface (device), iface)) { g_set_error (error, NM_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND, "The bond connection virtual interface name did not match."); return FALSE; } /* FIXME: match bond properties like mode, etc? */ return TRUE; }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMSettingBond *s_bond; if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_bond = nm_connection_get_setting_bond (connection); if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) return FALSE; /* FIXME: match bond properties like mode, etc? */ return TRUE; }
CEPage * ce_page_bond_new (NMConnectionEditor *editor, NMConnection *connection, GtkWindow *parent_window, NMClient *client, const char **out_secrets_setting_name, GError **error) { CEPageBond *self; CEPageBondPrivate *priv; self = CE_PAGE_BOND (ce_page_new (CE_TYPE_PAGE_BOND, editor, connection, parent_window, client, UIDIR "/ce-page-bond.ui", "BondPage", _("Bond"))); if (!self) { g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load bond user interface.")); return NULL; } bond_private_init (self); priv = CE_PAGE_BOND_GET_PRIVATE (self); priv->setting = nm_connection_get_setting_bond (connection); if (!priv->setting) { priv->setting = NM_SETTING_BOND (nm_setting_bond_new ()); nm_connection_add_setting (connection, NM_SETTING (priv->setting)); } priv->wired = nm_connection_get_setting_wired (connection); g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL); return CE_PAGE (self); }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { const char *iface; NMSettingBond *s_bond; if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_bond = nm_connection_get_setting_bond (connection); if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) return FALSE; /* Bond connections must specify the virtual interface name */ iface = nm_connection_get_interface_name (connection); if (!iface || strcmp (nm_device_get_iface (device), iface)) return FALSE; /* FIXME: match bond properties like mode, etc? */ return TRUE; }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingConnection *s_con; NMSettingBond *s_bond; const char *ctype, *dev_iface_name, *bond_iface_name; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); ctype = nm_setting_connection_get_connection_type (s_con); if (strcmp (ctype, NM_SETTING_BOND_SETTING_NAME) != 0) { g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION, "The connection was not a bond connection."); return FALSE; } s_bond = nm_connection_get_setting_bond (connection); if (!s_bond) { g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION, "The connection was not a valid bond connection."); return FALSE; } dev_iface_name = nm_device_get_iface (device); bond_iface_name = nm_setting_bond_get_interface_name (s_bond); if (g_strcmp0 (dev_iface_name, bond_iface_name) != 0) { g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH, "The interfaces of the device and the connection didn't match."); return FALSE; } /* FIXME: check slaves? But we can't... */ return TRUE; }
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; 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; 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); 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 NMActStageReturn apply_bonding_config (NMDevice *device) { NMConnection *connection; NMSettingBond *s_bond; int ifindex = nm_device_get_ifindex (device); const char *mode, *value; char *contents; gboolean set_arp_interval = TRUE; /* Option restrictions: * * arp_interval conflicts miimon > 0 * arp_interval conflicts [ alb, tlb ] * arp_validate needs [ active-backup ] * downdelay needs miimon * updelay needs miimon * primary needs [ active-backup, tlb, alb ] * * clearing miimon requires that arp_interval be 0, but clearing * arp_interval doesn't require miimon to be 0 */ connection = nm_device_get_applied_connection (device); g_assert (connection); s_bond = nm_connection_get_setting_bond (connection); g_assert (s_bond); mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); if (mode == NULL) mode = "balance-rr"; value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON); if (value && atoi (value)) { /* clear arp interval */ set_bond_attr (device, "arp_interval", "0"); set_arp_interval = FALSE; set_bond_attr (device, "miimon", value); set_simple_option (device, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY); set_simple_option (device, "downdelay", s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); } else if (!value) { /* If not given, and arp_interval is not given, default to 100 */ long int val_int; char *end; value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); errno = 0; val_int = strtol (value ? value : "0", &end, 10); if (!value || (val_int == 0 && errno == 0 && *end == '\0')) set_bond_attr (device, "miimon", "100"); } /* The stuff after 'mode' requires the given mode or doesn't care */ set_bond_attr (device, "mode", mode); /* arp_interval not compatible with ALB, TLB */ if (g_strcmp0 (mode, "balance-alb") == 0 || g_strcmp0 (mode, "balance-tlb") == 0) set_arp_interval = FALSE; if (set_arp_interval) { set_simple_option (device, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); /* Just let miimon get cleared automatically; even setting miimon to * 0 (disabled) clears arp_interval. */ } value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE); /* arp_validate > 0 only valid in active-backup mode */ if ( value && g_strcmp0 (value, "0") != 0 && g_strcmp0 (value, "none") != 0 && g_strcmp0 (mode, "active-backup") == 0) set_bond_attr (device, "arp_validate", value); else set_bond_attr (device, "arp_validate", "0"); if ( g_strcmp0 (mode, "active-backup") == 0 || g_strcmp0 (mode, "balance-alb") == 0 || g_strcmp0 (mode, "balance-tlb") == 0) { value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); set_bond_attr (device, "primary", value ? value : ""); } /* Clear ARP targets */ contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, "arp_ip_target"); set_arp_targets (device, contents, " \n", "-"); g_free (contents); /* Add new ARP targets */ value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); set_arp_targets (device, value, ",", "+"); set_simple_option (device, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT); set_simple_option (device, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC); set_simple_option (device, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); set_simple_option (device, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT); set_simple_option (device, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY); set_simple_option (device, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP); if ( g_strcmp0 (mode, "4") == 0 || g_strcmp0 (mode, "802.3ad") == 0) set_simple_option (device, "lacp_rate", s_bond, NM_SETTING_BOND_OPTION_LACP_RATE); return NM_ACT_STAGE_RETURN_SUCCESS; }