~cyruslien/network-manager-applet/network-manager-applet

« back to all changes in this revision

Viewing changes to src/connection-editor/page-dcb.c

  • Committer: cyrus.lien at canonical
  • Date: 2016-11-30 05:14:42 UTC
  • Revision ID: cyrus.lien@canonical.com-20161130051442-1odgw3pwcqbdmuuw
Import from soruce package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
/* NetworkManager Connection editor -- Connection editor for NetworkManager
 
3
 *
 
4
 * Dan Williams <dcbw@redhat.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License along
 
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
19
 *
 
20
 * Copyright 2013 - 2014 Red Hat, Inc.
 
21
 */
 
22
 
 
23
#include "nm-default.h"
 
24
 
 
25
#include <string.h>
 
26
#include <errno.h>
 
27
#include <stdlib.h>
 
28
 
 
29
#include "page-dcb.h"
 
30
 
 
31
G_DEFINE_TYPE (CEPageDcb, ce_page_dcb, CE_TYPE_PAGE)
 
32
 
 
33
#define CE_PAGE_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_DCB, CEPageDcbPrivate))
 
34
 
 
35
typedef struct {
 
36
        /* Copy of initial setting, if any; changes in the Options dialogs
 
37
         * update this setting, which is then copied to the final setting when
 
38
         * required.
 
39
         */
 
40
        NMSettingDcb *options;
 
41
 
 
42
        GtkToggleButton *enabled;
 
43
        GtkBox *box;
 
44
 
 
45
        gboolean initial_have_dcb;
 
46
} CEPageDcbPrivate;
 
47
 
 
48
/***************************************************************************/
 
49
 
 
50
static void
 
51
pfc_dialog_show (CEPageDcb *self)
 
52
{
 
53
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
54
        CEPage *parent = CE_PAGE (self);
 
55
        GtkWidget *dialog, *toplevel;
 
56
        GtkToggleButton *check;
 
57
        gint result;
 
58
        guint i;
 
59
        gboolean active;
 
60
        char *tmp;
 
61
 
 
62
        dialog = GTK_WIDGET (gtk_builder_get_object (parent->builder, "pfc_dialog"));
 
63
        g_assert (dialog);
 
64
        toplevel = gtk_widget_get_toplevel (parent->page);
 
65
        if (gtk_widget_is_toplevel (toplevel))
 
66
            gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
 
67
 
 
68
        /* Set the initial value */
 
69
        for (i = 0; i < 8; i++ ) {
 
70
                tmp = g_strdup_printf ("pfc_prio%u_checkbutton", i);
 
71
                check = GTK_TOGGLE_BUTTON (gtk_builder_get_object (parent->builder, tmp));
 
72
                g_free (tmp);
 
73
                g_assert (check);
 
74
 
 
75
                gtk_toggle_button_set_active (check, nm_setting_dcb_get_priority_flow_control (priv->options, i));
 
76
        }
 
77
 
 
78
        /* Run the dialog */
 
79
        result = gtk_dialog_run (GTK_DIALOG (dialog));
 
80
        if (result == GTK_RESPONSE_OK) {
 
81
                for (i = 0; i < 8; i++ ) {
 
82
                        tmp = g_strdup_printf ("pfc_prio%u_checkbutton", i);
 
83
                        check = GTK_TOGGLE_BUTTON (gtk_builder_get_object (parent->builder, tmp));
 
84
                        g_free (tmp);
 
85
                        g_assert (check);
 
86
 
 
87
                        active = gtk_toggle_button_get_active (check);
 
88
                        nm_setting_dcb_set_priority_flow_control (priv->options, i, active);
 
89
                }
 
90
        }
 
91
 
 
92
        gtk_widget_hide (dialog);
 
93
        ce_page_changed (CE_PAGE (self));
 
94
}
 
95
 
 
96
static gboolean
 
97
uint_entries_validate (GtkBuilder *builder, const char *fmt, gint max, gboolean sum)
 
