diff options
author | Thomas Haller <thaller@redhat.com> | 2018-08-10 10:39:00 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-08-10 10:39:00 +0200 |
commit | da3b72d8420e0fa25203f0989e20bad65bdfc2d8 (patch) | |
tree | c5b8d0e4909990bff9356a121230708ddd677ba8 | |
parent | c955d91d4bbd1aec0e00be8955ac24aecf64182f (diff) | |
parent | da109a291c6d219a554578e32c4c0daae6def241 (diff) | |
download | NetworkManager-da3b72d8420e0fa25203f0989e20bad65bdfc2d8.tar.gz |
all/ethtool: merge branch 'th/ethtool-options-rh1335409-1'
Add support for setting offload features (akin to ethtool's
-K|--offload|--feature).
https://bugzilla.redhat.com/show_bug.cgi?id=1335409
https://github.com/NetworkManager/NetworkManager/pull/179
96 files changed, 5049 insertions, 1951 deletions
diff --git a/Makefile.am b/Makefile.am index 516e9acbf2..fe156f9284 100644 --- a/Makefile.am +++ b/Makefile.am @@ -453,6 +453,7 @@ libnm_core_lib_h_pub_real = \ libnm-core/nm-setting-connection.h \ libnm-core/nm-setting-dcb.h \ libnm-core/nm-setting-dummy.h \ + libnm-core/nm-setting-ethtool.h \ libnm-core/nm-setting-generic.h \ libnm-core/nm-setting-gsm.h \ libnm-core/nm-setting-infiniband.h \ @@ -502,6 +503,7 @@ libnm_core_lib_h_priv = \ shared/nm-utils/nm-shared-utils.h \ shared/nm-utils/nm-random-utils.h \ shared/nm-utils/nm-udev-utils.h \ + shared/nm-ethtool-utils.h \ shared/nm-meta-setting.h \ libnm-core/crypto.h \ libnm-core/nm-connection-private.h \ @@ -524,6 +526,7 @@ libnm_core_lib_c_settings_real = \ libnm-core/nm-setting-connection.c \ libnm-core/nm-setting-dcb.c \ libnm-core/nm-setting-dummy.c \ + libnm-core/nm-setting-ethtool.c \ libnm-core/nm-setting-generic.c \ libnm-core/nm-setting-gsm.c \ libnm-core/nm-setting-infiniband.c \ @@ -565,6 +568,7 @@ libnm_core_lib_c_real = \ shared/nm-utils/nm-shared-utils.c \ shared/nm-utils/nm-random-utils.c \ shared/nm-utils/nm-udev-utils.c \ + shared/nm-ethtool-utils.c \ shared/nm-meta-setting.c \ libnm-core/crypto.c \ libnm-core/nm-connection.c \ @@ -2390,6 +2394,7 @@ EXTRA_DIST += \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected \ src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap \ src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap \ src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep \ @@ -3425,6 +3430,9 @@ clients_common_libnmc_la_SOURCES = \ shared/nm-meta-setting.c \ shared/nm-meta-setting.h \ \ + shared/nm-ethtool-utils.c \ + shared/nm-ethtool-utils.h \ + \ clients/common/nm-meta-setting-desc.c \ clients/common/nm-meta-setting-desc.h \ clients/common/nm-meta-setting-access.c \ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 5d8c3daff7..5361e11fb1 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -770,7 +770,8 @@ const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CO NM_SETTING_6LOWPAN_SETTING_NAME","\ NM_SETTING_PROXY_SETTING_NAME"," \ NM_SETTING_TC_CONFIG_SETTING_NAME"," \ - NM_SETTING_SRIOV_SETTING_NAME + NM_SETTING_SRIOV_SETTING_NAME"," \ + NM_SETTING_ETHTOOL_SETTING_NAME // NM_SETTING_DUMMY_SETTING_NAME // NM_SETTING_WIMAX_SETTING_NAME diff --git a/clients/cli/settings.c b/clients/cli/settings.c index b39713f901..2c6baeb426 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -662,25 +662,19 @@ nmc_setting_remove_property_option (NMSetting *setting, char ** nmc_setting_get_valid_properties (NMSetting *setting) { - char **valid_props = NULL; - GParamSpec **props, **iter; - guint num; - int i; - - /* Iterate through properties */ - i = 0; - props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (setting)), &num); - valid_props = g_malloc0 (sizeof (char*) * (num + 1)); - for (iter = props; iter && *iter; iter++) { - const char *key_name = g_param_spec_get_name (*iter); - - /* Add all properties except for "name" that is non-editable */ - if (g_strcmp0 (key_name, "name") != 0) - valid_props[i++] = g_strdup (key_name); - } - valid_props[i] = NULL; - g_free (props); + const NMMetaSettingInfoEditor *setting_info; + char **valid_props; + guint i, num; + + setting_info = nm_meta_setting_info_editor_find_by_setting (setting); + + num = setting_info ? setting_info->properties_num : 0; + + valid_props = g_new (char *, num + 1); + for (i = 0; i < num; i++) + valid_props[i] = g_strdup (setting_info->properties[i]->property_name); + valid_props[num] = NULL; return valid_props; } diff --git a/clients/cli/utils.c b/clients/cli/utils.c index ea2c7de860..8cbfe9f2fa 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -1092,7 +1092,18 @@ _print_fill (const NmcConfig *nmc_config, nm_assert (!to_free || value == to_free); - if (!nmc_config->overview || !is_default) + if ( is_default + && ( nmc_config->overview + || NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE))) { + /* don't mark the entry for display. This is to shorten the output in case + * the property is the default value. But we only do that, if the user + * opts in to this behavior (-overview), or of the property marks itself + * elegible to be hidden. + * + * In general, only new API shall mark itself eligible to be hidden. + * Long established properties cannot, because it would be a change + * in behavior. */ + } else header_cell->to_print = TRUE; if (NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_STRV)) { diff --git a/clients/common/meson.build b/clients/common/meson.build index f0c8160083..0db2868e7c 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -59,7 +59,7 @@ libnmc = static_library( sources: files( 'nm-meta-setting-access.c', 'nm-meta-setting-desc.c' - ) + shared_nm_utils_nm_meta_setting_c + [settings_docs_source], + ) + shared_nm_meta_setting_c + shared_nm_ethtool_utils_c + [settings_docs_source], dependencies: deps, c_args: cflags, link_with: libnmc_base, diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 2e3d45ca38..8c7553d83f 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -132,7 +132,7 @@ nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error) } gboolean -nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error) +nmc_string_to_ternary (const char *str, NMTernary *val, GError **error) { const char *s_true[] = { "true", "yes", "on", NULL }; const char *s_false[] = { "false", "no", "off", NULL }; @@ -150,11 +150,11 @@ nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error) } if (nmc_string_is_valid (str, s_true, NULL)) - *val = NMC_TRI_STATE_YES; + *val = NM_TERNARY_TRUE; else if (nmc_string_is_valid (str, s_false, NULL)) - *val = NMC_TRI_STATE_NO; + *val = NM_TERNARY_FALSE; else if (nmc_string_is_valid (str, s_unknown, NULL)) - *val = NMC_TRI_STATE_UNKNOWN; + *val = NM_TERNARY_DEFAULT; else { g_set_error (error, 1, 0, _("'%s' is not valid; use [%s], [%s] or [%s]"), diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h index cc0b7330ac..9d818873c0 100644 --- a/clients/common/nm-client-utils.h +++ b/clients/common/nm-client-utils.h @@ -24,12 +24,6 @@ #include "nm-active-connection.h" #include "nm-device.h" -typedef enum { - NMC_TRI_STATE_NO, - NMC_TRI_STATE_YES, - NMC_TRI_STATE_UNKNOWN, -} NMCTriStateValue; - const NMObject **nmc_objects_sort_by_path (const NMObject *const*objs, gssize len); const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error); @@ -40,7 +34,7 @@ gboolean nmc_string_to_uint (const char *str, unsigned long int max, unsigned long int *value); gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error); -gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error); +gboolean nmc_string_to_ternary (const char *str, NMTernary *val, GError **error); gboolean matches (const char *cmd, const char *pattern); diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c index cebf8ba8af..bd4064ded9 100644 --- a/clients/common/nm-meta-setting-access.c +++ b/clients/common/nm-meta-setting-access.c @@ -23,24 +23,32 @@ /*****************************************************************************/ +static const NMMetaSettingInfoEditor * +_get_meta_setting_info_editor_from_msi (const NMMetaSettingInfo *meta_setting_info) +{ + const NMMetaSettingInfoEditor *setting_info; + + if (!meta_setting_info) + return NULL; + + nm_assert (meta_setting_info->get_setting_gtype); + nm_assert (meta_setting_info->meta_type < G_N_ELEMENTS (nm_meta_setting_infos_editor)); + + setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type]; + + nm_assert (setting_info->general == meta_setting_info); + return setting_info; +} + const NMMetaSettingInfoEditor * nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias) { - const NMMetaSettingInfo *meta_setting_info; const NMMetaSettingInfoEditor *setting_info; guint i; g_return_val_if_fail (setting_name, NULL); - meta_setting_info = nm_meta_setting_infos_by_name (setting_name); - setting_info = NULL; - if (meta_setting_info) { - nm_assert (nm_streq0 (meta_setting_info->setting_name, setting_name)); - if (meta_setting_info->meta_type < G_N_ELEMENTS (nm_meta_setting_infos_editor)) { - setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type]; - nm_assert (setting_info->general == meta_setting_info); - } - } + setting_info = _get_meta_setting_info_editor_from_msi (nm_meta_setting_infos_by_name (setting_name)); if (!setting_info && use_alias) { for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { if (nm_streq0 (nm_meta_setting_infos_editor[i].alias, setting_name)) { @@ -56,25 +64,7 @@ nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use const NMMetaSettingInfoEditor * nm_meta_setting_info_editor_find_by_gtype (GType gtype) { - const NMMetaSettingInfo *meta_setting_info; - const NMMetaSettingInfoEditor *setting_info; - - meta_setting_info = nm_meta_setting_infos_by_gtype (gtype); - - if (!meta_setting_info) - return NULL; - - g_return_val_if_fail (meta_setting_info->get_setting_gtype, NULL); - g_return_val_if_fail (meta_setting_info->get_setting_gtype () == gtype, NULL); - - if (meta_setting_info->meta_type >= G_N_ELEMENTS (nm_meta_setting_infos_editor)) - return NULL; - - setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type]; - - g_return_val_if_fail (setting_info->general == meta_setting_info, NULL); - - return setting_info; + return _get_meta_setting_info_editor_from_msi (nm_meta_setting_infos_by_gtype (gtype)); } const NMMetaSettingInfoEditor * @@ -86,12 +76,13 @@ nm_meta_setting_info_editor_find_by_setting (NMSetting *setting) setting_info = nm_meta_setting_info_editor_find_by_gtype (G_OBJECT_TYPE (setting)); - nm_assert (setting_info == nm_meta_setting_info_editor_find_by_name (nm_setting_get_name (setting), FALSE)); - nm_assert (!setting_info || G_TYPE_CHECK_INSTANCE_TYPE (setting, setting_info->general->get_setting_gtype ())); - + nm_assert (setting_info); + nm_assert (G_TYPE_CHECK_INSTANCE_TYPE (setting, setting_info->general->get_setting_gtype ())); return setting_info; } +/*****************************************************************************/ + const NMMetaPropertyInfo * nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info, const char *property_name) { diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index aa21ce1023..c4b0414575 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -2719,19 +2719,19 @@ static gboolean _set_fcn_connection_metered (ARGS_SET_FCN) { NMMetered metered; - NMCTriStateValue ts_val; + NMTernary ts_val; - if (!nmc_string_to_tristate (value, &ts_val, error)) + if (!nmc_string_to_ternary (value, &ts_val, error)) return FALSE; switch (ts_val) { - case NMC_TRI_STATE_YES: + case NM_TERNARY_TRUE: metered = NM_METERED_YES; break; - case NMC_TRI_STATE_NO: + case NM_TERNARY_FALSE: metered = NM_METERED_NO; break; - case NMC_TRI_STATE_UNKNOWN: + case NM_TERNARY_DEFAULT: metered = NM_METERED_UNKNOWN; break; default: @@ -4823,6 +4823,85 @@ _validate_fcn_wireless_security_psk (const char *value, char **out_to_free, GErr /*****************************************************************************/ +static gconstpointer +_get_fcn_ethtool (ARGS_GET_FCN) +{ + const char *s; + NMTernary val; + NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id; + + RETURN_UNSUPPORTED_GET_TYPE (); + + val = nm_setting_ethtool_get_feature (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname); + + if (val == NM_TERNARY_TRUE) + s = N_("on"); + else if (val == NM_TERNARY_FALSE) + s = N_("off"); + else { + s = NULL; + NM_SET_OUT (out_is_default, TRUE); + *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE; + } + + if (s && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + s = gettext (s); + return s; +} + +static gboolean +_set_fcn_ethtool (ARGS_SET_FCN) +{ + gs_free char *value_clone = NULL; + NMTernary val; + NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id; + + value = nm_strstrip_avoid_copy (value, &value_clone); + + if (NM_IN_STRSET (value, "1", "yes", "true", "on")) + val = NM_TERNARY_TRUE; + else if (NM_IN_STRSET (value, "0", "no", "false", "off")) + val = NM_TERNARY_FALSE; + else if (NM_IN_STRSET (value, "", "ignore", "default")) + val = NM_TERNARY_DEFAULT; + else { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' is not valid; use 'on', 'off', or 'ignore'"), + value); + return FALSE; + } + + nm_setting_ethtool_set_feature (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname, + val); + return TRUE; +} + +static const char *const* +_complete_fcn_ethtool (ARGS_COMPLETE_FCN) +{ + static const char *const v[] = { + "true", + "false", + "1", + "0", + "yes", + "no", + "default", + "on", + "off", + "ignore", + NULL, + }; + + if (!text || !text[0]) + return &v[7]; + return v; +} + +/*****************************************************************************/ + static const NMMetaPropertyInfo property_info_BOND_OPTIONS; #define NESTED_PROPERTY_INFO_BOND(...) \ @@ -4979,6 +5058,12 @@ static const NMMetaPropertyType _pt_gobject_devices = { .complete_fcn = _complete_fcn_gobject_devices, }; +static const NMMetaPropertyType _pt_ethtool = { + .get_fcn = _get_fcn_ethtool, + .set_fcn = _set_fcn_ethtool, + .complete_fcn = _complete_fcn_ethtool, +}; + /*****************************************************************************/ #include "settings-docs.h" @@ -5775,6 +5860,72 @@ static const NMMetaPropertyInfo *const property_infos_DCB[] = { NULL }; +#define PROPERTY_INFO_ETHTOOL(xname) \ + PROPERTY_INFO (NM_ETHTOOL_OPTNAME_##xname, NULL, \ + .property_type = &_pt_ethtool, \ + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (ethtool, \ + .ethtool_id = NM_ETHTOOL_ID_##xname, \ + ), \ + ) + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_ETHTOOL +static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = { + PROPERTY_INFO_ETHTOOL (FEATURE_ESP_HW_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_ESP_TX_CSUM_HW_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_FCOE_MTU), + PROPERTY_INFO_ETHTOOL (FEATURE_GRO), + PROPERTY_INFO_ETHTOOL (FEATURE_GSO), + PROPERTY_INFO_ETHTOOL (FEATURE_HIGHDMA), + PROPERTY_INFO_ETHTOOL (FEATURE_HW_TC_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_L2_FWD_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_LOOPBACK), + PROPERTY_INFO_ETHTOOL (FEATURE_LRO), + PROPERTY_INFO_ETHTOOL (FEATURE_NTUPLE), + PROPERTY_INFO_ETHTOOL (FEATURE_RX), + PROPERTY_INFO_ETHTOOL (FEATURE_RXHASH), + PROPERTY_INFO_ETHTOOL (FEATURE_RXVLAN), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_ALL), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_FCS), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_GRO_HW), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_VLAN_FILTER), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_VLAN_STAG_FILTER), + PROPERTY_INFO_ETHTOOL (FEATURE_RX_VLAN_STAG_HW_PARSE), + PROPERTY_INFO_ETHTOOL (FEATURE_SG), + PROPERTY_INFO_ETHTOOL (FEATURE_TLS_HW_RECORD), + PROPERTY_INFO_ETHTOOL (FEATURE_TLS_HW_TX_OFFLOAD), + PROPERTY_INFO_ETHTOOL (FEATURE_TSO), + PROPERTY_INFO_ETHTOOL (FEATURE_TX), + PROPERTY_INFO_ETHTOOL (FEATURE_TXVLAN), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_CHECKSUM_FCOE_CRC), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_CHECKSUM_IPV4), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_CHECKSUM_IPV6), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_CHECKSUM_IP_GENERIC), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_CHECKSUM_SCTP), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_ESP_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_FCOE_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_GRE_CSUM_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_GRE_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_GSO_PARTIAL), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_GSO_ROBUST), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_IPXIP4_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_IPXIP6_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_NOCACHE_COPY), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_SCATTER_GATHER), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_SCATTER_GATHER_FRAGLIST), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_SCTP_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_TCP6_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_TCP_ECN_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_TCP_MANGLEID_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_TCP_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_UDP_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_UDP_TNL_SEGMENTATION), + PROPERTY_INFO_ETHTOOL (FEATURE_TX_VLAN_STAG_HW_INSERT), + NULL, +}; + #undef _CURRENT_NM_META_SETTING_TYPE #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GSM static const NMMetaPropertyInfo *const property_infos_GSM[] = { @@ -7740,6 +7891,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) #define SETTING_PRETTY_NAME_CONNECTION N_("General settings") #define SETTING_PRETTY_NAME_DCB N_("DCB settings") #define SETTING_PRETTY_NAME_DUMMY N_("Dummy settings") +#define SETTING_PRETTY_NAME_ETHTOOL N_("Ethtool settings") #define SETTING_PRETTY_NAME_GENERIC N_("Generic settings") #define SETTING_PRETTY_NAME_GSM N_("GSM mobile broadband connection") #define SETTING_PRETTY_NAME_INFINIBAND N_("InfiniBand connection") @@ -7827,6 +7979,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (BOND, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (BRIDGE, @@ -7834,6 +7987,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (BRIDGE, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (BRIDGE_PORT), @@ -7848,11 +8002,13 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { ), SETTING_INFO (CONNECTION), SETTING_INFO (DCB), + SETTING_INFO (ETHTOOL), SETTING_INFO_EMPTY (DUMMY, .valid_parts = NM_META_SETTING_VALID_PARTS ( NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (DUMMY, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO_EMPTY (GENERIC, @@ -7875,6 +8031,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (INFINIBAND, TRUE), NM_META_SETTING_VALID_PART_ITEM (SRIOV, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), .setting_init_fcn = _setting_init_fcn_infiniband, ), @@ -7889,6 +8046,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (IP_TUNNEL, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (MACSEC, @@ -7897,6 +8055,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (MACSEC, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (MACVLAN, @@ -7904,6 +8063,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (MACVLAN, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (OLPC_MESH, @@ -7928,6 +8088,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (IP4_CONFIG, FALSE), NM_META_SETTING_VALID_PART_ITEM (IP6_CONFIG, FALSE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (OVS_PATCH), @@ -7947,6 +8108,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (WIRED, TRUE), NM_META_SETTING_VALID_PART_ITEM (PPP, FALSE), NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (PPP), @@ -7961,6 +8123,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (TEAM, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (TEAM_PORT), @@ -7969,6 +8132,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (TUN, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), .setting_init_fcn = _setting_init_fcn_tun, ), @@ -7978,6 +8142,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (VLAN, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), .setting_init_fcn = _setting_init_fcn_vlan, ), @@ -7992,6 +8157,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (VXLAN, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (WIMAX, @@ -8008,6 +8174,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), NM_META_SETTING_VALID_PART_ITEM (DCB, FALSE), NM_META_SETTING_VALID_PART_ITEM (SRIOV, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), ), SETTING_INFO (WIRELESS, @@ -8017,6 +8184,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (WIRELESS, TRUE), NM_META_SETTING_VALID_PART_ITEM (WIRELESS_SECURITY, FALSE), NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE), ), .setting_init_fcn = _setting_init_fcn_wireless, ), diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h index 2aa27f1b73..31f1dd51bd 100644 --- a/clients/common/nm-meta-setting-desc.h +++ b/clients/common/nm-meta-setting-desc.h @@ -22,6 +22,7 @@ #include "nm-utils/nm-obj.h" #include "nm-meta-setting.h" +#include "nm-ethtool-utils.h" struct _NMDevice; @@ -147,6 +148,11 @@ typedef enum { typedef enum { NM_META_ACCESSOR_GET_OUT_FLAGS_NONE = 0, NM_META_ACCESSOR_GET_OUT_FLAGS_STRV = (1LL << 0), + + /* the property allows to be hidden, if and only if, it's value is set to the + * default. This should only be set by new properties, to preserve behavior + * of old properties, which were always printed. */ + NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE = (1LL << 1), } NMMetaAccessorGetOutFlags; typedef enum { @@ -263,6 +269,9 @@ struct _NMMetaPropertyTypData { struct { NMMetaPropertyTypeMacMode mode; } mac; + struct { + NMEthtoolID ethtool_id; + } ethtool; } subtype; const char *const*values_static; const NMMetaPropertyTypDataNested *nested; diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml index cba1661045..94ef406a1d 100644 --- a/docs/libnm/libnm-docs.xml +++ b/docs/libnm/libnm-docs.xml @@ -202,6 +202,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in <xi:include href="xml/nm-setting-cdma.xml"/> <xi:include href="xml/nm-setting-dcb.xml"/> <xi:include href="xml/nm-setting-dummy.xml"/> + <xi:include href="xml/nm-setting-ethtool.xml"/> <xi:include href="xml/nm-setting-generic.xml"/> <xi:include href="xml/nm-setting-gsm.xml"/> <xi:include href="xml/nm-setting-infiniband.xml"/> diff --git a/libnm-core/meson.build b/libnm-core/meson.build index 686f6ad360..0a0406dfab 100644 --- a/libnm-core/meson.build +++ b/libnm-core/meson.build @@ -69,6 +69,7 @@ libnm_core_settings_sources = files( 'nm-setting-connection.c', 'nm-setting-dcb.c', 'nm-setting-dummy.c', + 'nm-setting-ethtool.c', 'nm-setting-generic.c', 'nm-setting-gsm.c', 'nm-setting-infiniband.c', @@ -153,7 +154,8 @@ endif libnm_core_sources_all = libnm_core_sources libnm_core_sources_all += libnm_core_enum -libnm_core_sources_all += shared_nm_utils_nm_meta_setting_c +libnm_core_sources_all += shared_nm_meta_setting_c +libnm_core_sources_all += shared_nm_ethtool_utils_c libnm_core_sources_all += shared_files_libnm_core libnm_core_sources_all += [version_header] diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 38caa66ff9..0c999c8c84 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -84,6 +84,7 @@ #include "nm-vpn-dbus-interface.h" #include "nm-core-types-internal.h" #include "nm-vpn-editor-plugin.h" +#include "nm-meta-setting.h" /* IEEE 802.1D-1998 timer values */ #define NM_BR_MIN_HELLO_TIME 1 @@ -168,49 +169,43 @@ NMConnection *_nm_simple_connection_new_from_dbus (GVariant *dict, NMSettingParseFlags parse_flags, GError **error); -/* - * A setting's priority should roughly follow the OSI layer model, but it also - * controls which settings get asked for secrets first. Thus settings which - * relate to things that must be working first, like hardware, should get a - * higher priority than things which layer on top of the hardware. For example, - * the GSM/CDMA settings should provide secrets before the PPP setting does, - * because a PIN is required to unlock the device before PPP can even start. - * Even settings without secrets should be assigned the right priority. - * - * 0: reserved for invalid - * - * 1: reserved for the Connection setting - * - * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. - * These priority 1 settings are also "base types", which means that at least - * one of them is required for the connection to be valid, and their name is - * valid in the 'type' property of the Connection setting. - * - * 4: hardware-related auxiliary settings that require a base setting to be - * successful first, like Wi-Fi security, 802.1x, etc. - * - * 5: hardware-independent settings that are required before IP connectivity - * can be established, like PPP, PPPoE, etc. - * - * 6: IP-level stuff - * - * 10: NMSettingUser - */ -typedef enum { /*< skip >*/ - NM_SETTING_PRIORITY_INVALID = 0, - NM_SETTING_PRIORITY_CONNECTION = 1, - NM_SETTING_PRIORITY_HW_BASE = 2, - NM_SETTING_PRIORITY_HW_NON_BASE = 3, - NM_SETTING_PRIORITY_HW_AUX = 4, - NM_SETTING_PRIORITY_AUX = 5, - NM_SETTING_PRIORITY_IP = 6, - NM_SETTING_PRIORITY_USER = 10, -} NMSettingPriority; - NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting); gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); +/*****************************************************************************/ + +GHashTable *_nm_setting_gendata_hash (NMSetting *setting, + gboolean create_if_necessary); + +void _nm_setting_gendata_notify (NMSetting *setting, + gboolean keys_changed); + +guint _nm_setting_gendata_get_all (NMSetting *setting, + const char *const**out_names, + GVariant *const**out_values); + +gboolean _nm_setting_gendata_reset_from_hash (NMSetting *setting, + GHashTable *new); + +void _nm_setting_gendata_to_gvalue (NMSetting *setting, + GValue *value); + +GVariant *nm_setting_gendata_get (NMSetting *setting, + const char *name); + +const char *const*nm_setting_gendata_get_all_names (NMSetting *setting, + guint *out_len); + +GVariant *const*nm_setting_gendata_get_all_values (NMSetting *setting); + +/*****************************************************************************/ + +guint nm_setting_ethtool_init_features (NMSettingEthtool *setting, + NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */); + +/*****************************************************************************/ + #define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3) guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length); @@ -255,15 +250,6 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array); gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer needle); -gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last); -gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); - GSList * _nm_utils_strv_to_slist (char **strv, gboolean deep_copy); char ** _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy); @@ -526,4 +512,77 @@ gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin); gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting); +/*****************************************************************************/ + +typedef struct _NMSettInfoSetting NMSettInfoSetting; + +typedef GVariant *(*NMSettingPropertyGetFunc) (NMSetting *setting, + const char *property); +typedef GVariant *(*NMSettingPropertySynthFunc) (NMSetting *setting, + NMConnection *connection, + const char *property); +typedef gboolean (*NMSettingPropertySetFunc) (NMSetting *setting, + GVariant *connection_dict, + const char *property, + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error); +typedef gboolean (*NMSettingPropertyNotSetFunc) (NMSetting *setting, + GVariant *connection_dict, + const char *property, + NMSettingParseFlags parse_flags, + GError **error); +typedef GVariant *(*NMSettingPropertyTransformToFunc) (const GValue *from); +typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from, + GValue *to); + +typedef struct { + const char *name; + GParamSpec *param_spec; + const GVariantType *dbus_type; + + NMSettingPropertyGetFunc get_func; + NMSettingPropertySynthFunc synth_func; + NMSettingPropertySetFunc set_func; + NMSettingPropertyNotSetFunc not_set_func; + + NMSettingPropertyTransformToFunc to_dbus; + NMSettingPropertyTransformFromFunc from_dbus; +} NMSettInfoProperty; + +typedef struct { + const GVariantType *(*get_variant_type) (const struct _NMSettInfoSetting *sett_info, + const char *name, + GError **error); +} NMSettInfoSettGendata; + +typedef struct { + /* if set, then this setting class has no own fields. Instead, its + * data is entirely based on gendata. Meaning: it tracks all data + * as native GVariants. + * It might have some GObject properties, but these are merely accessors + * to the underlying gendata. + * + * Note, that at the moment there are few hooks, to customize the behavior + * of the setting further. They are currently unneeded. This is desired, + * but could be added when there is a good reason. + * + * However, a few hooks there are... see NMSettInfoSettGendata. */ + const NMSettInfoSettGendata *gendata_info; +} NMSettInfoSettDetail; + +struct _NMSettInfoSetting { + NMSettingClass *setting_class; + const NMSettInfoProperty *property_infos; + guint property_infos_len; + NMSettInfoSettDetail detail; +}; + +const NMSettInfoSetting *_nm_sett_info_setting_get (NMSettingClass *setting_class); + +const NMSettInfoProperty *_nm_sett_info_property_get (NMSettingClass *setting_class, + const char *property_name); + +/*****************************************************************************/ + #endif diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 622b104f60..4282fdfe5c 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -40,6 +40,7 @@ typedef struct _NMSettingCdma NMSettingCdma; typedef struct _NMSettingConnection NMSettingConnection; typedef struct _NMSettingDcb NMSettingDcb; typedef struct _NMSettingDummy NMSettingDummy; +typedef struct _NMSettingEthtool NMSettingEthtool; typedef struct _NMSettingGeneric NMSettingGeneric; typedef struct _NMSettingGsm NMSettingGsm; typedef struct _NMSettingInfiniband NMSettingInfiniband; diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index dbc0b187f1..3f9d60bbb7 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -2096,18 +2096,16 @@ typedef struct { }) typedef struct { - const char *setting_name; const ParseInfoProperty*const*properties; } ParseInfoSetting; -#define PARSE_INFO_SETTING(_setting_name, ...) \ - { \ - .setting_name = _setting_name, \ +#define PARSE_INFO_SETTING(setting_type, ...) \ + [setting_type] = (&((const ParseInfoSetting) { \ __VA_ARGS__ \ - } + })) -static const ParseInfoSetting parse_infos[] = { - PARSE_INFO_SETTING (NM_SETTING_WIRELESS_SETTING_NAME, +static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRELESS, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_BSSID, .parser = mac_address_parser_ETHER, @@ -2124,7 +2122,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_802_1X_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_802_1X, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CA_CERT, .parser = cert_parser, @@ -2156,7 +2154,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_WIRED_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRED, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, .parser = mac_address_parser_ETHER_cloned, @@ -2166,28 +2164,28 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BLUETOOTH, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR, .parser = mac_address_parser_ETHER, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BOND_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BOND, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BRIDGE_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS, .parser = mac_address_parser_ETHER, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_CONNECTION_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_CONNECTION, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_READ_ONLY, .parser_skip = TRUE, @@ -2199,14 +2197,14 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_INFINIBAND, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS, .parser = mac_address_parser_INFINIBAND, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP4_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES, .parser_no_check_key = TRUE, @@ -2228,7 +2226,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, .parser_no_check_key = TRUE, @@ -2256,14 +2254,14 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_SERIAL_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY, .parser = parity_parser, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_SRIOV_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SRIOV, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS, .parser_no_check_key = TRUE, @@ -2272,7 +2270,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TC_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS, .parser_no_check_key = TRUE, @@ -2286,7 +2284,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TEAM_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, @@ -2353,7 +2351,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM_PORT, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, @@ -2384,21 +2382,21 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_USER_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_USER, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_VLAN_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VLAN, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS, .writer_persist_default = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_VPN_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VPN, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_VPN_DATA, .parser_no_check_key = TRUE, @@ -2420,7 +2418,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_WIMAX_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIMAX, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS, .parser = mac_address_parser_ETHER, @@ -2430,21 +2428,24 @@ static const ParseInfoSetting parse_infos[] = { }; static const ParseInfoProperty * -_parse_info_find (const char *setting_name, const char *property_name) +_parse_info_find (NMSetting *setting, + const char *property_name, + const char **out_setting_name) { + const NMMetaSettingInfo *setting_info; + const ParseInfoSetting *pis; gssize idx; -#if NM_MORE_ASSERTS > 5 +#if NM_MORE_ASSERTS > 10 { guint i, j; for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { - const ParseInfoSetting *pis = &parse_infos[i]; + pis = parse_infos[i]; + + if (!pis) + continue; - g_assert (pis->setting_name); - if ( i > 0 - && strcmp (pis[-1].setting_name, pis->setting_name) >= 0) - g_error ("Wrong order at index #%d: \"%s\" before \"%s\"", i - 1, pis[-1].setting_name, pis->setting_name); g_assert (pis->properties); g_assert (pis->properties[0]); for (j = 0; pis->properties[j]; j++) { @@ -2454,32 +2455,35 @@ _parse_info_find (const char *setting_name, const char *property_name) g_assert (pip->property_name); if ( j > 0 && (pip0 = pis->properties[j - 1]) - && strcmp (pip0->property_name, pip->property_name) >= 0) - g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", i, j - 1, pis->setting_name, pip0->property_name, pis->setting_name, pip->property_name); + && strcmp (pip0->property_name, pip->property_name) >= 0) { + g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", + i, j - 1, + nm_meta_setting_infos[i].setting_name, pip0->property_name, + nm_meta_setting_infos[i].setting_name, pip->property_name); + } } } } #endif - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoSetting, setting_name) == 0); - idx = _nm_utils_array_find_binary_search (parse_infos, - sizeof (ParseInfoSetting), - G_N_ELEMENTS (parse_infos), - &setting_name, - nm_strcmp_p_with_data, - NULL); - if (idx >= 0) { - const ParseInfoSetting *pis = &parse_infos[idx]; + if ( !NM_IS_SETTING (setting) + || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) { + /* handle invalid setting objects gracefully. */ + *out_setting_name = NULL; + return NULL; + } + + *out_setting_name = setting_info->setting_name; + if ((pis = parse_infos[setting_info->meta_type])) { G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0); - nm_assert (nm_streq (pis->setting_name, setting_name)); - idx = _nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, - NM_PTRARRAY_LEN (pis->properties), - &property_name, - nm_strcmp_p_with_data, - NULL, - NULL, - NULL); + idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, + NM_PTRARRAY_LEN (pis->properties), + &property_name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); if (idx >= 0) return pis->properties[idx]; } @@ -2510,9 +2514,9 @@ read_one_setting_value (NMSetting *setting, if (!(flags & G_PARAM_WRITABLE)) return; - setting_name = nm_setting_get_name (setting); + pip = _parse_info_find (setting, key, &setting_name); - pip = _parse_info_find (setting_name, key); + nm_assert (setting_name); if ( !pip && nm_streq (key, NM_SETTING_NAME)) @@ -2680,6 +2684,8 @@ read_one_setting_value (NMSetting *setting, static NMSetting * read_setting (KeyfileReaderInfo *info) { + const NMSettInfoSetting *sett_info; + gs_unref_object NMSetting *setting = NULL; const char *alias; GType type; @@ -2688,22 +2694,92 @@ read_setting (KeyfileReaderInfo *info) alias = info->group; type = nm_setting_lookup_type (alias); - if (type) { - NMSetting *setting = g_object_new (type, NULL); - - info->setting = setting; - nm_setting_enumerate_values (setting, read_one_setting_value, info); - info->setting = NULL; - if (!info->error) - return setting; - - g_object_unref (setting); - } else { + if (!type) { handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid setting name '%s'"), info->group); + return NULL; } - return NULL; + setting = g_object_new (type, NULL); + + info->setting = setting; + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + gs_free char **keys = NULL; + gsize i, n_keys; + + keys = g_key_file_get_keys (info->keyfile, info->group, &n_keys, NULL); + if (n_keys > 0) { + GHashTable *h = _nm_setting_gendata_hash (setting, TRUE); + + nm_utils_strv_sort (keys, n_keys); + for (i = 0; i < n_keys; i++) { + gs_free char *key = keys[i]; + gs_free_error GError *local = NULL; + const GVariantType *variant_type; + GVariant *variant; + + /* a GKeyfile can return duplicate keys, there is just no API to make sense + * of them. Skip them. */ + if ( i + 1 < n_keys + && nm_streq (key, keys[i + 1])) + continue; + + /* currently, the API is very simple. The setting class just returns + * the desired variant type, and keyfile reader will try to parse + * it accordingly. Note, that this does currently not allow, that + * a particular key can contain different variant types, nor is it + * very flexible in general. + * + * We add flexibility when we need it. Keep it simple for now. */ + variant_type = sett_info->detail.gendata_info->get_variant_type (sett_info, + key, + &local); + if (!variant_type) { + if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key '%s.%s'"), + info->group, key)) + break; + continue; + } + + if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN)) { + gboolean v; + + v = g_key_file_get_boolean (info->keyfile, + info->group, + key, + &local); + if (local) { + if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not boolean"), + info->group, key)) + break; + continue; + } + variant = g_variant_new_boolean (v); + } else { + nm_assert_not_reached (); + continue; + } + + g_hash_table_insert (h, + g_steal_pointer (&key), + g_variant_take_ref (variant)); + } + for (; i < n_keys; i++) + g_free (keys[i]); + } + } else + nm_setting_enumerate_values (setting, read_one_setting_value, info); + + info->setting = NULL; + + if (info->error) + return NULL; + return g_steal_pointer (&setting); } static void @@ -2778,7 +2854,7 @@ nm_keyfile_read (GKeyFile *keyfile, base_dir = base_dir_free = g_get_current_dir (); } } else - g_return_val_if_fail ("/", NULL); + g_return_val_if_fail (base_dir[0] == '/', NULL); connection = nm_simple_connection_new (); @@ -2884,12 +2960,22 @@ write_setting_value (NMSetting *setting, if (info->error) return; - setting_name = nm_setting_get_name (setting); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); nm_assert (pspec); - pip = _parse_info_find (setting_name, key); + pip = _parse_info_find (setting, key, &setting_name); + + if (!setting_name) { + /* the setting type is unknown. That is highly unexpected + * (and as this is currently only called from NetworkManager + * daemon, not possible). + * + * Still, handle it gracefully, because later keyfile writer will become + * public API of libnm, where @setting is (untrusted) user input. + * + * Gracefully here just means: ignore the setting. */ + return; + } if ( !pip && nm_streq (key, NM_SETTING_NAME)) @@ -2984,6 +3070,8 @@ nm_keyfile_write (NMConnection *connection, GError **error) { KeyfileWriterInfo info = { 0 }; + gs_free NMSetting **settings = NULL; + guint i, length = 0; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (!error || !*error, NULL); @@ -2996,12 +3084,59 @@ nm_keyfile_write (NMConnection *connection, info.error = NULL; info.handler = handler; info.user_data = user_data; - nm_connection_for_each_setting_value (connection, write_setting_value, &info); + + settings = nm_connection_get_settings (connection, &length); + for (i = 0; i < length; i++) { + const NMSettInfoSetting *sett_info; + NMSetting *setting = settings[i]; + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + guint k, n_keys; + const char *const*keys; + + nm_assert (!nm_keyfile_plugin_get_alias_for_setting_name (sett_info->setting_class->setting_info->setting_name)); + + n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL); + + if (n_keys > 0) { + const char *setting_name = sett_info->setting_class->setting_info->setting_name; + GHashTable *h = _nm_setting_gendata_hash (setting, FALSE); + + for (k = 0; k < n_keys; k++) { + const char *key = keys[k]; + GVariant *v; + + v = g_hash_table_lookup (h, key); + + if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + g_key_file_set_boolean (info.keyfile, + setting_name, + key, + g_variant_get_boolean (v)); + } else { + /* BUG: The variant type is not implemented. Since the connection + * verifies, this can only mean we either wrongly didn't reject + * the connection as invalid, or we didn't properly implement the + * variant type. */ + nm_assert_not_reached (); + continue; + } + } + } + } else + nm_setting_enumerate_values (setting, write_setting_value, &info); + + if (info.error) + break; + } if (info.error) { g_propagate_error (error, info.error); g_key_file_unref (info.keyfile); return NULL; } + return info.keyfile; } diff --git a/libnm-core/nm-setting-6lowpan.c b/libnm-core/nm-setting-6lowpan.c index 647fef3f5d..c0ce232dab 100644 --- a/libnm-core/nm-setting-6lowpan.c +++ b/libnm-core/nm-setting-6lowpan.c @@ -51,8 +51,7 @@ struct _NMSetting6LowpanClass { * necessary for connection to 6LoWPAN interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING, - _nm_register_setting (6LOWPAN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) #define NM_SETTING_6LOWPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanPrivate)) @@ -196,17 +195,18 @@ finalize (GObject *object) } static void -nm_setting_6lowpan_class_init (NMSetting6LowpanClass *setting_class) +nm_setting_6lowpan_class_init (NMSetting6LowpanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSetting6LowpanPrivate)); + g_type_class_add_private (klass, sizeof (NMSetting6LowpanPrivate)); object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; + + setting_class->verify = verify; /** * NMSetting6Lowpan:parent: @@ -225,4 +225,6 @@ nm_setting_6lowpan_class_init (NMSetting6LowpanClass *setting_class) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_6LOWPAN); } diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index c21197ee25..0d61f91c5d 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -60,8 +60,7 @@ * ISBN: 978-1587051548 **/ -G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING, - _nm_register_setting (802_1X, NM_SETTING_PRIORITY_HW_AUX)) +G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) #define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) @@ -3761,22 +3760,19 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) +nm_setting_802_1x_class_init (NMSetting8021xClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate)); + g_type_class_add_private (klass, sizeof (NMSetting8021xPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; - - /* Properties */ + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; /** * NMSetting8021x:eap: @@ -4806,4 +4802,6 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_802_1X); } diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index 278efe780e..9ffff92783 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -37,8 +37,7 @@ * properties of ADSL connections. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING, - _nm_register_setting (ADSL, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING) #define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate)) @@ -345,22 +344,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_adsl_class_init (NMSettingAdslClass *setting_class) +nm_setting_adsl_class_init (NMSettingAdslClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingAdslPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingAdslPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingAdsl:username: @@ -447,4 +444,6 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class) 0, 65536, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_ADSL); } diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c index 21401489c5..bbc6a83de3 100644 --- a/libnm-core/nm-setting-bluetooth.c +++ b/libnm-core/nm-setting-bluetooth.c @@ -43,8 +43,7 @@ * Point (NAP) profiles. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING, - _nm_register_setting (BLUETOOTH, NM_SETTING_PRIORITY_HW_NON_BASE)) +G_DEFINE_TYPE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING) #define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) @@ -282,20 +281,19 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) +nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBluetoothPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBluetoothPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingBluetooth:bdaddr: @@ -309,10 +307,13 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BLUETOOTH_BDADDR, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BLUETOOTH_BDADDR), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingBluetooth:type: @@ -327,4 +328,7 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BLUETOOTH, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index a35e48529a..0c84b3a01c 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -57,8 +57,7 @@ typedef struct { NMUtilsNamedValue *options_idx_cache; } NMSettingBondPrivate; -G_DEFINE_TYPE_WITH_CODE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING, - _nm_register_setting (BOND, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) #define NM_SETTING_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate)) @@ -872,7 +871,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) { return options_equal (NM_SETTING_BOND (setting), @@ -881,9 +880,8 @@ compare_property (NMSetting *setting, flags); } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_bond_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_bond_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -960,21 +958,21 @@ finalize (GObject *object) } static void -nm_setting_bond_class_init (NMSettingBondClass *setting_class) +nm_setting_bond_class_init (NMSettingBondClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBondPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; + /** * NMSettingBond:options: (type GHashTable(utf8,utf8)): * @@ -996,10 +994,13 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BOND_OPTIONS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BOND_OPTIONS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /* ---dbus--- * property: interface-name @@ -1009,8 +1010,12 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class) * bond's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BOND, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c index 9ca478c8d3..4104f8c5cc 100644 --- a/libnm-core/nm-setting-bridge-port.c +++ b/libnm-core/nm-setting-bridge-port.c @@ -40,8 +40,7 @@ * optional properties that apply to bridge ports. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE_PORT, NM_SETTING_PRIORITY_AUX)) +G_DEFINE_TYPE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING) #define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate)) @@ -211,19 +210,18 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class) +nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingBridgePortPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBridgePortPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingBridgePort:priority: * @@ -289,4 +287,6 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_BRIDGE_PORT); } diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 1011dc9d53..71fe2ed234 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -38,8 +38,7 @@ * necessary for bridging connections. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) #define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate)) @@ -392,20 +391,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) +nm_setting_bridge_class_init (NMSettingBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBridgePrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBridgePrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingBridge:mac-address: * @@ -443,10 +442,13 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BRIDGE_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BRIDGE_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingBridge:stp: @@ -637,8 +639,12 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) * bridge's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c index bf606f9022..a5d5428d4b 100644 --- a/libnm-core/nm-setting-cdma.c +++ b/libnm-core/nm-setting-cdma.c @@ -37,8 +37,7 @@ * networks, including those using CDMA2000/EVDO technology. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING, - _nm_register_setting (CDMA, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) #define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) @@ -284,22 +283,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class) +nm_setting_cdma_class_init (NMSettingCdmaClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingCdmaPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingCdmaPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingCdma:number: @@ -374,4 +371,5 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class) NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_CDMA); } diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index c4190831b1..a7d1777f01 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -45,8 +45,7 @@ * a #NMSettingConnection setting. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING, - _nm_register_setting (CONNECTION, NM_SETTING_PRIORITY_CONNECTION)) +G_DEFINE_TYPE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) #define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) @@ -1268,7 +1267,6 @@ compare_property (NMSetting *setting, && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_TIMESTAMP) == 0) return TRUE; - /* Otherwise chain up to parent to handle generic compare */ return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags); } @@ -1503,21 +1501,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) +nm_setting_connection_class_init (NMSettingConnectionClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingConnectionPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingConnectionPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; /** * NMSettingConnection:id: @@ -1654,11 +1651,14 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, NM_SETTING_CONNECTION_INTERFACE_NAME, - G_VARIANT_TYPE_STRING, - NULL, - nm_setting_connection_set_interface_name, - nm_setting_connection_no_interface_name); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_CONNECTION_INTERFACE_NAME), + G_VARIANT_TYPE_STRING, + NULL, + nm_setting_connection_set_interface_name, + nm_setting_connection_no_interface_name); /** * NMSettingConnection:type: @@ -2128,4 +2128,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) NM_SETTING_CONNECTION_MDNS_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_CONNECTION, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c index 6471519607..dabcbbaf19 100644 --- a/libnm-core/nm-setting-dcb.c +++ b/libnm-core/nm-setting-dcb.c @@ -40,8 +40,7 @@ * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING, - _nm_register_setting (DCB, NM_SETTING_PRIORITY_HW_AUX)) +G_DEFINE_TYPE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING) #define NM_SETTING_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate)) @@ -906,20 +905,20 @@ finalize (GObject *object) } static void -nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) +nm_setting_dcb_class_init (NMSettingDcbClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingDcbPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingDcb:app-fcoe-flags: * @@ -1118,10 +1117,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_FLOW_CONTROL), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-group-flags: @@ -1166,10 +1168,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_ID, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_GROUP_ID), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-group-bandwidth: (type GArray(guint)) @@ -1192,10 +1197,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-bandwidth: (type GArray(guint)) @@ -1220,10 +1228,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean)) @@ -1246,10 +1257,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-traffic-class: (type GArray(guint)) @@ -1271,8 +1285,14 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_DCB, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-dummy.c b/libnm-core/nm-setting-dummy.c index 38c361f198..9ae05ec4e7 100644 --- a/libnm-core/nm-setting-dummy.c +++ b/libnm-core/nm-setting-dummy.c @@ -34,8 +34,7 @@ * necessary for connection to dummy devices **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING, - _nm_register_setting (DUMMY, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING) /** * nm_setting_dummy_new: @@ -67,9 +66,11 @@ nm_setting_dummy_init (NMSettingDummy *setting) } static void -nm_setting_dummy_class_init (NMSettingDummyClass *setting_class) +nm_setting_dummy_class_init (NMSettingDummyClass *klass) { - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - parent_class->verify = verify; + setting_class->verify = verify; + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_DUMMY); } diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c new file mode 100644 index 0000000000..7bdbcb1a22 --- /dev/null +++ b/libnm-core/nm-setting-ethtool.c @@ -0,0 +1,342 @@ +/* -*- 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. + * + * 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ethtool.h" + +#include "nm-setting-private.h" +#include "nm-ethtool-utils.h" + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-ethtool + * @short_description: Describes connection properties for ethtool related options + * + * The #NMSettingEthtool object is a #NMSetting subclass that describes properties + * to control network driver and hardware settings. + **/ + +/*****************************************************************************/ + +/** + * nm_ethtool_optname_is_feature: + * @optname: the option name to check + * + * Checks whether @optname is a valid option name for an offload feature. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.14 + */ +gboolean +nm_ethtool_optname_is_feature (const char *optname) +{ + return optname && nm_ethtool_id_is_feature (nm_ethtool_id_get_by_name (optname)); +} + +/*****************************************************************************/ + +/** + * NMSettingEthtool: + * + * Ethtool Ethernet Settings + * + * Since: 1.14 + */ +struct _NMSettingEthtool { + NMSetting parent; +}; + +struct _NMSettingEthtoolClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingEthtool, nm_setting_ethtool, NM_TYPE_SETTING) + +#define NM_SETTING_ETHTOOL_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingEthtool, NM_IS_SETTING_ETHTOOL, NMSetting) + +/*****************************************************************************/ + +static void +_notify_attributes (NMSettingEthtool *self) +{ + _nm_setting_gendata_notify (NM_SETTING (self), TRUE); +} + +/*****************************************************************************/ + +/** + * nm_setting_ethtool_get_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * + * Gets and offload feature setting. Returns %NM_TERNARY_DEFAULT if the + * feature is not set. + * + * Returns: a #NMTernary value indicating whether the offload feature + * is enabled, disabled, or left untouched. + * + * Since: 1.14 + */ +NMTernary +nm_setting_ethtool_get_feature (NMSettingEthtool *setting, + const char *optname) +{ + GVariant *v; + + g_return_val_if_fail (NM_IS_SETTING_ETHTOOL (setting), NM_TERNARY_DEFAULT); + g_return_val_if_fail (optname && nm_ethtool_optname_is_feature (optname), NM_TERNARY_DEFAULT); + + v = nm_setting_gendata_get (NM_SETTING (setting), optname); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + return g_variant_get_boolean (v) + ? NM_TERNARY_TRUE + : NM_TERNARY_FALSE; + } + return NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_ethtool_set_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * @value: the new value to set. The special value %NM_TERNARY_DEFAULT + * means to clear the offload feature setting. + * + * Sets and offload feature setting. + * + * Since: 1.14 + */ +void +nm_setting_ethtool_set_feature (NMSettingEthtool *setting, + const char *optname, + NMTernary value) +{ + GHashTable *hash; + GVariant *v; + + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + g_return_if_fail (optname && nm_ethtool_optname_is_feature (optname)); + g_return_if_fail (NM_IN_SET (value, NM_TERNARY_DEFAULT, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE)); + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), + value != NM_TERNARY_DEFAULT); + + if (value == NM_TERNARY_DEFAULT) { + if (hash) { + if (g_hash_table_remove (hash, optname)) + _notify_attributes (setting); + } + return; + } + + v = g_hash_table_lookup (hash, optname); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + if (g_variant_get_boolean (v)) { + if (value == NM_TERNARY_TRUE) + return; + } else { + if (value == NM_TERNARY_FALSE) + return; + } + } + + v = g_variant_ref_sink (g_variant_new_boolean (value != NM_TERNARY_FALSE)); + g_hash_table_insert (hash, + g_strdup (optname), + v); + _notify_attributes (setting); +} + +/** + * nm_setting_ethtool_clear_features: + * @setting: the #NMSettingEthtool + * + * Clears all offload features settings + * + * Since: 1.14 + */ +void +nm_setting_ethtool_clear_features (NMSettingEthtool *setting) +{ + GHashTable *hash; + GHashTableIter iter; + const char *name; + gboolean changed = FALSE; + + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); + if (!hash) + return; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) { + if (nm_ethtool_optname_is_feature (name)) { + g_hash_table_iter_remove (&iter); + changed = TRUE; + } + } + + if (changed) + _notify_attributes (setting); +} + +guint +nm_setting_ethtool_init_features (NMSettingEthtool *setting, + NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */) +{ + GHashTable *hash; + GHashTableIter iter; + guint i; + guint n_req = 0; + const char *name; + GVariant *variant; + + nm_assert (NM_IS_SETTING_ETHTOOL (setting)); + nm_assert (requested); + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + requested[i] = NM_TERNARY_DEFAULT; + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); + if (!hash) + return 0; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) { + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name (name); + + if (!nm_ethtool_id_is_feature (ethtool_id)) + continue; + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) + continue; + + requested[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST] = g_variant_get_boolean (variant) + ? NM_TERNARY_TRUE + : NM_TERNARY_FALSE; + n_req++; + } + + return n_req; +} + +/*****************************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + GHashTable *hash; + GHashTableIter iter; + const char *optname; + GVariant *variant; + + hash = _nm_setting_gendata_hash (setting, FALSE); + + if (!hash) + goto out; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &optname, (gpointer *) &variant)) { + if (!nm_ethtool_optname_is_feature (optname)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unsupported offload feature")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("offload feature has invalid variant type")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + } + +out: + return TRUE; +} + +/*****************************************************************************/ + +static const GVariantType * +get_variant_type (const NMSettInfoSetting *sett_info, + const char *name, + GError **error) +{ + if (nm_ethtool_optname_is_feature (name)) + return G_VARIANT_TYPE_BOOLEAN; + + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown ethtool option '%s'"), + name); + return NULL; +} + +/*****************************************************************************/ + +static void +nm_setting_ethtool_init (NMSettingEthtool *setting) +{ +} + +/** + * nm_setting_ethtool_new: + * + * Creates a new #NMSettingEthtool object with default values. + * + * Returns: (transfer full): the new empty #NMSettingEthtool object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_ethtool_new (void) +{ + return g_object_new (NM_TYPE_SETTING_ETHTOOL, NULL); +} + +static void +nm_setting_ethtool_class_init (NMSettingEthtoolClass *klass) +{ + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + setting_class->verify = verify; + + _nm_setting_class_commit_full (setting_class, + NM_META_SETTING_TYPE_ETHTOOL, + NM_SETT_INFO_SETT_DETAIL ( + .gendata_info = NM_SETT_INFO_SETT_GENDATA ( + .get_variant_type = get_variant_type, + ), + ), + NULL); +} diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h new file mode 100644 index 0000000000..6a0458a516 --- /dev/null +++ b/libnm-core/nm-setting-ethtool.h @@ -0,0 +1,124 @@ +/* -*- 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. + * + * 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_ETHTOOL_H__ +#define __NM_SETTING_ETHTOOL_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +/*****************************************************************************/ + +#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_HW_OFFLOAD "feature-esp-hw-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_TX_CSUM_HW_OFFLOAD "feature-esp-tx-csum-hw-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_FCOE_MTU "feature-fcoe-mtu" +#define NM_ETHTOOL_OPTNAME_FEATURE_GRO "feature-gro" +#define NM_ETHTOOL_OPTNAME_FEATURE_GSO "feature-gso" +#define NM_ETHTOOL_OPTNAME_FEATURE_HIGHDMA "feature-highdma" +#define NM_ETHTOOL_OPTNAME_FEATURE_HW_TC_OFFLOAD "feature-hw-tc-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_L2_FWD_OFFLOAD "feature-l2-fwd-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_LOOPBACK "feature-loopback" +#define NM_ETHTOOL_OPTNAME_FEATURE_LRO "feature-lro" +#define NM_ETHTOOL_OPTNAME_FEATURE_NTUPLE "feature-ntuple" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX "feature-rx" +#define NM_ETHTOOL_OPTNAME_FEATURE_RXHASH "feature-rxhash" +#define NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN "feature-rxvlan" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_ALL "feature-rx-all" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_FCS "feature-rx-fcs" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_GRO_HW "feature-rx-gro-hw" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD "feature-rx-udp_tunnel-port-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_FILTER "feature-rx-vlan-filter" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_FILTER "feature-rx-vlan-stag-filter" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_HW_PARSE "feature-rx-vlan-stag-hw-parse" +#define NM_ETHTOOL_OPTNAME_FEATURE_SG "feature-sg" +#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_RECORD "feature-tls-hw-record" +#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_TX_OFFLOAD "feature-tls-hw-tx-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_TSO "feature-tso" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX "feature-tx" +#define NM_ETHTOOL_OPTNAME_FEATURE_TXVLAN "feature-txvlan" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_FCOE_CRC "feature-tx-checksum-fcoe-crc" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV4 "feature-tx-checksum-ipv4" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV6 "feature-tx-checksum-ipv6" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IP_GENERIC "feature-tx-checksum-ip-generic" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_SCTP "feature-tx-checksum-sctp" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_ESP_SEGMENTATION "feature-tx-esp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_FCOE_SEGMENTATION "feature-tx-fcoe-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_CSUM_SEGMENTATION "feature-tx-gre-csum-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_SEGMENTATION "feature-tx-gre-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_PARTIAL "feature-tx-gso-partial" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_ROBUST "feature-tx-gso-robust" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP4_SEGMENTATION "feature-tx-ipxip4-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP6_SEGMENTATION "feature-tx-ipxip6-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_NOCACHE_COPY "feature-tx-nocache-copy" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER "feature-tx-scatter-gather" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER_FRAGLIST "feature-tx-scatter-gather-fraglist" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCTP_SEGMENTATION "feature-tx-sctp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP6_SEGMENTATION "feature-tx-tcp6-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_ECN_SEGMENTATION "feature-tx-tcp-ecn-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_MANGLEID_SEGMENTATION "feature-tx-tcp-mangleid-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_SEGMENTATION "feature-tx-tcp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_SEGMENTATION "feature-tx-udp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION "feature-tx-udp_tnl-csum-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_SEGMENTATION "feature-tx-udp_tnl-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_VLAN_STAG_HW_INSERT "feature-tx-vlan-stag-hw-insert" + +gboolean nm_ethtool_optname_is_feature (const char *optname); + +/*****************************************************************************/ + +#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type ()) +#define NM_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtool)) +#define NM_SETTING_ETHTOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) +#define NM_IS_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_ETHTOOL)) +#define NM_IS_SETTING_ETHTOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_ETHTOOL)) +#define NM_SETTING_ETHTOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) + +#define NM_SETTING_ETHTOOL_SETTING_NAME "ethtool" + +/*****************************************************************************/ + +typedef struct _NMSettingEthtoolClass NMSettingEthtoolClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_ethtool_get_type (void); + +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_ethtool_new (void); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_14 +NMTernary nm_setting_ethtool_get_feature (NMSettingEthtool *setting, + const char *optname); +NM_AVAILABLE_IN_1_14 +void nm_setting_ethtool_set_feature (NMSettingEthtool *setting, + const char *optname, + NMTernary value); +NM_AVAILABLE_IN_1_14 +void nm_setting_ethtool_clear_features (NMSettingEthtool *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_ETHTOOL_H__ */ diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c index 0c85d448ce..44402e397d 100644 --- a/libnm-core/nm-setting-generic.c +++ b/libnm-core/nm-setting-generic.c @@ -36,8 +36,7 @@ * the "connection type" setting on #NMConnections for generic devices. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING, - _nm_register_setting (GENERIC, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING) #define NM_SETTING_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate)) @@ -66,7 +65,11 @@ nm_setting_generic_init (NMSettingGeneric *setting) } static void -nm_setting_generic_class_init (NMSettingGenericClass *setting_class) +nm_setting_generic_class_init (NMSettingGenericClass *klass) { - g_type_class_add_private (setting_class, sizeof (NMSettingGenericPrivate)); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMSettingGenericPrivate)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_GENERIC); } diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c index b1ab193aa1..b31da68912 100644 --- a/libnm-core/nm-setting-gsm.c +++ b/libnm-core/nm-setting-gsm.c @@ -38,8 +38,7 @@ * networks, including those using GPRS/EDGE and UMTS/HSPA technology. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING, - _nm_register_setting (GSM, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) #define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) @@ -603,22 +602,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) +nm_setting_gsm_class_init (NMSettingGsmClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingGsmPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingGsmPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingGsm:number: @@ -821,10 +819,18 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) G_PARAM_STATIC_STRINGS)); /* Ignore incoming deprecated properties */ - _nm_setting_class_add_dbus_only_property (parent_class, "allowed-bands", - G_VARIANT_TYPE_UINT32, - NULL, NULL); - _nm_setting_class_add_dbus_only_property (parent_class, "network-type", - G_VARIANT_TYPE_INT32, - NULL, NULL); + _properties_override_add_dbus_only (properties_override, + "allowed-bands", + G_VARIANT_TYPE_UINT32, + NULL, + NULL); + + _properties_override_add_dbus_only (properties_override, + "network-type", + G_VARIANT_TYPE_INT32, + NULL, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_GSM, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c index b22a260e5e..d5ae708530 100644 --- a/libnm-core/nm-setting-infiniband.c +++ b/libnm-core/nm-setting-infiniband.c @@ -37,8 +37,7 @@ * necessary for connection to IP-over-InfiniBand networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING, - _nm_register_setting (INFINIBAND, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING) #define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate)) @@ -377,21 +376,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) +nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingInfinibandPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingInfinibandPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; + setting_class->verify = verify; - /* Properties */ /** * NMSettingInfiniband:mac-address: * @@ -424,10 +422,13 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_INFINIBAND_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_INFINIBAND_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingInfiniband:mtu: @@ -525,4 +526,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_INFINIBAND, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index fa5aa60f1a..5af9b64041 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -2621,7 +2621,7 @@ compare_property (NMSetting *setting, NMSettingCompareFlags flags) { NMSettingIPConfigPrivate *a_priv, *b_priv; - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i; if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ADDRESSES)) { @@ -2650,9 +2650,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -2879,22 +2878,37 @@ ip_gateway_set (NMSetting *setting, return TRUE; } +GArray * +_nm_sett_info_property_override_create_array_ip_config (void) +{ + nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref (NM_TYPE_SETTING_IP_CONFIG); + GArray *properties_override = _nm_sett_info_property_override_create_array (); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_GATEWAY), + G_VARIANT_TYPE_STRING, + NULL, + ip_gateway_set, + NULL); + + return properties_override; +} + static void -nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) +nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingIPConfigPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIPConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; /** * NMSettingIPConfig:method: @@ -3044,13 +3058,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_IP_CONFIG_GATEWAY, - G_VARIANT_TYPE_STRING, - NULL, - ip_gateway_set, - NULL); - /** * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) * diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 12ccd6a949..41314f5894 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -30,8 +30,7 @@ * @short_description: Describes connection properties for IP tunnel devices **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING, - _nm_register_setting (IP_TUNNEL, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING) #define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) @@ -622,18 +621,18 @@ finalize (GObject *object) } static void -nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) +nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingIPTunnelPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIPTunnelPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; + + setting_class->verify = verify; /** * NMSettingIPTunnel:parent: @@ -851,4 +850,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_IP_TUNNEL); } diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index a88a3f2b9c..44de154ec0 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -50,8 +50,7 @@ * connection. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP4_CONFIG, NM_SETTING_PRIORITY_IP)) +G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG) #define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) @@ -524,20 +523,19 @@ ip4_route_data_set (NMSetting *setting, } static void -nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) +nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass) { - NMSettingClass *setting_class = NM_SETTING_CLASS (ip4_class); - GObjectClass *object_class = G_OBJECT_CLASS (ip4_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config (); g_type_class_add_private (setting_class, sizeof (NMSettingIP4ConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; - /* properties */ + setting_class->verify = verify; /* ---ifcfg-rh--- * property: method @@ -797,11 +795,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * integers) * ---end--- */ - _nm_setting_class_transform_property (setting_class, - NM_SETTING_IP_CONFIG_DNS, - G_VARIANT_TYPE ("au"), - ip4_dns_to_dbus, - ip4_dns_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_DNS), + G_VARIANT_TYPE ("au"), + ip4_dns_to_dbus, + ip4_dns_from_dbus); /* ---dbus--- * property: addresses @@ -818,18 +817,19 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * for that subnet. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE ("aau"), - ip4_addresses_get, - ip4_addresses_set, - NULL); - - _nm_setting_class_add_dbus_only_property (setting_class, - "address-labels", - G_VARIANT_TYPE_STRING_ARRAY, - ip4_address_labels_get, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ADDRESSES), + G_VARIANT_TYPE ("aau"), + ip4_addresses_get, + ip4_addresses_set, + NULL); + + _properties_override_add_dbus_only (properties_override, + "address-labels", + G_VARIANT_TYPE_STRING_ARRAY, + ip4_address_labels_get, + NULL); /* ---dbus--- * property: address-data @@ -840,11 +840,11 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * also exist on some addresses. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "address-data", - G_VARIANT_TYPE ("aa{sv}"), - ip4_address_data_get, - ip4_address_data_set); + _properties_override_add_dbus_only (properties_override, + "address-data", + G_VARIANT_TYPE ("aa{sv}"), + ip4_address_data_get, + ip4_address_data_set); /* ---dbus--- * property: routes @@ -863,12 +863,13 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * property.) * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ROUTES, - G_VARIANT_TYPE ("aau"), - ip4_routes_get, - ip4_routes_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ROUTES), + G_VARIANT_TYPE ("aau"), + ip4_routes_get, + ip4_routes_set, + NULL); /* ---dbus--- * property: route-data @@ -883,10 +884,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * also exist on some routes. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "route-data", - G_VARIANT_TYPE ("aa{sv}"), - ip4_route_data_get, - ip4_route_data_set); - + _properties_override_add_dbus_only (properties_override, + "route-data", + G_VARIANT_TYPE ("aa{sv}"), + ip4_route_data_get, + ip4_route_data_set); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP4_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index 76a68aa085..a55fd80195 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -52,8 +52,7 @@ * supported. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP6_CONFIG, NM_SETTING_PRIORITY_IP)) +G_DEFINE_TYPE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG) #define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) @@ -548,20 +547,19 @@ finalize (GObject *object) } static void -nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) +nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (ip6_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (ip6_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config (); - g_type_class_add_private (ip6_class, sizeof (NMSettingIP6ConfigPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIP6ConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - setting_class->verify = verify; + object_class->finalize = finalize; - /* Properties */ + setting_class->verify = verify; /* ---ifcfg-rh--- * property: method @@ -890,11 +888,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * description: Array of IP addresses of DNS servers (in network byte order) * ---end--- */ - _nm_setting_class_transform_property (setting_class, - NM_SETTING_IP_CONFIG_DNS, - G_VARIANT_TYPE ("aay"), - ip6_dns_to_dbus, - ip6_dns_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_DNS), + G_VARIANT_TYPE ("aay"), + ip6_dns_to_dbus, + ip6_dns_from_dbus); /* ---dbus--- * property: addresses @@ -910,12 +909,13 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * that subnet. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE ("a(ayuay)"), - ip6_addresses_get, - ip6_addresses_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ADDRESSES), + G_VARIANT_TYPE ("a(ayuay)"), + ip6_addresses_get, + ip6_addresses_set, + NULL); /* ---dbus--- * property: address-data @@ -926,11 +926,11 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * also exist on some addresses. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "address-data", - G_VARIANT_TYPE ("aa{sv}"), - ip6_address_data_get, - ip6_address_data_set); + _properties_override_add_dbus_only (properties_override, + "address-data", + G_VARIANT_TYPE ("aa{sv}"), + ip6_address_data_get, + ip6_address_data_set); /* ---dbus--- * property: routes @@ -946,12 +946,13 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * default metric for the device. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ROUTES, - G_VARIANT_TYPE ("a(ayuayu)"), - ip6_routes_get, - ip6_routes_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ROUTES), + G_VARIANT_TYPE ("a(ayuayu)"), + ip6_routes_get, + ip6_routes_set, + NULL); /* ---dbus--- * property: route-data @@ -966,9 +967,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * also exist on some routes. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "route-data", - G_VARIANT_TYPE ("aa{sv}"), - ip6_route_data_get, - ip6_route_data_set); + _properties_override_add_dbus_only (properties_override, + "route-data", + G_VARIANT_TYPE ("aa{sv}"), + ip6_route_data_get, + ip6_route_data_set); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP6_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c index aca6d6cf70..2c7cff23b1 100644 --- a/libnm-core/nm-setting-macsec.c +++ b/libnm-core/nm-setting-macsec.c @@ -40,8 +40,7 @@ * necessary for connection to MACsec (IEEE 802.1AE) interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING, - _nm_register_setting (MACSEC, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING) #define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate)) @@ -473,18 +472,19 @@ finalize (GObject *object) } static void -nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class) +nm_setting_macsec_class_init (NMSettingMacsecClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingMacsecPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingMacsecPrivate)); object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; + + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; /** * NMSettingMacsec:parent: @@ -626,4 +626,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACSEC); } diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index b3934bb58d..1fc16116e0 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -39,8 +39,7 @@ * necessary for connection to macvlan interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING, - _nm_register_setting (MACVLAN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING) #define NM_SETTING_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate)) @@ -259,20 +258,18 @@ finalize (GObject *object) } static void -nm_setting_macvlan_class_init (NMSettingMacvlanClass *setting_class) +nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingMacvlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingMacvlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingMacvlan:parent: @@ -341,4 +338,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACVLAN); } diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c index 13ba22f0d0..7f4a1bbf11 100644 --- a/libnm-core/nm-setting-olpc-mesh.c +++ b/libnm-core/nm-setting-olpc-mesh.c @@ -39,8 +39,7 @@ static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting); -G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING, - _nm_register_setting (OLPC_MESH, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) @@ -213,20 +212,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) +nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingOlpcMeshPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingOlpcMesh:ssid: * @@ -267,8 +266,14 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_OLPC_MESH, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c index cf7495bed5..9ca5566fb9 100644 --- a/libnm-core/nm-setting-ovs-bridge.c +++ b/libnm-core/nm-setting-ovs-bridge.c @@ -61,8 +61,7 @@ struct _NMSettingOvsBridgeClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING, - _nm_register_setting (OVS_BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING) /*****************************************************************************/ @@ -263,15 +262,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class) +nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsBridge:fail-mode: @@ -333,4 +333,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_BRIDGE); } diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c index f674f3655c..a177098dbf 100644 --- a/libnm-core/nm-setting-ovs-interface.c +++ b/libnm-core/nm-setting-ovs-interface.c @@ -54,8 +54,7 @@ struct _NMSettingOvsInterfaceClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING, - _nm_register_setting (OVS_INTERFACE, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING) /*****************************************************************************/ @@ -362,15 +361,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class) +nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsInterface:type: @@ -387,4 +387,6 @@ nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_INTERFACE); } diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c index bed46256fb..15005eeaef 100644 --- a/libnm-core/nm-setting-ovs-patch.c +++ b/libnm-core/nm-setting-ovs-patch.c @@ -55,8 +55,7 @@ struct _NMSettingOvsPatchClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING, - _nm_register_setting (OVS_PATCH, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING) /*****************************************************************************/ @@ -181,15 +180,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class) +nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsPatch:peer: @@ -207,4 +207,6 @@ nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PATCH); } diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c index df18ec0a97..10e542e7d2 100644 --- a/libnm-core/nm-setting-ovs-port.c +++ b/libnm-core/nm-setting-ovs-port.c @@ -65,8 +65,7 @@ struct _NMSettingOvsPortClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING, - _nm_register_setting (OVS_PORT, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING) /*****************************************************************************/ @@ -360,15 +359,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) +nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsPort:vlan-mode: @@ -466,4 +466,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PORT); } diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c index 4702d8a042..7425da193b 100644 --- a/libnm-core/nm-setting-ppp.c +++ b/libnm-core/nm-setting-ppp.c @@ -35,8 +35,7 @@ * cable and DSL modems and some mobile broadband devices. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING, - _nm_register_setting (PPP, NM_SETTING_PRIORITY_AUX)) +G_DEFINE_TYPE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING) #define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate)) @@ -524,19 +523,18 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_ppp_class_init (NMSettingPppClass *setting_class) +nm_setting_ppp_class_init (NMSettingPppClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingPppPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingPppPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingPpp:noauth: * @@ -797,4 +795,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPP); } diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c index da5bfc9d0c..793d93cea2 100644 --- a/libnm-core/nm-setting-pppoe.c +++ b/libnm-core/nm-setting-pppoe.c @@ -38,8 +38,7 @@ * to provide IP transport, for example cable or DSL modems. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING, - _nm_register_setting (PPPOE, NM_SETTING_PRIORITY_AUX)) +G_DEFINE_TYPE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING) #define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate)) @@ -287,21 +286,20 @@ finalize (GObject *object) } static void -nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class) +nm_setting_pppoe_class_init (NMSettingPppoeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingPppoePrivate)); + g_type_class_add_private (klass, sizeof (NMSettingPppoePrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; + /** * NMSettingPppoe:parent: * @@ -373,4 +371,6 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class) NM_SETTING_SECRET_FLAG_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPPOE); } diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 043836a0f0..1e25226ede 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -31,19 +31,14 @@ #include "nm-core-internal.h" -void _nm_register_setting_impl (const char *name, - GType type, - NMSettingPriority priority); - -#define _nm_register_setting(name, priority) \ - G_STMT_START { \ - _nm_register_setting_impl ("" NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \ - } G_STMT_END +/*****************************************************************************/ NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting); NMSettingPriority _nm_setting_type_get_base_type_priority (GType type); int _nm_setting_compare_priority (gconstpointer a, gconstpointer b); +/*****************************************************************************/ + typedef enum NMSettingUpdateSecretResult { NM_SETTING_UPDATE_SECRET_ERROR = FALSE, NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE, @@ -85,6 +80,8 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, */ #define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + G_PARAM_USER_SHIFT)) +#define NM_SETTING_PARAM_GENDATA_BACKED (1 << (7 + G_PARAM_USER_SHIFT)) + GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting, NMConnection *connection, const char *property); @@ -110,44 +107,78 @@ NMSetting *_nm_setting_new_from_dbus (GType setting_type, NMSettingParseFlags parse_flags, GError **error); -typedef GVariant * (*NMSettingPropertyGetFunc) (NMSetting *setting, - const char *property); -typedef GVariant * (*NMSettingPropertySynthFunc) (NMSetting *setting, - NMConnection *connection, - const char *property); -typedef gboolean (*NMSettingPropertySetFunc) (NMSetting *setting, - GVariant *connection_dict, - const char *property, - GVariant *value, - NMSettingParseFlags parse_flags, - GError **error); -typedef gboolean (*NMSettingPropertyNotSetFunc) (NMSetting *setting, - GVariant *connection_dict, - const char *property, - NMSettingParseFlags parse_flags, - GError **error); - -void _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func); - -void _nm_setting_class_override_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func); - -typedef GVariant * (*NMSettingPropertyTransformToFunc) (const GValue *from); -typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from, GValue *to); - -void _nm_setting_class_transform_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus); +/*****************************************************************************/ + +static inline GArray * +_nm_sett_info_property_override_create_array (void) +{ + return g_array_new (FALSE, FALSE, sizeof (NMSettInfoProperty)); +} + +GArray *_nm_sett_info_property_override_create_array_ip_config (void); + +void _nm_setting_class_commit_full (NMSettingClass *setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray *properties_override); + +static inline void +_nm_setting_class_commit (NMSettingClass *setting_class, + NMMetaSettingType meta_type) +{ + _nm_setting_class_commit_full (setting_class, meta_type, NULL, NULL); +} + +#define NM_SETT_INFO_SETT_GENDATA(...) \ + ({ \ + static const NMSettInfoSettGendata _g = { \ + __VA_ARGS__ \ + }; \ + \ + &_g; \ + }) + +#define NM_SETT_INFO_SETT_DETAIL(...) \ + (&((const NMSettInfoSettDetail) { \ + __VA_ARGS__ \ + })) + +#define NM_SETT_INFO_PROPERTY(...) \ + (&((const NMSettInfoProperty) { \ + __VA_ARGS__ \ + })) + +void _properties_override_add_struct (GArray *properties_override, + const NMSettInfoProperty *prop_info); + +void _properties_override_add__helper (GArray *properties_override, + NMSettInfoProperty *prop_info); + +#define _properties_override_add(properties_override, \ + ...) \ + (_properties_override_add_struct (properties_override, \ + NM_SETT_INFO_PROPERTY (__VA_ARGS__))) + +void _properties_override_add_dbus_only (GArray *properties_override, + const char *property_name, + const GVariantType *dbus_type, + NMSettingPropertySynthFunc synth_func, + NMSettingPropertySetFunc set_func); + +void _properties_override_add_override (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyGetFunc get_func, + NMSettingPropertySetFunc set_func, + NMSettingPropertyNotSetFunc not_set_func); + +void _properties_override_add_transform (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyTransformToFunc to_dbus, + NMSettingPropertyTransformFromFunc from_dbus); + +/*****************************************************************************/ gboolean _nm_setting_use_legacy_property (NMSetting *setting, GVariant *connection_dict, @@ -156,4 +187,6 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting, GPtrArray *_nm_setting_need_secrets (NMSetting *setting); +/*****************************************************************************/ + #endif /* NM_SETTING_PRIVATE_H */ diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c index c32abd824e..d544c7fa14 100644 --- a/libnm-core/nm-setting-proxy.c +++ b/libnm-core/nm-setting-proxy.c @@ -39,8 +39,7 @@ * to fulfill client queries. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING, - _nm_register_setting (PROXY, NM_SETTING_PRIORITY_IP)) +G_DEFINE_TYPE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING) #define NM_SETTING_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate)) @@ -284,18 +283,18 @@ set_property (GObject *object, guint prop_id, } static void -nm_setting_proxy_class_init (NMSettingProxyClass *setting_class) +nm_setting_proxy_class_init (NMSettingProxyClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingProxyPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingProxyPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingProxy:method: @@ -383,4 +382,6 @@ nm_setting_proxy_class_init (NMSettingProxyClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PROXY); } diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c index e73bac8d8a..b173197db8 100644 --- a/libnm-core/nm-setting-serial.c +++ b/libnm-core/nm-setting-serial.c @@ -37,8 +37,7 @@ * such as mobile broadband or analog telephone connections. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING, - _nm_register_setting (SERIAL, NM_SETTING_PRIORITY_HW_AUX)) +G_DEFINE_TYPE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) #define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) @@ -237,19 +236,17 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_serial_class_init (NMSettingSerialClass *setting_class) +nm_setting_serial_class_init (NMSettingSerialClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingSerialPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingSerialPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - /* Properties */ - /** * NMSettingSerial:baud: * @@ -306,11 +303,13 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_SERIAL_PARITY, - G_VARIANT_TYPE_BYTE, - parity_to_dbus, - parity_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_SERIAL_PARITY), + G_VARIANT_TYPE_BYTE, + parity_to_dbus, + parity_from_dbus); /** * NMSettingSerial:stopbits: @@ -338,4 +337,7 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SERIAL, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c index 29161c8cd9..45b3a1d2f5 100644 --- a/libnm-core/nm-setting-sriov.c +++ b/libnm-core/nm-setting-sriov.c @@ -42,8 +42,7 @@ struct _NMSettingSriovClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING, - _nm_register_setting (SRIOV, NM_SETTING_PRIORITY_HW_AUX)) +G_DEFINE_TYPE (NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING) enum { PROP_0, @@ -1197,7 +1196,7 @@ compare_property (NMSetting *setting, { NMSettingSriov *a = NM_SETTING_SRIOV (setting); NMSettingSriov *b = NM_SETTING_SRIOV (other); - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i; if (nm_streq (prop_spec->name, NM_SETTING_SRIOV_VFS)) { @@ -1210,9 +1209,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -1232,16 +1230,18 @@ finalize (GObject *object) } static void -nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) +nm_setting_sriov_class_init (NMSettingSriovClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + 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->finalize = finalize; object_class->get_property = get_property; object_class->set_property = set_property; - parent_class->compare_property = compare_property; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; /** * NMSettingSriov:total-vfs @@ -1308,12 +1308,13 @@ nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_SRIOV_VFS, - G_VARIANT_TYPE ("aa{sv}"), - vfs_to_dbus, - vfs_from_dbus, - NULL); + _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 @@ -1350,4 +1351,7 @@ nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) 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); } diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c index 588446e5dd..43015d3708 100644 --- a/libnm-core/nm-setting-tc-config.c +++ b/libnm-core/nm-setting-tc-config.c @@ -834,8 +834,7 @@ struct _NMSettingTCConfigClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING, - _nm_register_setting (TC_CONFIG, NM_SETTING_PRIORITY_IP)) +G_DEFINE_TYPE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING) /** * nm_setting_tc_config_new: @@ -1242,7 +1241,7 @@ compare_property (NMSetting *setting, { NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG (setting); NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG (other); - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i; if (nm_streq (prop_spec->name, NM_SETTING_TC_CONFIG_QDISCS)) { @@ -1265,9 +1264,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -1589,19 +1587,18 @@ tc_tfilters_set (NMSetting *setting, } static void -nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) +nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; /** * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc)) @@ -1623,12 +1620,13 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_TC_CONFIG_QDISCS, - G_VARIANT_TYPE ("aa{sv}"), - tc_qdiscs_get, - tc_qdiscs_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TC_CONFIG_QDISCS), + G_VARIANT_TYPE ("aa{sv}"), + tc_qdiscs_get, + tc_qdiscs_set, + NULL); /** * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) @@ -1650,10 +1648,14 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_TC_CONFIG_TFILTERS, - G_VARIANT_TYPE ("aa{sv}"), - tc_tfilters_get, - tc_tfilters_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TC_CONFIG_TFILTERS), + G_VARIANT_TYPE ("aa{sv}"), + tc_tfilters_get, + tc_tfilters_set, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TC_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index d6412224e2..ee84aaf72e 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -39,8 +39,7 @@ * optional properties that apply to team ports. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING, - _nm_register_setting (TEAM_PORT, NM_SETTING_PRIORITY_AUX)) +G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING) #define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate)) @@ -408,7 +407,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; NMSettingTeamPortPrivate *a_priv, *b_priv; guint i, j; @@ -442,9 +441,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -587,21 +585,21 @@ finalize (GObject *object) } static void -nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) +nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTeamPortPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; + /** * NMSettingTeamPort:config: * @@ -715,10 +713,14 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TEAM_PORT_LINK_WATCHERS), + G_VARIANT_TYPE ("aa{sv}"), + team_link_watchers_to_dbus, + team_link_watchers_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM_PORT, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index 1718b3e55f..e6737e48ce 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -557,8 +557,7 @@ nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher) /*****************************************************************************/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING, - _nm_register_setting (TEAM, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING) #define NM_SETTING_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate)) @@ -1238,7 +1237,7 @@ compare_property (NMSetting *setting, NMSettingCompareFlags flags) { NMSettingTeamPrivate *a_priv, *b_priv; - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i, j; /* If we are trying to match a connection in order to assume it (and thus @@ -1271,9 +1270,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_team_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_team_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -1558,21 +1556,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_team_class_init (NMSettingTeamClass *setting_class) +nm_setting_team_class_init (NMSettingTeamClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingTeamPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTeamPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; + /** * NMSettingTeam:config: * @@ -1818,11 +1816,13 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_TEAM_LINK_WATCHERS, - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TEAM_LINK_WATCHERS), + G_VARIANT_TYPE ("aa{sv}"), + team_link_watchers_to_dbus, + team_link_watchers_from_dbus); /* ---dbus--- * property: interface-name @@ -1832,8 +1832,12 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * team's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c index de39439557..3e033e2586 100644 --- a/libnm-core/nm-setting-tun.c +++ b/libnm-core/nm-setting-tun.c @@ -38,8 +38,7 @@ * necessary for connection to TUN/TAP interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING, - _nm_register_setting (TUN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING) #define NM_SETTING_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate)) @@ -291,20 +290,19 @@ finalize (GObject *object) } static void -nm_setting_tun_class_init (NMSettingTunClass *setting_class) +nm_setting_tun_class_init (NMSettingTunClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingTunPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTunPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingTun:mode: * @@ -405,4 +403,6 @@ nm_setting_tun_class_init (NMSettingTunClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_TUN); } diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c index 56dd71e93f..d72c909462 100644 --- a/libnm-core/nm-setting-user.c +++ b/libnm-core/nm-setting-user.c @@ -63,8 +63,7 @@ struct _NMSettingUserClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING, - _nm_register_setting (USER, NM_SETTING_PRIORITY_USER)) +G_DEFINE_TYPE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING) #define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER) @@ -397,29 +396,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } static gboolean -hash_table_equal (GHashTable *a, GHashTable *b) -{ - guint n; - GHashTableIter iter; - const char *key, *value, *valu2; - - n = a ? g_hash_table_size (a) : 0; - if (n != (b ? g_hash_table_size (b) : 0)) - return FALSE; - if (n > 0) { - g_hash_table_iter_init (&iter, a); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { - if (!g_hash_table_lookup_extended (b, key, NULL, (gpointer *) &valu2)) - return FALSE; - if (!nm_streq (value, valu2)) - return FALSE; - } - } - return TRUE; - -} - -static gboolean compare_property (NMSetting *setting, NMSetting *other, const GParamSpec *prop_spec, @@ -436,10 +412,10 @@ compare_property (NMSetting *setting, priv = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (setting)); pri2 = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (other)); - if (!hash_table_equal (priv->data, pri2->data)) + if (!nm_utils_hash_table_equal (priv->data, pri2->data, TRUE, g_str_equal)) return FALSE; - if (!hash_table_equal (priv->data_invalid, pri2->data_invalid)) + if (!nm_utils_hash_table_equal (priv->data_invalid, pri2->data_invalid, TRUE, g_str_equal)) return FALSE; return TRUE; @@ -571,12 +547,14 @@ nm_setting_user_class_init (NMSettingUserClass *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->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; + setting_class->compare_property = compare_property; - setting_class->verify = verify; + setting_class->verify = verify; /** * NMSettingUser:data: (type GHashTable(utf8,utf8)) @@ -607,8 +585,13 @@ nm_setting_user_class_init (NMSettingUserClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - _nm_setting_class_transform_property (setting_class, NM_SETTING_USER_DATA, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_USER_DATA), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_USER, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index b9bea9e4cd..1b61da5578 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -41,8 +41,7 @@ * necessary for connection to VLAN interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING, - _nm_register_setting (VLAN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING) #define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate)) @@ -830,20 +829,19 @@ finalize (GObject *object) } static void -nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) +nm_setting_vlan_class_init (NMSettingVlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingVlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingVlan:parent: @@ -920,11 +918,14 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, NM_SETTING_VLAN_FLAGS, - NULL, - _override_flags_get, - NULL, - _override_flags_not_set); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VLAN_FLAGS), + NULL, + _override_flags_get, + NULL, + _override_flags_not_set); /** * NMSettingVlan:ingress-priority-map: @@ -986,8 +987,12 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) * vlan's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VLAN, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index d36ce93485..3b61736128 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -43,8 +43,7 @@ * properties. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING, - _nm_register_setting (VPN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING) #define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate)) @@ -888,27 +887,26 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) +nm_setting_vpn_class_init (NMSettingVpnClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingVpnPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVpnPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->update_one_secret = update_one_secret; - parent_class->get_secret_flags = get_secret_flags; - parent_class->set_secret_flags = set_secret_flags; - parent_class->need_secrets = need_secrets; - parent_class->compare_property = compare_property; - parent_class->clear_secrets_with_flags = clear_secrets_with_flags; + setting_class->verify = verify; + setting_class->update_one_secret = update_one_secret; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + setting_class->need_secrets = need_secrets; + setting_class->compare_property = compare_property; + setting_class->clear_secrets_with_flags = clear_secrets_with_flags; - /* Properties */ /** * NMSettingVpn:service-type: * @@ -974,10 +972,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_DATA, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VPN_DATA), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): @@ -1000,10 +1001,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_SECRETS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VPN_SECRETS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingVpn:timeout: @@ -1022,4 +1026,7 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VPN, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c index c76ac6229b..d00c5a7abd 100644 --- a/libnm-core/nm-setting-vxlan.c +++ b/libnm-core/nm-setting-vxlan.c @@ -36,8 +36,7 @@ * necessary for connection to VXLAN interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING, - _nm_register_setting (VXLAN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING) #define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) @@ -564,20 +563,18 @@ finalize (GObject *object) } static void -nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) +nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingVxlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVxlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingVxlan:parent: @@ -839,4 +836,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_VXLAN); } diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c index 0669b09e4f..4c1a572ee0 100644 --- a/libnm-core/nm-setting-wimax.c +++ b/libnm-core/nm-setting-wimax.c @@ -42,8 +42,7 @@ * connections cannot be activated. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING, - _nm_register_setting (WIMAX, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) #define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) @@ -206,20 +205,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) +nm_setting_wimax_class_init (NMSettingWimaxClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingWimaxPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWimaxPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingWimax:network-name: * @@ -250,8 +249,14 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_WIMAX_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIMAX_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIMAX, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index 104451e2d0..baa40cc4f4 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -40,8 +40,7 @@ * necessary for connection to Ethernet networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING, - _nm_register_setting (WIRED, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) #define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) @@ -782,15 +781,15 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq (prop_spec->name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) { return nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address, NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address); } - parent_class = NM_SETTING_CLASS (nm_setting_wired_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_wired_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static GVariant * @@ -977,21 +976,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) +nm_setting_wired_class_init (NMSettingWiredClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_wired_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wired_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_wired_class, sizeof (NMSettingWiredPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWiredPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; + + setting_class->verify = verify; setting_class->compare_property = compare_property; - /* Properties */ /** * NMSettingWired:port: * @@ -1102,12 +1101,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRED_AUTO_NEGOTIATE, - G_VARIANT_TYPE_BOOLEAN, - _override_autoneg_get, - NULL, - NULL); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_AUTO_NEGOTIATE), + G_VARIANT_TYPE_BOOLEAN, + _override_autoneg_get, + NULL, + NULL); /** * NMSettingWired:mac-address: @@ -1140,10 +1141,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWired:cloned-mac-address: @@ -1195,8 +1199,10 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_CLONED_MAC_ADDRESS), G_VARIANT_TYPE_BYTESTRING, _nm_utils_hwaddr_cloned_get, _nm_utils_hwaddr_cloned_set, @@ -1214,11 +1220,11 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) * "cloned-mac-address". * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "assigned-mac-address", - G_VARIANT_TYPE_STRING, - _nm_utils_hwaddr_cloned_data_synth, - _nm_utils_hwaddr_cloned_data_set); + _properties_override_add_dbus_only (properties_override, + "assigned-mac-address", + G_VARIANT_TYPE_STRING, + _nm_utils_hwaddr_cloned_data_synth, + _nm_utils_hwaddr_cloned_data_set); /** * NMSettingWired:generate-mac-address-mask: @@ -1388,10 +1394,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_S390_OPTIONS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_S390_OPTIONS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingWired:wake-on-lan: @@ -1430,4 +1439,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRED, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index 7ba038e490..d152782168 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -53,8 +53,7 @@ * ISBN: 978-1587051548 **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS_SECURITY, NM_SETTING_PRIORITY_HW_AUX)) +G_DEFINE_TYPE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) #define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate)) @@ -1430,25 +1429,24 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting_class) +nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingWirelessSecurityPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWirelessSecurityPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - parent_class->get_secret_flags = get_secret_flags; - parent_class->set_secret_flags = set_secret_flags; + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; - /* Properties */ /** * NMSettingWirelessSecurity:key-mgmt: * @@ -1855,11 +1853,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - G_VARIANT_TYPE_UINT32, - wep_key_type_to_dbus, - NULL); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE), + G_VARIANT_TYPE_UINT32, + wep_key_type_to_dbus, + NULL); /** * NMSettingWirelessSecurity:wps-method: * @@ -1921,4 +1921,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS_SECURITY, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index 40708e1729..a9cae6c0db 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -40,8 +40,7 @@ * necessary for connection to 802.11 Wi-Fi networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) #define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) @@ -936,15 +935,15 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq (prop_spec->name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) { return nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address, NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address); } - parent_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -1175,21 +1174,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) +nm_setting_wireless_class_init (NMSettingWirelessClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_wireless_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wireless_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_wireless_class, sizeof (NMSettingWirelessPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWirelessPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; + + setting_class->verify = verify; setting_class->compare_property = compare_property; - /* Properties */ /** * NMSettingWireless:ssid: * @@ -1307,10 +1306,13 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_BSSID, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_BSSID), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWireless:rate: @@ -1387,10 +1389,13 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWireless:cloned-mac-address: @@ -1440,12 +1445,14 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_cloned_get, - _nm_utils_hwaddr_cloned_set, - _nm_utils_hwaddr_cloned_not_set); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_cloned_get, + _nm_utils_hwaddr_cloned_set, + _nm_utils_hwaddr_cloned_not_set); /* ---dbus--- * property: assigned-mac-address @@ -1459,11 +1466,11 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * "cloned-mac-address". * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "assigned-mac-address", - G_VARIANT_TYPE_STRING, - _nm_utils_hwaddr_cloned_data_synth, - _nm_utils_hwaddr_cloned_data_set); + _properties_override_add_dbus_only (properties_override, + "assigned-mac-address", + G_VARIANT_TYPE_STRING, + _nm_utils_hwaddr_cloned_data_synth, + _nm_utils_hwaddr_cloned_data_set); /** * NMSettingWireless:generate-mac-address-mask: @@ -1678,9 +1685,11 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * NetworkManager daemons. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, "security", - G_VARIANT_TYPE_STRING, - nm_setting_wireless_get_security, NULL); + _properties_override_add_dbus_only (properties_override, + "security", + G_VARIANT_TYPE_STRING, + nm_setting_wireless_get_security, + NULL); /** * NMSettingWireless:wake-on-wlan: @@ -1707,4 +1716,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wpan.c b/libnm-core/nm-setting-wpan.c index 32a9dd0050..6e1aaadc45 100644 --- a/libnm-core/nm-setting-wpan.c +++ b/libnm-core/nm-setting-wpan.c @@ -65,8 +65,7 @@ struct _NMSettingWpanClass { * necessary for configuring IEEE 802.15.4 (WPAN) MAC layer devices. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING, - _nm_register_setting (WPAN, NM_SETTING_PRIORITY_HW_BASE)) +G_DEFINE_TYPE (NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) #define NM_SETTING_WPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WPAN, NMSettingWpanPrivate)) @@ -214,17 +213,18 @@ finalize (GObject *object) } static void -nm_setting_wpan_class_init (NMSettingWpanClass *setting_wpan_class) +nm_setting_wpan_class_init (NMSettingWpanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_wpan_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wpan_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); g_type_class_add_private (setting_class, sizeof (NMSettingWpanPrivate)); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - setting_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingWpan:mac-address: @@ -269,4 +269,6 @@ nm_setting_wpan_class_init (NMSettingWpanClass *setting_wpan_class) 0, G_MAXUINT16, G_MAXUINT16, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_WPAN); } diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 1b4f3b23e9..d59e3df79d 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -56,6 +56,12 @@ /*****************************************************************************/ typedef struct { + GHashTable *hash; + const char **names; + GVariant **values; +} GenData; + +typedef struct { const char *name; GType type; NMSettingPriority priority; @@ -69,7 +75,7 @@ enum { }; typedef struct { - const SettingInfo *info; + GenData *gendata; } NMSettingPrivate; G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) @@ -78,213 +84,56 @@ G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) /*****************************************************************************/ -static GHashTable *registered_settings = NULL; -static GHashTable *registered_settings_by_type = NULL; - -static gboolean -_nm_gtype_equal (gconstpointer v1, gconstpointer v2) -{ - return *((const GType *) v1) == *((const GType *) v2); -} -static guint -_nm_gtype_hash (gconstpointer v) -{ - return *((const GType *) v); -} - -/*****************************************************************************/ - -static void -_register_settings_ensure_types (void) -{ -#define ENSURE_TYPE(get_type) \ - G_STMT_START { \ - GType get_type (void); \ - \ - get_type (); \ - } G_STMT_END - - ENSURE_TYPE (nm_setting_6lowpan_get_type); - ENSURE_TYPE (nm_setting_802_1x_get_type); - ENSURE_TYPE (nm_setting_adsl_get_type); - ENSURE_TYPE (nm_setting_bluetooth_get_type); - ENSURE_TYPE (nm_setting_bond_get_type); - ENSURE_TYPE (nm_setting_bridge_get_type); - ENSURE_TYPE (nm_setting_bridge_port_get_type); - ENSURE_TYPE (nm_setting_cdma_get_type); - ENSURE_TYPE (nm_setting_connection_get_type); - ENSURE_TYPE (nm_setting_dcb_get_type); - ENSURE_TYPE (nm_setting_dummy_get_type); - ENSURE_TYPE (nm_setting_generic_get_type); - ENSURE_TYPE (nm_setting_gsm_get_type); - ENSURE_TYPE (nm_setting_infiniband_get_type); - ENSURE_TYPE (nm_setting_ip4_config_get_type); - ENSURE_TYPE (nm_setting_ip6_config_get_type); - ENSURE_TYPE (nm_setting_ip_tunnel_get_type); - ENSURE_TYPE (nm_setting_macsec_get_type); - ENSURE_TYPE (nm_setting_macvlan_get_type); - ENSURE_TYPE (nm_setting_olpc_mesh_get_type); - ENSURE_TYPE (nm_setting_ovs_bridge_get_type); - ENSURE_TYPE (nm_setting_ovs_interface_get_type); - ENSURE_TYPE (nm_setting_ovs_patch_get_type); - ENSURE_TYPE (nm_setting_ovs_port_get_type); - ENSURE_TYPE (nm_setting_ppp_get_type); - ENSURE_TYPE (nm_setting_pppoe_get_type); - ENSURE_TYPE (nm_setting_proxy_get_type); - ENSURE_TYPE (nm_setting_serial_get_type); - ENSURE_TYPE (nm_setting_sriov_get_type); - ENSURE_TYPE (nm_setting_tc_config_get_type); - ENSURE_TYPE (nm_setting_team_get_type); - ENSURE_TYPE (nm_setting_team_port_get_type); - ENSURE_TYPE (nm_setting_tun_get_type); - ENSURE_TYPE (nm_setting_user_get_type); - ENSURE_TYPE (nm_setting_vlan_get_type); - ENSURE_TYPE (nm_setting_vpn_get_type); - ENSURE_TYPE (nm_setting_vxlan_get_type); - ENSURE_TYPE (nm_setting_wimax_get_type); - ENSURE_TYPE (nm_setting_wired_get_type); - ENSURE_TYPE (nm_setting_wireless_get_type); - ENSURE_TYPE (nm_setting_wireless_security_get_type); - ENSURE_TYPE (nm_setting_wpan_get_type); -} - -/*****************************************************************************/ - -static int volatile _register_settings_ensure_inited_val = 0; - -#define _register_settings_ensure_inited() \ - G_STMT_START { \ - if (G_UNLIKELY (_register_settings_ensure_inited_val == 0)) \ - _register_settings_ensure_inited_impl (); \ - } G_STMT_END - -static void -_register_settings_ensure_inited_impl (void) -{ - _register_settings_ensure_types (); - g_atomic_int_set (&_register_settings_ensure_inited_val, 1); -} - -/*****************************************************************************/ - -#define _ensure_setting_info(self, priv) \ - G_STMT_START { \ - NMSettingPrivate *_priv_esi = (priv); \ - if (G_UNLIKELY (!_priv_esi->info)) { \ - _priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \ - g_assert (_priv_esi->info); \ - } \ - } G_STMT_END +static GenData *_gendata_hash (NMSetting *setting, gboolean create_if_necessary); /*****************************************************************************/ -/* - * _nm_register_setting_impl: - * @name: the name of the #NMSetting object to register - * @type: the #GType of the #NMSetting - * @priority: the sort priority of the setting, see #NMSettingPriority - * - * INTERNAL ONLY: registers a setting's internal properties with libnm. - * - * This should be called from within G_DEFINE_TYPE_WITH_CODE() when initializing - * the setting type. - */ -void -_nm_register_setting_impl (const char *name, - GType type, - NMSettingPriority priority) -{ - static GMutex mutex; - SettingInfo *info; - - nm_assert (name && *name); - nm_assert (!NM_IN_SET (type, G_TYPE_INVALID, G_TYPE_NONE)); - nm_assert (priority != NM_SETTING_PRIORITY_INVALID); - - nm_assert ( priority != NM_SETTING_PRIORITY_CONNECTION - || nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME)); - - info = g_slice_new0 (SettingInfo); - info->type = type; - info->priority = priority; - info->name = name; - - g_mutex_lock (&mutex); - - if (!registered_settings) { - nm_assert (!registered_settings_by_type); - registered_settings = g_hash_table_new (nm_str_hash, g_str_equal); - registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal); - } else { - nm_assert (!g_hash_table_contains (registered_settings, name)); - nm_assert (!g_hash_table_contains (registered_settings_by_type, &type)); - } - - g_hash_table_insert (registered_settings, (void *) info->name, info); - g_hash_table_insert (registered_settings_by_type, &info->type, info); - - g_mutex_unlock (&mutex); - - /* we cannot register types, after _register_settings_ensure_inited() is done. - * - * This means, you need to register the type in _register_settings_ensure_types() - * above. */ - nm_assert (g_atomic_int_get (&_register_settings_ensure_inited_val) == 0); -} - -static const SettingInfo * -_nm_setting_lookup_setting_by_type (GType type) -{ - _register_settings_ensure_inited (); - return g_hash_table_lookup (registered_settings_by_type, &type); -} - static NMSettingPriority -_get_setting_type_priority (GType type) +_get_base_type_priority (const NMMetaSettingInfo *setting_info, + GType gtype) { - const SettingInfo *info; + /* Historical oddity: PPPoE is a base-type even though it's not + * priority 1. It needs to be sorted *after* lower-level stuff like + * Wi-Fi security or 802.1x for secrets, but it's still allowed as a + * base type. + */ - g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32); + if (setting_info) { + if ( NM_IN_SET (setting_info->setting_priority, + NM_SETTING_PRIORITY_HW_BASE, + NM_SETTING_PRIORITY_HW_NON_BASE) + || gtype == NM_TYPE_SETTING_PPPOE) + return setting_info->setting_priority; + } - info = _nm_setting_lookup_setting_by_type (type); - return info->priority; + return NM_SETTING_PRIORITY_INVALID; } NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting) { - NMSettingPrivate *priv; + const NMMetaSettingInfo *setting_info; - g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32); - priv = NM_SETTING_GET_PRIVATE (setting); - _ensure_setting_info (setting, priv); - return priv->info->priority; + g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID); + + setting_info = NM_SETTING_GET_CLASS (setting)->setting_info; + return setting_info ? setting_info->setting_priority : NM_SETTING_PRIORITY_INVALID; } NMSettingPriority _nm_setting_type_get_base_type_priority (GType type) { - NMSettingPriority priority; - - /* Historical oddity: PPPoE is a base-type even though it's not - * priority 1. It needs to be sorted *after* lower-level stuff like - * Wi-Fi security or 802.1x for secrets, but it's still allowed as a - * base type. - */ - priority = _get_setting_type_priority (type); - if ( NM_IN_SET (priority, - NM_SETTING_PRIORITY_HW_BASE, - NM_SETTING_PRIORITY_HW_NON_BASE) - || type == NM_TYPE_SETTING_PPPOE) - return priority; - else - return NM_SETTING_PRIORITY_INVALID; + return _get_base_type_priority (nm_meta_setting_infos_by_gtype (type), + type); } NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting) { - return _nm_setting_type_get_base_type_priority (G_OBJECT_TYPE (setting)); + g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID); + + return _get_base_type_priority (NM_SETTING_GET_CLASS (setting)->setting_info, + G_OBJECT_TYPE (setting)); } /** @@ -299,14 +148,12 @@ _nm_setting_get_base_type_priority (NMSetting *setting) GType nm_setting_lookup_type (const char *name) { - const SettingInfo *info; + const NMMetaSettingInfo *setting_info; g_return_val_if_fail (name, G_TYPE_INVALID); - _register_settings_ensure_inited (); - - info = g_hash_table_lookup (registered_settings, name); - return info ? info->type : G_TYPE_INVALID; + setting_info = nm_meta_setting_infos_by_name (name); + return setting_info ? setting_info->get_setting_gtype () : G_TYPE_INVALID; } int @@ -354,90 +201,53 @@ _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_t /*****************************************************************************/ -typedef struct { - const char *name; - GParamSpec *param_spec; - const GVariantType *dbus_type; - - NMSettingPropertyGetFunc get_func; - NMSettingPropertySynthFunc synth_func; - NMSettingPropertySetFunc set_func; - NMSettingPropertyNotSetFunc not_set_func; - - NMSettingPropertyTransformToFunc to_dbus; - NMSettingPropertyTransformFromFunc from_dbus; -} NMSettingProperty; - -static NM_CACHED_QUARK_FCN ("nm-setting-property-overrides", setting_property_overrides_quark) -static NM_CACHED_QUARK_FCN ("nm-setting-properties", setting_properties_quark) - -static NMSettingProperty * -find_property (GArray *properties, const char *name) +static const NMSettInfoProperty * +_nm_sett_info_property_find_in_array (const NMSettInfoProperty *properties, guint len, const char *name) { - NMSettingProperty *property; - int i; - - if (!properties) - return NULL; + guint i; - for (i = 0; i < properties->len; i++) { - property = &g_array_index (properties, NMSettingProperty, i); - if (strcmp (name, property->name) == 0) - return property; + for (i = 0; i < len; i++) { + if (nm_streq (name, properties[i].name)) + return &properties[i]; } - return NULL; } -static void -add_property_override (NMSettingClass *setting_class, - const char *property_name, - GParamSpec *param_spec, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus) +void +_properties_override_add_struct (GArray *properties_override, + const NMSettInfoProperty *prop_info) { - GType setting_type = G_TYPE_FROM_CLASS (setting_class); - GArray *overrides; - NMSettingProperty override; - - g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark ()) == NULL); - - memset (&override, 0, sizeof (override)); - override.name = property_name; - override.param_spec = param_spec; - override.dbus_type = dbus_type; - override.get_func = get_func; - override.synth_func = synth_func; - override.set_func = set_func; - override.not_set_func = not_set_func; - override.to_dbus = to_dbus; - override.from_dbus = from_dbus; - - overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark ()); - if (!overrides) { - overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - g_type_set_qdata (setting_type, setting_property_overrides_quark (), overrides); + nm_assert (properties_override); + nm_assert (prop_info); + nm_assert (prop_info->name || prop_info->param_spec); + nm_assert (!prop_info->param_spec || !prop_info->name || nm_streq0 (prop_info->name, prop_info->param_spec->name)); + nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + properties_override->len, + prop_info->name ?: prop_info->param_spec->name)); + + nm_assert (!prop_info->from_dbus || prop_info->dbus_type); + nm_assert (!prop_info->set_func || prop_info->dbus_type); + + g_array_append_vals (properties_override, prop_info, 1); + + if (!prop_info->name) { + /* for convenience, allow omitting "name" if "param_spec" is given. */ + g_array_index (properties_override, + NMSettInfoProperty, + properties_override->len - 1).name = prop_info->param_spec->name; } - g_return_if_fail (find_property (overrides, property_name) == NULL); - - g_array_append_val (overrides, override); } /** - * _nm_setting_class_add_dbus_only_property: - * @setting_class: the setting class + * _properties_override_add_dbus_only: + * @properties_override: an array collecting the overrides * @property_name: the name of the property to override * @dbus_type: the type of the property (in its D-Bus representation) * @synth_func: (allow-none): function to call to synthesize a value for the property * @set_func: (allow-none): function to call to set the value of the property * * Registers a property named @property_name, which will be used in the D-Bus - * serialization of objects of @setting_class, but which does not correspond to + * serialization of objects of this setting type, but which does not correspond to * a #GObject property. * * When serializing a setting to D-Bus, @synth_func will be called to synthesize @@ -450,35 +260,30 @@ add_property_override (NMSettingClass *setting_class, * then the property will be ignored when deserializing.) */ void -_nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func) +_properties_override_add_dbus_only (GArray *properties_override, + const char *property_name, + const GVariantType *dbus_type, + NMSettingPropertySynthFunc synth_func, + NMSettingPropertySetFunc set_func) { - g_return_if_fail (NM_IS_SETTING_CLASS (setting_class)); - g_return_if_fail (property_name != NULL); - - /* Must not match any GObject property. */ - g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name)); - - add_property_override (setting_class, - property_name, NULL, dbus_type, - NULL, synth_func, set_func, NULL, - NULL, NULL); + _properties_override_add (properties_override, + .name = property_name, + .dbus_type = dbus_type, + .synth_func = synth_func, + .set_func = set_func); } /** - * _nm_setting_class_override_property: - * @setting_class: the setting class - * @property_name: the name of the property to override + * _properties_override_add_override: + * @properties_override: an array collecting the overrides + * @param_spec: the name of the property to override * @dbus_type: the type of the property (in its D-Bus representation) * @get_func: (allow-none): function to call to get the value of the property * @set_func: (allow-none): function to call to set the value of the property * @not_set_func: (allow-none): function to call to indicate the property was not set * - * Overrides the D-Bus representation of the #GObject property named - * @property_name on @setting_class. + * Overrides the D-Bus representation of the #GObject property that shares the + * same name as @param_spec. * * When serializing a setting to D-Bus, if @get_func is non-%NULL, then it will * be called to get the property's value. If it returns a #GVariant, the @@ -487,38 +292,38 @@ _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, * with g_object_get_property(), and added to the hash if it is not the default * value.) * - * When deserializing a D-Bus representation into a setting, if @property_name - * is present, then @set_func will be called to set it. (If @set_func is %NULL - * then the property will be set normally with g_object_set_property().) + * When deserializing a D-Bus representation into a setting, if a value with + * the name of @param_spec is present, then @set_func will be called to set it. + * (If @set_func is %NULL then the property will be set normally with + * g_object_set_property().) * * If @not_set_func is non-%NULL, then it will be called when deserializing a - * representation that does NOT contain @property_name. This can be used, eg, if - * a new property needs to be initialized from some older deprecated property + * representation that does NOT contain a value for the property. This can be used, + * eg, if a new property needs to be initialized from some older deprecated property * when it is not present. */ void -_nm_setting_class_override_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func) +_properties_override_add_override (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyGetFunc get_func, + NMSettingPropertySetFunc set_func, + NMSettingPropertyNotSetFunc not_set_func) { - GParamSpec *param_spec; - - param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name); - g_return_if_fail (param_spec != NULL); - - add_property_override (setting_class, - property_name, param_spec, dbus_type, - get_func, NULL, set_func, not_set_func, - NULL, NULL); + nm_assert (param_spec); + + _properties_override_add (properties_override, + .param_spec = param_spec, + .dbus_type = dbus_type, + .get_func = get_func, + .set_func = set_func, + .not_set_func = not_set_func); } /** - * _nm_setting_class_transform_property: - * @setting_class: the setting class - * @property: the name of the property to transform + * _properties_override_add_transform: + * @properties_override: an array collecting the overrides + * @param_spec: the param spec of the property to transform. * @dbus_type: the type of the property (in its D-Bus representation) * @to_dbus: function to convert from object to D-Bus format * @from_dbus: function to convert from D-Bus to object format @@ -532,23 +337,143 @@ _nm_setting_class_override_property (NMSettingClass *setting_class, * nm_property_compare() recognizes, as long as it recognizes @dbus_type. */ void -_nm_setting_class_transform_property (NMSettingClass *setting_class, - const char *property, - const GVariantType *dbus_type, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus) +_properties_override_add_transform (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyTransformToFunc to_dbus, + NMSettingPropertyTransformFromFunc from_dbus) { - GParamSpec *param_spec; + nm_assert (param_spec); + + _properties_override_add (properties_override, + .param_spec = param_spec, + .dbus_type = dbus_type, + .to_dbus = to_dbus, + .from_dbus = from_dbus); +} - param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property); - g_return_if_fail (param_spec != NULL); +static NMSettInfoSetting _sett_info_settings[_NM_META_SETTING_TYPE_NUM]; - add_property_override (setting_class, - property, param_spec, dbus_type, - NULL, NULL, NULL, NULL, - to_dbus, from_dbus); +void +_nm_setting_class_commit_full (NMSettingClass *setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray *properties_override) +{ + NMSettInfoSetting *sett_info; + gs_free GParamSpec **property_specs = NULL; + guint i, n_property_specs, override_len; + + nm_assert (NM_IS_SETTING_CLASS (setting_class)); + nm_assert (!setting_class->setting_info); + + nm_assert (meta_type < G_N_ELEMENTS (_sett_info_settings)); + + sett_info = &_sett_info_settings[meta_type]; + + nm_assert (!sett_info->setting_class); + nm_assert (!sett_info->property_infos_len); + nm_assert (!sett_info->property_infos); + + if (!properties_override) { + override_len = 0; + properties_override = _nm_sett_info_property_override_create_array (); + } else + override_len = properties_override->len; + + property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class), + &n_property_specs); + +#if NM_MORE_ASSERTS > 10 + /* assert that properties_override is constructed consistently. */ + for (i = 0; i < override_len; i++) { + guint j; + const NMSettInfoProperty *p = &g_array_index (properties_override, NMSettInfoProperty, i); + + nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + i, + p->name)); + for (j = 0; j < n_property_specs; j++) { + if (nm_streq (property_specs[j]->name, p->name)) { + nm_assert (p->param_spec == property_specs[j]); + break; + } + } + nm_assert ((j == n_property_specs) == (p->param_spec == NULL)); + } +#endif + + for (i = 0; i < n_property_specs; i++) { + const char *name = property_specs[i]->name; + NMSettInfoProperty *p; + + if (_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + override_len, + name)) + continue; + + g_array_set_size (properties_override, properties_override->len + 1); + p = &g_array_index (properties_override, NMSettInfoProperty, properties_override->len - 1); + memset (p, 0, sizeof (*p)); + p->name = name; + p->param_spec = property_specs[i]; + } + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0); + g_array_sort (properties_override, nm_strcmp_p); + + setting_class->setting_info = &nm_meta_setting_infos[meta_type]; + sett_info->setting_class = setting_class; + if (detail) + sett_info->detail = *detail; + sett_info->property_infos_len = properties_override->len; + sett_info->property_infos = (const NMSettInfoProperty *) g_array_free (properties_override, + properties_override->len == 0); +} + +const NMSettInfoSetting * +_nm_sett_info_setting_get (NMSettingClass *setting_class) +{ + if ( NM_IS_SETTING_CLASS (setting_class) + && setting_class->setting_info) { + nm_assert (setting_class->setting_info->meta_type < G_N_ELEMENTS (_sett_info_settings)); + return &_sett_info_settings[setting_class->setting_info->meta_type]; + } + return NULL; +} + +const NMSettInfoProperty * +_nm_sett_info_property_get (NMSettingClass *setting_class, + const char *property_name) +{ + const NMSettInfoSetting *sett_info = _nm_sett_info_setting_get (setting_class); + const NMSettInfoProperty *property; + gssize idx; + + if (!sett_info) + return NULL; + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0); + idx = nm_utils_array_find_binary_search (sett_info->property_infos, + sizeof (NMSettInfoProperty), + sett_info->property_infos_len, + &property_name, + nm_strcmp_p_with_data, + NULL); + + if (idx < 0) + return NULL; + + property = &sett_info->property_infos[idx]; + + nm_assert (idx == 0 || strcmp (property[-1].name, property[0].name) < 0); + nm_assert (idx == sett_info->property_infos_len - 1 || strcmp (property[0].name, property[1].name) < 0); + + return property; } +/*****************************************************************************/ + gboolean _nm_setting_use_legacy_property (NMSetting *setting, GVariant *connection_dict, @@ -585,77 +510,6 @@ _nm_setting_use_legacy_property (NMSetting *setting, return FALSE; } -static GArray * -nm_setting_class_ensure_properties (NMSettingClass *setting_class) -{ - GType type = G_TYPE_FROM_CLASS (setting_class), otype; - NMSettingProperty property, *override; - GArray *overrides, *type_overrides, *properties; - GParamSpec **property_specs; - guint n_property_specs, i; - - properties = g_type_get_qdata (type, setting_properties_quark ()); - if (properties) - return properties; - - /* Build overrides array from @setting_class and its superclasses */ - overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - for (otype = type; otype != G_TYPE_OBJECT; otype = g_type_parent (otype)) { - type_overrides = g_type_get_qdata (otype, setting_property_overrides_quark ()); - if (type_overrides) - g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len); - } - - /* Build the properties array from the GParamSpecs, obeying overrides */ - properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - - property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class), - &n_property_specs); - for (i = 0; i < n_property_specs; i++) { - override = find_property (overrides, property_specs[i]->name); - if (override) - property = *override; - else { - memset (&property, 0, sizeof (property)); - property.name = property_specs[i]->name; - property.param_spec = property_specs[i]; - } - g_array_append_val (properties, property); - } - g_free (property_specs); - - /* Add any remaining overrides not corresponding to GObject properties */ - for (i = 0; i < overrides->len; i++) { - override = &g_array_index (overrides, NMSettingProperty, i); - if (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), override->name)) - g_array_append_val (properties, *override); - } - g_array_unref (overrides); - - g_type_set_qdata (type, setting_properties_quark (), properties); - return properties; -} - -static const NMSettingProperty * -nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties) -{ - GArray *properties; - - properties = nm_setting_class_ensure_properties (setting_class); - - *n_properties = properties->len; - return (NMSettingProperty *) properties->data; -} - -static const NMSettingProperty * -nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name) -{ - GArray *properties; - - properties = nm_setting_class_ensure_properties (setting_class); - return find_property (properties, property_name); -} - /*****************************************************************************/ static const GVariantType * @@ -691,7 +545,7 @@ variant_type_for_gtype (GType type) static GVariant * get_property_for_dbus (NMSetting *setting, - const NMSettingProperty *property, + const NMSettInfoProperty *property, gboolean ignore_default) { GValue prop_value = { 0, }; @@ -728,7 +582,7 @@ get_property_for_dbus (NMSetting *setting, } static gboolean -set_property_from_dbus (const NMSettingProperty *property, +set_property_from_dbus (const NMSettInfoProperty *property, GVariant *src_value, GValue *dst_value) { @@ -779,40 +633,57 @@ set_property_from_dbus (const NMSettingProperty *property, GVariant * _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags) { + NMSettingPrivate *priv; GVariantBuilder builder; GVariant *dbus_value; - const NMSettingProperty *properties; + const NMSettInfoSetting *sett_info; guint n_properties, i; + const char *const*gendata_keys; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties); + priv = NM_SETTING_GET_PRIVATE (setting); g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING); + n_properties = _nm_setting_gendata_get_all (setting, &gendata_keys, NULL); for (i = 0; i < n_properties; i++) { - const NMSettingProperty *property = &properties[i]; + g_variant_builder_add (&builder, + "{sv}", + gendata_keys[i], + g_hash_table_lookup (priv->gendata->hash, gendata_keys[i])); + } + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property = &sett_info->property_infos[i]; GParamSpec *prop_spec = property->param_spec; - if (!prop_spec && !property->synth_func) { - /* D-Bus-only property with no synth_func, so we skip it. */ - continue; - } + if (!prop_spec) { + if (!property->synth_func) + continue; - if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE)) - continue; + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + continue; + } else { + if (!(prop_spec->flags & G_PARAM_WRITABLE)) + continue; - if ( prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY) - && !_nm_utils_is_manager_process) - continue; + if (NM_FLAGS_ANY (prop_spec->flags, NM_SETTING_PARAM_GENDATA_BACKED)) + continue; - if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS) - && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET))) - continue; + if ( (prop_spec->flags & NM_SETTING_PARAM_LEGACY) + && !_nm_utils_is_manager_process) + continue; - if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET))) - continue; + if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS) + && (prop_spec->flags & NM_SETTING_PARAM_SECRET)) + continue; + + if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + && !(prop_spec->flags & NM_SETTING_PARAM_SECRET)) + continue; + } if (property->synth_func) dbus_value = property->synth_func (setting, connection, property->name); @@ -859,8 +730,8 @@ _nm_setting_new_from_dbus (GType setting_type, { gs_unref_object NMSetting *setting = NULL; gs_unref_hashtable GHashTable *keys = NULL; - const NMSettingProperty *properties; - guint i, n_properties; + const NMSettInfoSetting *sett_info; + guint i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL); @@ -904,9 +775,29 @@ _nm_setting_new_from_dbus (GType setting_type, } } - properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties); - for (i = 0; i < n_properties; i++) { - const NMSettingProperty *property = &properties[i]; + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GHashTable *hash; + GVariantIter iter; + char *key; + GVariant *val; + + hash = _gendata_hash (setting, TRUE)->hash; + + g_variant_iter_init (&iter, setting_dict); + while (g_variant_iter_next (&iter, "{sv}", &key, &val)) { + g_hash_table_insert (hash, + key, + val); + } + + _nm_setting_gendata_notify (setting, TRUE); + return g_steal_pointer (&setting); + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property = &sett_info->property_infos[i]; gs_unref_variant GVariant *value = NULL; gs_free_error GError *local = NULL; @@ -1025,12 +916,12 @@ const GVariantType * nm_setting_get_dbus_property_type (NMSetting *setting, const char *property_name) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); g_return_val_if_fail (property_name != NULL, NULL); - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), property_name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), property_name); g_return_val_if_fail (property != NULL, NULL); if (property->dbus_type) @@ -1042,14 +933,32 @@ nm_setting_get_dbus_property_type (NMSetting *setting, gboolean _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value) { + const NMSettInfoSetting *sett_info; GParamSpec *prop_spec; g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (property_name, FALSE); g_return_val_if_fail (value, FALSE); - prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GVariant *variant; + GenData *gendata = _gendata_hash (setting, FALSE); + + variant = gendata ? g_hash_table_lookup (gendata->hash, property_name) : NULL; + if (!variant) { + g_value_unset (value); + return FALSE; + } + + g_value_init (value, G_TYPE_VARIANT); + g_value_set_variant (value, variant); + return TRUE; + } + + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); if (!prop_spec) { g_value_unset (value); return FALSE; @@ -1083,16 +992,37 @@ duplicate_setting (NMSetting *setting, NMSetting * nm_setting_duplicate (NMSetting *setting) { + const NMSettInfoSetting *sett_info; GObject *dup; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); dup = g_object_new (G_OBJECT_TYPE (setting), NULL); - g_object_freeze_notify (dup); - nm_setting_enumerate_values (setting, duplicate_setting, dup); - g_object_thaw_notify (dup); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GenData *gendata = _gendata_hash (setting, FALSE); + + if ( gendata + && g_hash_table_size (gendata->hash) > 0) { + GHashTableIter iter; + GHashTable *h = _gendata_hash (NM_SETTING (dup), TRUE)->hash; + const char *key; + GVariant *val; + g_hash_table_iter_init (&iter, gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + g_hash_table_insert (h, + g_strdup (key), + g_variant_ref (val)); + } + } + } else { + g_object_freeze_notify (dup); + nm_setting_enumerate_values (setting, duplicate_setting, dup); + g_object_thaw_notify (dup); + } return NM_SETTING (dup); } @@ -1108,12 +1038,12 @@ nm_setting_duplicate (NMSetting *setting) const char * nm_setting_get_name (NMSetting *setting) { - NMSettingPrivate *priv; + const NMMetaSettingInfo *setting_info; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - priv = NM_SETTING_GET_PRIVATE (setting); - _ensure_setting_info (setting, priv); - return priv->info->name; + + setting_info = NM_SETTING_GET_CLASS (setting)->setting_info; + return setting_info ? setting_info->setting_name : NULL; } /** @@ -1207,7 +1137,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GVariant *value1, *value2; int cmp; @@ -1239,7 +1169,7 @@ compare_property (NMSetting *setting, return TRUE; } - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), prop_spec->name); g_return_val_if_fail (property != NULL, FALSE); value1 = get_property_for_dbus (setting, property, TRUE); @@ -1272,6 +1202,7 @@ nm_setting_compare (NMSetting *a, NMSetting *b, NMSettingCompareFlags flags) { + const NMSettInfoSetting *sett_info; GParamSpec **property_specs; guint n_property_specs; int same = TRUE; @@ -1284,6 +1215,18 @@ nm_setting_compare (NMSetting *a, if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b)) return FALSE; + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a)); + + if (sett_info->detail.gendata_info) { + GenData *a_gendata = _gendata_hash (a, FALSE); + GenData *b_gendata = _gendata_hash (b, FALSE); + + return nm_utils_hash_table_equal (a_gendata ? a_gendata->hash : NULL, + b_gendata ? b_gendata->hash : NULL, + TRUE, + g_variant_equal); + } + /* And now all properties */ property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); for (i = 0; i < n_property_specs && same; i++) { @@ -1369,6 +1312,21 @@ should_compare_prop (NMSetting *setting, return TRUE; } +static void +_setting_diff_add_result (GHashTable *results, const char *prop_name, NMSettingDiffResult r) +{ + void *p; + + if (r == NM_SETTING_DIFF_RESULT_UNKNOWN) + return; + + if (g_hash_table_lookup_extended (results, prop_name, NULL, &p)) { + if (!NM_FLAGS_ALL ((guint) r, GPOINTER_TO_UINT (p))) + g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (((guint) r) | GPOINTER_TO_UINT (p))); + } else + g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (r)); +} + /** * nm_setting_diff: * @a: a #NMSetting @@ -1397,8 +1355,7 @@ nm_setting_diff (NMSetting *a, gboolean invert_results, GHashTable **results) { - GParamSpec **property_specs; - guint n_property_specs; + const NMSettInfoSetting *sett_info; guint i; NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; @@ -1442,78 +1399,117 @@ nm_setting_diff (NMSetting *a, results_created = TRUE; } - /* And now all properties */ - property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); - - for (i = 0; i < n_property_specs; i++) { - GParamSpec *prop_spec = property_specs[i]; - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; - - /* Handle compare flags */ - if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) - continue; - if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) - continue; - - compared_any = TRUE; - - if (b) { - gboolean different; + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a)); - different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); - if (different) { - gboolean a_is_default, b_is_default; + if (sett_info->detail.gendata_info) { + const char *key; + GVariant *val, *val2; + GHashTableIter iter; + GenData *a_gendata = _gendata_hash (a, FALSE); + GenData *b_gendata = b ? _gendata_hash (b, FALSE) : NULL; + + if (!a_gendata || !b_gendata) { + if (a_gendata || b_gendata) { + NMSettingDiffResult one_sided_result; + + one_sided_result = a_gendata ? a_result : b_result; + g_hash_table_iter_init (&iter, a_gendata ? a_gendata->hash : b_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, one_sided_result); + } + } + } else { + g_hash_table_iter_init (&iter, a_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = b_gendata ? g_hash_table_lookup (b_gendata->hash, key) : NULL; + compared_any = TRUE; + if ( !val2 + || !g_variant_equal (val, val2)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, a_result); + } + } + g_hash_table_iter_init (&iter, b_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = a_gendata ? g_hash_table_lookup (a_gendata->hash, key) : NULL; + compared_any = TRUE; + if ( !val2 + || !g_variant_equal (val, val2)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, b_result); + } + } + } + } else { + gs_free GParamSpec **property_specs = NULL; + guint n_property_specs; + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; + + /* Handle compare flags */ + if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) + continue; + if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) + continue; + + compared_any = TRUE; + + if (b) { + gboolean different; + + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); + if (different) { + gboolean a_is_default, b_is_default; + GValue value = G_VALUE_INIT; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + a_is_default = g_param_value_defaults (prop_spec, &value); + + g_value_reset (&value); + g_object_get_property (G_OBJECT (b), prop_spec->name, &value); + b_is_default = g_param_value_defaults (prop_spec, &value); + + g_value_unset (&value); + if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } + } + } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) + r = a_result; /* only in A */ + else { GValue value = G_VALUE_INIT; g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - a_is_default = g_param_value_defaults (prop_spec, &value); - - g_value_reset (&value); - g_object_get_property (G_OBJECT (b), prop_spec->name, &value); - b_is_default = g_param_value_defaults (prop_spec, &value); + if (!g_param_value_defaults (prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; g_value_unset (&value); - if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { - if (!a_is_default) - r |= a_result; - if (!b_is_default) - r |= b_result; - } else { - r |= a_result | b_result; - if (a_is_default) - r |= a_result_default; - if (b_is_default) - r |= b_result_default; - } } - } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) - r = a_result; /* only in A */ - else { - GValue value = G_VALUE_INIT; - - g_value_init (&value, prop_spec->value_type); - g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= a_result; - else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) - r |= a_result | a_result_default; - - g_value_unset (&value); - } - if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { - void *p; - - diff_found = TRUE; - if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { - if ((r & GPOINTER_TO_UINT (p)) != r) - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); - } else - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r)); + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + diff_found = TRUE; + _setting_diff_add_result (*results, prop_spec->name, r); + } } } - g_free (property_specs); if (!compared_any && !b) { /* special case: the setting has no properties, and the opposite @@ -1524,7 +1520,7 @@ nm_setting_diff (NMSetting *a, if (diff_found) { /* if there is a difference, we always return FALSE. It also means, we might - * have allocated a new @results hash, and return if to the caller. */ + * have allocated a new @results hash, and return it to the caller. */ return FALSE; } else { if (results_created) { @@ -1580,23 +1576,57 @@ nm_setting_enumerate_values (NMSetting *setting, NMSettingValueIterFn func, gpointer user_data) { + const NMSettInfoSetting *sett_info; GParamSpec **property_specs; - guint n_property_specs; - int i; + guint n_properties; + guint i; GType type; g_return_if_fail (NM_IS_SETTING (setting)); g_return_if_fail (func != NULL); - property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + const char *const*names; + + /* the properties of this setting are not real GObject properties. + * Hence, this API makes little sense (or does it?). Still, call + * @func with each value. */ + n_properties = _nm_setting_gendata_get_all (setting, &names, NULL); + if (n_properties > 0) { + gs_strfreev char **keys = g_strdupv ((char **) names); + GHashTable *h = _gendata_hash (setting, FALSE)->hash; + + for (i = 0; i < n_properties; i++) { + GValue value = G_VALUE_INIT; + GVariant *val = g_hash_table_lookup (h, keys[i]); + + if (!val) { + /* was deleted in the meantime? Skip */ + continue; + } + + g_value_init (&value, G_TYPE_VARIANT); + g_value_set_variant (&value, val); + /* call it will GParamFlags 0. It shall indicate that this + * is not a "real" GObject property. */ + func (setting, keys[i], &value, 0, user_data); + g_value_unset (&value); + } + } + return; + } + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_properties); /* sort the properties. This has an effect on the order in which keyfile * prints them. */ type = G_OBJECT_TYPE (setting); - g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer), + g_qsort_with_data (property_specs, n_properties, sizeof (gpointer), (GCompareDataFunc) _enumerate_values_sort, &type); - for (i = 0; i < n_property_specs; i++) { + for (i = 0; i < n_properties; i++) { GParamSpec *prop_spec = property_specs[i]; GValue value = G_VALUE_INIT; @@ -1622,7 +1652,7 @@ nm_setting_enumerate_values (NMSetting *setting, gboolean _nm_setting_clear_secrets (NMSetting *setting) { - GParamSpec **property_specs; + gs_free GParamSpec **property_specs = NULL; guint n_property_specs; guint i; gboolean changed = FALSE; @@ -1630,7 +1660,6 @@ _nm_setting_clear_secrets (NMSetting *setting) g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); - for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; @@ -1647,9 +1676,6 @@ _nm_setting_clear_secrets (NMSetting *setting) g_value_unset (&value); } } - - g_free (property_specs); - return changed; } @@ -1700,7 +1726,7 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, NMSettingClearSecretsWithFlagsFn func, gpointer user_data) { - GParamSpec **property_specs; + gs_free GParamSpec **property_specs = NULL; guint n_property_specs; guint i; gboolean changed = FALSE; @@ -1718,8 +1744,6 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, user_data); } } - - g_free (property_specs); return changed; } @@ -1753,11 +1777,11 @@ _nm_setting_need_secrets (NMSetting *setting) static int update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GParamSpec *prop_spec; GValue prop_value = { 0, }; - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), key); if (!property) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -1846,10 +1870,10 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro static gboolean is_secret_prop (NMSetting *setting, const char *secret_name, GError **error) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GParamSpec *pspec; - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), secret_name); if (!property) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -2024,17 +2048,257 @@ _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting, /*****************************************************************************/ -static void -nm_setting_init (NMSetting *setting) +static GenData * +_gendata_hash (NMSetting *setting, gboolean create_if_necessary) { + NMSettingPrivate *priv; + + nm_assert (NM_IS_SETTING (setting)); + + priv = NM_SETTING_GET_PRIVATE (setting); + + if (G_UNLIKELY (!priv->gendata)) { + if (!create_if_necessary) + return NULL; + priv->gendata = g_slice_new (GenData); + priv->gendata->hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + priv->gendata->names = NULL; + priv->gendata->values = NULL; + } + + return priv->gendata; } -static void -constructed (GObject *object) +GHashTable * +_nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary) +{ + GenData *gendata; + + gendata = _gendata_hash (setting, create_if_necessary); + return gendata ? gendata->hash : NULL; +} + +void +_nm_setting_gendata_notify (NMSetting *setting, + gboolean names_changed) +{ + GenData *gendata; + + gendata = _gendata_hash (setting, FALSE); + if (!gendata) + return; + + nm_clear_g_free (&gendata->values); + + if (names_changed) { + /* if only the values changed, it's sufficient to invalidate the + * values cache. Otherwise, the names cache must be invalidated too. */ + nm_clear_g_free (&gendata->names); + } + + /* Note, that currently there is now way to notify the subclass when gendata changed. + * gendata is only changed in two situations: + * 1) from within NMSetting itself, for example when creating a NMSetting instance + * from keyfile or a D-Bus GVariant. + * 2) actively from the subclass itself + * For 2), we don't need the notification, because the subclass knows that something + * changed. + * For 1), we currently don't need the notification either, because all that the subclass + * currently would do, is emit a g_object_notify() signal. However, 1) only happens when + * the setting instance is newly created, at that point, nobody listens to the signal. + * + * If we ever need it, then we would need to call a virtual function to notify the subclass + * that gendata changed. */ +} + +GVariant * +nm_setting_gendata_get (NMSetting *setting, + const char *name) +{ + GenData *gendata; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + g_return_val_if_fail (name, NULL); + + gendata = _gendata_hash (setting, FALSE); + return gendata ? g_hash_table_lookup (gendata->hash, name) : NULL; +} + +guint +_nm_setting_gendata_get_all (NMSetting *setting, + const char *const**out_names, + GVariant *const**out_values) +{ + GenData *gendata; + GHashTable *hash; + guint i, len; + + nm_assert (NM_IS_SETTING (setting)); + + gendata = _gendata_hash (setting, FALSE); + if (!gendata) + goto out_zero; + + hash = gendata->hash; + len = g_hash_table_size (hash); + if (len == 0) + goto out_zero; + + if (!out_names && !out_values) + return len; + + if (G_UNLIKELY (!gendata->names)) { + gendata->names = nm_utils_strdict_get_keys (hash, + TRUE, + NULL); + } + + if (out_values) { + if (G_UNLIKELY (!gendata->values)) { + gendata->values = g_new (GVariant *, len + 1); + for (i = 0; i < len; i++) + gendata->values[i] = g_hash_table_lookup (hash, gendata->names[i]); + gendata->values[i] = NULL; + } + *out_values = gendata->values; + } + + NM_SET_OUT (out_names, (const char *const*) gendata->names); + return len; + +out_zero: + NM_SET_OUT (out_names, NULL); + NM_SET_OUT (out_values, NULL); + return 0; +} + +/** + * nm_setting_gendata_get_all_names: + * @setting: the #NMSetting + * @out_len: (allow-none): (out): + * + * Gives the number of generic data elements and optionally returns all their + * key names and values. This API is low level access and unless you know what you + * are doing, it might not be what you want. + * + * Returns: (array length=out_len zero-terminated=1) (transfer none): + * A %NULL terminated array of key names. If no names are present, this returns + * %NULL. The returned array and the names are owned by %NMSetting and might be invalidated + * soon. + * + * Since: 1.14 + **/ +const char *const* +nm_setting_gendata_get_all_names (NMSetting *setting, + guint *out_len) { - _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object)); + const char *const*names; + guint len; - G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object); + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + len = _nm_setting_gendata_get_all (setting, &names, NULL); + NM_SET_OUT (out_len, len); + return names; +} + +/** + * nm_setting_gendata_get_all_values: + * @setting: the #NMSetting + * + * Gives the number of generic data elements and optionally returns all their + * key names and values. This API is low level access and unless you know what you + * are doing, it might not be what you want. + * + * Returns: (array zero-terminated=1) (transfer none): + * A %NULL terminated array of #GVariant. If no data is present, this returns + * %NULL. The returned array and the variants are owned by %NMSetting and might be invalidated + * soon. The sort order of nm_setting_gendata_get_all_names() and nm_setting_gendata_get_all_values() + * is consistent. That means, the nth value has the nth name returned by nm_setting_gendata_get_all_names(). + * + * Since: 1.14 + **/ +GVariant *const* +nm_setting_gendata_get_all_values (NMSetting *setting) +{ + GVariant *const*values; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + _nm_setting_gendata_get_all (setting, NULL, &values); + return values; +} + +void +_nm_setting_gendata_to_gvalue (NMSetting *setting, + GValue *value) +{ + GenData *gendata; + GHashTable *new; + const char *key; + GVariant *val; + GHashTableIter iter; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (value); + nm_assert (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_HASH_TABLE)); + + new = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + + gendata = _gendata_hash (setting, FALSE); + if (gendata) { + g_hash_table_iter_init (&iter, gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert (new, g_strdup (key), g_variant_ref (val)); + } + + g_value_take_boxed (value, new); +} + +gboolean +_nm_setting_gendata_reset_from_hash (NMSetting *setting, + GHashTable *new) +{ + GenData *gendata; + GHashTableIter iter; + const char *key; + GVariant *val; + guint num; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (new); + + num = new ? g_hash_table_size (new) : 0; + + gendata = _gendata_hash (setting, num > 0); + + if (num == 0) { + if ( !gendata + || g_hash_table_size (gendata->hash) == 0) + return FALSE; + + g_hash_table_remove_all (gendata->hash); + _nm_setting_gendata_notify (setting, TRUE); + return TRUE; + } + + /* let's not bother to find out whether the new hash has any different + * content the the current gendata. Just replace it. */ + g_hash_table_remove_all (gendata->hash); + if (num > 0) { + g_hash_table_iter_init (&iter, new); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert (gendata->hash, g_strdup (key), g_variant_ref (val)); + } + _nm_setting_gendata_notify (setting, TRUE); + return TRUE; +} + +/*****************************************************************************/ + +static void +nm_setting_init (NMSetting *setting) +{ } static void @@ -2054,6 +2318,21 @@ get_property (GObject *object, guint prop_id, } static void +finalize (GObject *object) +{ + NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); + + if (priv->gendata) { + g_free (priv->gendata->names); + g_free (priv->gendata->values); + g_hash_table_unref (priv->gendata->hash); + g_slice_free (GenData, priv->gendata); + } + + G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object); +} + +static void nm_setting_class_init (NMSettingClass *setting_class) { GObjectClass *object_class = G_OBJECT_CLASS (setting_class); @@ -2075,9 +2354,8 @@ nm_setting_class_init (NMSettingClass *setting_class) g_type_class_add_private (setting_class, sizeof (NMSettingPrivate)); - /* virtual methods */ - object_class->constructed = constructed; object_class->get_property = get_property; + object_class->finalize = finalize; setting_class->update_one_secret = update_one_secret; setting_class->get_secret_flags = get_secret_flags; @@ -2085,8 +2363,6 @@ nm_setting_class_init (NMSettingClass *setting_class) setting_class->compare_property = compare_property; setting_class->clear_secrets_with_flags = clear_secrets_with_flags; - /* Properties */ - /** * NMSetting:name: * diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 536aea709d..a7a0f81f40 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -168,6 +168,8 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting, NMSettingSecretFlags flags, gpointer user_data); +struct _NMMetaSettingInfo; + typedef struct { GObjectClass parent; @@ -211,7 +213,10 @@ typedef struct { NMSettingCompareFlags flags); /*< private >*/ - gpointer padding[7]; + const struct _NMMetaSettingInfo *setting_info; + + /*< private >*/ + gpointer padding[6]; } NMSettingClass; /** @@ -282,7 +287,8 @@ void nm_setting_enumerate_values (NMSetting *setting, char *nm_setting_to_string (NMSetting *setting); -/* Secrets */ +/*****************************************************************************/ + gboolean nm_setting_get_secret_flags (NMSetting *setting, const char *secret_name, NMSettingSecretFlags *out_flags, @@ -293,10 +299,13 @@ gboolean nm_setting_set_secret_flags (NMSetting *setting, NMSettingSecretFlags flags, GError **error); -/* Properties */ +/*****************************************************************************/ + const GVariantType *nm_setting_get_dbus_property_type (NMSetting *setting, const char *property_name); +/*****************************************************************************/ + G_END_DECLS #endif /* __NM_SETTING_H__ */ diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 2c9c1fd0ef..f481f11fe5 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -647,119 +647,6 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne return -1; } -gssize -_nm_utils_ptrarray_find_binary_search (gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last) -{ - gssize imin, imax, imid, i2min, i2max, i2mid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - - imin = 0; - if (len > 0) { - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (list[imid], needle, user_data); - if (cmp == 0) { - /* we found a matching entry at index imid. - * - * Does the caller request the first/last index as well (in case that - * there are multiple entries which compare equal). */ - - if (out_idx_first) { - i2min = imin; - i2max = imid + 1; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2max = i2mid -1; - else { - nm_assert (cmp < 0); - i2min = i2mid + 1; - } - } - *out_idx_first = i2min; - } - if (out_idx_last) { - i2min = imid + 1; - i2max = imax; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2min = i2mid + 1; - else { - nm_assert (cmp > 0); - i2max = i2mid - 1; - } - } - *out_idx_last = i2min - 1; - } - return imid; - } - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - imin = ~imin; - NM_SET_OUT (out_idx_first, imin); - NM_SET_OUT (out_idx_last, imin); - return imin; -} - -gssize -_nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data) -{ - gssize imin, imax, imid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - g_return_val_if_fail (elem_size > 0, ~((gssize) 0)); - - imin = 0; - if (len == 0) - return ~imin; - - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data); - if (cmp == 0) - return imid; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - return ~imin; -} - GVariant * _nm_utils_bytes_to_dbus (const GValue *prop_value) { diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index e4a9e8f952..db1d1c1447 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -43,6 +43,7 @@ #include "nm-setting-bridge-port.h" #include "nm-setting-cdma.h" #include "nm-setting-connection.h" +#include "nm-setting-ethtool.h" #include "nm-setting-generic.h" #include "nm-setting-gsm.h" #include "nm-setting-infiniband.h" @@ -65,6 +66,7 @@ #include "nm-simple-connection.h" #include "nm-keyfile-internal.h" #include "nm-utils/nm-dedup-multi.h" +#include "nm-ethtool-utils.h" #include "test-general-enums.h" @@ -6126,7 +6128,7 @@ _test_find_binary_search_do (const int *array, gsize len) expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle); - idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last); + idx = nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last); if (expected_result >= 0) { g_assert_cmpint (expected_result, ==, idx); } else { @@ -6188,12 +6190,12 @@ _test_find_binary_search_do_uint32 (const int *int_array, gsize len) expected_result = idx; } - idx = _nm_utils_array_find_binary_search (array, - sizeof (guint32), - len, - &NEEDLE, - nm_cmp_uint32_p_with_data, - NULL); + idx = nm_utils_array_find_binary_search (array, + sizeof (guint32), + len, + &NEEDLE, + nm_cmp_uint32_p_with_data, + NULL); if (expected_result >= 0) g_assert_cmpint (expected_result, ==, idx); else { @@ -6293,11 +6295,11 @@ test_nm_utils_ptrarray_find_binary_search_with_duplicates (void) for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { gconstpointer p = GINT_TO_POINTER (i); - idx = _nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last); + idx = nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last); idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p); - idx2 = _nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL); + idx2 = nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL); g_assert_cmpint (idx, ==, idx2); if (idx_first2 < 0) { @@ -7058,6 +7060,22 @@ test_nm_va_args_macros (void) /*****************************************************************************/ +static void +test_ethtool_offload (void) +{ + const NMEthtoolData *d; + + g_assert_cmpint (nm_ethtool_id_get_by_name ("invalid"), ==, NM_ETHTOOL_ID_UNKNOWN); + g_assert_cmpint (nm_ethtool_id_get_by_name ("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX); + + d = nm_ethtool_data_get_by_optname (NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); + g_assert (d); + g_assert_cmpint (d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH); + g_assert_cmpstr (d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -7197,8 +7215,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); - g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); - g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); + g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); + g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); @@ -7212,8 +7230,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format); g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); - g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros); + g_test_add_func ("/core/general/test_ethtool_offload", test_ethtool_offload); return g_test_run (); } diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index cb02d1c4a5..5526ad8a7e 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -28,6 +28,7 @@ #include "nm-setting-8021x.h" #include "nm-setting-bond.h" #include "nm-setting-dcb.h" +#include "nm-setting-ethtool.h" #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-setting-tc-config.h" @@ -36,6 +37,7 @@ #include "nm-simple-connection.h" #include "nm-setting-connection.h" #include "nm-errors.h" +#include "nm-keyfile-internal.h" #include "nm-utils/nm-test-utils.h" @@ -1265,6 +1267,79 @@ test_team_port_full_config (void) /*****************************************************************************/ static void +test_ethtool_1 (void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + gs_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection *s_con; + NMSettingEthtool *s_ethtool; + NMSettingEthtool *s_ethtool2; + NMSettingEthtool *s_ethtool3; + + con = nmtst_create_minimal_connection ("ethtool-1", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ethtool)); + + nm_setting_ethtool_set_feature (s_ethtool, + NM_ETHTOOL_OPTNAME_FEATURE_RX, + NM_TERNARY_TRUE); + nm_setting_ethtool_set_feature (s_ethtool, + NM_ETHTOOL_OPTNAME_FEATURE_LRO, + NM_TERNARY_FALSE); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); + + nmtst_connection_normalize (con); + + variant = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus (variant, &error); + nmtst_assert_success (con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); + + nmtst_assert_connection_verifies_without_normalization (con2); + + nmtst_assert_connection_equals (con, FALSE, con2, FALSE); + + keyfile = nm_keyfile_write (con, NULL, NULL, &error); + nmtst_assert_success (keyfile, error); + + con3 = nm_keyfile_read (keyfile, + "ethtool-keyfile-name", + NULL, + NULL, + NULL, + &error); + nmtst_assert_success (con3, error); + + nmtst_connection_normalize (con3); + + nmtst_assert_connection_equals (con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); +} + +/*****************************************************************************/ + +static void test_sriov_vf (void) { NMSriovVF *vf1, *vf2; @@ -1899,6 +1974,8 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/dcb/priorities", test_dcb_priorities_valid); g_test_add_func ("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums); + g_test_add_func ("/libnm/settings/ethtool/1", test_ethtool_1); + g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf); g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); g_test_add_func ("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan); diff --git a/libnm-util/nm-setting-connection.c b/libnm-util/nm-setting-connection.c index e51d2c91da..c7da1aa46c 100644 --- a/libnm-util/nm-setting-connection.c +++ b/libnm-util/nm-setting-connection.c @@ -912,7 +912,6 @@ compare_property (NMSetting *setting, && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_ID) == 0) return TRUE; - /* Otherwise chain up to parent to handle generic compare */ return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags); } diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 070a02a9af..a4af9b0d8e 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -72,6 +72,7 @@ #include "nm-setting-connection.h" #include "nm-setting-dcb.h" #include "nm-setting-dummy.h" +#include "nm-setting-ethtool.h" #include "nm-setting-generic.h" #include "nm-setting-gsm.h" #include "nm-setting-infiniband.h" diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 15f7283fea..042453daa4 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1394,6 +1394,11 @@ global: nm_device_wpan_get_type; nm_setting_6lowpan_get_type; nm_setting_connection_get_multi_connect; + nm_setting_ethtool_clear_features; + nm_setting_ethtool_get_feature; + nm_setting_ethtool_get_type; + nm_setting_ethtool_new; + nm_setting_ethtool_set_feature; nm_setting_sriov_add_vf; nm_setting_sriov_clear_vfs; nm_setting_sriov_get_autoprobe_drivers; diff --git a/libnm/nm-autoptr.h b/libnm/nm-autoptr.h index c56f1ecfae..665c28c0e4 100644 --- a/libnm/nm-autoptr.h +++ b/libnm/nm-autoptr.h @@ -47,6 +47,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingCdma, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingConnection, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingDcb, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingDummy, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingEthtool, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingGeneric, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingGsm, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingInfiniband, g_object_unref) diff --git a/po/POTFILES.in b/po/POTFILES.in index fafc4225d2..ee78d29344 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -67,6 +67,7 @@ libnm-core/nm-setting-bridge.c libnm-core/nm-setting-cdma.c libnm-core/nm-setting-connection.c libnm-core/nm-setting-dcb.c +libnm-core/nm-setting-ethtool.c libnm-core/nm-setting-gsm.c libnm-core/nm-setting-infiniband.c libnm-core/nm-setting-ip-config.c diff --git a/shared/meson.build b/shared/meson.build index db6b8a40d8..8faec8765b 100644 --- a/shared/meson.build +++ b/shared/meson.build @@ -36,7 +36,9 @@ version_header = configure_file( configuration: version_conf, ) -shared_nm_utils_nm_meta_setting_c = files('nm-meta-setting.c') +shared_nm_ethtool_utils_c = files('nm-ethtool-utils.c') + +shared_nm_meta_setting_c = files('nm-meta-setting.c') shared_nm_test_utils_impl_c = files('nm-test-utils-impl.c') diff --git a/shared/nm-ethtool-utils.c b/shared/nm-ethtool-utils.c new file mode 100644 index 0000000000..d50695ae0e --- /dev/null +++ b/shared/nm-ethtool-utils.c @@ -0,0 +1,225 @@ +/* -*- 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. + * + * 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-ethtool-utils.h" + +#include "nm-setting-ethtool.h" + +/*****************************************************************************/ + +#define ETHT_DATA(xname) \ + [NM_ETHTOOL_ID_##xname] = (&((const NMEthtoolData) { \ + .optname = NM_ETHTOOL_OPTNAME_##xname, \ + .id = NM_ETHTOOL_ID_##xname, \ + })) + +const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = { + /* indexed by NMEthtoolID */ + ETHT_DATA (FEATURE_ESP_HW_OFFLOAD), + ETHT_DATA (FEATURE_ESP_TX_CSUM_HW_OFFLOAD), + ETHT_DATA (FEATURE_FCOE_MTU), + ETHT_DATA (FEATURE_GRO), + ETHT_DATA (FEATURE_GSO), + ETHT_DATA (FEATURE_HIGHDMA), + ETHT_DATA (FEATURE_HW_TC_OFFLOAD), + ETHT_DATA (FEATURE_L2_FWD_OFFLOAD), + ETHT_DATA (FEATURE_LOOPBACK), + ETHT_DATA (FEATURE_LRO), + ETHT_DATA (FEATURE_NTUPLE), + ETHT_DATA (FEATURE_RX), + ETHT_DATA (FEATURE_RXHASH), + ETHT_DATA (FEATURE_RXVLAN), + ETHT_DATA (FEATURE_RX_ALL), + ETHT_DATA (FEATURE_RX_FCS), + ETHT_DATA (FEATURE_RX_GRO_HW), + ETHT_DATA (FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD), + ETHT_DATA (FEATURE_RX_VLAN_FILTER), + ETHT_DATA (FEATURE_RX_VLAN_STAG_FILTER), + ETHT_DATA (FEATURE_RX_VLAN_STAG_HW_PARSE), + ETHT_DATA (FEATURE_SG), + ETHT_DATA (FEATURE_TLS_HW_RECORD), + ETHT_DATA (FEATURE_TLS_HW_TX_OFFLOAD), + ETHT_DATA (FEATURE_TSO), + ETHT_DATA (FEATURE_TX), + ETHT_DATA (FEATURE_TXVLAN), + ETHT_DATA (FEATURE_TX_CHECKSUM_FCOE_CRC), + ETHT_DATA (FEATURE_TX_CHECKSUM_IPV4), + ETHT_DATA (FEATURE_TX_CHECKSUM_IPV6), + ETHT_DATA (FEATURE_TX_CHECKSUM_IP_GENERIC), + ETHT_DATA (FEATURE_TX_CHECKSUM_SCTP), + ETHT_DATA (FEATURE_TX_ESP_SEGMENTATION), + ETHT_DATA (FEATURE_TX_FCOE_SEGMENTATION), + ETHT_DATA (FEATURE_TX_GRE_CSUM_SEGMENTATION), + ETHT_DATA (FEATURE_TX_GRE_SEGMENTATION), + ETHT_DATA (FEATURE_TX_GSO_PARTIAL), + ETHT_DATA (FEATURE_TX_GSO_ROBUST), + ETHT_DATA (FEATURE_TX_IPXIP4_SEGMENTATION), + ETHT_DATA (FEATURE_TX_IPXIP6_SEGMENTATION), + ETHT_DATA (FEATURE_TX_NOCACHE_COPY), + ETHT_DATA (FEATURE_TX_SCATTER_GATHER), + ETHT_DATA (FEATURE_TX_SCATTER_GATHER_FRAGLIST), + ETHT_DATA (FEATURE_TX_SCTP_SEGMENTATION), + ETHT_DATA (FEATURE_TX_TCP6_SEGMENTATION), + ETHT_DATA (FEATURE_TX_TCP_ECN_SEGMENTATION), + ETHT_DATA (FEATURE_TX_TCP_MANGLEID_SEGMENTATION), + ETHT_DATA (FEATURE_TX_TCP_SEGMENTATION), + ETHT_DATA (FEATURE_TX_UDP_SEGMENTATION), + ETHT_DATA (FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION), + ETHT_DATA (FEATURE_TX_UDP_TNL_SEGMENTATION), + ETHT_DATA (FEATURE_TX_VLAN_STAG_HW_INSERT), + [_NM_ETHTOOL_ID_NUM] = NULL, +}; + +const guint8 const _by_name[_NM_ETHTOOL_ID_NUM] = { + /* sorted by optname. */ + NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_FCOE_MTU, + NM_ETHTOOL_ID_FEATURE_GRO, + NM_ETHTOOL_ID_FEATURE_GSO, + NM_ETHTOOL_ID_FEATURE_HIGHDMA, + NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_LOOPBACK, + NM_ETHTOOL_ID_FEATURE_LRO, + NM_ETHTOOL_ID_FEATURE_NTUPLE, + NM_ETHTOOL_ID_FEATURE_RX, + NM_ETHTOOL_ID_FEATURE_RX_ALL, + NM_ETHTOOL_ID_FEATURE_RX_FCS, + NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, + NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, + NM_ETHTOOL_ID_FEATURE_RXHASH, + NM_ETHTOOL_ID_FEATURE_RXVLAN, + NM_ETHTOOL_ID_FEATURE_SG, + NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, + NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_TSO, + NM_ETHTOOL_ID_FEATURE_TX, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, + NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, + NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, + NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, + NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, + NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, + NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, + NM_ETHTOOL_ID_FEATURE_TXVLAN, +}; + +/*****************************************************************************/ + +static void +_ASSERT_data (void) +{ +#if NM_MORE_ASSERTS > 10 + int i; + + G_STATIC_ASSERT_EXPR (_NM_ETHTOOL_ID_FIRST == 0); + G_STATIC_ASSERT_EXPR (_NM_ETHTOOL_ID_LAST == _NM_ETHTOOL_ID_NUM - 1); + G_STATIC_ASSERT_EXPR (_NM_ETHTOOL_ID_NUM > 0); + + nm_assert (NM_PTRARRAY_LEN (nm_ethtool_data) == _NM_ETHTOOL_ID_NUM); + nm_assert (G_N_ELEMENTS (_by_name) == _NM_ETHTOOL_ID_NUM); + nm_assert (G_N_ELEMENTS (nm_ethtool_data) == _NM_ETHTOOL_ID_NUM + 1); + + for (i = 0; i < _NM_ETHTOOL_ID_NUM; i++) { + const NMEthtoolData *d = nm_ethtool_data[i]; + + nm_assert (d); + nm_assert (d->id == (NMEthtoolID) i); + nm_assert (d->optname && d->optname[0]); + } + + for (i = 0; i < _NM_ETHTOOL_ID_NUM; i++) { + NMEthtoolID id = _by_name[i]; + const NMEthtoolData *d; + + nm_assert (id >= 0); + nm_assert (id < _NM_ETHTOOL_ID_NUM); + + d = nm_ethtool_data[id]; + if (i > 0) { + /* since we assert that all optnames are sorted strictly monotonically increasing, + * it also follows that there are no duplicates in the _by_name. + * It also follows, that all names in nm_ethtool_data are unique. */ + if (strcmp (nm_ethtool_data[_by_name[i - 1]]->optname, d->optname) >= 0) { + g_error ("nm_ethtool_data is not sorted asciibetically: %u/%s should be after %u/%s", + i - 1, nm_ethtool_data[_by_name[i - 1]]->optname, + i, d->optname); + } + } + } +#endif +} + +static int +_by_name_cmp (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + const guint8 *p_id = a; + const char *optname = b; + + nm_assert (p_id && p_id >= _by_name && p_id <= &_by_name[_NM_ETHTOOL_ID_NUM]); + nm_assert (*p_id < _NM_ETHTOOL_ID_NUM); + + return strcmp (nm_ethtool_data[*p_id]->optname, optname); +} + +const NMEthtoolData * +nm_ethtool_data_get_by_optname (const char *optname) +{ + gssize idx; + + nm_assert (optname); + + _ASSERT_data (); + + idx = nm_utils_array_find_binary_search ((gconstpointer *) _by_name, + sizeof (_by_name[0]), + _NM_ETHTOOL_ID_NUM, + optname, + _by_name_cmp, + NULL); + return (idx < 0) ? NULL : nm_ethtool_data[_by_name[idx]]; +} diff --git a/shared/nm-ethtool-utils.h b/shared/nm-ethtool-utils.h new file mode 100644 index 0000000000..5f22a9a06e --- /dev/null +++ b/shared/nm-ethtool-utils.h @@ -0,0 +1,120 @@ +/* -*- 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. + * + * 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#ifndef __NM_ETHTOOL_UTILS_H__ +#define __NM_ETHTOOL_UTILS_H__ + +/*****************************************************************************/ + +typedef enum { + NM_ETHTOOL_ID_UNKNOWN = -1, + + _NM_ETHTOOL_ID_FIRST = 0, + + _NM_ETHTOOL_ID_FEATURE_FIRST = _NM_ETHTOOL_ID_FIRST, + NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD = _NM_ETHTOOL_ID_FEATURE_FIRST, + NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_FCOE_MTU, + NM_ETHTOOL_ID_FEATURE_GRO, + NM_ETHTOOL_ID_FEATURE_GSO, + NM_ETHTOOL_ID_FEATURE_HIGHDMA, + NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_LOOPBACK, + NM_ETHTOOL_ID_FEATURE_LRO, + NM_ETHTOOL_ID_FEATURE_NTUPLE, + NM_ETHTOOL_ID_FEATURE_RX, + NM_ETHTOOL_ID_FEATURE_RXHASH, + NM_ETHTOOL_ID_FEATURE_RXVLAN, + NM_ETHTOOL_ID_FEATURE_RX_ALL, + NM_ETHTOOL_ID_FEATURE_RX_FCS, + NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, + NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, + NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, + NM_ETHTOOL_ID_FEATURE_SG, + NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, + NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, + NM_ETHTOOL_ID_FEATURE_TSO, + NM_ETHTOOL_ID_FEATURE_TX, + NM_ETHTOOL_ID_FEATURE_TXVLAN, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, + NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, + NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, + NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, + NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, + NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, + NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, + NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, + NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, + _NM_ETHTOOL_ID_FEATURE_LAST = NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, + _NM_ETHTOOL_ID_FEATURE_NUM = (_NM_ETHTOOL_ID_FEATURE_LAST - _NM_ETHTOOL_ID_FEATURE_FIRST + 1), + + _NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_FEATURE_LAST, + + _NM_ETHTOOL_ID_NUM = (_NM_ETHTOOL_ID_LAST - _NM_ETHTOOL_ID_FIRST + 1), +} NMEthtoolID; + +typedef struct { + const char *optname; + NMEthtoolID id; +} NMEthtoolData; + +extern const NMEthtoolData *const nm_ethtool_data[/*_NM_ETHTOOL_ID_NUM + NULL-terminated*/]; + +const NMEthtoolData *nm_ethtool_data_get_by_optname (const char *optname); + +/****************************************************************************/ + +static inline NMEthtoolID +nm_ethtool_id_get_by_name (const char *optname) +{ + const NMEthtoolData *d; + + d = nm_ethtool_data_get_by_optname (optname); + return d ? d->id : NM_ETHTOOL_ID_UNKNOWN; +} + +static inline gboolean +nm_ethtool_id_is_feature (NMEthtoolID id) +{ + return id >= _NM_ETHTOOL_ID_FEATURE_FIRST && id <= _NM_ETHTOOL_ID_FEATURE_LAST; +} + +/****************************************************************************/ + +#endif /* __NM_ETHTOOL_UTILS_H__ */ diff --git a/shared/nm-meta-setting.c b/shared/nm-meta-setting.c index 148f3753f9..c565e55f38 100644 --- a/shared/nm-meta-setting.c +++ b/shared/nm-meta-setting.c @@ -34,6 +34,7 @@ #include "nm-setting-connection.h" #include "nm-setting-dcb.h" #include "nm-setting-dummy.h" +#include "nm-setting-ethtool.h" #include "nm-setting-generic.h" #include "nm-setting-gsm.h" #include "nm-setting-infiniband.h" @@ -149,211 +150,259 @@ const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[] = { const NMMetaSettingInfo nm_meta_setting_infos[] = { [NM_META_SETTING_TYPE_6LOWPAN] = { .meta_type = NM_META_SETTING_TYPE_6LOWPAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_6LOWPAN_SETTING_NAME, .get_setting_gtype = nm_setting_6lowpan_get_type, }, [NM_META_SETTING_TYPE_802_1X] = { .meta_type = NM_META_SETTING_TYPE_802_1X, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, .setting_name = NM_SETTING_802_1X_SETTING_NAME, .get_setting_gtype = nm_setting_802_1x_get_type, }, [NM_META_SETTING_TYPE_ADSL] = { .meta_type = NM_META_SETTING_TYPE_ADSL, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_ADSL_SETTING_NAME, .get_setting_gtype = nm_setting_adsl_get_type, }, [NM_META_SETTING_TYPE_BLUETOOTH] = { .meta_type = NM_META_SETTING_TYPE_BLUETOOTH, + .setting_priority = NM_SETTING_PRIORITY_HW_NON_BASE, .setting_name = NM_SETTING_BLUETOOTH_SETTING_NAME, .get_setting_gtype = nm_setting_bluetooth_get_type, }, [NM_META_SETTING_TYPE_BOND] = { .meta_type = NM_META_SETTING_TYPE_BOND, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_BOND_SETTING_NAME, .get_setting_gtype = nm_setting_bond_get_type, }, [NM_META_SETTING_TYPE_BRIDGE] = { .meta_type = NM_META_SETTING_TYPE_BRIDGE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_BRIDGE_SETTING_NAME, .get_setting_gtype = nm_setting_bridge_get_type, }, [NM_META_SETTING_TYPE_BRIDGE_PORT] = { .meta_type = NM_META_SETTING_TYPE_BRIDGE_PORT, + .setting_priority = NM_SETTING_PRIORITY_AUX, .setting_name = NM_SETTING_BRIDGE_PORT_SETTING_NAME, .get_setting_gtype = nm_setting_bridge_port_get_type, }, [NM_META_SETTING_TYPE_CDMA] = { .meta_type = NM_META_SETTING_TYPE_CDMA, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_CDMA_SETTING_NAME, .get_setting_gtype = nm_setting_cdma_get_type, }, [NM_META_SETTING_TYPE_CONNECTION] = { .meta_type = NM_META_SETTING_TYPE_CONNECTION, + .setting_priority = NM_SETTING_PRIORITY_CONNECTION, .setting_name = NM_SETTING_CONNECTION_SETTING_NAME, .get_setting_gtype = nm_setting_connection_get_type, }, [NM_META_SETTING_TYPE_DCB] = { .meta_type = NM_META_SETTING_TYPE_DCB, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, .setting_name = NM_SETTING_DCB_SETTING_NAME, .get_setting_gtype = nm_setting_dcb_get_type, }, [NM_META_SETTING_TYPE_DUMMY] = { .meta_type = NM_META_SETTING_TYPE_DUMMY, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_DUMMY_SETTING_NAME, .get_setting_gtype = nm_setting_dummy_get_type, }, + [NM_META_SETTING_TYPE_ETHTOOL] = { + .meta_type = NM_META_SETTING_TYPE_ETHTOOL, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_ETHTOOL_SETTING_NAME, + .get_setting_gtype = nm_setting_ethtool_get_type, + }, [NM_META_SETTING_TYPE_GENERIC] = { .meta_type = NM_META_SETTING_TYPE_GENERIC, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_GENERIC_SETTING_NAME, .get_setting_gtype = nm_setting_generic_get_type, }, [NM_META_SETTING_TYPE_GSM] = { .meta_type = NM_META_SETTING_TYPE_GSM, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_GSM_SETTING_NAME, .get_setting_gtype = nm_setting_gsm_get_type, }, [NM_META_SETTING_TYPE_INFINIBAND] = { .meta_type = NM_META_SETTING_TYPE_INFINIBAND, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_INFINIBAND_SETTING_NAME, .get_setting_gtype = nm_setting_infiniband_get_type, }, [NM_META_SETTING_TYPE_IP4_CONFIG] = { .meta_type = NM_META_SETTING_TYPE_IP4_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, .setting_name = NM_SETTING_IP4_CONFIG_SETTING_NAME, .get_setting_gtype = nm_setting_ip4_config_get_type, }, [NM_META_SETTING_TYPE_IP6_CONFIG] = { .meta_type = NM_META_SETTING_TYPE_IP6_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, .setting_name = NM_SETTING_IP6_CONFIG_SETTING_NAME, .get_setting_gtype = nm_setting_ip6_config_get_type, }, [NM_META_SETTING_TYPE_IP_TUNNEL] = { .meta_type = NM_META_SETTING_TYPE_IP_TUNNEL, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME, .get_setting_gtype = nm_setting_ip_tunnel_get_type, }, [NM_META_SETTING_TYPE_MACSEC] = { .meta_type = NM_META_SETTING_TYPE_MACSEC, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_MACSEC_SETTING_NAME, .get_setting_gtype = nm_setting_macsec_get_type, }, [NM_META_SETTING_TYPE_MACVLAN] = { .meta_type = NM_META_SETTING_TYPE_MACVLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_MACVLAN_SETTING_NAME, .get_setting_gtype = nm_setting_macvlan_get_type, }, [NM_META_SETTING_TYPE_OLPC_MESH] = { .meta_type = NM_META_SETTING_TYPE_OLPC_MESH, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_OLPC_MESH_SETTING_NAME, .get_setting_gtype = nm_setting_olpc_mesh_get_type, }, [NM_META_SETTING_TYPE_OVS_BRIDGE] = { .meta_type = NM_META_SETTING_TYPE_OVS_BRIDGE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_OVS_BRIDGE_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_bridge_get_type, }, [NM_META_SETTING_TYPE_OVS_INTERFACE] = { .meta_type = NM_META_SETTING_TYPE_OVS_INTERFACE, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_OVS_INTERFACE_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_interface_get_type, }, [NM_META_SETTING_TYPE_OVS_PATCH] = { .meta_type = NM_META_SETTING_TYPE_OVS_PATCH, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_patch_get_type, }, [NM_META_SETTING_TYPE_OVS_PORT] = { .meta_type = NM_META_SETTING_TYPE_OVS_PORT, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_OVS_PORT_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_port_get_type, }, [NM_META_SETTING_TYPE_PPPOE] = { .meta_type = NM_META_SETTING_TYPE_PPPOE, + .setting_priority = NM_SETTING_PRIORITY_AUX, .setting_name = NM_SETTING_PPPOE_SETTING_NAME, .get_setting_gtype = nm_setting_pppoe_get_type, }, [NM_META_SETTING_TYPE_PPP] = { .meta_type = NM_META_SETTING_TYPE_PPP, + .setting_priority = NM_SETTING_PRIORITY_AUX, .setting_name = NM_SETTING_PPP_SETTING_NAME, .get_setting_gtype = nm_setting_ppp_get_type, }, [NM_META_SETTING_TYPE_PROXY] = { .meta_type = NM_META_SETTING_TYPE_PROXY, + .setting_priority = NM_SETTING_PRIORITY_IP, .setting_name = NM_SETTING_PROXY_SETTING_NAME, .get_setting_gtype = nm_setting_proxy_get_type, }, [NM_META_SETTING_TYPE_SERIAL] = { .meta_type = NM_META_SETTING_TYPE_SERIAL, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, .setting_name = NM_SETTING_SERIAL_SETTING_NAME, .get_setting_gtype = nm_setting_serial_get_type, }, [NM_META_SETTING_TYPE_SRIOV] = { .meta_type = NM_META_SETTING_TYPE_SRIOV, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, .setting_name = NM_SETTING_SRIOV_SETTING_NAME, .get_setting_gtype = nm_setting_sriov_get_type, }, [NM_META_SETTING_TYPE_TC_CONFIG] = { .meta_type = NM_META_SETTING_TYPE_TC_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_IP, .setting_name = NM_SETTING_TC_CONFIG_SETTING_NAME, .get_setting_gtype = nm_setting_tc_config_get_type, }, [NM_META_SETTING_TYPE_TEAM] = { .meta_type = NM_META_SETTING_TYPE_TEAM, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_TEAM_SETTING_NAME, .get_setting_gtype = nm_setting_team_get_type, }, [NM_META_SETTING_TYPE_TEAM_PORT] = { .meta_type = NM_META_SETTING_TYPE_TEAM_PORT, + .setting_priority = NM_SETTING_PRIORITY_AUX, .setting_name = NM_SETTING_TEAM_PORT_SETTING_NAME, .get_setting_gtype = nm_setting_team_port_get_type, }, [NM_META_SETTING_TYPE_TUN] = { .meta_type = NM_META_SETTING_TYPE_TUN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_TUN_SETTING_NAME, .get_setting_gtype = nm_setting_tun_get_type, }, [NM_META_SETTING_TYPE_USER] = { .meta_type = NM_META_SETTING_TYPE_USER, + .setting_priority = NM_SETTING_PRIORITY_USER, .setting_name = NM_SETTING_USER_SETTING_NAME, .get_setting_gtype = nm_setting_user_get_type, }, [NM_META_SETTING_TYPE_VLAN] = { .meta_type = NM_META_SETTING_TYPE_VLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_VLAN_SETTING_NAME, .get_setting_gtype = nm_setting_vlan_get_type, }, [NM_META_SETTING_TYPE_VPN] = { .meta_type = NM_META_SETTING_TYPE_VPN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_VPN_SETTING_NAME, .get_setting_gtype = nm_setting_vpn_get_type, }, [NM_META_SETTING_TYPE_VXLAN] = { .meta_type = NM_META_SETTING_TYPE_VXLAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_VXLAN_SETTING_NAME, .get_setting_gtype = nm_setting_vxlan_get_type, }, [NM_META_SETTING_TYPE_WIMAX] = { .meta_type = NM_META_SETTING_TYPE_WIMAX, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_WIMAX_SETTING_NAME, .get_setting_gtype = nm_setting_wimax_get_type, }, [NM_META_SETTING_TYPE_WIRED] = { .meta_type = NM_META_SETTING_TYPE_WIRED, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_WIRED_SETTING_NAME, .get_setting_gtype = nm_setting_wired_get_type, }, [NM_META_SETTING_TYPE_WIRELESS] = { .meta_type = NM_META_SETTING_TYPE_WIRELESS, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_WIRELESS_SETTING_NAME, .get_setting_gtype = nm_setting_wireless_get_type, }, [NM_META_SETTING_TYPE_WIRELESS_SECURITY] = { .meta_type = NM_META_SETTING_TYPE_WIRELESS_SECURITY, + .setting_priority = NM_SETTING_PRIORITY_HW_AUX, .setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, .get_setting_gtype = nm_setting_wireless_security_get_type, }, [NM_META_SETTING_TYPE_WPAN] = { .meta_type = NM_META_SETTING_TYPE_WPAN, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, .setting_name = NM_SETTING_WPAN_SETTING_NAME, .get_setting_gtype = nm_setting_wpan_get_type, }, @@ -366,27 +415,99 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = { const NMMetaSettingInfo * nm_meta_setting_infos_by_name (const char *name) { - int i; + gssize idx; + +#if NM_MORE_ASSERTS > 10 + { + guint i, j; - if (name) { for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { - if (nm_streq (nm_meta_setting_infos[i].setting_name, name)) - return &nm_meta_setting_infos[i]; + const NMMetaSettingInfo *setting_info = &nm_meta_setting_infos[i]; + + nm_assert (setting_info->meta_type == (NMMetaSettingType) i); + nm_assert (setting_info->setting_name); + nm_assert (setting_info->setting_name[0]); + nm_assert (setting_info->get_setting_gtype); + nm_assert (setting_info->setting_priority != NM_SETTING_PRIORITY_INVALID); + if ( i > 0 + && strcmp (nm_meta_setting_infos[i - 1].setting_name, setting_info->setting_name) >= 0) { + g_error ("nm_meta_setting_infos[%u, \"%s\"] is wrongly sorted before nm_meta_setting_infos[%u, \"%s\"]. Rearange NMMetaSettingType enum", + i - 1, nm_meta_setting_infos[i - 1].setting_name, + i, setting_info->setting_name); + } + for (j = 0; j < i; j++) { + const NMMetaSettingInfo *s = &nm_meta_setting_infos[j]; + + nm_assert (setting_info->get_setting_gtype != s->get_setting_gtype); + } } } - return NULL; +#endif + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMMetaSettingInfo, setting_name) == 0); + idx = nm_utils_array_find_binary_search (nm_meta_setting_infos, + sizeof (NMMetaSettingInfo), + _NM_META_SETTING_TYPE_NUM, + &name, + nm_strcmp_p_with_data, + NULL); + + return idx >= 0 ? &nm_meta_setting_infos[idx] : NULL; } const NMMetaSettingInfo * nm_meta_setting_infos_by_gtype (GType gtype) { - int i; +#if ((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) + nm_auto_unref_gtypeclass GTypeClass *gtypeclass_unref = NULL; + GTypeClass *gtypeclass; + NMSettingClass *klass; + + if (!g_type_is_a (gtype, NM_TYPE_SETTING)) + goto out_none; + + gtypeclass = g_type_class_peek (gtype); + if (!gtypeclass) + gtypeclass = gtypeclass_unref = g_type_class_ref (gtype); + + nm_assert (NM_IS_SETTING_CLASS (gtypeclass)); + + klass = (NMSettingClass *) gtypeclass; + + if (!klass->setting_info) + goto out_none; + + nm_assert (klass->setting_info->get_setting_gtype); + nm_assert (klass->setting_info->get_setting_gtype () == gtype); + + return klass->setting_info; + +out_none: + +#if NM_MORE_ASSERTS > 10 + { + int i; + + /* this might hint to a bug, but it would be expected for NM_TYPE_SETTING + * and NM_TYPE_SETTING_IP_CONFIG. + * + * Assert that we didn't lookup for a gtype, which we would expect to find. + * An assertion failure here, hints to a bug in nm_setting_*_class_init(). + */ + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) + nm_assert (nm_meta_setting_infos[i].get_setting_gtype () != gtype); + } +#endif + return NULL; +#else + guint i; for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { if (nm_meta_setting_infos[i].get_setting_gtype () == gtype) return &nm_meta_setting_infos[i]; } return NULL; +#endif } /*****************************************************************************/ diff --git a/shared/nm-meta-setting.h b/shared/nm-meta-setting.h index dd4780c5d9..c76a4b7008 100644 --- a/shared/nm-meta-setting.h +++ b/shared/nm-meta-setting.h @@ -26,6 +26,47 @@ /*****************************************************************************/ +/* + * A setting's priority should roughly follow the OSI layer model, but it also + * controls which settings get asked for secrets first. Thus settings which + * relate to things that must be working first, like hardware, should get a + * higher priority than things which layer on top of the hardware. For example, + * the GSM/CDMA settings should provide secrets before the PPP setting does, + * because a PIN is required to unlock the device before PPP can even start. + * Even settings without secrets should be assigned the right priority. + * + * 0: reserved for invalid + * + * 1: reserved for the Connection setting + * + * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. + * These priority 1 settings are also "base types", which means that at least + * one of them is required for the connection to be valid, and their name is + * valid in the 'type' property of the Connection setting. + * + * 4: hardware-related auxiliary settings that require a base setting to be + * successful first, like Wi-Fi security, 802.1x, etc. + * + * 5: hardware-independent settings that are required before IP connectivity + * can be established, like PPP, PPPoE, etc. + * + * 6: IP-level stuff + * + * 10: NMSettingUser + */ +typedef enum { /*< skip >*/ + NM_SETTING_PRIORITY_INVALID = 0, + NM_SETTING_PRIORITY_CONNECTION = 1, + NM_SETTING_PRIORITY_HW_BASE = 2, + NM_SETTING_PRIORITY_HW_NON_BASE = 3, + NM_SETTING_PRIORITY_HW_AUX = 4, + NM_SETTING_PRIORITY_AUX = 5, + NM_SETTING_PRIORITY_IP = 6, + NM_SETTING_PRIORITY_USER = 10, +} NMSettingPriority; + +/*****************************************************************************/ + typedef enum { NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT, NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT, @@ -56,8 +97,18 @@ extern const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[_NM_SETTI /*****************************************************************************/ typedef enum { + /* the enum (and their numeric values) are internal API. Do not assign + * any meaning the numeric values, because they already have one: + * + * they are sorted in a way, that corresponds to the asciibetical sort + * order of the corresponding setting-name. */ + NM_META_SETTING_TYPE_6LOWPAN, + NM_META_SETTING_TYPE_OLPC_MESH, + NM_META_SETTING_TYPE_WIRELESS, + NM_META_SETTING_TYPE_WIRELESS_SECURITY, NM_META_SETTING_TYPE_802_1X, + NM_META_SETTING_TYPE_WIRED, NM_META_SETTING_TYPE_ADSL, NM_META_SETTING_TYPE_BLUETOOTH, NM_META_SETTING_TYPE_BOND, @@ -67,15 +118,15 @@ typedef enum { NM_META_SETTING_TYPE_CONNECTION, NM_META_SETTING_TYPE_DCB, NM_META_SETTING_TYPE_DUMMY, + NM_META_SETTING_TYPE_ETHTOOL, NM_META_SETTING_TYPE_GENERIC, NM_META_SETTING_TYPE_GSM, NM_META_SETTING_TYPE_INFINIBAND, + NM_META_SETTING_TYPE_IP_TUNNEL, NM_META_SETTING_TYPE_IP4_CONFIG, NM_META_SETTING_TYPE_IP6_CONFIG, - NM_META_SETTING_TYPE_IP_TUNNEL, NM_META_SETTING_TYPE_MACSEC, NM_META_SETTING_TYPE_MACVLAN, - NM_META_SETTING_TYPE_OLPC_MESH, NM_META_SETTING_TYPE_OVS_BRIDGE, NM_META_SETTING_TYPE_OVS_INTERFACE, NM_META_SETTING_TYPE_OVS_PATCH, @@ -94,9 +145,6 @@ typedef enum { NM_META_SETTING_TYPE_VPN, NM_META_SETTING_TYPE_VXLAN, NM_META_SETTING_TYPE_WIMAX, - NM_META_SETTING_TYPE_WIRED, - NM_META_SETTING_TYPE_WIRELESS, - NM_META_SETTING_TYPE_WIRELESS_SECURITY, NM_META_SETTING_TYPE_WPAN, NM_META_SETTING_TYPE_UNKNOWN, @@ -104,12 +152,50 @@ typedef enum { _NM_META_SETTING_TYPE_NUM = NM_META_SETTING_TYPE_UNKNOWN, } NMMetaSettingType; -typedef struct { - NMMetaSettingType meta_type; +/* this header is statically linked with both libnm-core.la and libnmc.la. + * Though, there is no stable API/ABI, so whenever on of these components + * accesses NMMetaSettingInfo or NMMetaSettingType, it only has meaning + * inside the same component. + * + * Note how NMSettingClass has field of type "struct _NMMetaSettingInfo". + * It would be a serious bug, if libnmc tries to interpret this pointer + * with the meaning of NMMetaSettingInfo. They might be different, because + * libnm.so (libnm-core.la) might be a newer version than nmcli (libnmc.la). + * + * This define helps to ensure that we don't accidentally use the pointer + * in different contexts. */ +#if ((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL) +#define _NMMetaSettingInfoXX _NMMetaSettingInfo +#else +#define _NMMetaSettingInfoXX _NMMetaSettingInfoCli +#endif +struct _NMMetaSettingInfoXX { const char *setting_name; GType (*get_setting_gtype) (void); -} NMMetaSettingInfo; + NMMetaSettingType meta_type; + NMSettingPriority setting_priority; +}; +typedef struct _NMMetaSettingInfoXX NMMetaSettingInfo; + +/* note that we statically link nm-meta-setting.h both to libnm-core.la and + * libnmc.la. That means, there are two versions of nm_meta_setting_infos + * in nmcli. That is not easily avoidable, because at this point, we don't + * want yet to making it public API. + * + * Eventually, this should become public API of libnm, and nmcli/libnmc.la + * should use that version. + * + * Downsides of the current solution: + * + * - duplication of the array in nmcli. + * + * - there is no stable API/ABI. That means, when you have a NMMetaSettingInfo + * pointer, or a NMMetaSettingType value, the value can only be used within + * the current context (libnm-core.la or libnmc.la). In other words, libnmc.la + * (and nmcli) must never access a NMMetaSettingInfo/NMMetaSettingType value, + * that comes from libnm-core.la. + */ extern const NMMetaSettingInfo nm_meta_setting_infos[_NM_META_SETTING_TYPE_NUM + 1]; const NMMetaSettingInfo *nm_meta_setting_infos_by_name (const char *name); diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index d1391073eb..3d2520d131 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -1137,6 +1137,14 @@ nm_clear_g_cancellable (GCancellable **cancellable) && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \ }) +#define NM_DIV_ROUND_UP(x, y) \ + ({ \ + const typeof(x) _x = (x); \ + const typeof(y) _y = (y); \ + \ + (_x / _y + !!(_x % _y)); \ + }) + /*****************************************************************************/ #define NM_UTILS_LOOKUP_DEFAULT(v) return (v) diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c index 1b76b2d794..34c93c8108 100644 --- a/shared/nm-utils/nm-shared-utils.c +++ b/shared/nm-utils/nm-shared-utils.c @@ -1350,6 +1350,209 @@ nm_utils_strv_make_deep_copied (const char **strv) /*****************************************************************************/ +gssize +nm_utils_ptrarray_find_binary_search (gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data, + gssize *out_idx_first, + gssize *out_idx_last) +{ + gssize imin, imax, imid, i2min, i2max, i2mid; + int cmp; + + g_return_val_if_fail (list || !len, ~((gssize) 0)); + g_return_val_if_fail (cmpfcn, ~((gssize) 0)); + + imin = 0; + if (len > 0) { + imax = len - 1; + + while (imin <= imax) { + imid = imin + (imax - imin) / 2; + + cmp = cmpfcn (list[imid], needle, user_data); + if (cmp == 0) { + /* we found a matching entry at index imid. + * + * Does the caller request the first/last index as well (in case that + * there are multiple entries which compare equal). */ + + if (out_idx_first) { + i2min = imin; + i2max = imid + 1; + while (i2min <= i2max) { + i2mid = i2min + (i2max - i2min) / 2; + + cmp = cmpfcn (list[i2mid], needle, user_data); + if (cmp == 0) + i2max = i2mid -1; + else { + nm_assert (cmp < 0); + i2min = i2mid + 1; + } + } + *out_idx_first = i2min; + } + if (out_idx_last) { + i2min = imid + 1; + i2max = imax; + while (i2min <= i2max) { + i2mid = i2min + (i2max - i2min) / 2; + + cmp = cmpfcn (list[i2mid], needle, user_data); + if (cmp == 0) + i2min = i2mid + 1; + else { + nm_assert (cmp > 0); + i2max = i2mid - 1; + } + } + *out_idx_last = i2min - 1; + } + return imid; + } + + if (cmp < 0) + imin = imid + 1; + else + imax = imid - 1; + } + } + + /* return the inverse of @imin. This is a negative number, but + * also is ~imin the position where the value should be inserted. */ + imin = ~imin; + NM_SET_OUT (out_idx_first, imin); + NM_SET_OUT (out_idx_last, imin); + return imin; +} + +/*****************************************************************************/ + +/** + * nm_utils_array_find_binary_search: + * @list: the list to search. It must be sorted according to @cmpfcn ordering. + * @elem_size: the size in bytes of each element in the list + * @len: the number of elements in @list + * @needle: the value that is searched + * @cmpfcn: the compare function. The elements @list are passed as first + * argument to @cmpfcn, while @needle is passed as second. Usually, the + * needle is the same data type as inside the list, however, that is + * not necessary, as long as @cmpfcn takes care to cast the two arguments + * accordingly. + * @user_data: optional argument passed to @cmpfcn + * + * Performs binary search for @needle in @list. On success, returns the + * (non-negative) index where the compare function found the searched element. + * On success, it returns a negative value. Note that the return negative value + * is the bitwise inverse of the position where the element should be inserted. + * + * If the list contains multiple matching elements, an arbitrary index is + * returned. + * + * Returns: the index to the element in the list, or the (negative, bitwise inverted) + * position where it should be. + */ +gssize +nm_utils_array_find_binary_search (gconstpointer list, + gsize elem_size, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data) +{ + gssize imin, imax, imid; + int cmp; + + g_return_val_if_fail (list || !len, ~((gssize) 0)); + g_return_val_if_fail (cmpfcn, ~((gssize) 0)); + g_return_val_if_fail (elem_size > 0, ~((gssize) 0)); + + imin = 0; + if (len == 0) + return ~imin; + + imax = len - 1; + + while (imin <= imax) { + imid = imin + (imax - imin) / 2; + + cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data); + if (cmp == 0) + return imid; + + if (cmp < 0) + imin = imid + 1; + else + imax = imid - 1; + } + + /* return the inverse of @imin. This is a negative number, but + * also is ~imin the position where the value should be inserted. */ + return ~imin; +} + +/*****************************************************************************/ + +/** + * nm_utils_hash_table_equal: + * @a: one #GHashTable + * @b: other #GHashTable + * @treat_null_as_empty: if %TRUE, when either @a or @b is %NULL, it is + * treated like an empty hash. It means, a %NULL hash will compare equal + * to an empty hash. + * @equal_func: the equality function, for comparing the values. + * If %NULL, the values are not compared. In that case, the function + * only checks, if both dictionaries have the same keys -- according + * to @b's key equality function. + * Note that the values of @a will be passed as first argument + * to @equal_func. + * + * Compares two hash tables, whether they have equal content. + * This only makes sense, if @a and @b have the same key types and + * the same key compare-function. + * + * Returns: %TRUE, if both dictionaries have the same content. + */ +gboolean +nm_utils_hash_table_equal (const GHashTable *a, + const GHashTable *b, + gboolean treat_null_as_empty, + NMUtilsHashTableEqualFunc equal_func) +{ + guint n; + GHashTableIter iter; + gconstpointer key, v_a, v_b; + + if (a == b) + return TRUE; + if (!treat_null_as_empty) { + if (!a || !b) + return FALSE; + } + + n = a ? g_hash_table_size ((GHashTable *) a) : 0; + if (n != (b ? g_hash_table_size ((GHashTable *) b) : 0)) + return FALSE; + + if (n > 0) { + g_hash_table_iter_init (&iter, (GHashTable *) a); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &v_a)) { + if (!g_hash_table_lookup_extended ((GHashTable *) b, key, NULL, (gpointer *) &v_b)) + return FALSE; + if ( equal_func + && !equal_func (v_a, v_b)) + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + /** * nm_utils_get_start_time_for_pid: * @pid: the process identifier diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index e9885c6e35..6ee77b989f 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -555,6 +555,35 @@ nm_utils_strv_make_deep_copied_nonnull (const char **strv) return nm_utils_strv_make_deep_copied (strv) ?: g_new0 (char *, 1); } +/*****************************************************************************/ + +gssize nm_utils_ptrarray_find_binary_search (gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data, + gssize *out_idx_first, + gssize *out_idx_last); + +gssize nm_utils_array_find_binary_search (gconstpointer list, + gsize elem_size, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data); + +/*****************************************************************************/ + +typedef gboolean (*NMUtilsHashTableEqualFunc) (gconstpointer a, + gconstpointer b); + +gboolean nm_utils_hash_table_equal (const GHashTable *a, + const GHashTable *b, + gboolean treat_null_as_empty, + NMUtilsHashTableEqualFunc equal_func); + +/*****************************************************************************/ + void _nm_utils_strv_sort (const char **strv, gssize len); #define nm_utils_strv_sort(strv, len) _nm_utils_strv_sort (NM_CAST_STRV_MC (strv), len) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index d71005944b..908a0b5359 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -43,6 +43,7 @@ #include "nm-utils/nm-random-utils.h" #include "nm-utils/unaligned.h" +#include "nm-ethtool-utils.h" #include "nm-common-macros.h" #include "nm-device-private.h" #include "NetworkManagerUtils.h" @@ -65,6 +66,7 @@ #include "nm-firewall-manager.h" #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" +#include "nm-setting-ethtool.h" #include "nm-auth-utils.h" #include "nm-netns.h" #include "nm-dispatcher.h" @@ -172,6 +174,12 @@ struct _NMDeviceConnectivityHandle { bool is_periodic_bump_on_complete:1; }; +typedef struct { + int ifindex; + NMEthtoolFeatureStates *features; + NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM]; +} EthtoolState; + /*****************************************************************************/ enum { @@ -508,6 +516,8 @@ typedef struct _NMDevicePrivate { GHashTable * ip6_saved_properties; + EthtoolState *ethtool_state; + struct { NMDhcpClient * client; NMNDiscDHCPLevel mode; @@ -740,6 +750,79 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (mtu_source_to_str, NMDeviceMtuSource, /*****************************************************************************/ +static void +_ethtool_state_reset (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->ethtool_state) { + gs_free NMEthtoolFeatureStates *features = priv->ethtool_state->features; + gs_free EthtoolState *ethtool_state = g_steal_pointer (&priv->ethtool_state); + + if (!nm_platform_ethtool_set_features (nm_device_get_platform (self), + ethtool_state->ifindex, + features, + ethtool_state->requested, + FALSE)) + _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more offload features"); + else + _LOGD (LOGD_DEVICE, "ethtool: offload features successfully reset"); + } +} + +static void +_ethtool_state_set (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ifindex; + NMConnection *connection; + NMSettingEthtool *s_ethtool; + NMPlatform *platform; + gs_free EthtoolState *ethtool_state = NULL; + gs_free NMEthtoolFeatureStates *features = NULL; + + _ethtool_state_reset (self); + + connection = nm_device_get_applied_connection (self); + if (!connection) + return; + + ifindex = nm_device_get_ip_ifindex (self); + if (ifindex <= 0) + return; + + s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL)); + if (!s_ethtool) + return; + + ethtool_state = g_new (EthtoolState, 1); + if (nm_setting_ethtool_init_features (s_ethtool, ethtool_state->requested) == 0) + return; + + platform = nm_device_get_platform (self); + + features = nm_platform_ethtool_get_link_features (platform, ifindex); + if (!features) { + _LOGW (LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)"); + return; + } + + if (!nm_platform_ethtool_set_features (platform, + ifindex, + features, + ethtool_state->requested, + TRUE)) + _LOGW (LOGD_DEVICE, "ethtool: failure setting one or more offload features"); + else + _LOGD (LOGD_DEVICE, "ethtool: offload features successfully set"); + + ethtool_state->ifindex = ifindex; + ethtool_state->features = g_steal_pointer (&features); + priv->ethtool_state = g_steal_pointer (ðtool_state); +} + +/*****************************************************************************/ + NMSettings * nm_device_get_settings (NMDevice *self) { @@ -6228,6 +6311,8 @@ activate_stage2_device_config (NMDevice *self) if (!nm_device_sys_iface_state_is_external_or_assume (self)) { NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + _ethtool_state_set (self); + if (!tc_commit (self)) { _LOGW (LOGD_IP6, "failed applying traffic control rules"); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); @@ -14022,6 +14107,8 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean priv->ip6_mtu_initial = 0; } + _ethtool_state_reset (self); + _cleanup_generic_post (self, cleanup_type); } diff --git a/src/nm-config-data.c b/src/nm-config-data.c index f0ec8a882e..d8ad07c054 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -655,12 +655,12 @@ nm_config_data_log (const NMConfigData *self, const char *group = default_values[g].group; gssize idx; - idx = _nm_utils_array_find_binary_search ((gconstpointer *) groups_full->pdata, - sizeof (char *), - groups_full->len, - &group, - (GCompareDataFunc) _nm_config_data_log_sort, - NULL); + idx = nm_utils_array_find_binary_search ((gconstpointer *) groups_full->pdata, + sizeof (char *), + groups_full->len, + &group, + (GCompareDataFunc) _nm_config_data_log_sort, + NULL); if (idx < 0) g_ptr_array_insert (groups_full, (~idx), (gpointer) group); } diff --git a/src/nm-manager.c b/src/nm-manager.c index b0387749fd..769afc700d 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -6796,12 +6796,12 @@ nm_manager_set_capability (NMManager *self, priv = NM_MANAGER_GET_PRIVATE (self); - idx = _nm_utils_array_find_binary_search (&g_array_index (priv->capabilities, guint32, 0), - sizeof (guint32), - priv->capabilities->len, - &cap_i, - nm_cmp_uint32_p_with_data, - NULL); + idx = nm_utils_array_find_binary_search (&g_array_index (priv->capabilities, guint32, 0), + sizeof (guint32), + priv->capabilities->len, + &cap_i, + nm_cmp_uint32_p_with_data, + NULL); if (idx >= 0) return; diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 0d224443fa..9459fbc993 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -36,12 +36,15 @@ #include "nm-utils.h" #include "nm-setting-wired.h" +#include "nm-ethtool-utils.h" #include "nm-core-utils.h" -/****************************************************************** +#define ONOFF(bool_val) ((bool_val) ? "on" : "off") + +/****************************************************************************** * utils - ******************************************************************/ + *****************************************************************************/ extern char *if_indextoname (unsigned __ifindex, char *__ifname); unsigned if_nametoindex (const char *__ifname); @@ -63,9 +66,45 @@ nmp_utils_if_nametoindex (const char *ifname) return if_nametoindex (ifname); } -/****************************************************************** +/*****************************************************************************/ + +typedef struct { + int fd; + int ifindex; + char ifname[IFNAMSIZ]; +} SocketHandle; + +static int +socket_handle_init (SocketHandle *shandle, int ifindex) +{ + if (!nmp_utils_if_indextoname (ifindex, shandle->ifname)) { + shandle->ifindex = 0; + return -ENODEV; + } + + shandle->fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (shandle->fd < 0) { + shandle->ifindex = 0; + return -errno; + } + + shandle->ifindex = ifindex; + return 0; +} + +static void +socket_handle_destroy (SocketHandle *shandle) +{ + if (shandle->ifindex) { + shandle->ifindex = 0; + nm_close (shandle->fd); + } +} +#define nm_auto_socket_handle nm_auto(socket_handle_destroy) + +/****************************************************************************** * ethtool - ******************************************************************/ + *****************************************************************************/ NM_UTILS_ENUM2STR_DEFINE_STATIC (_ethtool_cmd_to_string, guint32, NM_UTILS_ENUM2STR (ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"), @@ -77,6 +116,7 @@ NM_UTILS_ENUM2STR_DEFINE_STATIC (_ethtool_cmd_to_string, guint32, NM_UTILS_ENUM2STR (ETHTOOL_GSTATS, "ETHTOOL_GSTATS"), NM_UTILS_ENUM2STR (ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"), NM_UTILS_ENUM2STR (ETHTOOL_GWOL, "ETHTOOL_GWOL"), + NM_UTILS_ENUM2STR (ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"), NM_UTILS_ENUM2STR (ETHTOOL_SSET, "ETHTOOL_SSET"), NM_UTILS_ENUM2STR (ETHTOOL_SWOL, "ETHTOOL_SWOL"), ); @@ -87,6 +127,8 @@ _ethtool_data_to_string (gconstpointer edata, char *buf, gsize len) return _ethtool_cmd_to_string (*((guint32 *) edata), buf, len); } +/*****************************************************************************/ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) #define ethtool_cmd_speed(pedata) ((pedata)->speed) @@ -94,117 +136,553 @@ _ethtool_data_to_string (gconstpointer edata, char *buf, gsize len) G_STMT_START { (pedata)->speed = (guint16) (speed); } G_STMT_END #endif -static gboolean -ethtool_get (int ifindex, gpointer edata) +static int +ethtool_call_handle (SocketHandle *shandle, gpointer edata) { - char ifname[IFNAMSIZ]; + struct ifreq ifr = { + .ifr_data = edata, + }; char sbuf[50]; + int errsv; + + nm_assert (shandle); + nm_assert (shandle->ifindex); + nm_assert (shandle->ifname[0]); + nm_assert (strlen (shandle->ifname) < IFNAMSIZ); + nm_assert (edata); + + memcpy (ifr.ifr_name, shandle->ifname, IFNAMSIZ); + if (ioctl (shandle->fd, SIOCETHTOOL, &ifr) < 0) { + errsv = errno; + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: failed: %s", + shandle->ifindex, + _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), + shandle->ifname, + strerror (errsv)); + return -errsv; + } - nm_assert (ifindex > 0); + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: success", + shandle->ifindex, + _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), + shandle->ifname); + return 0; +} - /* ethtool ioctl API uses the ifname to refer to an interface. That is racy - * as interfaces can be renamed *sigh*. - * - * Note that we anyway have to verify whether the interface exists, before - * calling ioctl for a non-existing ifname. This is to prevent autoloading - * of kernel modules *sigh*. - * Thus, as we anyway verify the existence of ifname before doing the call, - * go one step further and lookup the ifname everytime anew. - * - * This does not solve the renaming race, but it minimizes the time for - * the race to happen as much as possible. */ +static int +ethtool_call_ifindex (int ifindex, gpointer edata) +{ + nm_auto_socket_handle SocketHandle shandle = { }; + int r; + char sbuf[50]; + + nm_assert (edata); - if (!nmp_utils_if_indextoname (ifindex, ifname)) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: request fails resolving ifindex: %s", + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failed creating ethtool socket: %s", ifindex, _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), - g_strerror (errno)); + g_strerror (-r)); + return r; + } + + return ethtool_call_handle (&shandle, edata); +} + +/*****************************************************************************/ + +static struct ethtool_gstrings * +ethtool_get_stringset (SocketHandle *shandle, int stringset_id) +{ + struct { + struct ethtool_sset_info info; + guint32 sentinel; + } sset_info = { }; + gs_free struct ethtool_gstrings *gstrings = NULL; + guint32 i, len; + + sset_info.info.cmd = ETHTOOL_GSSET_INFO; + sset_info.info.reserved = 0; + sset_info.info.sset_mask = (1ULL << stringset_id); + + if (ethtool_call_handle (shandle, &sset_info) < 0) + return NULL; + if (!sset_info.info.sset_mask) + return NULL; + + len = sset_info.info.data[0]; + + gstrings = g_malloc0 (sizeof (*gstrings) + (len * ETH_GSTRING_LEN)); + gstrings->cmd = ETHTOOL_GSTRINGS; + gstrings->string_set = stringset_id; + gstrings->len = len; + if (gstrings->len > 0) { + if (ethtool_call_handle (shandle, gstrings) < 0) + return NULL; + for (i = 0; i < gstrings->len; i++) { + /* ensure NUL terminated */ + gstrings->data[i * ETH_GSTRING_LEN + (ETH_GSTRING_LEN - 1)] = '\0'; + } + } + + return g_steal_pointer (&gstrings); +} + +static int +ethtool_gstrings_find (const struct ethtool_gstrings *gstrings, const char *needle) +{ + guint32 i; + + /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. + * that means, we cannot possibly request longer names. */ + nm_assert (needle && strlen (needle) < ETH_GSTRING_LEN); + + for (i = 0; i < gstrings->len; i++) { + if (nm_streq ((char *) &gstrings->data[i * ETH_GSTRING_LEN], needle)) + return i; + } + return -1; +} + +static int +ethtool_get_stringset_index (SocketHandle *shandle, int stringset_id, const char *needle) +{ + gs_free struct ethtool_gstrings *gstrings = NULL; + + /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. + * that means, we cannot possibly request longer names. */ + nm_assert (needle && strlen (needle) < ETH_GSTRING_LEN); + + gstrings = ethtool_get_stringset (shandle, stringset_id); + if (gstrings) + return ethtool_gstrings_find (gstrings, needle); + return -1; +} + +/*****************************************************************************/ + +static const NMEthtoolFeatureInfo _ethtool_feature_infos[_NM_ETHTOOL_ID_FEATURE_NUM] = { +#define ETHT_FEAT(eid, ...) \ + { \ + .ethtool_id = eid, \ + .n_kernel_names = NM_NARG (__VA_ARGS__), \ + .kernel_names = ((const char *const[]) { __VA_ARGS__ }), \ + } + + /* the order does only matter for one thing: if it happens that more than one NMEthtoolID + * reference the same kernel-name, then the one that is mentioned *later* will win in + * case these NMEthtoolIDs are set. That mostly only makes sense for ethtool-ids which + * refer to multiple features ("feature-tso"), while also having more specific ids + * ("feature-tx-tcp-segmentation"). */ + + /* names from ethtool utility, which are aliases for multiple features. */ + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_SG, "tx-scatter-gather", + "tx-scatter-gather-fraglist"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TSO, "tx-tcp-segmentation", + "tx-tcp-ecn-segmentation", + "tx-tcp-mangleid-segmentation", + "tx-tcp6-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX, "tx-checksum-ipv4", + "tx-checksum-ip-generic", + "tx-checksum-ipv6", + "tx-checksum-fcoe-crc", + "tx-checksum-sctp"), + + /* names from ethtool utility, which are aliases for one feature. */ + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert"), + + /* names of features, as known by kernel. */ + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), + ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), +}; + +/* the number of kernel features that we handle. It essentially is the sum of all + * kernel_names. So, all ethtool-ids that reference exactly one kernel-name + * (_NM_ETHTOOL_ID_FEATURE_NUM) + some extra, for ethtool-ids that are aliases + * for multiple kernel-names. */ +#define N_ETHTOOL_KERNEL_FEATURES (((guint) _NM_ETHTOOL_ID_FEATURE_NUM) + 8u) + +static void +_ASSERT_ethtool_feature_infos (void) +{ +#if NM_MORE_ASSERTS > 10 + guint i, k, n; + bool found[_NM_ETHTOOL_ID_FEATURE_NUM] = { }; + + G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (_ethtool_feature_infos) == _NM_ETHTOOL_ID_FEATURE_NUM); + + n = 0; + for (i = 0; i < G_N_ELEMENTS (_ethtool_feature_infos); i++) { + NMEthtoolFeatureState kstate; + const NMEthtoolFeatureInfo *inf = &_ethtool_feature_infos[i]; + + g_assert (inf->ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST); + g_assert (inf->ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); + g_assert (inf->n_kernel_names > 0); + + for (k = 0; k < i; k++) + g_assert (inf->ethtool_id != _ethtool_feature_infos[k].ethtool_id); + + g_assert (!found[inf->ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]); + found[inf->ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST] = TRUE; + + kstate.idx_kernel_name = inf->n_kernel_names - 1; + g_assert ((guint) kstate.idx_kernel_name == (guint) (inf->n_kernel_names - 1)); + + n += inf->n_kernel_names; + for (k = 0; k < inf->n_kernel_names; k++) { + g_assert (nm_utils_strv_find_first ((char **) inf->kernel_names, + k, + inf->kernel_names[k]) < 0); + } + } + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + g_assert (found[i]); + + g_assert (n == N_ETHTOOL_KERNEL_FEATURES); +#endif +} + +static NMEthtoolFeatureStates * +ethtool_get_features (SocketHandle *shandle) +{ + gs_free NMEthtoolFeatureStates *states = NULL; + gs_free struct ethtool_gstrings *ss_features = NULL; + + _ASSERT_ethtool_feature_infos (); + + ss_features = ethtool_get_stringset (shandle, ETH_SS_FEATURES); + if (!ss_features) + return NULL; + + if (ss_features->len > 0) { + gs_free struct ethtool_gfeatures *gfeatures = NULL; + guint idx; + const NMEthtoolFeatureState *states_list0 = NULL; + const NMEthtoolFeatureState *const*states_plist0 = NULL; + guint states_plist_n = 0; + + gfeatures = g_malloc0 ( sizeof (struct ethtool_gfeatures) + + (NM_DIV_ROUND_UP (ss_features->len, 32u) * sizeof(gfeatures->features[0]))); + + gfeatures->cmd = ETHTOOL_GFEATURES; + gfeatures->size = NM_DIV_ROUND_UP (ss_features->len, 32u); + if (ethtool_call_handle (shandle, gfeatures) < 0) + return NULL; + + for (idx = 0; idx < G_N_ELEMENTS (_ethtool_feature_infos); idx++) { + const NMEthtoolFeatureInfo *info = &_ethtool_feature_infos[idx]; + guint idx_kernel_name; + + for (idx_kernel_name = 0; idx_kernel_name < info->n_kernel_names; idx_kernel_name++) { + NMEthtoolFeatureState *kstate; + const char *kernel_name = info->kernel_names[idx_kernel_name]; + int i_feature; + guint i_block; + guint32 i_flag; + + i_feature = ethtool_gstrings_find (ss_features, kernel_name); + if (i_feature < 0) + continue; + + i_block = ((guint) i_feature) / 32u; + i_flag = (guint32) (1u << (((guint) i_feature) % 32u)); + + if (!states) { + states = g_malloc0 (sizeof (NMEthtoolFeatureStates) + + (N_ETHTOOL_KERNEL_FEATURES * sizeof (NMEthtoolFeatureState)) + + ((N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)) * sizeof (NMEthtoolFeatureState *))); + states_list0 = &states->states_list[0]; + states_plist0 = (gpointer) &states_list0[N_ETHTOOL_KERNEL_FEATURES]; + states->n_ss_features = ss_features->len; + } + + nm_assert (states->n_states < N_ETHTOOL_KERNEL_FEATURES); + kstate = (NMEthtoolFeatureState *) &states_list0[states->n_states]; + states->n_states++; + + kstate->info = info; + kstate->idx_ss_features = i_feature; + kstate->idx_kernel_name = idx_kernel_name; + kstate->available = !!(gfeatures->features[i_block].available & i_flag); + kstate->requested = !!(gfeatures->features[i_block].requested & i_flag); + kstate->active = !!(gfeatures->features[i_block].active & i_flag); + kstate->never_changed = !!(gfeatures->features[i_block].never_changed & i_flag); + + nm_assert (states_plist_n < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)); + + if (!states->states_indexed[info->ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]) + states->states_indexed[info->ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST] = &states_plist0[states_plist_n]; + ((const NMEthtoolFeatureState **) states_plist0)[states_plist_n] = kstate; + states_plist_n++; + } + + if (states && states->states_indexed[info->ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]) { + nm_assert (states_plist_n < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)); + nm_assert (!states_plist0[states_plist_n]); + states_plist_n++; + } + } + } + + return g_steal_pointer (&states); +} + +NMEthtoolFeatureStates * +nmp_utils_ethtool_get_features (int ifindex) +{ + nm_auto_socket_handle SocketHandle shandle = { }; + NMEthtoolFeatureStates *features; + int r; + + g_return_val_if_fail (ifindex > 0, 0); + + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failed creating ethtool socket: %s", + ifindex, + "get-features", + g_strerror (-r)); return FALSE; } - { - nm_auto_close int fd = -1; - struct ifreq ifr = { - .ifr_data = edata, - }; + features = ethtool_get_features (&shandle); - memcpy (ifr.ifr_name, ifname, sizeof (ifname)); + if (!features) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting features", + ifindex, + "get-features"); + return NULL; + } - fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: failed creating socket for ioctl: %s", - ifindex, - _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), - ifname, - g_strerror (errno)); - return FALSE; + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel features", + ifindex, + "get-features"); + return features; +} + +static const char * +_ethtool_feature_state_to_string (char *buf, gsize buf_size, const NMEthtoolFeatureState *s, const char *prefix) +{ + int l; + + l = g_snprintf (buf, buf_size, + "%s %s%s", + prefix ?: "", + ONOFF (s->active), + (!s->available || s->never_changed) + ? ", [fixed]" + : ((s->requested != s->active) + ? (s->requested ? ", [requested on]" : ", [requested off]") + : "")); + nm_assert (l < buf_size); + return buf; +} + +gboolean +nmp_utils_ethtool_set_features (int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */) +{ + nm_auto_socket_handle SocketHandle shandle = { }; + gs_free struct ethtool_sfeatures *sfeatures = NULL; + int r; + guint i, j; + struct { + const NMEthtoolFeatureState *f_state; + NMTernary requested; + } set_states[N_ETHTOOL_KERNEL_FEATURES]; + guint set_states_n = 0; + gboolean success = TRUE; + + g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail (features, 0); + g_return_val_if_fail (requested, 0); + + nm_assert (features->n_states <= N_ETHTOOL_KERNEL_FEATURES); + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { + const NMEthtoolFeatureState *const*states_indexed; + + if (requested[i] == NM_TERNARY_DEFAULT) + continue; + + if (!(states_indexed = features->states_indexed[i])) { + if (do_set) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set feature %s: skip (not found)", + ifindex, + "set-features", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname); + success = FALSE; + } + continue; } - if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: failed: %s", + for (j = 0; states_indexed[j]; j++) { + const NMEthtoolFeatureState *s = states_indexed[j]; + char sbuf[255]; + + if (set_states_n >= G_N_ELEMENTS (set_states)) + g_return_val_if_reached (FALSE); + + if (s->never_changed) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s feature %s (%s): %s, %s (skip feature marked as never changed)", + ifindex, + "set-features", + do_set ? "set" : "reset", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + s->info->kernel_names[s->idx_kernel_name], + ONOFF (do_set ? requested[i] == NM_TERNARY_TRUE : s->active), + _ethtool_feature_state_to_string (sbuf, sizeof (sbuf), s, do_set ? " currently:" : " before:")); + continue; + } + + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s feature %s (%s): %s, %s", ifindex, - _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), - ifname, - strerror (errno)); - return FALSE; + "set-features", + do_set ? "set" : "reset", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + s->info->kernel_names[s->idx_kernel_name], + ONOFF (do_set ? requested[i] == NM_TERNARY_TRUE : s->active), + _ethtool_feature_state_to_string (sbuf, sizeof (sbuf), s, do_set ? " currently:" : " before:")); + + if ( do_set + && (!s->available || s->never_changed) + && (s->active != (requested[i] == NM_TERNARY_TRUE))) { + /* we request to change a flag which kernel reported as fixed. + * While the ethtool operation will silently succeed, mark the request + * as failure. */ + success = FALSE; + } + + set_states[set_states_n].f_state = s; + set_states[set_states_n].requested = requested[i]; + set_states_n++; } + } - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: success", + if (set_states_n == 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: no feature requested", ifindex, - _ethtool_data_to_string (edata, sbuf, sizeof (sbuf)), - ifname); + "set-features"); return TRUE; } -} -static int -ethtool_get_stringset_index (int ifindex, int stringset_id, const char *string) -{ - gs_free struct ethtool_sset_info *info = NULL; - gs_free struct ethtool_gstrings *strings = NULL; - guint32 len, i; + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failed creating ethtool socket: %s", + ifindex, + "set-features", + g_strerror (-r)); + return FALSE; + } - g_return_val_if_fail (ifindex > 0, -1); + sfeatures = g_malloc0 (sizeof (struct ethtool_sfeatures) + + (NM_DIV_ROUND_UP (features->n_ss_features, 32U) * sizeof(sfeatures->features[0]))); + sfeatures->cmd = ETHTOOL_SFEATURES; + sfeatures->size = NM_DIV_ROUND_UP (features->n_ss_features, 32U); - info = g_malloc0 (sizeof (*info) + sizeof (guint32)); - info->cmd = ETHTOOL_GSSET_INFO; - info->reserved = 0; - info->sset_mask = 1ULL << stringset_id; + for (i = 0; i < set_states_n; i++) { + const NMEthtoolFeatureState *s = set_states[i].f_state; + guint i_block; + guint32 i_flag; + gboolean is_requested; - if (!ethtool_get (ifindex, info)) - return -1; - if (!info->sset_mask) - return -1; + i_block = s->idx_ss_features / 32u; + i_flag = (guint32) (1u << (s->idx_ss_features % 32u)); - len = info->data[0]; + sfeatures->features[i_block].valid |= i_flag; - strings = g_malloc0 (sizeof (*strings) + len * ETH_GSTRING_LEN); - strings->cmd = ETHTOOL_GSTRINGS; - strings->string_set = stringset_id; - strings->len = len; - if (!ethtool_get (ifindex, strings)) - return -1; + if (do_set) + is_requested = (set_states[i].requested == NM_TERNARY_TRUE); + else + is_requested = s->active; - for (i = 0; i < len; i++) { - if (!strcmp ((char *) &strings->data[i * ETH_GSTRING_LEN], string)) - return i; + if (is_requested) + sfeatures->features[i_block].requested |= i_flag; + else + sfeatures->features[i_block].requested &= ~i_flag; } - return -1; + if ((r = ethtool_call_handle (&shandle, sfeatures)) < 0) { + success = FALSE; + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting features (%s)", + ifindex, + "set-features", + g_strerror (-r)); + return FALSE; + } + + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s", + ifindex, + "set-features", + success + ? "successfully setting features" + : "at least some of the features were not successfuly set"); + return success; } +/*****************************************************************************/ + gboolean nmp_utils_ethtool_get_driver_info (int ifindex, NMPUtilsEthtoolDriverInfo *data) { struct ethtool_drvinfo *drvinfo; - G_STATIC_ASSERT (sizeof (*data) == sizeof (*drvinfo)); - G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, driver) == offsetof (struct ethtool_drvinfo, driver)); - G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, version) == offsetof (struct ethtool_drvinfo, version)); - G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, fw_version) == offsetof (struct ethtool_drvinfo, fw_version)); - G_STATIC_ASSERT (sizeof (data->driver) == sizeof (drvinfo->driver)); - G_STATIC_ASSERT (sizeof (data->version) == sizeof (drvinfo->version)); - G_STATIC_ASSERT (sizeof (data->fw_version) == sizeof (drvinfo->fw_version)); + + G_STATIC_ASSERT_EXPR (sizeof (*data) == sizeof (*drvinfo)); + G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, driver) == offsetof (struct ethtool_drvinfo, driver)); + G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, version) == offsetof (struct ethtool_drvinfo, version)); + G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, fw_version) == offsetof (struct ethtool_drvinfo, fw_version)); + G_STATIC_ASSERT_EXPR (sizeof (data->driver) == sizeof (drvinfo->driver)); + G_STATIC_ASSERT_EXPR (sizeof (data->version) == sizeof (drvinfo->version)); + G_STATIC_ASSERT_EXPR (sizeof (data->fw_version) == sizeof (drvinfo->fw_version)); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (data, FALSE); @@ -213,7 +691,7 @@ nmp_utils_ethtool_get_driver_info (int ifindex, memset (drvinfo, 0, sizeof (*drvinfo)); drvinfo->cmd = ETHTOOL_GDRVINFO; - return ethtool_get (ifindex, drvinfo); + return ethtool_call_ifindex (ifindex, drvinfo) >= 0; } gboolean @@ -233,7 +711,7 @@ nmp_utils_ethtool_get_permanent_address (int ifindex, edata.e.cmd = ETHTOOL_GPERMADDR; edata.e.size = NM_UTILS_HWADDR_LEN_MAX; - if (!ethtool_get (ifindex, &edata.e)) + if (ethtool_call_ifindex (ifindex, &edata.e) < 0) return FALSE; if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX) @@ -252,8 +730,8 @@ nmp_utils_ethtool_get_permanent_address (int ifindex, } return FALSE; } -not_all_0or1: +not_all_0or1: memcpy (buf, edata.e.data, edata.e.size); *length = edata.e.size; return TRUE; @@ -270,20 +748,30 @@ nmp_utils_ethtool_supports_carrier_detect (int ifindex) * assume the device supports carrier-detect, otherwise we assume it * doesn't. */ - return ethtool_get (ifindex, &edata); + return ethtool_call_ifindex (ifindex, &edata) >= 0; } gboolean nmp_utils_ethtool_supports_vlans (int ifindex) { + nm_auto_socket_handle SocketHandle shandle = { }; + int r; gs_free struct ethtool_gfeatures *features = NULL; int idx, block, bit, size; g_return_val_if_fail (ifindex > 0, FALSE); - idx = ethtool_get_stringset_index (ifindex, ETH_SS_FEATURES, "vlan-challenged"); - if (idx == -1) { - nm_log_dbg (LOGD_PLATFORM, "ethtool: vlan-challenged ethtool feature does not exist for %d?", ifindex); + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failed creating ethtool socket: %s", + ifindex, + "support-vlans", + g_strerror (-r)); + return FALSE; + } + + idx = ethtool_get_stringset_index (&shandle, ETH_SS_FEATURES, "vlan-challenged"); + if (idx < 0) { + nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: vlan-challenged ethtool feature does not exist?", ifindex); return FALSE; } @@ -295,7 +783,7 @@ nmp_utils_ethtool_supports_vlans (int ifindex) features->cmd = ETHTOOL_GFEATURES; features->size = size; - if (!ethtool_get (ifindex, features)) + if (ethtool_call_handle (&shandle, features) < 0) return FALSE; return !(features->features[block].active & (1 << bit)); @@ -304,21 +792,32 @@ nmp_utils_ethtool_supports_vlans (int ifindex) int nmp_utils_ethtool_get_peer_ifindex (int ifindex) { + nm_auto_socket_handle SocketHandle shandle = { }; + int r; + gs_free struct ethtool_stats *stats = NULL; int peer_ifindex_stat; g_return_val_if_fail (ifindex > 0, 0); - peer_ifindex_stat = ethtool_get_stringset_index (ifindex, ETH_SS_STATS, "peer_ifindex"); - if (peer_ifindex_stat == -1) { - nm_log_dbg (LOGD_PLATFORM, "ethtool: peer_ifindex stat for %d does not exist?", ifindex); + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failed creating ethtool socket: %s", + ifindex, + "get-peer-ifindex", + g_strerror (-r)); + return FALSE; + } + + peer_ifindex_stat = ethtool_get_stringset_index (&shandle, ETH_SS_STATS, "peer_ifindex"); + if (peer_ifindex_stat < 0) { + nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: peer_ifindex stat does not exist?", ifindex); return FALSE; } stats = g_malloc0 (sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64)); stats->cmd = ETHTOOL_GSTATS; stats->n_stats = peer_ifindex_stat + 1; - if (!ethtool_get (ifindex, stats)) + if (ethtool_call_ifindex (ifindex, stats) < 0) return 0; return stats->data[peer_ifindex_stat]; @@ -333,7 +832,7 @@ nmp_utils_ethtool_get_wake_on_lan (int ifindex) memset (&wol, 0, sizeof (wol)); wol.cmd = ETHTOOL_GWOL; - if (!ethtool_get (ifindex, &wol)) + if (ethtool_call_ifindex (ifindex, &wol) < 0) return FALSE; return wol.wolopts != 0; @@ -351,7 +850,7 @@ nmp_utils_ethtool_get_link_settings (int ifindex, g_return_val_if_fail (ifindex > 0, FALSE); - if (!ethtool_get (ifindex, &edata)) + if (ethtool_call_ifindex (ifindex, &edata) < 0) return FALSE; if (out_autoneg) @@ -433,7 +932,7 @@ nmp_utils_ethtool_set_link_settings (int ifindex, || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE); /* retrieve first current settings */ - if (!ethtool_get (ifindex, &edata)) + if (ethtool_call_ifindex (ifindex, &edata) < 0) return FALSE; /* then change the needed ones */ @@ -485,7 +984,7 @@ nmp_utils_ethtool_set_link_settings (int ifindex, } } - return ethtool_get (ifindex, &edata); + return ethtool_call_ifindex (ifindex, &edata) >= 0; } gboolean @@ -500,8 +999,8 @@ nmp_utils_ethtool_set_wake_on_lan (int ifindex, if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) return TRUE; - nm_log_dbg (LOGD_PLATFORM, "setting Wake-on-LAN options 0x%x, password '%s'", - (unsigned) wol, wol_password); + nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: setting Wake-on-LAN options 0x%x, password '%s'", + ifindex, (unsigned) wol, wol_password); wol_info.cmd = ETHTOOL_SWOL; wol_info.wolopts = 0; @@ -521,45 +1020,41 @@ nmp_utils_ethtool_set_wake_on_lan (int ifindex, if (wol_password) { if (!nm_utils_hwaddr_aton (wol_password, wol_info.sopass, ETH_ALEN)) { - nm_log_dbg (LOGD_PLATFORM, "couldn't parse Wake-on-LAN password '%s'", wol_password); + nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: couldn't parse Wake-on-LAN password '%s'", ifindex, wol_password); return FALSE; } wol_info.wolopts |= WAKE_MAGICSECURE; } - return ethtool_get (ifindex, &wol_info); + return ethtool_call_ifindex (ifindex, &wol_info) >= 0; } -/****************************************************************** +/****************************************************************************** * mii - ******************************************************************/ + *****************************************************************************/ gboolean nmp_utils_mii_supports_carrier_detect (int ifindex) { - char ifname[IFNAMSIZ]; - nm_auto_close int fd = -1; + nm_auto_socket_handle SocketHandle shandle = { }; + int r; struct ifreq ifr; struct mii_ioctl_data *mii; g_return_val_if_fail (ifindex > 0, FALSE); - if (!nmp_utils_if_indextoname (ifindex, ifname)) { - nm_log_trace (LOGD_PLATFORM, "mii[%d]: carrier-detect no: request fails resolving ifindex: %s", ifindex, g_strerror (errno)); - return FALSE; - } - - fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: couldn't open control socket: %s", ifindex, ifname, g_strerror (errno)); + if ((r = socket_handle_init (&shandle, ifindex)) < 0) { + nm_log_trace (LOGD_PLATFORM, "mii[%d]: carrier-detect no: failed creating ethtool socket: %s", + ifindex, + g_strerror (-r)); return FALSE; } memset (&ifr, 0, sizeof (struct ifreq)); - memcpy (ifr.ifr_name, ifname, IFNAMSIZ); + memcpy (ifr.ifr_name, shandle.ifname, IFNAMSIZ); - if (ioctl (fd, SIOCGMIIPHY, &ifr) < 0) { - nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIPHY failed: %s", ifindex, ifname, strerror (errno)); + if (ioctl (shandle.fd, SIOCGMIIPHY, &ifr) < 0) { + nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIPHY failed: %s", ifindex, shandle.ifname, strerror (errno)); return FALSE; } @@ -567,18 +1062,18 @@ nmp_utils_mii_supports_carrier_detect (int ifindex) mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; mii->reg_num = MII_BMSR; - if (ioctl (fd, SIOCGMIIREG, &ifr) != 0) { - nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIREG failed: %s", ifindex, ifname, strerror (errno)); + if (ioctl (shandle.fd, SIOCGMIIREG, &ifr) != 0) { + nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIREG failed: %s", ifindex, shandle.ifname, strerror (errno)); return FALSE; } - nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", ifindex, ifname, mii->val_out); + nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", ifindex, shandle.ifname, mii->val_out); return TRUE; } -/****************************************************************** +/****************************************************************************** * udev - ******************************************************************/ + *****************************************************************************/ const char * nmp_utils_udev_get_driver (struct udev_device *udevice) diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 97f5630a4d..bad77aee38 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -23,6 +23,9 @@ #include "nm-platform.h" #include "nm-setting-wired.h" +#include "nm-ethtool-utils.h" + +/*****************************************************************************/ const char *nmp_utils_ethtool_get_driver (int ifindex); gboolean nmp_utils_ethtool_supports_carrier_detect (int ifindex); @@ -35,6 +38,10 @@ gboolean nmp_utils_ethtool_set_wake_on_lan (int ifindex, NMSettingWiredWakeOnLan gboolean nmp_utils_ethtool_get_link_settings (int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex); gboolean nmp_utils_ethtool_set_link_settings (int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex); +gboolean nmp_utils_ethtool_get_permanent_address (int ifindex, + guint8 *buf, + size_t *length); + typedef struct { /* We don't want to include <linux/ethtool.h> in header files, * thus create a ABI compatible version of struct ethtool_drvinfo.*/ @@ -55,9 +62,52 @@ typedef struct { gboolean nmp_utils_ethtool_get_driver_info (int ifindex, NMPUtilsEthtoolDriverInfo *data); -gboolean nmp_utils_ethtool_get_permanent_address (int ifindex, - guint8 *buf, - size_t *length); +typedef struct { + NMEthtoolID ethtool_id; + + guint8 n_kernel_names; + + /* one NMEthtoolID refers to one or more kernel_names. The reason for supporting this complexity + * (where one NMSettingEthtool option refers to multiple kernel features) is to follow what + * ethtool does, where "tx" is an alias for multiple features. */ + const char *const*kernel_names; +} NMEthtoolFeatureInfo; + +typedef struct { + const NMEthtoolFeatureInfo *info; + + guint idx_ss_features; + + /* one NMEthtoolFeatureInfo references one or more kernel_names. This is the index + * of the matching info->kernel_names */ + guint8 idx_kernel_name; + + bool available:1; + bool requested:1; + bool active:1; + bool never_changed:1; +} NMEthtoolFeatureState; + +struct _NMEthtoolFeatureStates { + guint n_states; + + guint n_ss_features; + + /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ + const NMEthtoolFeatureState *const*states_indexed[_NM_ETHTOOL_ID_FEATURE_NUM]; + + /* the same content, here as a list of n_states entries. */ + const NMEthtoolFeatureState states_list[]; +}; + +NMEthtoolFeatureStates *nmp_utils_ethtool_get_features (int ifindex); + +gboolean nmp_utils_ethtool_set_features (int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */); + +/*****************************************************************************/ gboolean nmp_utils_mii_supports_carrier_detect (int ifindex); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 22af971505..0020acc924 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3213,6 +3213,32 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_platform_link_duplex_type_to_string, NMPlatformLi /*****************************************************************************/ +NMEthtoolFeatureStates * +nm_platform_ethtool_get_link_features (NMPlatform *self, int ifindex) +{ + _CHECK_SELF_NETNS (self, klass, netns, NULL); + + g_return_val_if_fail (ifindex > 0, NULL); + + return nmp_utils_ethtool_get_features (ifindex); +} + +gboolean +nm_platform_ethtool_set_features (NMPlatform *self, + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */) +{ + _CHECK_SELF_NETNS (self, klass, netns, FALSE); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return nmp_utils_ethtool_set_features (ifindex, features, requested, do_set); +} + +/*****************************************************************************/ + const NMDedupMultiHeadEntry * nm_platform_lookup_all (NMPlatform *platform, NMPCacheIdType cache_id_type, diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index bbc9fccabc..994e041719 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1534,6 +1534,17 @@ int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPla gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password); gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex); gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex); + +typedef struct _NMEthtoolFeatureStates NMEthtoolFeatureStates; + +NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features (NMPlatform *self, + int ifindex); +gboolean nm_platform_ethtool_set_features (NMPlatform *self, + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */); + const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex); void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 8b8c87d833..12d9181208 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -60,7 +60,7 @@ test_cleanup_internal (void) g_assert (ifindex > 0); /* wait for kernel to add the IPv6 link local address... it takes a bit. */ - NMTST_WAIT_ASSERT (100, { + NMTST_WAIT_ASSERT (300, { gs_unref_array GArray *addrs = NULL; const NMPlatformIP6Address *a; diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 854285357a..20b3374b28 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -2713,6 +2713,102 @@ test_sysctl_netns_switch (void) /*****************************************************************************/ +static void +ethtool_features_dump (const NMEthtoolFeatureStates *features) +{ + guint i, j; + + g_assert (features); + + _LOGT (">>> %u features (%u ss-features)", features->n_states, features->n_ss_features); + + for (i = 0; i < features->n_states; i++) { + const NMEthtoolFeatureState *s = &features->states_list[i]; + + _LOGT (">>> feature-list[%3u]: %3d = %-32s (%3u) | %s %s %s %s", + i, + (int) s->info->ethtool_id, + s->info->kernel_names[s->idx_kernel_name], + s->idx_ss_features, + s->active ? "ACT" : "act", + s->available ? "AVA" : "ava", + s->never_changed ? "NCH" : "nch", + s->requested ? "REQ" : "req"); + } + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { + _LOGT (">>> feature-idx [%3u]: %-32s = %u features", + i + (guint) _NM_ETHTOOL_ID_FEATURE_FIRST, + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + (guint) NM_PTRARRAY_LEN (features->states_indexed[i])); + for (j = 0; features->states_indexed[i] && features->states_indexed[i][j]; j++) { + const NMEthtoolFeatureState *s = features->states_indexed[i][j]; + + _LOGT (">>> %3u: %-32s | %s %s %s %s", + j, + s->info->kernel_names[s->idx_kernel_name], + s->active ? "ACT" : "act", + s->available ? "AVA" : "ava", + s->never_changed ? "NCH" : "nch", + s->requested ? "REQ" : "req"); + } + } +} + +static void +test_ethtool_features_get (void) +{ + gs_unref_ptrarray GPtrArray *gfree_keeper = g_ptr_array_new_with_free_func (g_free); + const int IFINDEX = 1; + guint i; + guint i_run; + + for (i_run = 0; i_run < 5; i_run++) { + NMEthtoolFeatureStates *features; + NMTernary *requested; + gboolean do_set = TRUE; + + requested = g_new (NMTernary, _NM_ETHTOOL_ID_FEATURE_NUM); + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + requested[i] = NM_TERNARY_DEFAULT; + g_ptr_array_add (gfree_keeper, requested); + + if (i_run == 0) { + requested[NM_ETHTOOL_ID_FEATURE_RX] = NM_TERNARY_FALSE; + requested[NM_ETHTOOL_ID_FEATURE_TSO] = NM_TERNARY_FALSE; + requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION] = NM_TERNARY_FALSE; + } else if (i_run == 1) + do_set = FALSE; + else if (i_run == 2) { + requested[NM_ETHTOOL_ID_FEATURE_TSO] = NM_TERNARY_FALSE; + requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION] = NM_TERNARY_TRUE; + } else if (i_run == 3) + do_set = FALSE; + + _LOGT (">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset"); + + features = nmp_utils_ethtool_get_features (IFINDEX); + g_ptr_array_add (gfree_keeper, features); + + ethtool_features_dump (features); + + if (_LOGT_ENABLED ()) { + int ignore; + + ignore = system ("ethtool -k lo"); + (void) ignore; + } + + if (!do_set) { + requested = gfree_keeper->pdata[i_run * 2 - 2]; + features = gfree_keeper->pdata[i_run * 2 - 1]; + } + + nmp_utils_ethtool_set_features (IFINDEX, features, requested, do_set); + } +} + +/*****************************************************************************/ + NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void @@ -2774,5 +2870,7 @@ _nmtstp_setup_tests (void) g_test_add_func ("/general/sysctl/rename", test_sysctl_rename); g_test_add_func ("/general/sysctl/netns-switch", test_sysctl_netns_switch); + + g_test_add_func ("/link/ethtool/features/get", test_ethtool_features_get); } } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index f5bd0820e5..804139e41d 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -41,6 +41,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" +#include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-bond.h" #include "nm-setting-team.h" @@ -53,6 +54,7 @@ #include "nm-setting-generic.h" #include "nm-core-internal.h" #include "nm-utils.h" +#include "nm-ethtool-utils.h" #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" @@ -4046,199 +4048,253 @@ wireless_connection_from_ifcfg (const char *file, } static void -parse_ethtool_option_autoneg (const char *value, gboolean *out_autoneg) +parse_ethtool_option (const char *value, + NMSettingWiredWakeOnLan *out_flags, + char **out_password, + gboolean *out_autoneg, + guint32 *out_speed, + const char **out_duplex, + NMSettingEthtool **out_s_ethtool) { - if (!value) { - PARSE_WARNING ("Auto-negotiation option missing"); + gs_free const char **words = NULL; + guint i; + + words = nm_utils_strsplit_set (value, NULL); + if (!words) return; - } - if (g_str_equal (value, "off")) - *out_autoneg = FALSE; - else if (g_str_equal (value, "on")) - *out_autoneg = TRUE; - else - PARSE_WARNING ("Auto-negotiation unknown value: %s", value); -} + if (words[0] && words[0][0] == '-') { + /* /sbin/ethtool $opts */ + if (NM_IN_STRSET (words[0], "-K", "--features", "--offload")) { + if (!words[1]) { + /* first argument must be the interface name. This is invalid. */ + return; + } -static void -parse_ethtool_option_speed (const char *value, guint32 *out_speed) -{ - if (!value) { - PARSE_WARNING ("Speed option missing"); - return; - } + if (!*out_s_ethtool) + *out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); - *out_speed = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0); - if (errno) - PARSE_WARNING ("Speed value '%s' is invalid", value); -} + for (i = 2; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + const NMEthtoolData *d = NULL; + NMTernary onoff = NM_TERNARY_DEFAULT; -static void -parse_ethtool_option_duplex (const char *value, const char **out_duplex) -{ - if (!value) { - PARSE_WARNING ("Duplex option missing"); - return; - } + if (nm_streq0 (opt_val, "on")) + onoff = NM_TERNARY_TRUE; + else if (nm_streq0 (opt_val, "off")) + onoff = NM_TERNARY_FALSE; - if (g_str_equal (value, "half")) - *out_duplex = "half"; - else if (g_str_equal (value, "full")) - *out_duplex = "full"; - else - PARSE_WARNING ("Duplex unknown value: %s", value); + d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt); -} + if (!d) { + if (onoff != NM_TERNARY_DEFAULT) { + /* the next value is just the on/off argument. Skip it too. */ + i++; + } -static void -parse_ethtool_option_wol (const char *value, NMSettingWiredWakeOnLan *out_flags) -{ - NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + /* silently ignore unsupported offloading features. */ + continue; + } - if (!value) { - PARSE_WARNING ("Wake-on-LAN options missing"); + i++; + + if (onoff == NM_TERNARY_DEFAULT) { + PARSE_WARNING ("Expects on/off argument for feature '%s'", opt); + continue; + } + + nm_setting_ethtool_set_feature (*out_s_ethtool, + d->optname, + onoff); + } + } return; } - for (; *value; value++) { - switch (*value) { - case 'p': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; - break; - case 'u': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; - break; - case 'm': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; - break; - case 'b': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; - break; - case 'a': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; - break; - case 'g': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; - break; - case 's': - break; - case 'd': - wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - break; - default: - PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *value); + /* /sbin/ethtool -s ${REALDEVICE} $opts */ + for (i = 0; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + + if (nm_streq (opt, "autoneg")) { + if (!opt_val) { + PARSE_WARNING ("Auto-negotiation option missing"); + break; + } + i++; + + if (nm_streq (opt_val, "off")) + *out_autoneg = FALSE; + else if (nm_streq (opt_val, "on")) + *out_autoneg = TRUE; + else + PARSE_WARNING ("Auto-negotiation unknown value: %s", opt_val); + continue; } - } - *out_flags = wol_flags; -} + if (nm_streq (opt, "speed")) { + guint32 speed; -static void parse_ethtool_option_sopass (const char *value, char **out_password) -{ - if (!value) { - PARSE_WARNING ("Wake-on-LAN password missing"); - return; - } + if (!opt_val) { + PARSE_WARNING ("Speed option missing"); + break; + } + i++; - g_clear_pointer (out_password, g_free); - if (!nm_utils_hwaddr_valid (value, ETH_ALEN)) { - PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", value); - return; - } + speed = _nm_utils_ascii_str_to_int64 (opt_val, 10, 0, G_MAXUINT32, 0); + if (errno == 0) + *out_speed = speed; + else + PARSE_WARNING ("Speed value '%s' is invalid", opt_val); + continue; + } - *out_password = g_strdup (value); -} + if (nm_streq (opt, "duplex")) { + if (!opt_val) { + PARSE_WARNING ("Duplex option missing"); + break; + } + i++; -static void -parse_ethtool_option (const char *value, - NMSettingWiredWakeOnLan *out_flags, - char **out_password, - gboolean *out_autoneg, - guint32 *out_speed, - const char **out_duplex) -{ - gs_free const char **words = NULL; - const char *const *iter; - const char *opt_val, *opt; + if (nm_streq (opt_val, "half")) + *out_duplex = "half"; + else if (nm_streq (opt_val, "full")) + *out_duplex = "full"; + else + PARSE_WARNING ("Duplex unknown value: %s", opt_val); + continue; + } - words = nm_utils_strsplit_set (value, "\t "); - if (!words) - return; + if (nm_streq (opt, "wol")) { + NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - iter = words; - - while (iter[0]) { - opt = iter++[0]; - opt_val = iter[0]; - - if (nm_streq (opt, "autoneg")) - parse_ethtool_option_autoneg (opt_val, out_autoneg); - else if (nm_streq (opt, "speed")) - parse_ethtool_option_speed (opt_val, out_speed); - else if (nm_streq (opt, "duplex")) - parse_ethtool_option_duplex (opt_val, out_duplex); - else if (nm_streq (opt, "wol")) - parse_ethtool_option_wol (opt_val, out_flags); - else if (nm_streq (opt, "sopass")) - parse_ethtool_option_sopass (opt_val, out_password); - else { - /* Silently skip unknown options */ + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN options missing"); + break; + } + i++; + + for (; *opt_val; opt_val++) { + switch (*opt_val) { + case 'p': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; + break; + case 'u': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; + break; + case 'm': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; + break; + case 'b': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; + break; + case 'a': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; + break; + case 'g': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; + break; + case 's': + break; + case 'd': + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + break; + default: + PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *opt_val); + } + } + + *out_flags = wol_flags; continue; } - if (iter[0]) - iter++; + if (nm_streq (opt, "sopass")) { + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN password missing"); + break; + } + i++; + + if (nm_utils_hwaddr_valid (opt_val, ETH_ALEN)) { + g_clear_pointer (out_password, g_free); + *out_password = g_strdup (opt_val); + } else + PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", opt_val); + continue; + } + + /* Silently skip unknown options */ } } static void -parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *value) +parse_ethtool_options (shvarFile *ifcfg, NMConnection *connection) { + NMSettingWired *s_wired; + gs_unref_object NMSettingEthtool *s_ethtool = NULL; NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; - gs_free char *wol_password = NULL, *wol_value = NULL; - gboolean ignore_wol_password = FALSE, autoneg = FALSE; + gs_free char *ethtool_opts_free = NULL; + const char *ethtool_opts; + gs_free char *wol_password = NULL; + gs_free char *wol_value_free = NULL; + const char *tmp; + gboolean autoneg = FALSE; guint32 speed = 0; const char *duplex = NULL; - if (value) { - gs_free const char **opts = NULL; - const char *const *iter; - + ethtool_opts = svGetValue (ifcfg, "ETHTOOL_OPTS", ðtool_opts_free); + if (ethtool_opts) { /* WAKE_ON_LAN_IGNORE is inferred from a specified but empty ETHTOOL_OPTS */ - if (!value[0]) + if (!ethtool_opts[0]) wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; - - opts = nm_utils_strsplit_set (value, ";"); - for (iter = opts; iter && iter[0]; iter++) { - /* in case of repeated wol_passwords, parse_ethtool_option() - * will do the right thing and clear wol_password before resetting. */ - parse_ethtool_option (iter[0], &wol_flags, &wol_password, &autoneg, &speed, &duplex); + else { + gs_free const char **opts = NULL; + const char *const *iter; + + opts = nm_utils_strsplit_set (ethtool_opts, ";"); + for (iter = opts; iter && iter[0]; iter++) { + /* in case of repeated wol_passwords, parse_ethtool_option() + * will do the right thing and clear wol_password before resetting. */ + parse_ethtool_option (iter[0], + &wol_flags, + &wol_password, + &autoneg, + &speed, + &duplex, + &s_ethtool); + } } } /* ETHTOOL_WAKE_ON_LAN = ignore overrides WoL settings in ETHTOOL_OPTS */ - wol_value = svGetValueStr_cp (ifcfg, "ETHTOOL_WAKE_ON_LAN"); - if (wol_value) { - if (strcmp (wol_value, "ignore") == 0) - wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; - else - PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", wol_value); - } + tmp = svGetValueStr (ifcfg, "ETHTOOL_WAKE_ON_LAN", &wol_value_free); + if (nm_streq0 (tmp, "ignore")) + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; + else if (tmp) + PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", tmp); if ( wol_password && !NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) { PARSE_WARNING ("Wake-on-LAN password not expected"); - ignore_wol_password = TRUE; + nm_clear_g_free (&wol_password); } - g_object_set (s_wired, - NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, - NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, ignore_wol_password ? NULL : wol_password, - NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, - NM_SETTING_WIRED_SPEED, speed, - NM_SETTING_WIRED_DUPLEX, duplex, - NULL); + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + g_object_set (s_wired, + NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, wol_password, + NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, + NM_SETTING_WIRED_SPEED, speed, + NM_SETTING_WIRED_DUPLEX, duplex, + NULL); + } + + if (s_ethtool) { + nm_connection_add_setting (connection, + NM_SETTING (g_steal_pointer (&s_ethtool))); + } } static NMSetting * @@ -4380,10 +4436,6 @@ make_wired_setting (shvarFile *ifcfg, nm_clear_g_free (&value); } - parse_ethtool_options (ifcfg, s_wired, - svGetValue (ifcfg, "ETHTOOL_OPTS", &value)); - nm_clear_g_free (&value); - return (NMSetting *) g_steal_pointer (&s_wired); } @@ -5610,6 +5662,8 @@ connection_from_file_full (const char *filename, if (!connection) return NULL; + parse_ethtool_options (parsed, connection); + has_complex_routes_v4 = utils_has_complex_routes (filename, AF_INET); has_complex_routes_v6 = utils_has_complex_routes (filename, AF_INET6); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 862e640e02..49096d262f 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -470,3 +470,104 @@ nms_ifcfg_rh_utils_user_key_decode (const char *name, GString *str_buffer) return TRUE; } + +/*****************************************************************************/ + +const char *const _nm_ethtool_ifcfg_names[] = { +#define ETHT_NAME(eid, ename) \ +[eid - _NM_ETHTOOL_ID_FEATURE_FIRST] = ""ename"" + /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_GRO, "gro"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_GSO, "gso"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_LRO, "lro"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_NTUPLE, "ntuple"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX, "rx"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RXHASH, "rxhash"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RXVLAN, "rxvlan"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_SG, "sg"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TSO, "tso"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX, "tx"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TXVLAN, "txvlan"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), +}; + +const NMEthtoolData * +nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) +{ + static const struct { + NMEthtoolID ethtool_id; + const char *kernel_name; + } kernel_names[] = { + { NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro" }, + { NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation" }, + { NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro" }, + { NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter" }, + { NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum" }, + { NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing" }, + { NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse" }, + { NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert" }, + }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (_nm_ethtool_ifcfg_names); i++) { + if (nm_streq (name, _nm_ethtool_ifcfg_names[i])) + return nm_ethtool_data[i]; + } + + /* Option not found. Note that ethtool utility has built-in features and + * NetworkManager's API follows the naming of these built-in features, whenever + * they exist. + * For example, NM's "ethtool.feature-ntuple" corresponds to ethtool utility's "ntuple" + * feature. However the underlying kernel feature is called "rx-ntuple-filter" (as reported + * for ETH_SS_FEATURES). + * + * With ethtool utility, whose command line we attempt to parse here, the user can also + * specify the name of the underlying kernel feature directly. So, check whether that is + * the case and if yes, map them to the corresponding NetworkManager's features. */ + for (i = 0; i < G_N_ELEMENTS (kernel_names); i++) { + if (nm_streq (name, kernel_names[i].kernel_name)) + return nm_ethtool_data[kernel_names[i].ethtool_id]; + } + + return NULL; +} diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 3756af7cc6..d95b1f61cf 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -22,6 +22,7 @@ #define _UTILS_H_ #include "nm-connection.h" +#include "nm-ethtool-utils.h" #include "shvar.h" @@ -80,4 +81,20 @@ _nms_ifcfg_rh_utils_numbered_tag (char *buf, gsize buf_len, const char *tag_name _nms_ifcfg_rh_utils_numbered_tag (buf, sizeof (buf), ""tag_name"", (which)); \ }) +/*****************************************************************************/ + +extern const char *const _nm_ethtool_ifcfg_names[_NM_ETHTOOL_ID_FEATURE_NUM]; + +static inline const char * +nms_ifcfg_rh_utils_get_ethtool_name (NMEthtoolID ethtool_id) +{ + nm_assert (ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST && ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); + nm_assert ((ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST) < G_N_ELEMENTS (_nm_ethtool_ifcfg_names)); + nm_assert (_nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]); + + return _nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]; +} + +const NMEthtoolData *nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name); + #endif /* _UTILS_H_ */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index f29017e3a7..a2abe995a8 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -37,6 +37,7 @@ #include "nm-setting-connection.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" +#include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-proxy.h" #include "nm-setting-ip4-config.h" @@ -50,6 +51,7 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-meta-setting.h" +#include "nm-ethtool-utils.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" @@ -809,7 +811,7 @@ write_wireless_setting (NMConnection *connection, const char *device_mac, *cloned_mac; guint32 mtu, chan, i; gboolean adhoc = FALSE, hex_ssid = FALSE; - const char * const *macaddr_blacklist; + const char *const*macaddr_blacklist; s_wireless = nm_connection_get_setting_wireless (connection); if (!s_wireless) { @@ -1041,16 +1043,9 @@ static gboolean write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) { NMSettingWired *s_wired; - const char *device_mac, *cloned_mac; - char *tmp; - const char *nettype, *portname, *ctcprot, *s390_key, *s390_val, *duplex; - guint32 mtu, num_opts, speed, i; - const char *const *s390_subchannels; - GString *str = NULL; - const char * const *macaddr_blacklist; - gboolean auto_negotiate; - NMSettingWiredWakeOnLan wol; - const char *wol_password; + const char *const*s390_subchannels; + guint32 mtu, num_opts, i; + const char *const*macaddr_blacklist; s_wired = nm_connection_get_setting_wired (connection); if (!s_wired) { @@ -1059,144 +1054,211 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return FALSE; } - device_mac = nm_setting_wired_get_mac_address (s_wired); - svSetValueStr (ifcfg, "HWADDR", device_mac); + svSetValueStr (ifcfg, "HWADDR", + nm_setting_wired_get_mac_address (s_wired)); - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - svSetValueStr (ifcfg, "MACADDR", cloned_mac); + svSetValueStr (ifcfg, "MACADDR", + nm_setting_wired_get_cloned_mac_address (s_wired)); svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", nm_setting_wired_get_generate_mac_address_mask (s_wired)); - svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); if (macaddr_blacklist[0]) { - char *blacklist_str; + gs_free char *blacklist_str = NULL; blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); - g_free (blacklist_str); - } + } else + svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); mtu = nm_setting_wired_get_mtu (s_wired); svSetValueInt64_cond (ifcfg, "MTU", mtu != 0, mtu); - svUnsetValue (ifcfg, "SUBCHANNELS"); s390_subchannels = nm_setting_wired_get_s390_subchannels (s_wired); - if (s390_subchannels) { - int len = g_strv_length ((char **)s390_subchannels); - tmp = NULL; + { + gs_free char *tmp = NULL; + gsize len = NM_PTRARRAY_LEN (s390_subchannels); + if (len == 2) { - tmp = g_strdup_printf ("%s,%s", s390_subchannels[0], s390_subchannels[1]); + tmp = g_strdup_printf ("%s,%s", + s390_subchannels[0], + s390_subchannels[1]); } else if (len == 3) { - tmp = g_strdup_printf ("%s,%s,%s", s390_subchannels[0], s390_subchannels[1], + tmp = g_strdup_printf ("%s,%s,%s", + s390_subchannels[0], + s390_subchannels[1], s390_subchannels[2]); } + svSetValueStr (ifcfg, "SUBCHANNELS", tmp); - g_free (tmp); } - svUnsetValue (ifcfg, "NETTYPE"); - nettype = nm_setting_wired_get_s390_nettype (s_wired); - if (nettype) - svSetValueStr (ifcfg, "NETTYPE", nettype); + svSetValueStr (ifcfg, "NETTYPE", + nm_setting_wired_get_s390_nettype (s_wired)); - svUnsetValue (ifcfg, "PORTNAME"); - portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname"); - if (portname) - svSetValueStr (ifcfg, "PORTNAME", portname); + svSetValueStr (ifcfg, "PORTNAME", + nm_setting_wired_get_s390_option_by_key (s_wired, "portname")); - svUnsetValue (ifcfg, "CTCPROT"); - ctcprot = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot"); - if (ctcprot) - svSetValueStr (ifcfg, "CTCPROT", ctcprot); + svSetValueStr (ifcfg, "CTCPROT", + nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot")); svUnsetValue (ifcfg, "OPTIONS"); num_opts = nm_setting_wired_get_num_s390_options (s_wired); if (s390_subchannels && num_opts) { - str = g_string_sized_new (30); + nm_auto_free_gstring GString *tmp = NULL; + for (i = 0; i < num_opts; i++) { + const char *s390_key, *s390_val; + nm_setting_wired_get_s390_option (s_wired, i, &s390_key, &s390_val); /* portname is handled separately */ if (!strcmp (s390_key, "portname") || !strcmp (s390_key, "ctcprot")) continue; - if (str->len) - g_string_append_c (str, ' '); - g_string_append_printf (str, "%s=%s", s390_key, s390_val); + if (!tmp) + tmp = g_string_sized_new (30); + else + g_string_append_c (tmp, ' '); + g_string_append_printf (tmp, "%s=%s", s390_key, s390_val); } - if (str->len) - svSetValueStr (ifcfg, "OPTIONS", str->str); - g_string_free (str, TRUE); + if (tmp) + svSetValueStr (ifcfg, "OPTIONS", tmp->str); } - /* Stuff ETHTOOL_OPT with required options */ - str = NULL; - auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired); - speed = nm_setting_wired_get_speed (s_wired); - duplex = nm_setting_wired_get_duplex (s_wired); + svSetValueStr (ifcfg, "TYPE", TYPE_ETHERNET); - /* autoneg off + speed 0 + duplex NULL, means we want NM - * to skip link configuration which is default. So write - * down link config only if we have auto-negotiate true or - * a valid value for one among speed and duplex. - */ - if (auto_negotiate) { - str = g_string_sized_new (64); - g_string_printf (str, "autoneg on"); - } else if (speed || duplex) { - str = g_string_sized_new (64); - g_string_printf (str, "autoneg off"); + return TRUE; +} + +static gboolean +write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingWired *s_wired; + NMSettingEthtool *s_ethtool; + const char *duplex; + guint32 speed; + GString *str = NULL; + gboolean auto_negotiate; + NMSettingWiredWakeOnLan wol; + const char *wol_password; + + s_wired = nm_connection_get_setting_wired (connection); + s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL)); + + if (!s_wired && !s_ethtool) { + svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + svUnsetValue (ifcfg, "ETHTOOL_OPTS"); + return TRUE; } - if (speed) - g_string_append_printf (str, " speed %u", speed); - if (duplex) - g_string_append_printf (str, " duplex %s", duplex); - wol = nm_setting_wired_get_wake_on_lan (s_wired); - wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired); + if (s_wired) { + auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired); + speed = nm_setting_wired_get_speed (s_wired); + duplex = nm_setting_wired_get_duplex (s_wired); + + /* autoneg off + speed 0 + duplex NULL, means we want NM + * to skip link configuration which is default. So write + * down link config only if we have auto-negotiate true or + * a valid value for one among speed and duplex. + */ + if (auto_negotiate) { + str = g_string_sized_new (64); + g_string_printf (str, "autoneg on"); + } else if (speed || duplex) { + str = g_string_sized_new (64); + g_string_printf (str, "autoneg off"); + } + if (speed) + g_string_append_printf (str, " speed %u", speed); + if (duplex) + g_string_append_printf (str, " duplex %s", duplex); + + wol = nm_setting_wired_get_wake_on_lan (s_wired); + wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired); + + svSetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN", + wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE + ? "ignore" + : NULL); + if (!NM_IN_SET (wol, NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE, + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)) { + if (!str) + str = g_string_sized_new (30); + else + g_string_append (str, " "); + + g_string_append (str, "wol "); + + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) + g_string_append (str, "p"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) + g_string_append (str, "u"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) + g_string_append (str, "m"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) + g_string_append (str, "b"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) + g_string_append (str, "a"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append (str, "g"); + + if (!NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) + g_string_append (str, "d"); + + if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append_printf (str, "s sopass %s", wol_password); + } + } else + svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + + if (s_ethtool) { + NMEthtoolID ethtool_id; + NMSettingConnection *s_con; + const char *iface = NULL; + + s_con = nm_connection_get_setting_connection (connection); + if (s_con) { + iface = nm_setting_connection_get_interface_name (s_con); + if ( iface + && ( !iface[0] + || !NM_STRCHAR_ALL (iface, ch, (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9') + || NM_IN_SET (ch, '_')))) + iface = NULL; + } - if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) - svSetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN", "ignore"); - else if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) { - if (!str) - svUnsetValue (ifcfg, "ETHTOOL_OPTS"); - } else { if (!str) str = g_string_sized_new (30); else - g_string_append (str, " "); + g_string_append (str, " ; "); + g_string_append (str, "-K "); + g_string_append (str, iface ?: "net0"); - g_string_append (str, "wol "); + for (ethtool_id = _NM_ETHTOOL_ID_FEATURE_FIRST; ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST; ethtool_id++) { + const NMEthtoolData *ed = nm_ethtool_data[ethtool_id]; + NMTernary val; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) - g_string_append (str, "p"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) - g_string_append (str, "u"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) - g_string_append (str, "m"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) - g_string_append (str, "b"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) - g_string_append (str, "a"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - g_string_append (str, "g"); + nm_assert (nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id)); - if (!NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) - g_string_append (str, "d"); + val = nm_setting_ethtool_get_feature (s_ethtool, ed->optname); + if (val == NM_TERNARY_DEFAULT) + continue; - if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - g_string_append_printf (str, "s sopass %s", wol_password); + g_string_append_c (str, ' '); + g_string_append (str, nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id)); + g_string_append (str, val == NM_TERNARY_TRUE ? " on" : " off"); + } } + if (str) { svSetValueStr (ifcfg, "ETHTOOL_OPTS", str->str); g_string_free (str, TRUE); - } - /* End ETHTOOL_OPT stuffing */ - - svSetValueStr (ifcfg, "TYPE", TYPE_ETHERNET); + } else + svUnsetValue (ifcfg, "ETHTOOL_OPTS"); return TRUE; } @@ -2962,6 +3024,9 @@ do_write_construct (NMConnection *connection, if (!write_proxy_setting (connection, ifcfg, error)) return FALSE; + if (!write_ethtool_setting (connection, ifcfg, error)) + return FALSE; + if (!write_user_setting (connection, ifcfg, error)) return FALSE; diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected index 8f421cfbda..214f5da55b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected @@ -1,7 +1,7 @@ -ETHTOOL_OPTS="autoneg off speed 10 duplex half" TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg off speed 10 duplex half" BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected index 398a301780..de66dcddb8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected @@ -1,7 +1,7 @@ -ETHTOOL_OPTS="wol umgs sopass 00:00:00:11:22:33" TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no +ETHTOOL_OPTS="wol umgs sopass 00:00:00:11:22:33" BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected new file mode 100644 index 0000000000..426085765c --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write Wired Auto-Negotiate" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 8d4efbbfd1..fc42937d0e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -43,12 +43,14 @@ #include "nm-setting-pppoe.h" #include "nm-setting-ppp.h" #include "nm-setting-vpn.h" +#include "nm-setting-ethtool.h" #include "nm-setting-gsm.h" #include "nm-setting-cdma.h" #include "nm-setting-serial.h" #include "nm-setting-vlan.h" #include "nm-setting-dcb.h" #include "nm-core-internal.h" +#include "nm-ethtool-utils.h" #include "NetworkManagerUtils.h" @@ -185,7 +187,8 @@ _assert_expected_content (NMConnection *connection, const char *filename, const if ( len_expectd != len_written || memcmp (content_expectd, content_written, len_expectd) != 0) { - if (g_getenv ("NMTST_IFCFG_RH_UPDATE_EXPECTED")) { + if ( g_getenv ("NMTST_IFCFG_RH_UPDATE_EXPECTED") + || nm_streq0 (g_getenv ("NM_TEST_REGENERATE"), "1")) { if (uuid) { gs_free char *search = g_strdup_printf ("UUID=%s\n", uuid); const char *s; @@ -3725,6 +3728,7 @@ test_write_wired_auto_negotiate_on (void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingWired *s_wired; + NMSettingEthtool *s_ethtool; char *val; shvarFile *f; @@ -3734,8 +3738,14 @@ test_write_wired_auto_negotiate_on (void) NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); - _writer_new_connection (connection, + s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); + nm_setting_ethtool_set_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX, NM_TERNARY_TRUE); + nm_setting_ethtool_set_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN, NM_TERNARY_FALSE); + nm_connection_add_setting (connection, NM_SETTING (s_ethtool)); + + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR, + TEST_IFCFG_DIR"/ifcfg-test_write_wired_auto_negotiate_on.cexpected", &testfile); f = _svOpenFile (testfile); @@ -3749,7 +3759,15 @@ test_write_wired_auto_negotiate_on (void) reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + nmtst_assert_connection_verifies_without_normalization (reread); + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); + + s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (reread, NM_TYPE_SETTING_ETHTOOL)); + g_assert (s_ethtool); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TXVLAN), ==, NM_TERNARY_DEFAULT); } static void |