libnm-util: add Data Center Bridging (DCB) setting
authorDan Williams <dcbw@redhat.com>
Fri, 13 Sep 2013 14:44:56 +0000 (09:44 -0500)
committerDan Williams <dcbw@redhat.com>
Thu, 31 Oct 2013 18:28:42 +0000 (13:28 -0500)
Includes various fixes & cleanups from Thomas Haller.

.gitignore
docs/libnm-util/libnm-util-docs.sgml
libnm-util/Makefile.am
libnm-util/libnm-util.ver
libnm-util/nm-connection.c
libnm-util/nm-connection.h
libnm-util/nm-setting-dcb.c [new file with mode: 0644]
libnm-util/nm-setting-dcb.h [new file with mode: 0644]
libnm-util/tests/Makefile.am
libnm-util/tests/test-setting-dcb.c [new file with mode: 0644]
po/POTFILES.in

index dd50214..ebb5eb2 100644 (file)
@@ -176,6 +176,7 @@ valgrind-*.log
 /libnm-util/tests/test-need-secrets
 /libnm-util/tests/test-secrets
 /libnm-util/tests/test-setting-8021x
+/libnm-util/tests/test-setting-dcb
 /libnm-glib/tests/test-remote-settings-client
 /src/tests/test-dhcp-options
 /src/tests/test-ip4-config
index eaef262..2c43164 100644 (file)
@@ -62,6 +62,7 @@
     <xi:include href="xml/nm-setting-vlan.xml"/>
     <xi:include href="xml/nm-setting-olpc-mesh.xml"/>
     <xi:include href="xml/nm-setting-adsl.xml"/>
+    <xi:include href="xml/nm-setting-dcb.xml"/>
     <xi:include href="xml/nm-setting-8021x.xml"/>
     <xi:include href="xml/nm-setting-ip4-config.xml"/>
     <xi:include href="xml/nm-setting-ip6-config.xml"/>
index 6f267c1..f5b7773 100644 (file)
@@ -32,6 +32,7 @@ libnm_util_include_HEADERS =          \
        nm-setting-bridge.h             \
        nm-setting-bridge-port.h        \
        nm-setting-connection.h         \
+       nm-setting-dcb.h                \
        nm-setting-infiniband.h         \
        nm-setting-ip4-config.h         \
        nm-setting-vlan.h               \
@@ -71,6 +72,7 @@ libnm_util_la_csources = \
        nm-setting-bridge.c             \
        nm-setting-bridge-port.c        \
        nm-setting-connection.c         \
+       nm-setting-dcb.c                \
        nm-setting-infiniband.c         \
        nm-setting-ip4-config.c         \
        nm-setting-vlan.c               \
index dd8fcfa..f613c32 100644 (file)
@@ -23,6 +23,7 @@ global:
        nm_connection_get_setting_by_name;
        nm_connection_get_setting_cdma;
        nm_connection_get_setting_connection;
+       nm_connection_get_setting_dcb;
        nm_connection_get_setting_generic;
        nm_connection_get_setting_gsm;
        nm_connection_get_setting_infiniband;
@@ -263,6 +264,32 @@ global:
        nm_setting_connection_permissions_user_allowed;
        nm_setting_connection_remove_permission;
        nm_setting_connection_remove_secondary;
+       nm_setting_dcb_error_get_type;
+       nm_setting_dcb_error_quark;
+       nm_setting_dcb_flags_get_type;
+       nm_setting_dcb_get_app_fcoe_flags;
+       nm_setting_dcb_get_app_fcoe_mode;
+       nm_setting_dcb_get_app_fcoe_priority;
+       nm_setting_dcb_get_app_fip_flags;
+       nm_setting_dcb_get_app_fip_priority;
+       nm_setting_dcb_get_app_iscsi_flags;
+       nm_setting_dcb_get_app_iscsi_priority;
+       nm_setting_dcb_get_priority_bandwidth;
+       nm_setting_dcb_get_priority_flow_control;
+       nm_setting_dcb_get_priority_flow_control_flags;
+       nm_setting_dcb_get_priority_group_bandwidth;
+       nm_setting_dcb_get_priority_group_flags;
+       nm_setting_dcb_get_priority_group_id;
+       nm_setting_dcb_get_priority_strict_bandwidth;
+       nm_setting_dcb_get_priority_traffic_class;
+       nm_setting_dcb_get_type;
+       nm_setting_dcb_new;
+       nm_setting_dcb_set_priority_bandwidth;
+       nm_setting_dcb_set_priority_flow_control;
+       nm_setting_dcb_set_priority_group_bandwidth;
+       nm_setting_dcb_set_priority_group_id;
+       nm_setting_dcb_set_priority_strict_bandwidth;
+       nm_setting_dcb_set_priority_traffic_class;
        nm_setting_diff;
        nm_setting_diff_result_get_type;
        nm_setting_duplicate;
index 01223da..7c67e84 100644 (file)
@@ -1326,6 +1326,22 @@ nm_connection_get_setting_connection (NMConnection *connection)
        return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
 }
 