98
{
 
99
        long int num;
 
100
        GtkEntry *entry;
 
101
        char *tmp;
 
102
        const char *text;
 
103
        guint i, total = 0;
 
104
        gboolean valid = TRUE;
 
105
        GdkRGBA bgcolor;
 
106
 
 
107
        gdk_rgba_parse (&bgcolor, "red3");
 
108
 
 
109
        for (i = 0; i < 8; i++) {
 
110
                tmp = g_strdup_printf (fmt, i);
 
111
                entry = GTK_ENTRY (gtk_builder_get_object (builder, tmp));
 
112
                g_free (tmp);
 
113
                g_assert (entry);
 
114
 
 
115
                text = gtk_entry_get_text (entry);
 
116
                if (text) {
 
117
                        errno = 0;
 
118
                        num = strtol (text, NULL, 10);
 
119
                        if (errno || num < 0 || num > max) {
 
120
                                /* FIXME: only sets highlight color? */
 
121
                                utils_override_bg_color (GTK_WIDGET (entry), &bgcolor);
 
122
                                valid = FALSE;
 
123
                        } else
 
124
                                utils_override_bg_color (GTK_WIDGET (entry), NULL);
 
125
 
 
126
                        total += (guint) num;
 
127
                        if (sum && total > 100)
 
128
                                utils_override_bg_color (GTK_WIDGET (entry), &bgcolor);
 
129
                }
 
130
        }
 
131
        if (sum && total != 100) {
 
132
                utils_override_bg_color (GTK_WIDGET (entry), &bgcolor);
 
133
                valid = FALSE;
 
134
        }
 
135
 
 
136
        return valid;
 
137
}
 
138
 
 
139
static void
 
140
pg_dialog_valid_func (GtkBuilder *builder)
 
141
{
 
142
        GtkDialog *dialog;
 
143
        gboolean b1, b2, valid = FALSE;
 
144
 
 
145
        b1 = uint_entries_validate (builder, "pg_pgpct%u_entry", 100, TRUE);
 
146
        b2 = uint_entries_validate (builder, "pg_uppct%u_entry", 100, FALSE);
 
147
        valid = b1 && b2;
 
148
 
 
149
        dialog = GTK_DIALOG (gtk_builder_get_object (builder, "pg_dialog"));
 
150
        gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, valid);
 
151
}
 
152
 
 
153
 
 
154
static void
 
155
combos_handle (GtkBuilder *builder,
 
156
               NMSettingDcb *s_dcb,
 
157
               const char *fmt,
 
158
               guint max,
 
159
               gint last_idx,
 
160
               guint other_num,
 
161
               guint (*get_func) (NMSettingDcb *s_dcb, guint n),
 
162
               void (*set_func) (NMSettingDcb *s_dcb, guint n, guint val))
 
163
{
 
164
        char *tmp;
 
165
        GtkComboBox *combo;
 
166
        guint i, num;
 
167
 
 
168
        for (i = 0; i < 8; i++) {
 
169
                tmp = g_strdup_printf (fmt, i);
 
170
                combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, tmp));
 
171
                g_free (tmp);
 
172
                g_assert (combo);
 
173
 
 
174
                if (get_func) {
 
175
                        num = get_func (s_dcb, i);
 
176
                        if (other_num && (num == other_num))
 
177
                                gtk_combo_box_set_active (combo, last_idx);
 
178
                        else if (num <= max)
 
179
                                gtk_combo_box_set_active (combo, num);
 
180
                        g_signal_connect_swapped (combo, "changed", (GCallback) pg_dialog_valid_func, builder);
 
181
                } else if (set_func) {
 
182
                        gint idx = gtk_combo_box_get_active (combo);
 
183
 
 
184
                        if (idx >= 0 && idx <= max)
 
185
                                set_func (s_dcb, i, idx);
 
186
                        else if (idx == last_idx)
 
187
                                set_func (s_dcb, i, other_num);
 
188
                } else
 
189
                        g_assert_not_reached ();
 
190
        }
 
191
}
 
192
 
 
193
static void
 
194
uint_filter_cb (GtkEditable *editable,
 
195
               gchar *text,
 
196
               gint length,
 
197
               gint *position,
 
198
               gpointer user_data)
 
199
{
 
200
        utils_filter_editable_on_insert_text (editable,
 
201
                                              text, length, position, user_data,
 
202
                                              utils_char_is_ascii_digit,
 
203
                                              uint_filter_cb);
 
204
}
 
205
 
 
206
static void
 
