summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-08-10 10:39:00 +0200
committerThomas Haller <thaller@redhat.com>2018-08-10 10:39:00 +0200
commitda3b72d8420e0fa25203f0989e20bad65bdfc2d8 (patch)
treec5b8d0e4909990bff9356a121230708ddd677ba8
parentc955d91d4bbd1aec0e00be8955ac24aecf64182f (diff)
parentda109a291c6d219a554578e32c4c0daae6def241 (diff)
downloadNetworkManager-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
-rw-r--r--Makefile.am8
-rw-r--r--clients/cli/connections.c3
-rw-r--r--clients/cli/settings.c30
-rw-r--r--clients/cli/utils.c13
-rw-r--r--clients/common/meson.build2
-rw-r--r--clients/common/nm-client-utils.c8
-rw-r--r--clients/common/nm-client-utils.h8
-rw-r--r--clients/common/nm-meta-setting-access.c55
-rw-r--r--clients/common/nm-meta-setting-desc.c178
-rw-r--r--clients/common/nm-meta-setting-desc.h9
-rw-r--r--docs/libnm/libnm-docs.xml1
-rw-r--r--libnm-core/meson.build4
-rw-r--r--libnm-core/nm-core-internal.h155
-rw-r--r--libnm-core/nm-core-types.h1
-rw-r--r--libnm-core/nm-keyfile.c275
-rw-r--r--libnm-core/nm-setting-6lowpan.c16
-rw-r--r--libnm-core/nm-setting-8021x.c20
-rw-r--r--libnm-core/nm-setting-adsl.c21
-rw-r--r--libnm-core/nm-setting-bluetooth.c30
-rw-r--r--libnm-core/nm-setting-bond.c49
-rw-r--r--libnm-core/nm-setting-bridge-port.c18
-rw-r--r--libnm-core/nm-setting-bridge.c40
-rw-r--r--libnm-core/nm-setting-cdma.c20
-rw-r--r--libnm-core/nm-setting-connection.c35
-rw-r--r--libnm-core/nm-setting-dcb.c86
-rw-r--r--libnm-core/nm-setting-dummy.c11
-rw-r--r--libnm-core/nm-setting-ethtool.c342
-rw-r--r--libnm-core/nm-setting-ethtool.h124
-rw-r--r--libnm-core/nm-setting-generic.c11
-rw-r--r--libnm-core/nm-setting-gsm.c40
-rw-r--r--libnm-core/nm-setting-infiniband.c29
-rw-r--r--libnm-core/nm-setting-ip-config.c45
-rw-r--r--libnm-core/nm-setting-ip-tunnel.c17
-rw-r--r--libnm-core/nm-setting-ip4-config.c87
-rw-r--r--libnm-core/nm-setting-ip6-config.c78
-rw-r--r--libnm-core/nm-setting-macsec.c18
-rw-r--r--libnm-core/nm-setting-macvlan.c17
-rw-r--r--libnm-core/nm-setting-olpc-mesh.c31
-rw-r--r--libnm-core/nm-setting-ovs-bridge.c16
-rw-r--r--libnm-core/nm-setting-ovs-interface.c16
-rw-r--r--libnm-core/nm-setting-ovs-patch.c16
-rw-r--r--libnm-core/nm-setting-ovs-port.c16
-rw-r--r--libnm-core/nm-setting-ppp.c18
-rw-r--r--libnm-core/nm-setting-pppoe.c20
-rw-r--r--libnm-core/nm-setting-private.h125
-rw-r--r--libnm-core/nm-setting-proxy.c19
-rw-r--r--libnm-core/nm-setting-serial.c30
-rw-r--r--libnm-core/nm-setting-sriov.c40
-rw-r--r--libnm-core/nm-setting-tc-config.c52
-rw-r--r--libnm-core/nm-setting-team-port.c40
-rw-r--r--libnm-core/nm-setting-team.c50
-rw-r--r--libnm-core/nm-setting-tun.c18
-rw-r--r--libnm-core/nm-setting-user.c47
-rw-r--r--libnm-core/nm-setting-vlan.c41
-rw-r--r--libnm-core/nm-setting-vpn.c53
-rw-r--r--libnm-core/nm-setting-vxlan.c17
-rw-r--r--libnm-core/nm-setting-wimax.c31
-rw-r--r--libnm-core/nm-setting-wired.c78
-rw-r--r--libnm-core/nm-setting-wireless-security.c39
-rw-r--r--libnm-core/nm-setting-wireless.c80
-rw-r--r--libnm-core/nm-setting-wpan.c16
-rw-r--r--libnm-core/nm-setting.c1298
-rw-r--r--libnm-core/nm-setting.h15
-rw-r--r--libnm-core/nm-utils.c113
-rw-r--r--libnm-core/tests/test-general.c42
-rw-r--r--libnm-core/tests/test-setting.c77
-rw-r--r--libnm-util/nm-setting-connection.c1
-rw-r--r--libnm/NetworkManager.h1
-rw-r--r--libnm/libnm.ver5
-rw-r--r--libnm/nm-autoptr.h1
-rw-r--r--po/POTFILES.in1
-rw-r--r--shared/meson.build4
-rw-r--r--shared/nm-ethtool-utils.c225
-rw-r--r--shared/nm-ethtool-utils.h120
-rw-r--r--shared/nm-meta-setting.c133
-rw-r--r--shared/nm-meta-setting.h102
-rw-r--r--shared/nm-utils/nm-macros-internal.h8
-rw-r--r--shared/nm-utils/nm-shared-utils.c203
-rw-r--r--shared/nm-utils/nm-shared-utils.h29
-rw-r--r--src/devices/nm-device.c87
-rw-r--r--src/nm-config-data.c12
-rw-r--r--src/nm-manager.c12
-rw-r--r--src/platform/nm-platform-utils.c733
-rw-r--r--src/platform/nm-platform-utils.h56
-rw-r--r--src/platform/nm-platform.c26
-rw-r--r--src/platform/nm-platform.h11
-rw-r--r--src/platform/tests/test-cleanup.c2
-rw-r--r--src/platform/tests/test-link.c98
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c358
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c101
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h17
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c255
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected15
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c22
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 (&ethtool_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", &ethtool_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