1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* NetworkManager Connection editor -- Connection editor for NetworkManager
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License along
15
* with this program; if not, write to the Free Software Foundation, Inc.,
16
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
* Copyright 2012 Red Hat, Inc.
25
#include <glib/gi18n.h>
27
#include <nm-setting-connection.h>
28
#include <nm-setting-bond.h>
30
#include "page-bond.h"
31
#include "page-ethernet.h"
32
#include "page-infiniband.h"
33
#include "nm-connection-editor.h"
34
#include "new-connection.h"
36
G_DEFINE_TYPE (CEPageBond, ce_page_bond, CE_TYPE_PAGE)
38
#define CE_PAGE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_BOND, CEPageBondPrivate))
41
NMRemoteConnection *connection;
43
NMRemoteSettings *settings;
45
NMSettingBond *setting;
49
PageNewConnectionFunc new_slave_func;
53
GtkEntry *interface_name;
55
GtkComboBox *monitoring;
56
GtkSpinButton *frequency;
57
GtkSpinButton *updelay;
58
GtkWidget *updelay_label;
59
GtkWidget *updelay_box;
60
GtkSpinButton *downdelay;
61
GtkWidget *downdelay_label;
62
GtkWidget *downdelay_box;
63
GtkEntry *arp_targets;
64
GtkWidget *arp_targets_label;
67
int table_row_spacing;
72
GtkTreeView *connections;
73
GtkTreeModel *connections_model;
74
GtkButton *add, *edit, *delete;
78
#define MODE_BALANCE_RR 0
79
#define MODE_ACTIVE_BACKUP 1
80
#define MODE_BALANCE_XOR 2
81
#define MODE_BROADCAST 3
82
#define MODE_802_3AD 4
83
#define MODE_BALANCE_TLB 5
84
#define MODE_BALANCE_ALB 6
86
#define MONITORING_MII 0
87
#define MONITORING_ARP 1
95
name_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
97
NMConnection *conn_a, *conn_b;
100
/* We fetch COL_CONNECTION rather than COL_NAME to avoid a strdup/free. */
101
gtk_tree_model_get (model, a, COL_CONNECTION, &conn_a, -1);
102
gtk_tree_model_get (model, b, COL_CONNECTION, &conn_b, -1);
103
ret = strcmp (nm_connection_get_id (conn_a), nm_connection_get_id (conn_b));
104
g_object_unref (conn_a);
105
g_object_unref (conn_b);
111
bond_private_init (CEPageBond *self)
113
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
116
builder = CE_PAGE (self)->builder;
118
priv->interface_name = GTK_ENTRY (gtk_builder_get_object (builder, "bond_interface"));
119
priv->connections = GTK_TREE_VIEW (gtk_builder_get_object (builder, "bond_connections"));
120
priv->connections_model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "bond_connections_model"));
121
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->connections_model),
122
COL_NAME, name_sort_func,
124
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->connections_model),
125
COL_NAME, GTK_SORT_ASCENDING);
127
priv->mode = GTK_COMBO_BOX (gtk_builder_get_object (builder, "bond_mode"));
128
priv->monitoring = GTK_COMBO_BOX (gtk_builder_get_object (builder, "bond_monitoring"));
129
priv->frequency = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "bond_frequency"));
130
priv->updelay = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "bond_updelay"));
131
priv->updelay_label = GTK_WIDGET (gtk_builder_get_object (builder, "bond_updelay_label"));
132
priv->updelay_box = GTK_WIDGET (gtk_builder_get_object (builder, "bond_updelay_box"));
133
priv->downdelay = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "bond_downdelay"));
134
priv->downdelay_label = GTK_WIDGET (gtk_builder_get_object (builder, "bond_downdelay_label"));
135
priv->downdelay_box = GTK_WIDGET (gtk_builder_get_object (builder, "bond_downdelay_box"));
136
priv->arp_targets = GTK_ENTRY (gtk_builder_get_object (builder, "bond_arp_targets"));
137
priv->arp_targets_label = GTK_WIDGET (gtk_builder_get_object (builder, "bond_arp_targets_label"));
138
priv->add = GTK_BUTTON (gtk_builder_get_object (builder, "bond_connection_add"));
139
priv->edit = GTK_BUTTON (gtk_builder_get_object (builder, "bond_connection_edit"));
140
priv->delete = GTK_BUTTON (gtk_builder_get_object (builder, "bond_connection_delete"));
142
priv->toplevel = GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (priv->connections),
145
priv->table = GTK_TABLE (gtk_builder_get_object (builder, "BondPage"));
146
priv->table_row_spacing = gtk_table_get_default_row_spacing (priv->table);
147
gtk_container_child_get (GTK_CONTAINER (priv->table), priv->updelay_label,
148
"top-attach", &priv->updelay_row,
150
gtk_container_child_get (GTK_CONTAINER (priv->table), priv->downdelay_label,
151
"top-attach", &priv->downdelay_row,
153
gtk_container_child_get (GTK_CONTAINER (priv->table), priv->arp_targets_label,
154
"top-attach", &priv->arp_targets_row,
159
dispose (GObject *object)
161
CEPageBond *self = CE_PAGE_BOND (object);
162
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
165
if (priv->settings) {
166
g_signal_handlers_disconnect_matched (priv->settings, G_SIGNAL_MATCH_DATA,
167
0, 0, NULL, NULL, self);
168
g_object_unref (priv->settings);
169
priv->settings = NULL;
172
g_object_unref (priv->client);
175
if (priv->connection) {
176
g_object_unref (priv->connection);
177
priv->connection = NULL;
180
if (gtk_tree_model_get_iter_first (priv->connections_model, &iter)) {
182
NMRemoteConnection *connection = NULL;
184
gtk_tree_model_get (priv->connections_model, &iter,
185
COL_CONNECTION, &connection,
187
g_signal_handlers_disconnect_matched (connection, G_SIGNAL_MATCH_DATA,
188
0, 0, NULL, NULL, self);
189
g_object_unref (connection);
190
} while (gtk_tree_model_iter_next (priv->connections_model, &iter));
193
G_OBJECT_CLASS (ce_page_bond_parent_class)->dispose (object);
197
stuff_changed (GtkWidget *w, gpointer user_data)
199
ce_page_changed (CE_PAGE (user_data));
203
connection_removed (NMRemoteConnection *connection, gpointer user_data)
205
CEPageBond *self = CE_PAGE_BOND (user_data);
206
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
209
if (!gtk_tree_model_get_iter_first (priv->connections_model, &iter))
213
NMRemoteConnection *candidate = NULL;
215
gtk_tree_model_get (priv->connections_model, &iter,
216
COL_CONNECTION, &candidate,
218
if (candidate == connection) {
219
gtk_list_store_remove (GTK_LIST_STORE (priv->connections_model), &iter);
220
stuff_changed (NULL, self);
222
if (!gtk_tree_model_get_iter_first (priv->connections_model, &iter)) {
223
priv->slave_type = G_TYPE_INVALID;
224
priv->new_slave_func = NULL;
228
} while (gtk_tree_model_iter_next (priv->connections_model, &iter));
232
connection_added (NMRemoteSettings *settings,
233
NMRemoteConnection *connection,
236
CEPageBond *self = CE_PAGE_BOND (user_data);
237
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
238
NMSettingConnection *s_con;
239
const char *slave_type, *master;
240
const char *interface_name;
243
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
247
slave_type = nm_setting_connection_get_slave_type (s_con);
248
if (!slave_type || strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME) != 0)
251
master = nm_setting_connection_get_master (s_con);
255
interface_name = nm_setting_bond_get_interface_name (priv->setting);
256
if (!strcmp (master, interface_name)) {
257
/* Ugh. Fix that... */
258
g_object_set (G_OBJECT (connection),
259
NM_SETTING_CONNECTION_MASTER, priv->uuid,
261
nm_remote_connection_commit_changes (connection, NULL, NULL);
262
} else if (strcmp (master, priv->uuid) != 0)
265
gtk_list_store_append (GTK_LIST_STORE (priv->connections_model), &iter);
266
gtk_list_store_set (GTK_LIST_STORE (priv->connections_model), &iter,
267
COL_CONNECTION, connection,
268
COL_NAME, nm_setting_connection_get_id (s_con),
270
stuff_changed (NULL, self);
272
/* FIXME: a bit kludgy */
273
if (nm_connection_is_type (NM_CONNECTION (connection), NM_SETTING_INFINIBAND_SETTING_NAME)) {
274
priv->slave_type = NM_TYPE_SETTING_INFINIBAND;
275
priv->new_slave_func = infiniband_connection_new;
276
gtk_combo_box_set_active (priv->mode, MODE_ACTIVE_BACKUP);
277
gtk_widget_set_sensitive (GTK_WIDGET (priv->mode), FALSE);
279
priv->slave_type = NM_TYPE_SETTING_WIRED;
280
priv->new_slave_func = ethernet_connection_new;
281
gtk_widget_set_sensitive (GTK_WIDGET (priv->mode), TRUE);
284
g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED,
285
G_CALLBACK (connection_removed), self);
289
monitoring_mode_changed (GtkComboBox *combo, gpointer user_data)
291
CEPageBond *self = user_data;
292
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
294
if (gtk_combo_box_get_active (combo) == MONITORING_MII) {
295
gtk_widget_show (GTK_WIDGET (priv->updelay));
296
gtk_widget_show (priv->updelay_label);
297
gtk_widget_show (priv->updelay_box);
298
gtk_widget_show (GTK_WIDGET (priv->downdelay));
299
gtk_widget_show (priv->downdelay_label);
300
gtk_widget_show (priv->downdelay_box);
301
gtk_widget_hide (GTK_WIDGET (priv->arp_targets));
302
gtk_widget_hide (priv->arp_targets_label);
304
gtk_table_set_row_spacing (priv->table, priv->updelay_row, priv->table_row_spacing);
305
gtk_table_set_row_spacing (priv->table, priv->downdelay_row, priv->table_row_spacing);
306
gtk_table_set_row_spacing (priv->table, priv->arp_targets_row, 0);
308
gtk_widget_hide (GTK_WIDGET (priv->updelay));
309
gtk_widget_hide (priv->updelay_label);
310
gtk_widget_hide (priv->updelay_box);
311
gtk_widget_hide (GTK_WIDGET (priv->downdelay));
312
gtk_widget_hide (priv->downdelay_label);
313
gtk_widget_hide (priv->downdelay_box);
314
gtk_widget_show (GTK_WIDGET (priv->arp_targets));
315
gtk_widget_show (priv->arp_targets_label);
317
gtk_table_set_row_spacing (priv->table, priv->updelay_row, 0);
318
gtk_table_set_row_spacing (priv->table, priv->downdelay_row, 0);
319
gtk_table_set_row_spacing (priv->table, priv->arp_targets_row, priv->table_row_spacing);
324
frequency_changed (GtkSpinButton *button, gpointer user_data)
326
CEPageBond *self = user_data;
327
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
328
int frequency, delay;
330
frequency = gtk_spin_button_get_value_as_int (priv->frequency);
332
/* Round updelay and downdelay up to a multiple of frequency */
334
delay = gtk_spin_button_get_value_as_int (priv->updelay);
335
if (frequency == 0) {
337
gtk_spin_button_set_value (priv->updelay, 0.0);
338
} else if (delay % frequency) {
339
delay += frequency - (delay % frequency);
340
gtk_spin_button_set_value (priv->updelay, delay);
342
gtk_spin_button_set_increments (priv->updelay, frequency, frequency);
344
delay = gtk_spin_button_get_value_as_int (priv->downdelay);
345
if (frequency == 0) {
347
gtk_spin_button_set_value (priv->downdelay, 0.0);
348
} else if (delay % frequency) {
349
delay += frequency - (delay % frequency);
350
gtk_spin_button_set_value (priv->downdelay, (gdouble)delay);
352
gtk_spin_button_set_increments (priv->downdelay, frequency, frequency);
356
delay_changed (GtkSpinButton *button, gpointer user_data)
358
CEPageBond *self = user_data;
359
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
360
int frequency, delay;
362
/* Clamp to nearest multiple of frequency */
364
frequency = gtk_spin_button_get_value_as_int (priv->frequency);
365
delay = gtk_spin_button_get_value_as_int (button);
366
if (frequency == 0) {
368
gtk_spin_button_set_value (button, 0.0);
369
} else if (delay % frequency) {
370
if (delay % frequency < frequency / 2)
371
delay -= delay % frequency;
373
delay += frequency - (delay % frequency);
374
gtk_spin_button_set_value (button, (gdouble)delay);
379
prettify_targets (const char *text)
381
char **addrs, *targets;
386
addrs = g_strsplit (text, ",", -1);
387
targets = g_strjoinv (", ", addrs);
394
uglify_targets (const char *text)
396
char **addrs, *targets;
402
addrs = g_strsplit (text, ",", -1);
403
for (i = 0; addrs[i]; i++)
404
g_strstrip (addrs[i]);
405
targets = g_strjoinv (",", addrs);
412
populate_ui (CEPageBond *self)
414
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
415
NMSettingBond *setting = priv->setting;
416
NMSettingConnection *s_con;
418
GSList *connections, *c;
419
const char *mode, *frequency, *updelay, *downdelay, *raw_targets;
421
int mode_idx = MODE_BALANCE_RR;
423
s_con = nm_connection_get_setting_connection (NM_CONNECTION (priv->connection));
424
g_return_if_fail (s_con != NULL);
427
iface = nm_setting_bond_get_interface_name (setting);
428
gtk_entry_set_text (priv->interface_name, iface ? iface : "");
430
/* Bonded connections */
431
connections = nm_remote_settings_list_connections (priv->settings);
432
for (c = connections; c; c = c->next)
433
connection_added (priv->settings, c->data, self);
436
mode = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_MODE);
438
if (!strcmp (mode, "balance-rr"))
439
mode_idx = MODE_BALANCE_RR;
440
else if (!strcmp (mode, "active-backup"))
441
mode_idx = MODE_ACTIVE_BACKUP;
442
else if (!strcmp (mode, "balance-xor"))
443
mode_idx = MODE_BALANCE_XOR;
444
else if (!strcmp (mode, "broadcast"))
445
mode_idx = MODE_BROADCAST;
446
else if (!strcmp (mode, "802.3ad"))
447
mode_idx = MODE_802_3AD;
448
else if (!strcmp (mode, "balance-tlb"))
449
mode_idx = MODE_BALANCE_TLB;
450
else if (!strcmp (mode, "balance-alb"))
451
mode_idx = MODE_BALANCE_ALB;
453
gtk_combo_box_set_active (priv->mode, mode_idx);
455
/* Monitoring mode/frequency */
456
frequency = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
458
gtk_combo_box_set_active (priv->monitoring, MONITORING_ARP);
460
gtk_combo_box_set_active (priv->monitoring, MONITORING_MII);
461
frequency = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_MIIMON);
463
g_signal_connect (priv->monitoring, "changed",
464
G_CALLBACK (monitoring_mode_changed),
466
monitoring_mode_changed (priv->monitoring, self);
469
gtk_spin_button_set_value (priv->frequency, (gdouble) atoi (frequency));
471
gtk_spin_button_set_value (priv->frequency, 0.0);
472
g_signal_connect (priv->frequency, "value-changed",
473
G_CALLBACK (frequency_changed),
476
updelay = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_UPDELAY);
478
gtk_spin_button_set_value (priv->updelay, (gdouble) atoi (updelay));
480
gtk_spin_button_set_value (priv->updelay, 0.0);
481
g_signal_connect (priv->updelay, "value-changed",
482
G_CALLBACK (delay_changed),
484
downdelay = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_DOWNDELAY);
486
gtk_spin_button_set_value (priv->downdelay, (gdouble) atoi (downdelay));
488
gtk_spin_button_set_value (priv->downdelay, 0.0);
489
g_signal_connect (priv->downdelay, "value-changed",
490
G_CALLBACK (delay_changed),
494
raw_targets = nm_setting_bond_get_option_by_name (setting, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
495
targets = prettify_targets (raw_targets);
497
gtk_entry_set_text (priv->arp_targets, targets);
503
connections_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
505
CEPageBond *self = user_data;
506
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
509
NMRemoteConnection *connection;
510
NMSettingConnection *s_con;
511
gboolean sensitive = FALSE;
513
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
514
gtk_tree_model_get (model, &iter,
517
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
520
sensitive = !nm_setting_connection_get_read_only (s_con);
523
gtk_widget_set_sensitive (GTK_WIDGET (priv->edit), sensitive);
524
gtk_widget_set_sensitive (GTK_WIDGET (priv->delete), sensitive);
528
add_response_cb (NMConnectionEditor *editor, NMRemoteConnection *connection,
529
gboolean added, gpointer user_data)
531
g_object_unref (editor);
535
add_bond_connection (NMConnection *connection,
538
CEPageBond *self = user_data;
539
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
540
NMSettingConnection *s_con;
541
NMConnectionEditor *editor;
542
const char *iface_name;
548
/* Mark the connection as a bond slave so that the editor knows not
549
* to add IPv4 and IPv6 pages, and rename it.
551
s_con = nm_connection_get_setting_connection (connection);
552
g_assert (s_con != NULL);
554
iface_name = gtk_entry_get_text (priv->interface_name);
556
iface_name = nm_setting_bond_get_interface_name (priv->setting);
559
name = g_strdup_printf (_("%s slave %d"), iface_name,
560
gtk_tree_model_iter_n_children (priv->connections_model, NULL) + 1);
562
g_object_set (G_OBJECT (s_con),
563
NM_SETTING_CONNECTION_ID, name,
564
NM_SETTING_CONNECTION_MASTER, priv->uuid,
565
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
566
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
570
editor = nm_connection_editor_new (priv->toplevel,
575
g_object_unref (connection);
579
g_signal_connect (editor, "done", G_CALLBACK (add_response_cb), self);
580
nm_connection_editor_run (editor);
584
connection_type_filter (GType type, gpointer user_data)
586
if (type == NM_TYPE_SETTING_WIRED ||
587
type == NM_TYPE_SETTING_INFINIBAND)
594
add_clicked (GtkButton *button, gpointer user_data)
596
CEPageBond *self = user_data;
597
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
599
if (priv->new_slave_func) {
600
new_connection_of_type (priv->toplevel,
603
priv->new_slave_func,
607
new_connection_dialog (priv->toplevel,
609
connection_type_filter,
615
static NMRemoteConnection *
616
get_selected_connection (CEPageBond *self)
618
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
619
GtkTreeSelection *selection;
620
GList *selected_rows;
621
GtkTreeModel *model = NULL;
623
NMRemoteConnection *connection = NULL;
625
selection = gtk_tree_view_get_selection (priv->connections);
626
selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
630
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) selected_rows->data))
631
gtk_tree_model_get (model, &iter, 0, &connection, -1);
634
g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
635
g_list_free (selected_rows);
641
edit_done_cb (NMConnectionEditor *editor, GtkResponseType response, gpointer user_data)
643
g_object_unref (editor);
647
edit_clicked (GtkButton *button, gpointer user_data)
649
CEPageBond *self = user_data;
650
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
651
NMConnectionEditor *editor;
652
NMRemoteConnection *connection;
654
connection = get_selected_connection (self);
658
editor = nm_connection_editor_get (NM_CONNECTION (connection));
660
nm_connection_editor_present (editor);
664
editor = nm_connection_editor_new (priv->toplevel,
665
NM_CONNECTION (connection),
671
g_signal_connect (editor, "done", G_CALLBACK (edit_done_cb), self);
672
nm_connection_editor_run (editor);
676
connection_double_clicked_cb (GtkTreeView *tree_view,
678
GtkTreeViewColumn *column,
681
edit_clicked (NULL, user_data);
685
delete_clicked (GtkButton *button, gpointer user_data)
687
CEPageBond *self = user_data;
688
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
689
NMRemoteConnection *connection;
691
connection = get_selected_connection (self);
695
delete_connection (priv->toplevel, connection, NULL, NULL);
699
finish_setup (CEPageBond *self, gpointer unused, GError *error, gpointer user_data)
701
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
702
GtkTreeSelection *selection;
709
g_signal_connect (priv->interface_name, "changed", G_CALLBACK (stuff_changed), self);
710
g_signal_connect (priv->mode, "changed", G_CALLBACK (stuff_changed), self);
711
g_signal_connect (priv->monitoring, "changed", G_CALLBACK (stuff_changed), self);
712
g_signal_connect (priv->frequency, "value-changed", G_CALLBACK (stuff_changed), self);
713
g_signal_connect (priv->updelay, "value-changed", G_CALLBACK (stuff_changed), self);
714
g_signal_connect (priv->downdelay, "value-changed", G_CALLBACK (stuff_changed), self);
715
g_signal_connect (priv->arp_targets, "changed", G_CALLBACK (stuff_changed), self);
717
g_signal_connect (priv->add, "clicked", G_CALLBACK (add_clicked), self);
718
g_signal_connect (priv->edit, "clicked", G_CALLBACK (edit_clicked), self);
719
g_signal_connect (priv->delete, "clicked", G_CALLBACK (delete_clicked), self);
721
g_signal_connect (priv->connections, "row-activated", G_CALLBACK (connection_double_clicked_cb), self);
723
selection = gtk_tree_view_get_selection (priv->connections);
724
g_signal_connect (selection, "changed", G_CALLBACK (connections_selection_changed_cb), self);
725
connections_selection_changed_cb (selection, self);
729
ce_page_bond_new (NMConnection *connection,
730
GtkWindow *parent_window,
732
NMRemoteSettings *settings,
733
const char **out_secrets_setting_name,
737
CEPageBondPrivate *priv;
738
NMSettingConnection *s_con;
740
self = CE_PAGE_BOND (ce_page_new (CE_TYPE_PAGE_BOND,
745
UIDIR "/ce-page-bond.ui",
749
g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
750
_("Could not load bond user interface."));
754
bond_private_init (self);
755
priv = CE_PAGE_BOND_GET_PRIVATE (self);
757
priv->connection = g_object_ref (connection);
758
priv->client = g_object_ref (client);
759
priv->settings = g_object_ref (settings);
761
s_con = nm_connection_get_setting_connection (connection);
762
priv->uuid = nm_setting_connection_get_uuid (s_con);
764
g_signal_connect (settings, NM_REMOTE_SETTINGS_NEW_CONNECTION,
765
G_CALLBACK (connection_added), self);
767
priv->setting = (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND);
768
if (!priv->setting) {
769
priv->setting = NM_SETTING_BOND (nm_setting_bond_new ());
770
nm_connection_add_setting (connection, NM_SETTING (priv->setting));
773
g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
775
return CE_PAGE (self);
779
ui_to_setting (CEPageBond *self)
781
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
782
const char *interface_name;
784
const char *frequency;
786
const char *downdelay;
790
interface_name = gtk_entry_get_text (priv->interface_name);
791
g_object_set (priv->setting,
792
NM_SETTING_BOND_INTERFACE_NAME, interface_name,
796
switch (gtk_combo_box_get_active (priv->mode)) {
797
case MODE_BALANCE_RR:
800
case MODE_ACTIVE_BACKUP:
801
mode = "active-backup";
803
case MODE_BALANCE_XOR:
804
mode = "balance-xor";
812
case MODE_BALANCE_TLB:
813
mode = "balance-tlb";
815
case MODE_BALANCE_ALB:
816
mode = "balance-alb";
819
g_assert_not_reached ();
823
/* Monitoring mode/frequency */
824
frequency = gtk_entry_get_text (GTK_ENTRY (priv->frequency));
825
updelay = gtk_entry_get_text (GTK_ENTRY (priv->updelay));
826
downdelay = gtk_entry_get_text (GTK_ENTRY (priv->downdelay));
827
targets = uglify_targets (gtk_entry_get_text (priv->arp_targets));
829
switch (gtk_combo_box_get_active (priv->monitoring)) {
831
nm_setting_bond_add_option (priv->setting, NM_SETTING_BOND_OPTION_MIIMON, frequency);
832
nm_setting_bond_add_option (priv->setting, NM_SETTING_BOND_OPTION_UPDELAY, updelay);
833
nm_setting_bond_add_option (priv->setting, NM_SETTING_BOND_OPTION_DOWNDELAY, downdelay);
834
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
835
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
838
nm_setting_bond_add_option (priv->setting, NM_SETTING_BOND_OPTION_ARP_INTERVAL, frequency);
840
nm_setting_bond_add_option (priv->setting, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, targets);
842
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
843
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_MIIMON);
844
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_UPDELAY);
845
nm_setting_bond_remove_option (priv->setting, NM_SETTING_BOND_OPTION_DOWNDELAY);
848
g_assert_not_reached ();
854
/* Slaves are updated as they're edited, so nothing to do */
858
validate (CEPage *page, NMConnection *connection, GError **error)
860
CEPageBond *self = CE_PAGE_BOND (page);
861
CEPageBondPrivate *priv = CE_PAGE_BOND_GET_PRIVATE (self);
864
/* Need at least one slave connection; we don't need to
865
* recursively check that the connections are valid because they
866
* can't end up in the table if they're not.
868
if (!gtk_tree_model_get_iter_first (priv->connections_model, &iter))
871
ui_to_setting (self);
872
return nm_setting_verify (NM_SETTING (priv->setting), NULL, error);
876
ce_page_bond_init (CEPageBond *self)
881
ce_page_bond_class_init (CEPageBondClass *bond_class)
883
GObjectClass *object_class = G_OBJECT_CLASS (bond_class);
884
CEPageClass *parent_class = CE_PAGE_CLASS (bond_class);
886
g_type_class_add_private (object_class, sizeof (CEPageBondPrivate));
888
/* virtual methods */
889
object_class->dispose = dispose;
891
parent_class->validate = validate;
896
bond_connection_new (GtkWindow *parent,
898
NMRemoteSettings *settings,
899
PageNewConnectionResultFunc result_func,
902
NMConnection *connection;
903
int bond_num, max_bond_num, num;
904
GSList *connections, *iter;
906
NMSettingBond *s_bond;
910
connection = ce_page_new_connection (_("Bond connection %d"),
911
NM_SETTING_BOND_SETTING_NAME,
915
nm_connection_add_setting (connection, nm_setting_bond_new ());
917
/* Find an available interface name */
918
bond_num = max_bond_num = 0;
919
connections = nm_remote_settings_list_connections (settings);
920
for (iter = connections; iter; iter = iter->next) {
923
if (!nm_connection_is_type (conn2, NM_SETTING_BOND_SETTING_NAME))
925
s_bond = nm_connection_get_setting_bond (conn2);
928
iface = nm_setting_bond_get_interface_name (s_bond);
929
if (!iface || strncmp (iface, "bond", 4) != 0 || !g_ascii_isdigit (iface[4]))
932
num = atoi (iface + 4);
933
if (num > max_bond_num)
936
bond_num = max_bond_num + 1;
938
g_slist_free (connections);
940
my_iface = g_strdup_printf ("bond%d", bond_num);
941
s_bond = nm_connection_get_setting_bond (connection);
942
g_object_set (G_OBJECT (s_bond),
943
NM_SETTING_BOND_INTERFACE_NAME, my_iface,
947
(*result_func) (connection, FALSE, NULL, user_data);