207
uint_entries_handle (GtkBuilder *builder,
 
208
                     NMSettingDcb *s_dcb,
 
209
                     const char *fmt,
 
210
                     guint (*get_func) (NMSettingDcb *s_dcb, guint n),
 
211
                     void (*set_func) (NMSettingDcb *s_dcb, guint n, guint val))
 
212
{
 
213
        char *tmp;
 
214
        GtkEntry *entry;
 
215
        guint i;
 
216
        const char *text;
 
217
 
 
218
        for (i = 0; i < 8; i++) {
 
219
                tmp = g_strdup_printf (fmt, i);
 
220
                entry = GTK_ENTRY (gtk_builder_get_object (builder, tmp));
 
221
                g_free (tmp);
 
222
                g_assert (entry);
 
223
 
 
224
                if (get_func) {
 
225
                        tmp = g_strdup_printf ("%u", get_func (s_dcb, i));
 
226
                        gtk_entry_set_text (entry, tmp);
 
227
                        g_free (tmp);
 
228
 
 
229
                        g_signal_connect (entry, "insert-text", (GCallback) uint_filter_cb, NULL);
 
230
                        g_signal_connect_swapped (entry, "changed", (GCallback) pg_dialog_valid_func, builder);
 
231
                } else if (set_func) {
 
232
                        long int num;
 
233
 
 
234
                        text = gtk_entry_get_text (entry);
 
235
                        if (text) {
 
236
                                errno = 0;
 
237
                                num = strtol (text, NULL, 10);
 
238
                                if (errno == 0 && num >= 0 && num <= 100)
 
239
                                        set_func (s_dcb, i, (guint) num);
 
240
                        }
 
241
                } else
 
242
                        g_assert_not_reached ();
 
243
        }
 
244
}
 
245
 
 
246
static void
 
247
bool_entries_handle (GtkBuilder *builder,
 
248
                     NMSettingDcb *s_dcb,
 
249
                     const char *fmt,
 
250
                     gboolean (*get_func) (NMSettingDcb *s_dcb, guint n),
 
251
                     void (*set_func) (NMSettingDcb *s_dcb, guint n, gboolean val))
 
252
{
 
253
        char *tmp;
 
254
        GtkToggleButton *toggle;
 
255
        guint i;
 
256
 
 
257
        for (i = 0; i < 8; i++) {
 
258
                tmp = g_strdup_printf (fmt, i);
 
259
                toggle = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, tmp));
 
260
                g_free (tmp);
 
261
                g_assert (toggle);
 
262
 
 
263
                if (get_func)
 
264
                        gtk_toggle_button_set_active (toggle, get_func (s_dcb, i));
 
265
                else if (set_func)
 
266
                        set_func (s_dcb, i, gtk_toggle_button_get_active (toggle));
 
267
                else
 
268
                        g_assert_not_reached ();
 
269
        }
 
270
}
 
271
 
 
272
static void
 
273
pg_dialog_show (CEPageDcb *self)
 
