diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /libnm-core/nm-setting-sriov.c | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'libnm-core/nm-setting-sriov.c')
| -rw-r--r-- | libnm-core/nm-setting-sriov.c | 1372 |
1 files changed, 0 insertions, 1372 deletions
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c deleted file mode 100644 index 47625a41..00000000 --- a/libnm-core/nm-setting-sriov.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.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 - **/ - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, PROP_TOTAL_VFS, PROP_VFS, PROP_AUTOPROBE_DRIVERS, ); - -/** - * 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) - -/*****************************************************************************/ - -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_sriov_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_new(NMSriovVF); - *vf = (NMSriovVF){ - .refcount = 1, - .index = index, - .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); - nm_g_slice_free(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_new(VFVlan); - *vlan = (VFVlan){ - .id = vlan_id, - .qos = qos, - .protocol = protocol, - }; - - if (!vf->vlans) - vf->vlans = _vf_vlan_create_hash(); - - g_hash_table_add(vf->vlans, vlan); - nm_clear_g_free(&vf->vlan_ids); -} - -/** - * 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); -} - -const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAC, - G_VARIANT_TYPE_STRING, - .str_type = 'm', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ), - /* D-Bus only, synthetic attributes */ - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE("vlans", G_VARIANT_TYPE_STRING, .str_type = '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 (g_variant_type_equal(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; - - nm_clear_g_free(&vf->vlan_ids); - 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) (array length=length): 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_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)); - _notify(setting, PROP_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); - _notify(setting, PROP_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); - _notify(setting, PROP_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); - _notify(setting, PROP_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 int -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); - _notify(setting, PROP_VFS); - } - - return need_sort; -} - -/*****************************************************************************/ - -static GVariant * -vfs_to_dbus(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - 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 = 0; - - 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 accommodate 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 NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingSriov *a; - NMSettingSriov *b; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_SRIOV_VFS)) { - if (set_b) { - a = NM_SETTING_SRIOV(set_a); - b = NM_SETTING_SRIOV(set_b); - - 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; - } - - return NM_SETTING_CLASS(nm_setting_sriov_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -/*****************************************************************************/ - -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 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 -nm_setting_sriov_init(NMSettingSriov *setting) -{ - setting->vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); - - setting->autoprobe_drivers = NM_TERNARY_DEFAULT; -} - -/** - * 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 g_object_new(NM_TYPE_SETTING_SRIOV, NULL); -} - -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. - * - * Note that when the sriov setting is present NetworkManager - * enforces the number of virtual functions on the interface - * (also when it is zero) during activation and resets it - * upon deactivation. To prevent any changes to SR-IOV - * parameters don't add a sriov setting to the connection. - * - * 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--- - */ - obj_properties[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_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". - * - * Multiple VFs can be specified using a comma as separator. - * Currently, the following attributes are supported: mac, - * spoof-check, trust, min-tx-rate, max-tx-rate, vlans. - * - * The "vlans" attribute is represented as a semicolon-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--- - */ - obj_properties[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); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_VFS], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = vfs_to_dbus, - .from_dbus_fcn = vfs_from_dbus, )); - - /** - * 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--- - */ - obj_properties[PROP_AUTOPROBE_DRIVERS] = g_param_spec_enum( - NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, - "", - "", - NM_TYPE_TERNARY, - NM_TERNARY_DEFAULT, - NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - _nm_setting_class_commit_full(setting_class, - NM_META_SETTING_TYPE_SRIOV, - NULL, - properties_override); -} |