diff options
Diffstat (limited to 'libnm-core/nm-setting-sriov.c')
| -rw-r--r-- | libnm-core/nm-setting-sriov.c | 1357 |
1 files changed, 0 insertions, 1357 deletions
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c deleted file mode 100644 index 45b3a1d2..00000000 --- a/libnm-core/nm-setting-sriov.c +++ /dev/null @@ -1,1357 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * 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. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/>. - * - * Copyright 2018 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-setting-sriov.h" -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-sriov - * @short_description: Describes SR-IOV connection properties - * @include: nm-setting-sriov.h - **/ - -/** - * NMSettingSriov: - * - * SR-IOV settings. - * - * Since: 1.14 - */ -struct _NMSettingSriov { - NMSetting parent; - GPtrArray *vfs; - guint total_vfs; - NMTernary autoprobe_drivers; -}; - -struct _NMSettingSriovClass { - NMSettingClass parent; -}; - -G_DEFINE_TYPE (NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING) - -enum { - PROP_0, - PROP_TOTAL_VFS, - PROP_VFS, - PROP_AUTOPROBE_DRIVERS, - - LAST_PROP -}; - -/*****************************************************************************/ - -G_DEFINE_BOXED_TYPE (NMSriovVF, nm_sriov_vf, nm_sriov_vf_dup, nm_sriov_vf_unref) - -struct _NMSriovVF { - guint refcount; - guint index; - GHashTable *attributes; - GHashTable *vlans; - guint *vlan_ids; -}; - -typedef struct { - guint id; - guint qos; - NMSriovVFVlanProtocol protocol; -} VFVlan; - -static guint -_vf_vlan_hash (gconstpointer ptr) -{ - return nm_hash_val (1348254767u, *((guint *) ptr)); -} - -static gboolean -_vf_vlan_equal (gconstpointer a, gconstpointer b) -{ - return *((guint *) a) == *((guint *) b); -} - -static GHashTable * -_vf_vlan_create_hash (void) -{ - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (VFVlan, id) == 0); - return g_hash_table_new_full (_vf_vlan_hash, - _vf_vlan_equal, - NULL, - nm_g_slice_free_fcn (VFVlan)); -} - -/** - * nm_srio_vf_new: - * @index: the VF index - * - * Creates a new #NMSriovVF object. - * - * Returns: (transfer full): the new #NMSriovVF object. - * - * Since: 1.14 - **/ -NMSriovVF * -nm_sriov_vf_new (guint index) -{ - NMSriovVF *vf; - - vf = g_slice_new0 (NMSriovVF); - vf->refcount = 1; - vf->index = index; - vf->attributes = g_hash_table_new_full (nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - return vf; -} - -/** - * nm_sriov_vf_ref: - * @vf: the #NMSriovVF - * - * Increases the reference count of the object. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_ref (NMSriovVF *vf) -{ - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - - vf->refcount++; -} - -/** - * nm_sriov_vf_unref: - * @vf: the #NMSriovVF - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_unref (NMSriovVF *vf) -{ - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - - vf->refcount--; - if (vf->refcount == 0) { - g_hash_table_unref (vf->attributes); - if (vf->vlans) - g_hash_table_unref (vf->vlans); - g_free (vf->vlan_ids); - g_slice_free (NMSriovVF, vf); - } -} - -/** - * nm_sriov_vf_equal: - * @vf: the #NMSriovVF - * @other: the #NMSriovVF to compare @vf to. - * - * Determines if two #NMSriovVF objects have the same index, - * attributes and VLANs. - * - * Returns: %TRUE if the objects contain the same values, %FALSE - * if they do not. - * - * Since: 1.14 - **/ -gboolean -nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other) -{ - GHashTableIter iter; - const char *key; - GVariant *value, *value2; - VFVlan *vlan, *vlan2; - guint n_vlans; - - g_return_val_if_fail (vf, FALSE); - g_return_val_if_fail (vf->refcount > 0, FALSE); - g_return_val_if_fail (other, FALSE); - g_return_val_if_fail (other->refcount > 0, FALSE); - - if (vf == other) - return TRUE; - - if (vf->index != other->index) - return FALSE; - - if (g_hash_table_size (vf->attributes) != g_hash_table_size (other->attributes)) - return FALSE; - g_hash_table_iter_init (&iter, vf->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup (other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal (value, value2)) - return FALSE; - } - - n_vlans = vf->vlans ? g_hash_table_size (vf->vlans) : 0u; - if (n_vlans != (other->vlans ? g_hash_table_size (other->vlans) : 0u)) - return FALSE; - if (n_vlans > 0) { - g_hash_table_iter_init (&iter, vf->vlans); - while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) { - vlan2 = g_hash_table_lookup (other->vlans, vlan); - if (!vlan2) - return FALSE; - if ( vlan->qos != vlan2->qos - || vlan->protocol != vlan2->protocol) - return FALSE; - } - } - - return TRUE; -} - -static void -vf_add_vlan (NMSriovVF *vf, - guint vlan_id, - guint qos, - NMSriovVFVlanProtocol protocol) -{ - VFVlan *vlan; - - vlan = g_slice_new0 (VFVlan); - vlan->id = vlan_id; - vlan->qos = qos; - vlan->protocol = protocol; - - if (!vf->vlans) - vf->vlans = _vf_vlan_create_hash (); - - g_hash_table_add (vf->vlans, vlan); - g_clear_pointer (&vf->vlan_ids, g_free); -} - -/** - * nm_sriov_vf_dup: - * @vf: the #NMSriovVF - * - * Creates a copy of @vf. - * - * Returns: (transfer full): a copy of @vf - * - * Since: 1.14 - **/ -NMSriovVF * -nm_sriov_vf_dup (const NMSriovVF *vf) -{ - NMSriovVF *copy; - GHashTableIter iter; - const char *name; - GVariant *variant; - VFVlan *vlan; - - g_return_val_if_fail (vf, NULL); - g_return_val_if_fail (vf->refcount > 0, NULL); - - copy = nm_sriov_vf_new (vf->index); - - g_hash_table_iter_init (&iter, vf->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) - nm_sriov_vf_set_attribute (copy, name, variant); - - if (vf->vlans) { - g_hash_table_iter_init (&iter, vf->vlans); - while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) - vf_add_vlan (copy, vlan->id, vlan->qos, vlan->protocol); - } - - return copy; -} - -/** - * nm_sriov_vf_get_index: - * @vf: the #NMSriovVF - * - * Gets the index property of this VF object. - * - * Returns: the VF index - * - * Since: 1.14 - **/ -guint -nm_sriov_vf_get_index (const NMSriovVF *vf) -{ - g_return_val_if_fail (vf, 0); - g_return_val_if_fail (vf->refcount > 0, 0); - - return vf->index; -} - -/** - * nm_sriov_vf_set_attribute: - * @vf: the #NMSriovVF - * @name: the name of a route attribute - * @value: (transfer none) (allow-none): the value - * - * Sets the named attribute on @vf to the given value. - * - * Since: 1.14 - **/ -void -nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value) -{ - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - g_return_if_fail (name && *name != '\0'); - g_return_if_fail (!nm_streq (name, "index")); - - if (value) { - g_hash_table_insert (vf->attributes, - g_strdup (name), - g_variant_ref_sink (value)); - } else - g_hash_table_remove (vf->attributes, name); -} - -/** - * nm_sriov_vf_get_attribute_names: - * @vf: the #NMSriovVF - * - * Gets an array of attribute names defined on @vf. - * - * Returns: (transfer container): a %NULL-terminated array of attribute names - * - * Since: 1.14 - **/ -const char ** -nm_sriov_vf_get_attribute_names (const NMSriovVF *vf) -{ - g_return_val_if_fail (vf, NULL); - g_return_val_if_fail (vf->refcount > 0, NULL); - - return nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL); -} - -/** - * nm_sriov_vf_get_attribute: - * @vf: the #NMSriovVF - * @name: the name of a VF attribute - * - * Gets the value of the attribute with name @name on @vf - * - * Returns: (transfer none): the value of the attribute with name @name on - * @vf, or %NULL if @vf has no such attribute. - * - * Since: 1.14 - **/ -GVariant * -nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name) -{ - g_return_val_if_fail (vf, NULL); - g_return_val_if_fail (vf->refcount > 0, NULL); - g_return_val_if_fail (name && *name != '\0', NULL); - - return g_hash_table_lookup (vf->attributes, name); -} - -#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \ - &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type } - -const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = { - SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'), - SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, 0), - SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, 0), - SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, 0), - SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, 0), - /* D-Bus only, synthetic attributes */ - SRIOV_ATTR_SPEC_PTR ("vlans", G_VARIANT_TYPE_STRING, 'd'), - NULL, -}; - -/** - * nm_sriov_vf_attribute_validate: - * @name: the attribute name - * @value: the attribute value - * @known: (out): on return, whether the attribute name is a known one - * @error: (allow-none): return location for a #GError, or %NULL - * - * Validates a VF attribute, i.e. checks that the attribute is a known one, - * the value is of the correct type and well-formed. - * - * Returns: %TRUE if the attribute is valid, %FALSE otherwise - * - * Since: 1.14 - */ -gboolean -nm_sriov_vf_attribute_validate (const char *name, - GVariant *value, - gboolean *known, - GError **error) -{ - const NMVariantAttributeSpec *const *iter; - const NMVariantAttributeSpec *spec = NULL; - - g_return_val_if_fail (name, FALSE); - g_return_val_if_fail (value, FALSE); - g_return_val_if_fail (!error || !*error, FALSE); - - for (iter = _nm_sriov_vf_attribute_spec; *iter; iter++) { - if (nm_streq (name, (*iter)->name)) { - spec = *iter; - break; - } - } - - if (!spec || spec->str_type == 'd') { - NM_SET_OUT (known, FALSE); - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unknown attribute")); - return FALSE; - } - - NM_SET_OUT (known, TRUE); - - if (!g_variant_is_of_type (value, spec->type)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid attribute type '%s'"), - g_variant_get_type_string (value)); - return FALSE; - } - - if (spec->type == G_VARIANT_TYPE_STRING) { - const char *string; - - switch (spec->str_type) { - case 'm': /* MAC address */ - string = g_variant_get_string (value, NULL); - if (!nm_utils_hwaddr_valid (string, -1)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("'%s' is not a valid MAC address"), - string); - return FALSE; - } - break; - default: - break; - } - } - - return TRUE; -} - -gboolean -_nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error) -{ - GHashTableIter iter; - const char *name; - GVariant *variant; - GVariant *min, *max; - - g_return_val_if_fail (vf, FALSE); - g_return_val_if_fail (vf->refcount > 0, FALSE); - - g_hash_table_iter_init (&iter, vf->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) { - if (!nm_sriov_vf_attribute_validate (name, variant, NULL, error)) { - g_prefix_error (error, "attribute '%s':", name); - return FALSE; - } - } - - min = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE); - max = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE); - if ( min - && max - && g_variant_get_uint32 (min) > g_variant_get_uint32 (max)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - "min_tx_rate is greater than max_tx_rate"); - return FALSE; - } - - return TRUE; -} - -/** - * nm_sriov_vf_add_vlan: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Adds a VLAN to the VF. - * - * Returns: %TRUE if the VLAN was added; %FALSE if it already existed - * - * Since: 1.14 - **/ -gboolean -nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id) -{ - g_return_val_if_fail (vf, FALSE); - g_return_val_if_fail (vf->refcount > 0, FALSE); - - if ( vf->vlans - && g_hash_table_contains (vf->vlans, &vlan_id)) - return FALSE; - - vf_add_vlan (vf, vlan_id, 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - return TRUE; -} - -/** - * nm_sriov_vf_remove_vlan: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Removes a VLAN from a VF. - * - * Returns: %TRUE if the VLAN was removed, %FALSE if the VLAN @vlan_id - * did not belong to the VF. - * - * Since: 1.14 - */ -gboolean -nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id) -{ - g_return_val_if_fail (vf, FALSE); - g_return_val_if_fail (vf->refcount > 0, FALSE); - - if ( !vf->vlans - || !g_hash_table_remove (vf->vlans, &vlan_id)) - return FALSE; - - g_clear_pointer (&vf->vlan_ids, g_free); - return TRUE; -} - -static int -vlan_id_compare (gconstpointer a, gconstpointer b, gpointer user_data) -{ - guint id_a = *(guint *) a; - guint id_b = *(guint *) b; - - if (id_a < id_b) - return -1; - else if (id_a > id_b) - return 1; - else return 0; -} - -/** - * nm_sriov_vf_get_vlan_ids: - * @vf: the #NMSriovVF - * @length: (out) (allow-none): on return, the number of VLANs configured - * - * Returns the VLANs currently configured on the VF. - * - * Returns: (transfer none): a list of VLAN ids configured on the VF. - * - * Since: 1.14 - */ -const guint * -nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length) -{ - GHashTableIter iter; - VFVlan *vlan; - guint num, i; - - g_return_val_if_fail (vf, NULL); - g_return_val_if_fail (vf->refcount > 0, NULL); - - num = vf->vlans ? g_hash_table_size (vf->vlans) : 0u; - NM_SET_OUT (length, num); - - if (vf->vlan_ids) - return vf->vlan_ids; - if (num == 0) - return NULL; - - /* vf is const, however, vlan_ids is a mutable field caching the - * result ("mutable" in C++ terminology) */ - ((NMSriovVF *) vf)->vlan_ids = g_new0 (guint, num); - - i = 0; - g_hash_table_iter_init (&iter, vf->vlans); - while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) - vf->vlan_ids[i++] = vlan->id; - - nm_assert (num == i); - - g_qsort_with_data (vf->vlan_ids, num, sizeof (guint), vlan_id_compare, NULL); - - return vf->vlan_ids; -} - -/** - * nm_sriov_vf_set_vlan_qos: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * @qos: a QoS (priority) value - * - * Sets a QoS value for the given VLAN. - * - * Since: 1.14 - */ -void -nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos) -{ - VFVlan *vlan; - - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - - if ( !vf->vlans - || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) - g_return_if_reached (); - - vlan->qos = qos; -} - -/** - * nm_sriov_vf_set_vlan_protocol: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * @protocol: the VLAN protocol - * - * Sets the protocol for the given VLAN. - * - * Since: 1.14 - */ -void -nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol) -{ - VFVlan *vlan; - - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - - if ( !vf->vlans - || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) - g_return_if_reached (); - - vlan->protocol = protocol; -} - -/** - * nm_sriov_vf_get_vlan_qos: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Returns the QoS value for the given VLAN. - * - * Returns: the QoS value - * - * Since: 1.14 - */ -guint32 -nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id) -{ - VFVlan *vlan; - - g_return_val_if_fail (vf, 0); - g_return_val_if_fail (vf->refcount > 0, 0); - - if ( !vf->vlans - || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) - g_return_val_if_reached (0); - - return vlan->qos; -} - -/* - * nm_sriov_vf_get_vlan_protocol: - * @vf: the #NMSriovVF - * @vlan_id: the VLAN id - * - * Returns the configured protocol for the given VLAN. - * - * Returns: the configured protocol - * - * Since: 1.14 - */ -NMSriovVFVlanProtocol -nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id) -{ - VFVlan *vlan; - - g_return_val_if_fail (vf, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - g_return_val_if_fail (vf->refcount > 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - if ( !vf->vlans - || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) - g_return_val_if_reached (NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); - - return vlan->protocol; -} - -/*****************************************************************************/ - -/** - * nm_setting_sriov_new: - * - * Creates a new #NMSettingSriov object with default values. - * - * Returns: (transfer full): the new empty #NMSettingSriov object - * - * Since: 1.14 - **/ -NMSetting * -nm_setting_sriov_new (void) -{ - return (NMSetting *) g_object_new (NM_TYPE_SETTING_SRIOV, NULL); -} - -/** - * nm_setting_sriov_get_total_vfs: - * @setting: the #NMSettingSriov - * - * Returns the value contained in the #NMSettingSriov:total-vfs - * property. - * - * Returns: the total number of SR-IOV virtual functions to create - * - * Since: 1.14 - **/ -guint -nm_setting_sriov_get_total_vfs (NMSettingSriov *setting) -{ - g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0); - - return setting->total_vfs; -} - -/** - * nm_setting_sriov_get_num_vfs: - * @setting: the #NMSettingSriov - * - * Returns: the number of configured VFs - * - * Since: 1.14 - **/ -guint -nm_setting_sriov_get_num_vfs (NMSettingSriov *setting) -{ - g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0); - - return setting->vfs->len; -} - -/** - * nm_setting_sriov_get_vf: - * @setting: the #NMSettingSriov - * @idx: index number of the VF to return - * - * Returns: (transfer none): the VF at index @idx - * - * Since: 1.14 - **/ -NMSriovVF * -nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx) -{ - g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NULL); - g_return_val_if_fail (idx < setting->vfs->len, NULL); - - return setting->vfs->pdata[idx]; -} - -/** - * nm_setting_sriov_add_vf: - * @setting: the #NMSettingSriov - * @vf: the VF to add - * - * Appends a new VF and associated information to the setting. The - * given VF is duplicated internally and is not changed by this function. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf) -{ - g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); - g_return_if_fail (vf); - g_return_if_fail (vf->refcount > 0); - - g_ptr_array_add (setting->vfs, nm_sriov_vf_dup (vf)); - g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); -} - -/** - * nm_setting_sriov_remove_vf: - * @setting: the #NMSettingSriov - * @idx: index number of the VF - * - * Removes the VF at index @idx. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx) -{ - g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); - g_return_if_fail (idx < setting->vfs->len); - - g_ptr_array_remove_index (setting->vfs, idx); - g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); -} - -/** - * nm_setting_sriov_remove_vf_by_index: - * @setting: the #NMSettingSriov - * @index: the VF index of the VF to remove - * - * Removes the VF with VF index @index. - * - * Returns: %TRUE if the VF was found and removed; %FALSE if it was not - * - * Since: 1.14 - **/ -gboolean -nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting, - guint index) -{ - guint i; - - g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), FALSE); - - for (i = 0; i < setting->vfs->len; i++) { - if (nm_sriov_vf_get_index (setting->vfs->pdata[i]) == index) { - g_ptr_array_remove_index (setting->vfs, i); - g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_sriov_clear_vfs: - * @setting: the #NMSettingSriov - * - * Removes all configured VFs. - * - * Since: 1.14 - **/ -void -nm_setting_sriov_clear_vfs (NMSettingSriov *setting) -{ - g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); - - if (setting->vfs->len != 0) { - g_ptr_array_set_size (setting->vfs, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); - } -} - -/** - * nm_setting_sriov_get_autoprobe_drivers: - * @setting: the #NMSettingSriov - * - * Returns the value contained in the #NMSettingSriov:autoprobe-drivers - * property. - * - * Returns: the autoprobe-drivers property value - * - * Since: 1.14 - **/ -NMTernary -nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting) -{ - g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NM_TERNARY_DEFAULT); - - return setting->autoprobe_drivers; -} - -static gint -vf_index_compare (gconstpointer a, gconstpointer b) -{ - NMSriovVF *vf_a = *(NMSriovVF **) a; - NMSriovVF *vf_b = *(NMSriovVF **) b; - - if (vf_a->index < vf_b->index) - return -1; - else if (vf_a->index > vf_b->index) - return 1; - else - return 0; -} - -gboolean -_nm_setting_sriov_sort_vfs (NMSettingSriov *setting) -{ - gboolean need_sort = FALSE; - guint i; - - for (i = 1; i < setting->vfs->len; i++) { - NMSriovVF *vf_prev = setting->vfs->pdata[i - 1]; - NMSriovVF *vf = setting->vfs->pdata[i]; - - if (vf->index <= vf_prev->index) { - need_sort = TRUE; - break; - } - } - - if (need_sort) - g_ptr_array_sort (setting->vfs, vf_index_compare); - - return need_sort; -} - -/*****************************************************************************/ - -static GVariant * -vfs_to_dbus (NMSetting *setting, const char *property) -{ - gs_unref_ptrarray GPtrArray *vfs = NULL; - GVariantBuilder builder; - guint i; - - g_object_get (setting, NM_SETTING_SRIOV_VFS, &vfs, NULL); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); - - if (vfs) { - for (i = 0; i < vfs->len; i++) { - gs_free const char **attr_names = NULL; - NMSriovVF *vf = vfs->pdata[i]; - GVariantBuilder vf_builder; - const guint *vlan_ids; - const char **name; - guint num_vlans; - - g_variant_builder_init (&vf_builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&vf_builder, "{sv}", "index", - g_variant_new_uint32 (nm_sriov_vf_get_index (vf))); - - attr_names = nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL); - if (attr_names) { - for (name = attr_names; *name; name++) { - g_variant_builder_add (&vf_builder, - "{sv}", - *name, - nm_sriov_vf_get_attribute (vf, *name)); - } - } - - /* VLANs are translated into an array of maps, where each map has - * keys 'id', 'qos' and 'proto'. This guarantees enough flexibility - * to accomodate any future new option. */ - vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans); - if (num_vlans) { - GVariantBuilder vlans_builder; - guint j; - - g_variant_builder_init (&vlans_builder, G_VARIANT_TYPE ("aa{sv}")); - for (j = 0; j < num_vlans; j++) { - GVariantBuilder vlan_builder; - - g_variant_builder_init (&vlan_builder, G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_add (&vlan_builder, - "{sv}", "id", - g_variant_new_uint32 (vlan_ids[j])); - g_variant_builder_add (&vlan_builder, - "{sv}", "qos", - g_variant_new_uint32 (nm_sriov_vf_get_vlan_qos (vf, - vlan_ids[j]))); - g_variant_builder_add (&vlan_builder, - "{sv}", "protocol", - g_variant_new_uint32 (nm_sriov_vf_get_vlan_protocol (vf, - vlan_ids[j]))); - g_variant_builder_add (&vlans_builder, - "a{sv}", - &vlan_builder); - } - g_variant_builder_add (&vf_builder , "{sv}", "vlans", g_variant_builder_end (&vlans_builder)); - } - g_variant_builder_add (&builder, "a{sv}", &vf_builder); - } - } - - return g_variant_builder_end (&builder); -} - -static gboolean -vfs_from_dbus (NMSetting *setting, - GVariant *connection_dict, - const char *property, - GVariant *value, - NMSettingParseFlags parse_flags, - GError **error) -{ - GPtrArray *vfs; - GVariantIter vf_iter; - GVariant *vf_var; - - g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE); - - vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); - g_variant_iter_init (&vf_iter, value); - while (g_variant_iter_next (&vf_iter, "@a{sv}", &vf_var)) { - NMSriovVF *vf; - guint32 index; - GVariantIter attr_iter; - const char *attr_name; - GVariant *attr_var, *vlans_var; - - if (!g_variant_lookup (vf_var, "index", "u", &index)) - goto next; - - vf = nm_sriov_vf_new (index); - - g_variant_iter_init (&attr_iter, vf_var); - while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) { - if (!NM_IN_STRSET (attr_name, "index", "vlans")) - nm_sriov_vf_set_attribute (vf, attr_name, attr_var); - g_variant_unref (attr_var); - } - - if (g_variant_lookup (vf_var, "vlans", "@aa{sv}", &vlans_var)) { - GVariantIter vlan_iter; - GVariant *vlan_var; - - g_variant_iter_init (&vlan_iter, vlans_var); - while (g_variant_iter_next (&vlan_iter, "@a{sv}", &vlan_var)) { - NMSriovVFVlanProtocol proto = NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q; - gint64 vlan_id = -1; - guint qos = 0; - - g_variant_iter_init (&attr_iter, vlan_var); - while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) { - if ( nm_streq (attr_name, "id") - && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) - vlan_id = g_variant_get_uint32 (attr_var); - else if ( nm_streq (attr_name, "qos") - && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) - qos = g_variant_get_uint32 (attr_var); - else if ( nm_streq (attr_name, "protocol") - && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) - proto = g_variant_get_uint32 (attr_var); - g_variant_unref (attr_var); - } - if (vlan_id != -1) - vf_add_vlan (vf, vlan_id, qos, proto); - g_variant_unref (vlan_var); - } - g_variant_unref (vlans_var); - } - - g_ptr_array_add (vfs, vf); -next: - g_variant_unref (vf_var); - } - - g_object_set (setting, NM_SETTING_SRIOV_VFS, vfs, NULL); - g_ptr_array_unref (vfs); - - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -verify (NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingSriov *self = NM_SETTING_SRIOV (setting); - guint i; - - if (self->vfs->len) { - gs_unref_hashtable GHashTable *h = NULL; - - h = g_hash_table_new (nm_direct_hash, NULL); - for (i = 0; i < self->vfs->len; i++) { - NMSriovVF *vf = self->vfs->pdata[i]; - gs_free_error GError *local = NULL; - - if (vf->index >= self->total_vfs) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("VF with index %u, but the total number of VFs is %u"), - vf->index, self->total_vfs); - g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - if (!_nm_sriov_vf_attribute_validate_all (vf, &local)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid VF %u: %s"), - vf->index, - local->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - if (g_hash_table_contains (h, GUINT_TO_POINTER (vf->index))) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("duplicate VF index %u"), vf->index); - g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return FALSE; - } - - g_hash_table_add (h, GUINT_TO_POINTER (vf->index)); - } - } - - /* Failures from here on are NORMALIZABLE... */ - - if (self->vfs->len) { - for (i = 1; i < self->vfs->len; i++) { - NMSriovVF *vf_prev = self->vfs->pdata[i - 1]; - NMSriovVF *vf = self->vfs->pdata[i]; - - if (vf->index <= vf_prev->index) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("VFs %d and %d are not sorted by ascending index"), - vf_prev->index, vf->index); - g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, - NM_SETTING_SRIOV_VFS); - return NM_SETTING_VERIFY_NORMALIZABLE; - } - } - } - - return TRUE; -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMSettingSriov *self = NM_SETTING_SRIOV (object); - - switch (prop_id) { - case PROP_TOTAL_VFS: - self->total_vfs = g_value_get_uint (value); - break; - case PROP_VFS: - g_ptr_array_unref (self->vfs); - self->vfs = _nm_utils_copy_array (g_value_get_boxed (value), - (NMUtilsCopyFunc) nm_sriov_vf_dup, - (GDestroyNotify) nm_sriov_vf_unref); - break; - case PROP_AUTOPROBE_DRIVERS: - self->autoprobe_drivers = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMSettingSriov *self = NM_SETTING_SRIOV (object); - - switch (prop_id) { - case PROP_TOTAL_VFS: - g_value_set_uint (value, self->total_vfs); - break; - case PROP_VFS: - g_value_take_boxed (value, _nm_utils_copy_array (self->vfs, - (NMUtilsCopyFunc) nm_sriov_vf_dup, - (GDestroyNotify) nm_sriov_vf_unref)); - break; - case PROP_AUTOPROBE_DRIVERS: - g_value_set_enum (value, self->autoprobe_drivers); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -compare_property (NMSetting *setting, - NMSetting *other, - const GParamSpec *prop_spec, - NMSettingCompareFlags flags) -{ - NMSettingSriov *a = NM_SETTING_SRIOV (setting); - NMSettingSriov *b = NM_SETTING_SRIOV (other); - NMSettingClass *setting_class; - guint i; - - if (nm_streq (prop_spec->name, NM_SETTING_SRIOV_VFS)) { - if (a->vfs->len != b->vfs->len) - return FALSE; - for (i = 0; i < a->vfs->len; i++) { - if (!nm_sriov_vf_equal (a->vfs->pdata[i], b->vfs->pdata[i])) - return FALSE; - } - return TRUE; - } - - setting_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class); - return setting_class->compare_property (setting, other, prop_spec, flags); -} - -static void -nm_setting_sriov_init (NMSettingSriov *setting) -{ - setting->vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); -} - -static void -finalize (GObject *object) -{ - NMSettingSriov *self = NM_SETTING_SRIOV (object); - - g_ptr_array_unref (self->vfs); - - G_OBJECT_CLASS (nm_setting_sriov_parent_class)->finalize (object); -} - -static void -nm_setting_sriov_class_init (NMSettingSriovClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - GArray *properties_override = _nm_sett_info_property_override_create_array (); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->compare_property = compare_property; - setting_class->verify = verify; - - /** - * NMSettingSriov:total-vfs - * - * The total number of virtual functions to create. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: total-vfs - * variable: SRIOV_TOTAL_VFS(+) - * description: The total number of virtual functions to create - * example: SRIOV_TOTAL_VFS=16 - * ---end--- - */ - g_object_class_install_property - (object_class, PROP_TOTAL_VFS, - g_param_spec_uint (NM_SETTING_SRIOV_TOTAL_VFS, "", "", - 0, G_MAXUINT32, 0, - NM_SETTING_PARAM_FUZZY_IGNORE | - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - /** - * NMSettingSriov:vfs: (type GPtrArray(NMSriovVF)) - * - * Array of virtual function descriptors. - * - * Each VF descriptor is a dictionary mapping attribute names - * to GVariant values. The 'index' entry is mandatory for - * each VF. - * - * When represented as string a VF is in the form: - * - * "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". - * - * for example: - * - * "2 mac=00:11:22:33:44:55 spoof-check=true". - * - * The "vlans" attribute is represented as a semicolor-separated - * list of VLAN descriptors, where each descriptor has the form - * - * "ID[.PRIORITY[.PROTO]]". - * - * PROTO can be either 'q' for 802.1Q (the default) or 'ad' for - * 802.1ad. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: vfs - * variable: SRIOV_VF1(+), SRIOV_VF2(+), ... - * description: SR-IOV virtual function descriptors - * example: SRIOV_VF10="mac=00:11:22:33:44:55", ... - * ---end--- - */ - g_object_class_install_property - (object_class, PROP_VFS, - g_param_spec_boxed (NM_SETTING_SRIOV_VFS, "", "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | - NM_SETTING_PARAM_INFERRABLE | - G_PARAM_STATIC_STRINGS)); - - _properties_override_add_override (properties_override, - g_object_class_find_property (G_OBJECT_CLASS (setting_class), - NM_SETTING_SRIOV_VFS), - G_VARIANT_TYPE ("aa{sv}"), - vfs_to_dbus, - vfs_from_dbus, - NULL); - - /** - * NMSettingSriov:autoprobe-drivers - * - * Whether to autoprobe virtual functions by a compatible driver. - * - * If set to %NM_TERNARY_TRUE, the kernel will try to bind VFs to - * a compatible driver and if this succeeds a new network - * interface will be instantiated for each VF. - * - * If set to %NM_TERNARY_FALSE, VFs will not be claimed and no - * network interfaces will be created for them. - * - * When set to %NM_TERNARY_DEFAULT, the global default is used; in - * case the global default is unspecified it is assumed to be - * %NM_TERNARY_TRUE. - * - * Since: 1.14 - **/ - /* ---ifcfg-rh--- - * property: autoprobe-drivers - * variable: SRIOV_AUTOPROBE_DRIVERS(+) - * default: missing variable means global default - * description: Whether to autoprobe virtual functions by a compatible driver - * example: SRIOV_AUTOPROBE_DRIVERS=0,1 - * ---end--- - */ - g_object_class_install_property - (object_class, PROP_AUTOPROBE_DRIVERS, - g_param_spec_enum (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, "", "", - nm_ternary_get_type (), - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SRIOV, - NULL, properties_override); -} |