274
{
 
275
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
276
        CEPage *parent = CE_PAGE (self);
 
277
        GtkWidget *dialog, *toplevel;
 
278
        gint result;
 
279
 
 
280
        dialog = GTK_WIDGET (gtk_builder_get_object (parent->builder, "pg_dialog"));
 
281
        g_assert (dialog);
 
282
        toplevel = gtk_widget_get_toplevel (parent->page);
 
283
        if (gtk_widget_is_toplevel (toplevel))
 
284
            gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
 
285
 
 
286
        combos_handle (parent->builder,
 
287
                       priv->options,
 
288
                       "pg_pgid%u_combo",
 
289
                       7,
 
290
                       8,
 
291
                       15,
 
292
                       nm_setting_dcb_get_priority_group_id,
 
293
                       NULL);
 
294
 
 
295
        uint_entries_handle (parent->builder,
 
296
                             priv->options,
 
297
                             "pg_pgpct%u_entry",
 
298
                             nm_setting_dcb_get_priority_group_bandwidth,
 
299
                             NULL);
 
300
 
 
301
        uint_entries_handle (parent->builder,
 
302
                             priv->options,
 
303
                             "pg_uppct%u_entry",
 
304
                             nm_setting_dcb_get_priority_bandwidth,
 
305
                             NULL);
 
306
 
 
307
        bool_entries_handle (parent->builder,
 
308
                             priv->options,
 
309
                             "pg_strict%u_checkbutton",
 
310
                             nm_setting_dcb_get_priority_strict_bandwidth,
 
311
                             NULL);
 
312
 
 
313
        combos_handle (parent->builder,
 
314
                       priv->options,
 
315
                       "pg_up2tc%u_combo",
 
316
                       7,
 
317
                       0,
 
318
                       0,
 
319
                       nm_setting_dcb_get_priority_traffic_class,
 
320
                       NULL);
 
321
 
 
322
        pg_dialog_valid_func (parent->builder);
 
323
 
 
324
        /* Run the dialog */
 
325
        result = gtk_dialog_run (GTK_DIALOG (dialog));
 
326
        if (result == GTK_RESPONSE_OK) {
 
327
                combos_handle (parent->builder,
 
328
                               priv->options,
 
329
                               "pg_pgid%u_combo",
 
330
                               7,
 
331
                               8,
 
332
                               15,
 
333
                               NULL,
 
334
                               nm_setting_dcb_set_priority_group_id);
 
335
 
 
336
                uint_entries_handle (parent->builder,
 
337
                                     priv->options,
 
338
                                     "pg_pgpct%u_entry",
 
339
                                     NULL,
 
340
                                     nm_setting_dcb_set_priority_group_bandwidth);
 
341
 
 
342
                uint_entries_handle (parent->builder,
 
343
                                     priv->options,
 
344
                                     "pg_uppct%u_entry",
 
345
                                     NULL,
 
346
                                     nm_setting_dcb_set_priority_bandwidth);
 
347
 
 
348
                bool_entries_handle (parent->builder,
 
349
                                     priv->options,
 
350
                                     "pg_strict%u_checkbutton",
 
351
                                     NULL,
 
352
                                     nm_setting_dcb_set_priority_strict_bandwidth);
 
353
 
 
354
                combos_handle (parent->builder,
 
355
                               priv->options,
 
356
                               "pg_up2tc%u_combo",
 
357
                               7,
 
358
                               0,
 
359
                               0,
 
360
                               NULL,
 
361
                               nm_setting_dcb_set_priority_traffic_class);
 
362
        }
 
363
 
 
364
        gtk_widget_hide (dialog);
 
365
        ce_page_changed (CE_PAGE (self));
 
366
}
 
367
 
 
368
static void
 
369
pg_enabled (CEPageDcb *self, gboolean enabled)
 
370
{
 
371
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
372
        guint i;
 
373
        gboolean set_default = TRUE;
 
374
 
 
375
        if (!enabled)
 
376
                return;
 
377
 
 
378
        /* If the connection did not previously have DCB enabled, and the user
 
379
         * just enabled DCB, set a valid priority group bandwidth so that the
 
380
         * user doesn't have to go mess with the PG options dialog.
 
381
         */
 
382
        for (i = 0; i < 8; i++) {
 
383
                if (nm_setting_dcb_get_priority_group_bandwidth (priv->options, i)) {
 
384
                        set_default = FALSE;
 
385
                        break;
 
386
                }
 
387
        }
 
388
 
 
389
        if (set_default)
 
390
                nm_setting_dcb_set_priority_group_bandwidth (priv->options, 0, 100);
 
391
 
 
392
        ce_page_changed (CE_PAGE (self));
 
393
}
 
394
 
 
395
/***************************************************************************/
 
396
 
 
397
typedef void (*OptionsFunc) (CEPageDcb *self);
 
398
typedef void (*EnabledFunc) (CEPageDcb *self, gboolean enabled);
 
399
 
 
400
typedef struct {
 
401
        const char *prefix;
 
402
        const char *flags_prop;
 
403
        const char *priority_prop;
 
404
        const OptionsFunc options_func;
 
405
        const EnabledFunc enabled_func;
 
406
} Feature;
 