+/**
+ * nm_connection_get_setting_dcb:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingDcb the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL
+ **/
+NMSettingDcb *
+nm_connection_get_setting_dcb (NMConnection *connection)
+{
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+       return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB);
+}
+
 /**
  * nm_connection_get_setting_generic:
  * @connection: the #NMConnection
index f310319..cda8391 100644 (file)
@@ -39,6 +39,7 @@
 #include <nm-setting-bridge-port.h>
 #include <nm-setting-cdma.h>
 #include <nm-setting-connection.h>
+#include <nm-setting-dcb.h>
 #include <nm-setting-generic.h>
 #include <nm-setting-gsm.h>
 #include <nm-setting-infiniband.h>
@@ -208,6 +209,7 @@ NMSettingBridge *          nm_connection_get_setting_bridge            (NMConnec
 NMSettingBridgePort *      nm_connection_get_setting_bridge_port       (NMConnection *connection);
 NMSettingCdma *            nm_connection_get_setting_cdma              (NMConnection *connection);
 NMSettingConnection *      nm_connection_get_setting_connection        (NMConnection *connection);
+NMSettingDcb *             nm_connection_get_setting_dcb               (NMConnection *connection);
 NMSettingGeneric *         nm_connection_get_setting_generic           (NMConnection *connection);
 NMSettingGsm *             nm_connection_get_setting_gsm               (NMConnection *connection);
 NMSettingInfiniband *      nm_connection_get_setting_infiniband        (NMConnection *connection);
diff --git a/libnm-util/nm-setting-dcb.c b/libnm-util/nm-setting-dcb.c
new file mode 100644 (file)
index 0000000..cf2d47d
--- /dev/null
@@ -0,0 +1,1258 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
+#include "nm-setting-dcb.h"
+#include "nm-param-spec-specialized.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-dcb
+ * @short_description: Connection properties for Data Center Bridging
+ * @include: nm-setting-dcb.h
+ *
+ * The #NMSettingDcb object is a #NMSetting subclass that describes properties
+ * for enabling and using Data Center Bridging (DCB) on Ethernet networks.
+ * DCB is a set of protocols (including 802.1Qbb, 802.1Qaz, 802.1Qau, and
+ * 802.1AB) to eliminate packet loss in Ethernet networks and support the use
+ * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI.
+ *
+ * Since: 0.9.10
+ **/
+
+/**
+ * nm_setting_dcb_error_quark:
+ *
+ * Registers an error quark for #NMSettingDcb if necessary.
+ *
+ * Returns: the error quark used for #NMSettingDcb errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_setting_dcb_error_quark (void)
+{
+       static GQuark quark;
+
+       if (G_UNLIKELY (!quark))
+               quark = g_quark_from_static_string ("nm-setting-dcb-error-quark");
+       return quark;
+}
+
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING,
+                         _nm_register_setting (NM_SETTING_DCB_SETTING_NAME,
+                                               g_define_type_id,
+                                               2,
+                                               NM_SETTING_DCB_ERROR))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DCB)
+
+#define NM_SETTING_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate))
+
+typedef struct {
+       NMSettingDcbFlags app_fcoe_flags;
+       gint              app_fcoe_priority;
+       const char *      app_fcoe_mode;
+
+       NMSettingDcbFlags app_iscsi_flags;
+       gint              app_iscsi_priority;
+
+       NMSettingDcbFlags app_fip_flags;
+       gint              app_fip_priority;
+
+       /* Priority Flow Control */
+       NMSettingDcbFlags pfc_flags;
+       guint             pfc[8];
+
+       /* Priority Groups */
+       NMSettingDcbFlags priority_group_flags;
+       guint             priority_group_id[8];
+       guint             priority_group_bandwidth[8];
+       guint             priority_bandwidth[8];
+       guint             priority_strict[8];
+       guint             priority_traffic_class[8];
+} NMSettingDcbPrivate;
+
+enum {
+       PROP_0,
+       PROP_APP_FCOE_FLAGS,
+       PROP_APP_FCOE_PRIORITY,
+       PROP_APP_FCOE_MODE,
+
+       PROP_APP_ISCSI_FLAGS,
+       PROP_APP_ISCSI_PRIORITY,
+
+       PROP_APP_FIP_FLAGS,
+       PROP_APP_FIP_PRIORITY,
+
+       PROP_PFC_FLAGS,
+       PROP_PFC,
+
+       PROP_PRIORITY_GROUP_FLAGS,
+       PROP_PRIORITY_GROUP_ID,
+       PROP_PRIORITY_GROUP_BANDWIDTH,
+       PROP_PRIORITY_BANDWIDTH,
+       PROP_PRIORITY_STRICT,
+       PROP_PRIORITY_TRAFFIC_CLASS,
+
+       LAST_PROP
+};
+
+/**
+ * nm_setting_dcb_new:
+ *
+ * Creates a new #NMSettingDcb object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingDcb object
+ *
+ * Since: 0.9.10
+ **/
+NMSetting *
+nm_setting_dcb_new (void)
+{
+       return (NMSetting *) g_object_new (NM_TYPE_SETTING_DCB, NULL);
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_mode:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-mode property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_dcb_get_app_fcoe_mode (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), NULL);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_mode;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_priority;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-flow-control-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_flow_control_flags (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->pfc_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve flow control for
+ *
+ * Returns: %TRUE if flow control is enabled for the given @user_priority,
+ * %FALSE if not enabled
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_dcb_get_priority_flow_control (NMSettingDcb *setting, guint user_priority)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), FALSE);
+       g_return_val_if_fail (user_priority <= 7, FALSE);
+
+       return !!NM_SETTING_DCB_GET_PRIVATE (setting)->pfc[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @enabled: %TRUE to enable flow control for this priority, %FALSE to disable it
+ *
+ * These values are only valid when #NMSettingDcb:priority-flow-control includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_flow_control (NMSettingDcb *setting,
+                                          guint user_priority,
+                                          gboolean enabled)
+{
+       NMSettingDcbPrivate *priv;
+       guint uint_enabled = enabled ? 1 : 0;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (user_priority <= 7);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->pfc[user_priority] != uint_enabled) {
+               priv->pfc[user_priority] = uint_enabled;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL);
+       }
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-group-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group ID for
+ *
+ * Returns: the group number @user_priority is assigned to.  These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_group_id (NMSettingDcb *setting, guint user_priority)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+       g_return_val_if_fail (user_priority <= 7, 0);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_id[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @group_id: the group (0 - 7) to assign @user_priority to, or 15 for the
+ * unrestricted group.
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_group_id (NMSettingDcb *setting,
+                                      guint user_priority,
+                                      guint group_id)
+{
+       NMSettingDcbPrivate *priv;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (user_priority <= 7);
+       g_return_if_fail (group_id <= 7 || group_id == 15);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->priority_group_id[user_priority] != group_id) {
+               priv->priority_group_id[user_priority] = group_id;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_ID);
+       }
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to retrieve the bandwidth percentage for
+ *
+ * Returns: the bandwidth percentage assigned to @group_id.  These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_group_bandwidth (NMSettingDcb *setting, guint group_id)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+       g_return_val_if_fail (group_id <= 7, FALSE);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_bandwidth[group_id];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) to assign to @group_id to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_group_bandwidth (NMSettingDcb *setting,
+                                             guint group_id,
+                                             guint bandwidth_percent)
+{
+       NMSettingDcbPrivate *priv;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (group_id <= 7);
+       g_return_if_fail (bandwidth_percent <= 100);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->priority_group_bandwidth[group_id] != bandwidth_percent) {
+               priv->priority_group_bandwidth[group_id] = bandwidth_percent;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH);
+       }
+}
+
+/**
+ * nm_setting_dcb_get_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group bandwidth percentage for
+ *
+ * Returns: the allowed bandwidth percentage of @user_priority in its priority group.
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+       g_return_val_if_fail (user_priority <= 7, FALSE);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_bandwidth[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) that @user_priority is
+ * allowed to use within its priority group
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_bandwidth (NMSettingDcb *setting,
+                                       guint user_priority,
+                                       guint bandwidth_percent)
+{
+       NMSettingDcbPrivate *priv;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (user_priority <= 7);
+       g_return_if_fail (bandwidth_percent <= 100);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->priority_bandwidth[user_priority] != bandwidth_percent) {
+               priv->priority_bandwidth[user_priority] = bandwidth_percent;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_BANDWIDTH);
+       }
+}
+
+/**
+ * nm_setting_dcb_get_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve strict bandwidth for
+ *
+ * Returns: %TRUE if @user_priority may use all of the bandwidth allocated to its
+ * assigned group, or %FALSE if not. These values are only valid when
+ * #NMSettingDcb:priority-group-flags includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+       g_return_val_if_fail (user_priority <= 7, FALSE);
+
+       return !!NM_SETTING_DCB_GET_PRIVATE (setting)->priority_strict[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set strict bandwidth for
+ * @strict: %TRUE to allow @user_priority to use all the bandwidth allocated to
+ * its priority group, or %FALSE if not
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+                                              guint user_priority,
+                                              gboolean strict)
+{
+       NMSettingDcbPrivate *priv;
+       guint uint_strict = strict ? 1 : 0;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (user_priority <= 7);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->priority_strict[user_priority] != uint_strict) {
+               priv->priority_strict[user_priority] = uint_strict;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH);
+       }
+}
+
+/**
+ * nm_setting_dcb_get_priority_traffic_class:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the traffic class for
+ *
+ * Returns: the traffic class assigned to @user_priority. These values are only
+ * valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_traffic_class (NMSettingDcb *setting, guint user_priority)
+{
+       g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+       g_return_val_if_fail (user_priority <= 7, FALSE);
+
+       return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_traffic_class[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_traffic_clas:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @traffic_class: the traffic_class (0 - 7) that @user_priority should map to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_traffic_class (NMSettingDcb *setting,
+                                           guint user_priority,
+                                           guint traffic_class)
+{
+       NMSettingDcbPrivate *priv;
+
+       g_return_if_fail (NM_IS_SETTING_DCB (setting));
+       g_return_if_fail (user_priority <= 7);
+       g_return_if_fail (traffic_class <= 7);
+
+       priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+       if (priv->priority_traffic_class[user_priority] != traffic_class) {
+               priv->priority_traffic_class[user_priority] = traffic_class;
+               g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS);
+       }
+}
+
+/******************************************************************/
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+                       NM_SETTING_DCB_FLAG_ADVERTISE | \
+                       NM_SETTING_DCB_FLAG_WILLING)
+
+static gboolean
+check_dcb_flags (NMSettingDcbFlags flags, const char *prop_name, GError **error)
+{
+       if (flags & ~DCB_FLAGS_ALL) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                    _("flags invalid"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+               return FALSE;
+       }
+
+       if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (flags & ~NM_SETTING_DCB_FLAG_ENABLE)) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                    _("flags invalid - disabled"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static gboolean
+check_uint_array (const guint *array,
+                  guint len,
+                  NMSettingDcbFlags flags,
+                  guint max,
+                  guint extra,
+                  gboolean sum_pct,
+                  const char *prop_name,
+                  GError **error)
+{
+       guint i, sum = 0;
+
+       /* Ensure each element is <= to max or equals extra */
+       for (i = 0; i < len; i++) {
+               if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && array[i]) {
+                       g_set_error_literal (error,
+                                            NM_SETTING_DCB_ERROR,
+                                            NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                            _("property invalid (not enabled)"));
+                       g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+                       return FALSE;
+               }
+
+               if ((array[i] > max) && (array[i] != extra)) {
+                       g_set_error_literal (error,
+                                            NM_SETTING_DCB_ERROR,
+                                            NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                            _("element invalid"));
+                       g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+                       return FALSE;
+               }
+               sum += array[i];
+       }
+
+       /* Verify sum of percentages */
+       if (sum_pct) {
+               if (flags & NM_SETTING_DCB_FLAG_ENABLE) {
+                       /* If the feature is enabled, sum must equal 100% */
+                       if (sum != 100) {
+                               g_set_error_literal (error,
+                                                    NM_SETTING_DCB_ERROR,
+                                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                                    _("sum not 100%"));
+                               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+                               return FALSE;
+                       }
+               } else {
+                       /* If the feature is disabled, sum must equal 0%, which was checked
+                        * by the for() loop above.
+                        */
+                       g_assert_cmpint (sum, ==, 0);
+               }
+       }
+
+       return TRUE;
+}
+
+static gboolean
+check_priority (gint val,
+                NMSettingDcbFlags flags,
+                const char *prop_name,
+                GError **error)
+{
+       if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (val >= 0)) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                    _("property invalid (not enabled)"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+               return FALSE;
+       }
+
+       if (val < -1 || val > 7) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                    _("property invalid"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+       NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+       if (!check_dcb_flags (priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS, error))
+               return FALSE;
+
+       if (!check_priority (priv->app_fcoe_priority, priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_PRIORITY, error))
+               return FALSE;
+
+       if (!priv->app_fcoe_mode) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_MISSING_PROPERTY,
+                                    _("property missing"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+               return FALSE;
+       }
+
+       if (strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_FABRIC) &&
+           strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_VN2VN)) {
+               g_set_error_literal (error,
+                                    NM_SETTING_DCB_ERROR,
+                                    NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+                                    _("property invalid"));
+               g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+               return FALSE;
+       }
+
+       if (!check_dcb_flags (priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS, error))
+               return FALSE;
+
+       if (!check_priority (priv->app_iscsi_priority, priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_PRIORITY, error))
+               return FALSE;
+
+       if (!check_dcb_flags (priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS, error))
+               return FALSE;
+
+       if (!check_priority (priv->app_fip_priority, priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_PRIORITY, error))
+               return FALSE;
+
+       if (!check_dcb_flags (priv->pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, error))
+               return FALSE;
+
+       if (!check_uint_array (priv->pfc, G_N_ELEMENTS (priv->pfc), priv->pfc_flags, 1, 0, FALSE, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, error))
+               return FALSE;
+
+       if (!check_dcb_flags (priv->priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, error))
+               return FALSE;
+
+       if (!check_uint_array (priv->priority_group_id,
+                              G_N_ELEMENTS (priv->priority_group_id),
+                              priv->priority_group_flags,
+                              7,
+                              15,
+                              FALSE,
+                              NM_SETTING_DCB_PRIORITY_GROUP_ID,
+                              error))
+               return FALSE;
+
+       if (!check_uint_array (priv->priority_group_bandwidth,
+                              G_N_ELEMENTS (priv->priority_group_bandwidth),
+                              priv->priority_group_flags,
+                              100,
+                              0,
+                              TRUE,
+                              NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+                              error))
+               return FALSE;
+
+       /* FIXME: sum bandwidths in each group */
+       if (!check_uint_array (priv->priority_bandwidth,
+                              G_N_ELEMENTS (priv->priority_bandwidth),
+                              priv->priority_group_flags,
+                              100,
+                              0,
+                              FALSE,
+                              NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+                              error))
+               return FALSE;
+
+       if (!check_uint_array (priv->priority_strict,
+                              G_N_ELEMENTS (priv->priority_strict),
+                              priv->priority_group_flags,
+                              1,
+                              0,
+                              FALSE,
+                              NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+                              error))
+               return FALSE;
+
+       if (!check_uint_array (priv->priority_traffic_class,
+                              G_N_ELEMENTS (priv->priority_traffic_class),
+                              priv->priority_group_flags,
+                              7,
+                              0,
+                              FALSE,
+                              NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+                              error))
+               return FALSE;
+
+       return TRUE;
+}
+
+/******************************************************************/
+
+static void
+nm_setting_dcb_init (NMSettingDcb *setting)
+{
+       g_object_set (setting, NM_SETTING_NAME, NM_SETTING_DCB_SETTING_NAME, NULL);
+}
+
+static inline void
+set_uint_array (const GValue *v, uint *a, size_t len)
+{
+       GArray *src = g_value_get_boxed (v);
+       const guint total_len = len * sizeof (a[0]);
+
+       memset (a, 0, total_len);
+       if (src) {
+               g_return_if_fail (g_array_get_element_size (src) == sizeof (a[0]));
+               g_return_if_fail (src->len == len);
+               memcpy (a, src->data, total_len);
+       }
+}
+#define SET_UINT_ARRAY(v, a)  set_uint_array (v, a, G_N_ELEMENTS (a))
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+       NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (object);
+
+       switch (prop_id) {
+       case PROP_APP_FCOE_FLAGS:
+               priv->app_fcoe_flags = g_value_get_uint (value);
+               break;
+       case PROP_APP_FCOE_PRIORITY:
+               priv->app_fcoe_priority = g_value_get_int (value);
+               break;
+       case PROP_APP_FCOE_MODE:
+               priv->app_fcoe_mode = g_value_dup_string (value);
+               break;
+       case PROP_APP_ISCSI_FLAGS:
+               priv->app_iscsi_flags = g_value_get_uint (value);
+               break;
+       case PROP_APP_ISCSI_PRIORITY:
+               priv->app_iscsi_priority = g_value_get_int (value);
+               break;
+       case PROP_APP_FIP_FLAGS:
+               priv->app_fip_flags = g_value_get_uint (value);
+               break;
+       case PROP_APP_FIP_PRIORITY:
+               priv->app_fip_priority = g_value_get_int (value);
+               break;
+       case PROP_PFC_FLAGS:
+               priv->pfc_flags = g_value_get_uint (value);
+               break;
+       case PROP_PFC:
+               SET_UINT_ARRAY (value, priv->pfc);
+               break;
+       case PROP_PRIORITY_GROUP_FLAGS:
+               priv->priority_group_flags = g_value_get_uint (value);
+               break;
+       case PROP_PRIORITY_GROUP_ID:
+               SET_UINT_ARRAY (value, priv->priority_group_id);
+               break;
+       case PROP_PRIORITY_GROUP_BANDWIDTH:
+               SET_UINT_ARRAY (value, priv->priority_group_bandwidth);
+               break;
+       case PROP_PRIORITY_BANDWIDTH:
+               SET_UINT_ARRAY (value, priv->priority_bandwidth);
+               break;
+       case PROP_PRIORITY_STRICT:
+               SET_UINT_ARRAY (value, priv->priority_strict);
+               break;
+       case PROP_PRIORITY_TRAFFIC_CLASS:
+               SET_UINT_ARRAY (value, priv->priority_traffic_class);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+#define TAKE_UINT_ARRAY(v, a) \
+{ \
+       guint len = G_N_ELEMENTS (a); \
+       GArray *dst = g_array_sized_new (FALSE, TRUE, sizeof (guint), len); \
+       g_array_append_vals (dst, (a), len); \
+       g_value_take_boxed (v, dst); \
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+       NMSettingDcb *setting = NM_SETTING_DCB (object);
+       NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+       switch (prop_id) {
+       case PROP_APP_FCOE_FLAGS:
+               g_value_set_uint (value, priv->app_fcoe_flags);
+               break;
+       case PROP_APP_FCOE_PRIORITY:
+               g_value_set_int (value, priv->app_fcoe_priority);
+               break;
+       case PROP_APP_FCOE_MODE:
+               g_value_set_string (value, priv->app_fcoe_mode);
+               break;
+       case PROP_APP_ISCSI_FLAGS:
+               g_value_set_uint (value, priv->app_iscsi_flags);
+               break;
+       case PROP_APP_ISCSI_PRIORITY:
+               g_value_set_int (value, priv->app_iscsi_priority);
+               break;
+       case PROP_APP_FIP_FLAGS:
+               g_value_set_uint (value, priv->app_fip_flags);
+               break;
+       case PROP_APP_FIP_PRIORITY:
+               g_value_set_int (value, priv->app_fip_priority);
+               break;
+       case PROP_PFC_FLAGS:
+               g_value_set_uint (value, priv->pfc_flags);
+               break;
+       case PROP_PFC:
+               TAKE_UINT_ARRAY (value, priv->pfc);
+               break;
+       case PROP_PRIORITY_GROUP_FLAGS:
+               g_value_set_uint (value, priv->priority_group_flags);
+               break;
+       case PROP_PRIORITY_GROUP_ID:
+               TAKE_UINT_ARRAY (value, priv->priority_group_id);
+               break;
+       case PROP_PRIORITY_GROUP_BANDWIDTH:
+               TAKE_UINT_ARRAY (value, priv->priority_group_bandwidth);
+               break;
+       case PROP_PRIORITY_BANDWIDTH:
+               TAKE_UINT_ARRAY (value, priv->priority_bandwidth);
+               break;
+       case PROP_PRIORITY_STRICT:
+               TAKE_UINT_ARRAY (value, priv->priority_strict);
+               break;
+       case PROP_PRIORITY_TRAFFIC_CLASS:
+               TAKE_UINT_ARRAY (value, priv->priority_traffic_class);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+nm_setting_dcb_class_init (NMSettingDcbClass *setting_class)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+       NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+       g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate));
+
+       /* virtual methods */
+       object_class->set_property = set_property;
+       object_class->get_property = get_property;
+       parent_class->verify       = verify;
+
+       /* Properties */
+       /**
+        * NMSettingDcb:app-fcoe-flags:
+        *
+        * Specifies the %NMSettingDcbFlags for the DCB FCoE application.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_FCOE_FLAGS,
+                g_param_spec_uint (NM_SETTING_DCB_APP_FCOE_FLAGS,
+                                   "App FCoE Flags",
+                                   "Specifies the flags for the DCB FCoE application. "
+                                   "Flags may be any combination of 0x1 (enable), 0x2 "
+                                   "(advertise), and 0x4 (willing).",
+                                   0, DCB_FLAGS_ALL, 0,
+                                   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-fcoe-priority:
+        *
+        * The highest User Priority (0 - 7) which FCoE frames should use, or -1 for
+        * default priority.  Only used when #NMSettingDcb:app-fcoe-flags includes
+        * %NM_SETTING_DCB_FLAG_ENABLE.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_FCOE_PRIORITY,
+                g_param_spec_int (NM_SETTING_DCB_APP_FCOE_PRIORITY,
+                                  "App FCoE Priority",
+                                  "The highest User Priority (0 - 7) which FCoE "
+                                  "frames should use, or -1 for default priority. Only "
+                                  "used when the 'app-fcoe-flags' property includes "
+                                  "the 'enabled' flag.",
+                                  -1, 7, -1,
+                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-fcoe-mode:
+        *
+        * The FCoE controller mode; either %NM_SETTING_DCB_FCOE_MODE_FABRIC (default)
+        * or %NM_SETTING_DCB_FCOE_MODE_VN2VN.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_FCOE_MODE,
+                g_param_spec_string (NM_SETTING_DCB_APP_FCOE_MODE,
+                                     "App FCoE Mode",
+                                     "The FCoe controller mode; either 'fabric' (default) "
+                                     "or 'vn2vn'.",
+                                     NM_SETTING_DCB_FCOE_MODE_FABRIC,
+                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-iscsi-flags:
+        *
+        * Specifies the %NMSettingDcbFlags for the DCB iSCSI application.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_ISCSI_FLAGS,
+                g_param_spec_uint (NM_SETTING_DCB_APP_ISCSI_FLAGS,
+                                   "App iSCSI Flags",
+                                   "Specifies the flags for the DCB iSCSI application. "
+                                   "Flags may be any combination of 0x1 (enable), 0x2 "
+                                   "(advertise), and 0x4 (willing).",
+                                   0, DCB_FLAGS_ALL, 0,
+                                   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-iscsi-priority:
+        *
+        * The highest User Priority (0 - 7) which iSCSI frames should use.  Only
+        * used when #NMSettingDcb:app-iscsi-flags includes %NM_SETTING_DCB_FLAG_ENABLE.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_ISCSI_PRIORITY,
+                g_param_spec_int (NM_SETTING_DCB_APP_ISCSI_PRIORITY,
+                                  "App iSCSI Priority",
+                                  "The highest User Priority (0 - 7) which iSCSI "
+                                  "frames should use, or -1 for default priority. Only "
+                                  "used when the 'app-iscsi-flags' property includes "
+                                  "the 'enabled' flag.",
+                                  -1, 7, -1,
+                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-fip-flags:
+        *
+        * Specifies the %NMSettingDcbFlags for the DCB FIP application.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_FIP_FLAGS,
+                g_param_spec_uint (NM_SETTING_DCB_APP_FIP_FLAGS,
+                                   "App FIP Flags",
+                                   "Specifies the flags for the DCB FIP application. "
+                                   "Flags may be any combination of 0x1 (enable), 0x2 "
+                                   "(advertise), and 0x4 (willing).",
+                                   0, DCB_FLAGS_ALL, 0,
+                                   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:app-fip-priority:
+        *
+        * The highest User Priority (0 - 7) which FIP frames should use.  Only
+        * used when #NMSettingDcb:app-fip-flags includes %NM_SETTING_DCB_FLAG_ENABLE.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_APP_FIP_PRIORITY,
+                g_param_spec_int (NM_SETTING_DCB_APP_FIP_PRIORITY,
+                                  "App FIP Priority",
+                                  "The highest User Priority (0 - 7) which FIP "
+                                  "frames should use, or -1 for default priority. Only "
+                                  "used when the 'app-fip-flags' property includes "
+                                  "the 'enabled' flag.",
+                                  -1, 7, -1,
+                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-flow-control-flags:
+        *
+        * Specifies the %NMSettingDcbFlags for DCB Priority Flow Control (PFC).
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PFC_FLAGS,
+                g_param_spec_uint (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS,
+                                   "Priority Flow Control Flags",
+                                   "Specifies the flags for DCB Priority Flow Control. "
+                                   "Flags may be any combination of 0x1 (enable), 0x2 "
+                                   "(advertise), and 0x4 (willing).",
+                                   0, DCB_FLAGS_ALL, 0,
+                                   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-flow-control:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * User Priority (0 - 7) and the value indicates whether or not the
+        * corresponding priority should transmit priority pause.  Allowed values
+        * are 0 (do not transmit pause) and 1 (transmit pause).
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PFC,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL,
+                                            "Priority Flow Control",
+                                            "An array of 8 uint values, where the array index "
+                                            "corresponds to the User Priority (0 - 7) and the "
+                                            "value indicates whether or not the corresponding "
+                                            "priority should transmit priority pause.  Allowed "
+                                            "values are 0 (do not transmit pause) and 1 "
+                                            "(transmit pause).",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-group-flags:
+        *
+        * Specifies the %NMSettingDcbFlags for DCB Priority Groups.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_GROUP_FLAGS,
+                g_param_spec_uint (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS,
+                                   "Priority Group Flags",
+                                   "Specifies the flags for DCB Priority Groups. "
+                                   "Flags may be any combination of 0x1 (enable), 0x2 "
+                                   "(advertise), and 0x4 (willing).",
+                                   0, DCB_FLAGS_ALL, 0,
+                                   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-group-id:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * User Priority (0 - 7) and the value indicates the Priority Group ID.
+        * Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted
+        * group.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_GROUP_ID,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_GROUP_ID,
+                                            "Priority Group ID",
+                                            "An array of 8 uint values, where the array "
+                                            "index corresponds to the User Priority (0 - 7) "
+                                            "and the value indicates the Priority Group ID. "
+                                            "Allowed Priority Group ID values are 0 - 7 or "
+                                            "15 for the unrestricted group.",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-group-bandwidth:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * Priority Group ID (0 - 7) and the value indicates the percentage of
+        * link bandwidth allocated to that group.  Allowed values are 0 - 100,
+        * and the sum of all values must total 100 percent.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_GROUP_BANDWIDTH,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+                                            "Priority Group Bandwidth",
+                                            "An array of 8 uint values, where the array index "
+                                            "corresponds to the Priority Group ID (0 - 7) and "
+                                            "the value indicates the percentage of link bandwidth "
+                                            "allocated to that group.  Allowed values are 0 - 100, "
+                                            "and the sum of all values must total 100 percent.",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-bandwidth:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * User Priority (0 - 7) and the value indicates the percentage of bandwidth
+        * of the priority's assigned group that the priority may use.  The sum of
+        * all percentages for priorities which belong to the same group must total
+        * 100 percent.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_BANDWIDTH,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+                                            "Priority Bandwidth",
+                                            "An array of 8 uint values, where the array index "
+                                            "corresponds to the User Priority (0 - 7) and the "
+                                            "value indicates the percentage of bandwidth of "
+                                            "the priority's assigned group that the priority may "
+                                            "use.  The sum of all percentages for priorities which "
+                                            "belong to the same group must total 100 percent.",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-strict:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * User Priority (0 - 7) and the value indicates whether or not the
+        * priority may use all of the bandwidth allocated to its assigned group.
+        * Allowed values are 0 (the priority may not utilize all bandwidth) or
+        * 1 (the priority may utilize all bandwidth).
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_STRICT,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+                                            "Priority Strict",
+                                            "An array of 8 uint values, where the array index "
+                                            "corresponds to the User Priority (0 - 7) and the "
+                                            "value indicates whether or not the priority may "
+                                            "use all of the bandwidth allocated to its assigned "
+                                            "group. Allowed values are 0 (the priority may not "
+                                            "utilize all bandwidth) or 1 (the priority may "
+                                            "utilize all bandwidth).",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+       /**
+        * NMSettingDcb:priority-traffic-class:
+        *
+        * An array of 8 uint values, where the array index corresponds to the
+        * User Priority (0 - 7) and the value indicates the traffic class (0 - 7)
+        * to which the priority is mapped.
+        *
+        * Since: 0.9.10
+        **/
+       g_object_class_install_property
+               (object_class, PROP_PRIORITY_TRAFFIC_CLASS,
+                _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+                                            "Priority Traffic Class",
+                                            "An array of 8 uint values, where the array index "
+                                            "corresponds to the User Priority (0 - 7) and the "
+                                            "value indicates the traffic class (0 - 7) to which "
+                                            "the priority is mapped.",
+                                            DBUS_TYPE_G_UINT_ARRAY,
+                                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+}
+
diff --git a/libnm-util/nm-setting-dcb.h b/libnm-util/nm-setting-dcb.h
new file mode 100644 (file)
index 0000000..a8523d2
--- /dev/null
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTING_DCB_H
+#define NM_SETTING_DCB_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_DCB            (nm_setting_dcb_get_type ())
+#define NM_SETTING_DCB(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_DCB, NMSettingDcb))
+#define NM_SETTING_DCB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+#define NM_IS_SETTING_DCB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_DCB))
+#define NM_IS_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_DCB))
+#define NM_SETTING_DCB_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+
+#define NM_SETTING_DCB_SETTING_NAME "dcb"
+
+/**
+ * NMSettingDcbError:
+ * @NM_SETTING_DCB_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_DCB_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_DCB_ERROR_MISSING_PROPERTY: the property was missing and is
+ * required
+ */
+typedef enum {
+       NM_SETTING_DCB_ERROR_UNKNOWN = 0,      /*< nick=UnknownError >*/
+       NM_SETTING_DCB_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+       NM_SETTING_DCB_ERROR_MISSING_PROPERTY  /*< nick=MissingProperty >*/
+} NMSettingDcbError;
+
+#define NM_SETTING_DCB_ERROR nm_setting_dcb_error_quark ()
+GQuark nm_setting_dcb_error_quark (void);
+
+/**
+ * NMSettingDcbFlags:
+ * @NM_SETTING_DCB_FLAG_NONE: no flag
+ * @NM_SETTING_DCB_FLAG_ENABLE: the feature is enabled
+ * @NM_SETTING_DCB_FLAG_ADVERTISE: the feature is advertised
+ * @NM_SETTING_DCB_FLAG_WILLING: the feature is willing to change based on
+ * peer configuration advertisements
+ *
+ * DCB feature flags.
+ *
+ * Since: 0.9.10
+ **/
+typedef enum {
+       NM_SETTING_DCB_FLAG_NONE      = 0x00000000,
+       NM_SETTING_DCB_FLAG_ENABLE    = 0x00000001,
+       NM_SETTING_DCB_FLAG_ADVERTISE = 0x00000002,
+       NM_SETTING_DCB_FLAG_WILLING   = 0x00000004
+} NMSettingDcbFlags;
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_FABRIC:
+ *
+ * Indicates that the FCoE controller should use "fabric" mode (default)
+ *
+ * Since: 0.9.10
+ */
+#define NM_SETTING_DCB_FCOE_MODE_FABRIC  "fabric"
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_VN2VN:
+ *
+ * Indicates that the FCoE controller should use "VN2VN" mode.
+ *
+ * Since: 0.9.10
+ */
+#define NM_SETTING_DCB_FCOE_MODE_VN2VN   "vn2vn"
+
+
+/* Properties */
+#define NM_SETTING_DCB_APP_FCOE_FLAGS         "app-fcoe-flags"
+#define NM_SETTING_DCB_APP_FCOE_PRIORITY      "app-fcoe-priority"
+#define NM_SETTING_DCB_APP_FCOE_MODE          "app-fcoe-mode"
+
+#define NM_SETTING_DCB_APP_ISCSI_FLAGS        "app-iscsi-flags"
+#define NM_SETTING_DCB_APP_ISCSI_PRIORITY     "app-iscsi-priority"
+
+#define NM_SETTING_DCB_APP_FIP_FLAGS          "app-fip-flags"
+#define NM_SETTING_DCB_APP_FIP_PRIORITY       "app-fip-priority"
+
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS  "priority-flow-control-flags"
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL        "priority-flow-control"
+
+#define NM_SETTING_DCB_PRIORITY_GROUP_FLAGS      "priority-group-flags"
+#define NM_SETTING_DCB_PRIORITY_GROUP_ID         "priority-group-id"
+#define NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH  "priority-group-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_BANDWIDTH        "priority-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH "priority-strict-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS    "priority-traffic-class"
+
+
+typedef struct {
+       NMSetting parent;
+} NMSettingDcb;
+
+typedef struct {
+       NMSettingClass parent;
+
+       /* Padding for future expansion */
+       void (*_reserved1) (void);
+       void (*_reserved2) (void);
+       void (*_reserved3) (void);
+       void (*_reserved4) (void);
+} NMSettingDcbClass;
+
+GType nm_setting_dcb_get_type (void);
+
+NMSetting *       nm_setting_dcb_new                      (void);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags     (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_fcoe_priority  (NMSettingDcb *setting);
+const char *      nm_setting_dcb_get_app_fcoe_mode      (NMSettingDcb *setting);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_iscsi_flags    (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags      (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_fip_priority   (NMSettingDcb *setting);
+
+/* Priority Flow Control */
+NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags    (NMSettingDcb *setting);
+gboolean          nm_setting_dcb_get_priority_flow_control          (NMSettingDcb *setting,
+                                                                     guint user_priority);
+void              nm_setting_dcb_set_priority_flow_control          (NMSettingDcb *setting,
+                                                                     guint user_priority,
+                                                                     gboolean enabled);
+
+/* Priority Groups */
+NMSettingDcbFlags nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting);
+
+guint    nm_setting_dcb_get_priority_group_id         (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_group_id         (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint group_id);
+
+guint    nm_setting_dcb_get_priority_group_bandwidth  (NMSettingDcb *setting,
+                                                       guint group_id);
+void     nm_setting_dcb_set_priority_group_bandwidth  (NMSettingDcb *setting,
+                                                       guint group_id,
+                                                       guint bandwidth_percent);
+
+guint    nm_setting_dcb_get_priority_bandwidth        (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_bandwidth        (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint bandwidth_percent);
+
+gboolean nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       gboolean strict);
+
+guint    nm_setting_dcb_get_priority_traffic_class    (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_traffic_class    (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint traffic_class);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_DCB_H */
index 45690c4..b5bbacc 100644 (file)
@@ -16,7 +16,8 @@ noinst_PROGRAMS = \
        test-crypto \
        test-secrets \
        test-general \
-       test-setting-8021x
+       test-setting-8021x \
+       test-setting-dcb
 
 test_settings_defaults_SOURCES = \
        test-settings-defaults.c
@@ -58,10 +59,19 @@ test_setting_8021x_LDADD = \
        $(GLIB_LIBS) \
        $(DBUS_LIBS)
 
-check-local: test-settings-defaults test-crypto test-secrets
+test_setting_dcb_SOURCES = \
+       test-setting-dcb.c
+
+test_setting_dcb_LDADD = \
+       $(top_builddir)/libnm-util/libnm-util.la \
+       $(GLIB_LIBS) \
+       $(DBUS_LIBS)
+
+check-local: test-settings-defaults test-crypto test-secrets test-setting-8021x test-setting-dcb
        $(abs_builddir)/test-settings-defaults
        $(abs_builddir)/test-secrets
        $(abs_builddir)/test-general
+       $(abs_builddir)/test-setting-dcb
 
 # Private key and CA certificate in the same file (PEM)
        $(abs_builddir)/test-setting-8021x $(srcdir)/certs/test_key_and_cert.pem "test"
diff --git a/libnm-util/tests/test-setting-dcb.c b/libnm-util/tests/test-setting-dcb.c
new file mode 100644 (file)
index 0000000..cefdeed
--- /dev/null
@@ -0,0 +1,308 @@
+/* -*- 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, 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <nm-utils.h>
+#include "nm-setting-dcb.h"
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+                       NM_SETTING_DCB_FLAG_ADVERTISE | \
+                       NM_SETTING_DCB_FLAG_WILLING)
+
+static void
+test_dcb_flags_valid (void)
+{
+       NMSettingDcb *s_dcb;
+       GError *error = NULL;
+       gboolean success;
+       guint i;
+
+       s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+       g_assert (s_dcb);
+
+       g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, 0);
+       g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, 0);
+       g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, 0);
+       g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, 0);
+       g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, 0);
+
+       g_object_set (G_OBJECT (s_dcb),
+                     NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_FLAGS_ALL,
+                     NM_SETTING_DCB_APP_ISCSI_FLAGS, DCB_FLAGS_ALL,
+                     NM_SETTING_DCB_APP_FIP_FLAGS, DCB_FLAGS_ALL,
+                     NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, DCB_FLAGS_ALL,
+                     NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, DCB_FLAGS_ALL,
+                     NULL);
+       /* Priority Group Bandwidth must total 100% */
+       for (i = 0; i < 7; i++)
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 12);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, DCB_FLAGS_ALL);
+       g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, DCB_FLAGS_ALL);
+       g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, DCB_FLAGS_ALL);
+       g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, DCB_FLAGS_ALL);
+       g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, DCB_FLAGS_ALL);
+}
+
+#define TEST_FLAG(p, f, v) \
+{ \
+       /* GObject property min/max should ensure the property does not get set to \
+        * the invalid value, so we ensure the value we just tried to set is 0 and \
+        * that verify is successful since the property never got set. \
+        */ \
+       g_object_set (G_OBJECT (s_dcb), p, v, NULL); \
+       g_assert_cmpint (f (s_dcb), ==, 0); \
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+       g_assert_no_error (error); \
+       g_assert (success); \
+}
+
+static void
+test_dcb_flags_invalid (void)
+{
+       NMSettingDcb *s_dcb;
+       GError *error = NULL;
+       gboolean success;
+
+       s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+       g_assert (s_dcb);
+
+       TEST_FLAG (NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523);
+       TEST_FLAG (NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF);
+       TEST_FLAG (NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111);
+       TEST_FLAG (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, nm_setting_dcb_get_priority_flow_control_flags, G_MAXUINT32);
+       TEST_FLAG (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, nm_setting_dcb_get_priority_group_flags,
+                  (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + 1);
+}
+
+#define TEST_APP_PRIORITY(lcprop, ucprop, v) \
+{ \
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+ \
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \
+       g_assert_cmpint (nm_setting_dcb_get_app_##lcprop##_priority (s_dcb), ==, v); \
+ \
+       /* Assert that the setting is invalid while the app is disabled unless v is default */ \
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+       if (v >= 0) { \
+               g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY); \
+               g_assert (success == FALSE); \
+       } else { \
+               g_assert_no_error (error); \
+               g_assert (success); \
+       } \
+       g_clear_error (&error); \
+ \
+       /* Set the enable flag and re-verify, this time it should be valid */ \
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+       g_assert_no_error (error); \
+       g_assert (success); \
+ \
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \
+}
+
+static void
+test_dcb_app_priorities (void)
+{
+       NMSettingDcb *s_dcb;
+       GError *error = NULL;
+       gboolean success;
+
+       s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+       g_assert (s_dcb);
+
+       /* Defaults */
+       g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, -1);
+       g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, -1);
+       g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, -1);
+
+       TEST_APP_PRIORITY (fcoe, FCOE, 6);
+       TEST_APP_PRIORITY (iscsi, ISCSI, 5);
+       TEST_APP_PRIORITY (fip, FIP, 4);
+
+       TEST_APP_PRIORITY (fcoe, FCOE, -1);
+       TEST_APP_PRIORITY (iscsi, ISCSI, -1);
+       TEST_APP_PRIORITY (fip, FIP, -1);
+}
+
+#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \
+{ \
+       /* Assert that setting the value gets the same value back out */ \
+       nm_setting_dcb_set_priority_##fn (s_dcb, id, val); \
+       g_assert_cmpint (nm_setting_dcb_get_priority_##fn (s_dcb, id), ==, val); \
+ \
+       if (verify) { \
+               if (val != 0) { \
+                       /* Assert that verify fails because the flags do not include 'enabled' \
+                        * and a value has been set. \
+                        */ \
+                       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+                       g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY); \
+                       g_assert (success == FALSE); \
+                       g_clear_error (&error); \
+               } \
+ \
+               /* Assert that adding the 'enabled' flag verifies the setting */ \
+               g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+               success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+               g_assert_no_error (error); \
+               g_assert (success); \
+       } \
+ \
+       /* Reset everything */ \
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+       nm_setting_dcb_set_priority_##fn (s_dcb, id, 0); \
+}
+
+/* If Priority Groups are enabled, PG bandwidth must equal 100% */
+#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \
+{ \
+       guint x; \
+       for (x = 0; x < 7; x++) \
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, x, 12); \
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16); \
+}
+
+static void
+test_dcb_priorities_valid (void)
+{
+       NMSettingDcb *s_dcb;
+       GError *error = NULL;
+       gboolean success;
+       guint i;
+
+       s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+       g_assert (s_dcb);
+
+       for (i = 0; i < 8; i++)
+               TEST_PRIORITY_VALID (flow_control, i, TRUE, FLOW_CONTROL, TRUE);
+
+       SET_VALID_PRIORITY_GROUP_BANDWIDTH
+       for (i = 0; i < 8; i++) {
+               TEST_PRIORITY_VALID (group_id, i, i, GROUP, TRUE);
+               TEST_PRIORITY_VALID (group_id, i, 7 - i, GROUP, TRUE);
+       }
+
+       /* Clear PG bandwidth from earlier tests */
+       for (i = 0; i < 8; i++)
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 0);
+
+       /* Priority Group Bandwidth must add up to 100% if enabled, which requires
+        * some dancing for verifying individual values here.
+        */
+       for (i = 0; i < 8; i++) {
+               guint other = 7 - (i % 8);
+
+               /* Set another priority group to the remaining bandwidth */
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - i);
+               TEST_PRIORITY_VALID (group_bandwidth, i, i, GROUP, TRUE);
+
+               /* Set another priority group to the remaining bandwidth */
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - (7 - i));
+               TEST_PRIORITY_VALID (group_bandwidth, i, 7 - i, GROUP, TRUE);
+
+               /* Clear remaining bandwidth */
+               nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 0);
+       }
+
+       SET_VALID_PRIORITY_GROUP_BANDWIDTH
+       for (i = 0; i < 8; i++) {
+               TEST_PRIORITY_VALID (bandwidth, i, i, GROUP, TRUE);
+               TEST_PRIORITY_VALID (bandwidth, i, 7 - i, GROUP, TRUE);
+       }
+
+       SET_VALID_PRIORITY_GROUP_BANDWIDTH
+       for (i = 0; i < 8; i++)
+               TEST_PRIORITY_VALID (strict_bandwidth, i, TRUE, GROUP, TRUE);
+
+       SET_VALID_PRIORITY_GROUP_BANDWIDTH
+       for (i = 0; i < 8; i++) {
+               TEST_PRIORITY_VALID (traffic_class, i, i, GROUP, TRUE);
+               TEST_PRIORITY_VALID (traffic_class, i, 7 - i, GROUP, TRUE);
+       }
+}
+
+static void
+test_dcb_bandwidth_sums (void)
+{
+       NMSettingDcb *s_dcb;
+       GError *error = NULL;
+       gboolean success;
+
+       s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+       g_assert (s_dcb);
+
+       /* Assert that setting the value gets the same value back out */
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 0, 9);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 1, 10);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 2, 11);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 3, 12);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 13);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 5, 14);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 6, 15);
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+       /* Assert verify success when sums total 100% */
+       g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL);
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       /* Assert verify fails when sums do not total 100% */
+       nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 20);
+       success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+       g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY);
+       g_assert (success == FALSE);
+       g_clear_error (&error);
+}
+
+#define TPATH "/libnm-util/settings/dcb/"
+
+int main (int argc, char **argv)
+{
+       GError *error = NULL;
+       gboolean success;
+
+       g_test_init (&argc, &argv, NULL);
+       g_type_init ();
+
+       success = nm_utils_init (&error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
+
+       g_test_add_func (TPATH "flags-valid", test_dcb_flags_valid);
+       g_test_add_func (TPATH "flags-invalid", test_dcb_flags_invalid);
+       g_test_add_func (TPATH "app-priorities", test_dcb_app_priorities);
+       g_test_add_func (TPATH "priorities", test_dcb_priorities_valid);
+       g_test_add_func (TPATH "bandwidth-sums", test_dcb_bandwidth_sums);
+
+       return g_test_run ();
+}
+
index e953666..3be5735 100644 (file)
@@ -19,6 +19,7 @@ libnm-util/nm-setting-bridge-port.c
 libnm-util/nm-setting-bridge.c
 libnm-util/nm-setting-cdma.c
 libnm-util/nm-setting-connection.c
+libnm-util/nm-setting-dcb.c
 libnm-util/nm-setting-gsm.c
 libnm-util/nm-setting-infiniband.c
 libnm-util/nm-setting-ip4-config.c