407
 
 
408
static const Feature features[] = {
 
409
        { "fcoe",  NM_SETTING_DCB_APP_FCOE_FLAGS,
 
410
                   NM_SETTING_DCB_APP_FCOE_PRIORITY },
 
411
 
 
412
        { "iscsi", NM_SETTING_DCB_APP_ISCSI_FLAGS,
 
413
                   NM_SETTING_DCB_APP_ISCSI_PRIORITY },
 
414
 
 
415
        { "fip",   NM_SETTING_DCB_APP_FIP_FLAGS,
 
416
                   NM_SETTING_DCB_APP_FIP_PRIORITY },
 
417
 
 
418
        { "pfc",   NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS,
 
419
                   NULL,
 
420
                   pfc_dialog_show },
 
421
 
 
422
        { "pg",    NM_SETTING_DCB_PRIORITY_GROUP_FLAGS,
 
423
                   NULL,
 
424
                   pg_dialog_show,
 
425
                   pg_enabled },
 
426
};
 
427
 
 
428
typedef struct {
 
429
        CEPage *page;
 
430
        const Feature *f;
 
431
} EnableInfo;
 
432
 
 
433
static GtkWidget *
 
434
get_widget (GtkBuilder *builder, const char *prefix, const char *suffix)
 
435
{
 
436
        GtkWidget *widget;
 
437
        char *s;
 
438
 
 
439
        s = g_strdup_printf ("%s%s", prefix, suffix);
 
440
        widget = GTK_WIDGET (gtk_builder_get_object (builder, s));
 
441
        g_assert (widget);
 
442
        g_free (s);
 
443
        return widget;
 
444
}
 
445
 
 
446
static void
 
447
enable_toggled_cb (GtkToggleButton *button, EnableInfo *info)
 
448
{
 
449
        gboolean enabled = gtk_toggle_button_get_active (button);
 
450
        GtkWidget *widget;
 
451
 
 
452
        /* Set other feature widgets sensitive or not depending on enabled */
 
453
 
 
454
        widget = get_widget (info->page->builder, info->f->prefix, "_advertise_checkbutton");
 
455
        gtk_widget_set_sensitive (widget, enabled);
 
456
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
 
457
 
 
458
        widget = get_widget (info->page->builder, info->f->prefix, "_willing_checkbutton");
 
459
        gtk_widget_set_sensitive (widget, enabled);
 
460
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
 
461
 
 
462
        if (info->f->priority_prop) {
 
463
                widget = get_widget (info->page->builder, info->f->prefix, "_priority_combo");
 
464
                gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
 
465
                gtk_widget_set_sensitive (widget, enabled);
 
466
        }
 
467
 
 
468
        if (info->f->options_func) {
 
469
                widget = get_widget (info->page->builder, info->f->prefix, "_options_button");
 
470
                gtk_widget_set_sensitive (widget, enabled);
 
471
        }
 
472
 
 
473
        /* FCoE mode combo */
 
474
        if (!strcmp (info->f->prefix, "fcoe")) {
 
475
                widget = get_widget (info->page->builder, info->f->prefix, "_mode_combo");
 
476
                gtk_widget_set_sensitive (widget, enabled);
 
477
        }
 
478
 
 
479
        if (info->f->enabled_func)
 
480
                info->f->enabled_func (CE_PAGE_DCB (info->page), gtk_toggle_button_get_active (button));
 
481
 
 
482
        ce_page_changed (info->page);
 
483
}
 
484
 
 
485
static void
 
486
feature_setup (CEPageDcb *self, NMSettingDcb *s_dcb, const Feature *f)
 
487
{
 
488
        CEPage *parent = CE_PAGE (self);
 
489
        GtkWidget *widget;
 
490
        NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
 
491
        gboolean enabled;
 
492
        EnableInfo *info;
 
493
 
 
494
        if (s_dcb)
 
495
                g_object_get (G_OBJECT (s_dcb), f->flags_prop, (guint32 *) &flags, NULL);
 
496
        enabled = flags & NM_SETTING_DCB_FLAG_ENABLE;
 
497
 
 
498
        /* Enable */
 
499
        widget = get_widget (parent->builder, f->prefix, "_enable_checkbutton");
 
500
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), enabled);
 
501
 
 
502
        info = g_malloc0 (sizeof (EnableInfo));
 
503
        info->f = f;
 
504
        info->page = parent;
 
505
        g_signal_connect (widget, "toggled", G_CALLBACK (enable_toggled_cb), info);
 
506
        g_object_weak_ref (G_OBJECT (widget), (GWeakNotify) g_free, info);
 
507
 
 
508
        /* Advertise */
 
509
        widget = get_widget (parent->builder, f->prefix, "_advertise_checkbutton");
 
510
        gtk_widget_set_sensitive (widget, enabled);
 
511
        if (enabled)
 
512
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), flags & NM_SETTING_DCB_FLAG_ADVERTISE);
 
513
        g_signal_connect_swapped (widget, "toggled", G_CALLBACK (ce_page_changed), self);
 
514
 
 
515
        /* Willing */
 
516
        widget = get_widget (parent->builder, f->prefix, "_willing_checkbutton");
 
517
        gtk_widget_set_sensitive (widget, enabled);
 
518
        if (enabled)
 
519
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), flags & NM_SETTING_DCB_FLAG_WILLING);
 
520
        g_signal_connect_swapped (widget, "toggled", G_CALLBACK (ce_page_changed), self);
 
521
 
 
522
        if (f->priority_prop) {
 
523
                gint priority = -1;
 
524
 
 
525
                if (s_dcb)
 
526
                        g_object_get (G_OBJECT (s_dcb), f->priority_prop, &priority, NULL);
 
527
                priority = CLAMP (priority, -1, 7);
 
528
 
 
529
                widget = get_widget (parent->builder, f->prefix, "_priority_combo");
 
530
                gtk_widget_set_sensitive (widget, enabled);
 
531
                gtk_combo_box_set_active (GTK_COMBO_BOX (widget), priority + 1);
 
532
                g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), self);
 
533
        }
 
534
 
 
535
        if (f->options_func) {
 
536
                widget = get_widget (parent->builder, f->prefix, "_options_button");
 
537
                gtk_widget_set_sensitive (widget, enabled);
 
538
                g_signal_connect_swapped (widget, "clicked", G_CALLBACK (f->options_func), self);
 
539
        }
 
540
 
 
541
        /* Set up the FCoE mode combo */
 
542
        if (!strcmp (f->prefix, "fcoe")) {
 
543
                const char *mode = s_dcb ? nm_setting_dcb_get_app_fcoe_mode (s_dcb) : NULL;
 
544
                guint idx = 0;
 
545
 
 
546
                widget = get_widget (info->page->builder, info->f->prefix, "_mode_combo");
 
547
                if (g_strcmp0 (mode, NM_SETTING_DCB_FCOE_MODE_VN2VN) == 0)
 
548
                        idx = 1;
 
549
                gtk_combo_box_set_active (GTK_COMBO_BOX (widget), idx);
 
550
                gtk_widget_set_sensitive (widget, enabled);
 
551
                g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), self);
 
552
        }
 
553
}
 
554
 
 
555
static void
 
556
enable_toggled (GtkToggleButton *button, gpointer user_data)
 
557
{
 
558
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (user_data);
 
559
 
 
560
        gtk_widget_set_sensitive (GTK_WIDGET (priv->box), gtk_toggle_button_get_active (button));
 
561
        ce_page_changed (CE_PAGE (user_data));
 
562
}
 
563
 
 
564
static void
 
565
finish_setup (CEPageDcb *self, gpointer unused, GError *error, gpointer user_data)
 
566
{
 
567
        CEPage *parent = CE_PAGE (self);
 
568
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
569
        NMSettingDcb *s_dcb = nm_connection_get_setting_dcb (parent->connection);
 
570
        guint i;
 
571
 
 
572
        if (error)
 
573
                return;
 
574
 
 
575
        gtk_toggle_button_set_active (priv->enabled, priv->initial_have_dcb);
 
576
        g_signal_connect (priv->enabled, "toggled", G_CALLBACK (enable_toggled), self);
 
577
        gtk_widget_set_sensitive (GTK_WIDGET (priv->box), priv->initial_have_dcb);
 
578
 
 
579
        for (i = 0; i < G_N_ELEMENTS (features); i++)
 
580
                feature_setup (self, s_dcb, &features[i]);
 
581
}
 
582
 
 
583
CEPage *
 
584
ce_page_dcb_new (NMConnectionEditor *editor,
 
585
                 NMConnection *connection,
 
586
                 GtkWindow *parent_window,
 
587
                 NMClient *client,
 
588
                 const char **out_secrets_setting_name,
 
589
                 GError **error)
 
590
{
 
591
        CEPageDcb *self;
 
592
        CEPageDcbPrivate *priv;
 
593
        CEPage *parent;
 
594
        NMSettingDcb *s_dcb;
 
595
 
 
596
        self = CE_PAGE_DCB (ce_page_new (CE_TYPE_PAGE_DCB,
 
597
                                         editor,
 
598
                                         connection,
 
599
                                         parent_window,
 
600
                                         client,
 
601
                                         UIDIR "/ce-page-dcb.ui",
 
602
                                         "DcbPage",
 
603
                                         _("DCB")));
 
604
        if (!self) {
 
605
                g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load DCB user interface."));
 
606
                return NULL;
 
607
        }
 
608
 
 
609
        priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
610
        parent = CE_PAGE (self);
 
611
 
 
612
        priv->enabled = GTK_TOGGLE_BUTTON (gtk_builder_get_object (parent->builder, "dcb_enabled_checkbutton"));
 
613
        priv->box = GTK_BOX (gtk_builder_get_object (parent->builder, "dcb_box"));
 
614
 
 
615
        s_dcb = nm_connection_get_setting_dcb (connection);
 
616
        if (s_dcb) {
 
617
                priv->initial_have_dcb = TRUE;
 
618
                priv->options = (NMSettingDcb *) nm_setting_duplicate (NM_SETTING (s_dcb));
 
619
        } else
 
620
                priv->options = (NMSettingDcb *) nm_setting_dcb_new ();
 
621
 
 
622
        g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
 
623
 
 
624
        return CE_PAGE (self);
 
625
}
 
626
 
 
627
static void
 
628
ui_to_setting (CEPageDcb *self, NMSettingDcb *s_dcb)
 
629
{
 
630
        CEPage *parent = CE_PAGE (self);
 
631
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
632
        NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
 
633
        GtkWidget *widget;
 
634
        gboolean enabled, b;
 
635
        const char *tmp;
 
636
        guint i, num;
 
637
 
 
638
        enabled = gtk_toggle_button_get_active (priv->enabled);
 
639
        for (i = 0; i < G_N_ELEMENTS (features); i++) {
 
640
                const Feature *f = &features[i];
 
641
 
 
642
                flags = NM_SETTING_DCB_FLAG_NONE;
 
643
 
 
644
                /* Enable */
 
645
                widget = get_widget (parent->builder, f->prefix, "_enable_checkbutton");
 
646
                if (enabled && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
647
                        flags |= NM_SETTING_DCB_FLAG_ENABLE;
 
648
 
 
649
                /* Advertise */
 
650
                widget = get_widget (parent->builder, f->prefix, "_advertise_checkbutton");
 
651
                if (enabled && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
652
                        flags |= NM_SETTING_DCB_FLAG_ADVERTISE;
 
653
 
 
654
                /* Willing */
 
655
                widget = get_widget (parent->builder, f->prefix, "_willing_checkbutton");
 
656
                if (enabled && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
657
                        flags |= NM_SETTING_DCB_FLAG_WILLING;
 
658
 
 
659
                g_object_set (G_OBJECT (s_dcb), f->flags_prop, flags, NULL);
 
660
 
 
661
                if (f->priority_prop) {
 
662
                        gint idx = 0;
 
663
 
 
664
                        widget = get_widget (parent->builder, f->prefix, "_priority_combo");
 
665
                        if (enabled)
 
666
                                idx = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
667
                        g_object_set (G_OBJECT (s_dcb), f->priority_prop, (gint) (idx - 1), NULL);
 
668
                }
 
669
        }
 
670
 
 
671
        /* FCoE Mode */
 
672
        flags = nm_setting_dcb_get_app_fcoe_flags (s_dcb);
 
673
        tmp = NM_SETTING_DCB_FCOE_MODE_FABRIC;
 
674
        if (flags & NM_SETTING_DCB_FLAG_ENABLE) {
 
675
                widget = get_widget (parent->builder, "fcoe", "_mode_combo");
 
676
                num = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
677
                if (num == 0)
 
678
                        tmp = NM_SETTING_DCB_FCOE_MODE_FABRIC;
 
679
                else if (num == 1)
 
680
                        tmp = NM_SETTING_DCB_FCOE_MODE_VN2VN;
 
681
                else
 
682
                        g_assert_not_reached ();
 
683
        }
 
684
        g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_FCOE_MODE, tmp, NULL);
 
685
 
 
686
        /* Priority Flow Control */
 
687
        flags = nm_setting_dcb_get_priority_flow_control_flags (s_dcb);
 
688
        for (i = 0; i < 8; i++) {
 
689
                b = FALSE;
 
690
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
691
                        b = nm_setting_dcb_get_priority_flow_control (priv->options, i);
 
692
                nm_setting_dcb_set_priority_flow_control (s_dcb, i, b);
 
693
        }
 
694
 
 
695
        /* Priority Groups */
 
696
        flags = nm_setting_dcb_get_priority_group_flags (s_dcb);
 
697
        for (i = 0; i < 8; i++) {
 
698
                /* Group ID */
 
699
                num = 0;
 
700
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
701
                        num = nm_setting_dcb_get_priority_group_id (priv->options, i);
 
702
                nm_setting_dcb_set_priority_group_id (s_dcb, i, num);
 
703
 
 
704
                num = 0;
 
705
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
706
                        num = nm_setting_dcb_get_priority_group_bandwidth (priv->options, i);
 
707
                nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, num);
 
708
 
 
709
                num = 0;
 
710
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
711
                        num = nm_setting_dcb_get_priority_bandwidth (priv->options, i);
 
712
                nm_setting_dcb_set_priority_bandwidth (s_dcb, i, num);
 
713
 
 
714
                b = 0;
 
715
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
716
                        b = nm_setting_dcb_get_priority_strict_bandwidth (priv->options, i);
 
717
                nm_setting_dcb_set_priority_strict_bandwidth (s_dcb, i, b);
 
718
 
 
719
                num = 0;
 
720
                if (flags & NM_SETTING_DCB_FLAG_ENABLE)
 
721
                        num = nm_setting_dcb_get_priority_traffic_class (priv->options, i);
 
722
                nm_setting_dcb_set_priority_traffic_class (s_dcb, i, num);
 
723
        }
 
724
 
 
725
}
 
726
 
 
727
static gboolean
 
728
ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
 
729
{
 
730
        CEPageDcb *self = CE_PAGE_DCB (page);
 
731
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (self);
 
732
        NMSettingDcb *s_dcb;
 
733
 
 
734
        if (!gtk_toggle_button_get_active (priv->enabled)) {
 
735
                nm_connection_remove_setting (connection, NM_TYPE_SETTING_DCB);
 
736
                return TRUE;
 
737
        }
 
738
 
 
739
        s_dcb = nm_connection_get_setting_dcb (connection);
 
740
        if (!s_dcb) {
 
741
                s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
 
742
                nm_connection_add_setting (connection, NM_SETTING (s_dcb));
 
743
        }
 
744
        ui_to_setting (self, s_dcb);
 
745
 
 
746
        return nm_setting_verify (NM_SETTING (s_dcb), NULL, error);
 
747
}
 
748
 
 
749
static void
 
750
ce_page_dcb_init (CEPageDcb *self)
 
751
{
 
752
}
 
753
 
 
754
static void
 
755
dispose (GObject *object)
 
756
{
 
757
        CEPageDcbPrivate *priv = CE_PAGE_DCB_GET_PRIVATE (object);
 
758
 
 
759
        g_clear_object (&priv->options);
 
760
 
 
761
        G_OBJECT_CLASS (ce_page_dcb_parent_class)->dispose (object);
 
762
}
 
763
 
 
764
static void
 
765
ce_page_dcb_class_init (CEPageDcbClass *security_class)
 
766
{
 
767
        GObjectClass *object_class = G_OBJECT_CLASS (security_class);
 
768
        CEPageClass *parent_class = CE_PAGE_CLASS (security_class);
 
769
 
 
770
        g_type_class_add_private (object_class, sizeof (CEPageDcbPrivate));
 
771
 
 
772
        /* virtual methods */
 
773
        object_class->dispose = dispose;
 
774
 
 
775
        parent_class->ce_page_validate_v = ce_page_validate_v;
 
776
}