diff options
| author | Michael Biebl <biebl@debian.org> | 2024-02-22 17:21:11 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2024-02-22 17:21:11 +0100 |
| commit | bba2e4b4de668db525cbfdfc35292e5a0b51671a (patch) | |
| tree | 38d20cddfcc6f71572b9e169deefab5fa96e8d0c /src/libnm-core-impl | |
| parent | 6681f77b757bbc42ce5c8868ee9142b7ebc8c059 (diff) | |
New upstream version 1.46.0 upstream/1.46.0
Diffstat (limited to 'src/libnm-core-impl')
| -rw-r--r-- | src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in | 22 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-connection.c | 7 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-connection.c | 22 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-generic.c | 128 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-ip-config.c | 6 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-ip6-config.c | 22 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-macsec.c | 49 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-private.h | 96 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-sriov.c | 133 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting-wireguard.c | 3 | ||||
| -rw-r--r-- | src/libnm-core-impl/nm-setting.c | 153 | ||||
| -rw-r--r-- | src/libnm-core-impl/tests/test-setting.c | 37 |
12 files changed, 603 insertions, 75 deletions
diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in index 84220043..146f9282 100644 --- a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in +++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in @@ -769,7 +769,7 @@ /> <property name="autoconnect-ports" dbus-type="i" - gprop-type="NMTernary" + gprop-type="gint" /> <property name="autoconnect-priority" dbus-type="i" @@ -1331,6 +1331,10 @@ <setting name="generic" gtype="NMSettingGeneric" > + <property name="device-handler" + dbus-type="s" + gprop-type="gchararray" + /> </setting> <setting name="gsm" gtype="NMSettingGsm" @@ -1876,6 +1880,10 @@ dbus-type="i" gprop-type="gint" /> + <property name="offload" + dbus-type="i" + gprop-type="gint" + /> <property name="parent" dbus-type="s" gprop-type="gchararray" @@ -2198,6 +2206,18 @@ dbus-type="i" gprop-type="NMTernary" /> + <property name="eswitch-encap-mode" + dbus-type="i" + gprop-type="gint" + /> + <property name="eswitch-inline-mode" + dbus-type="i" + gprop-type="gint" + /> + <property name="eswitch-mode" + dbus-type="i" + gprop-type="gint" + /> <property name="total-vfs" dbus-type="u" gprop-type="guint" diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c index a23dc113..33360d04 100644 --- a/src/libnm-core-impl/nm-connection.c +++ b/src/libnm-core-impl/nm-connection.c @@ -3207,6 +3207,13 @@ nm_connection_is_virtual(NMConnection *connection) return !!nm_setting_pppoe_get_parent(s_pppoe); } + if (nm_streq(type, NM_SETTING_GENERIC_SETTING_NAME)) { + NMSettingGeneric *s_generic; + + s_generic = nm_connection_get_setting_generic(connection); + return !!nm_setting_generic_get_device_handler(s_generic); + } + return FALSE; } diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c index 616a3e5e..7c58c84f 100644 --- a/src/libnm-core-impl/nm-setting-connection.c +++ b/src/libnm-core-impl/nm-setting-connection.c @@ -2655,7 +2655,7 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass) * when this connection is activated. * ---end--- */ - prop_idx = _nm_setting_property_define_direct_enum( + prop_idx = _nm_setting_property_define_direct_real_enum( properties_override, obj_properties, NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, @@ -2776,16 +2776,16 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass) * example: CONNECTION_METERED=yes * ---end--- */ - _nm_setting_property_define_direct_enum(properties_override, - obj_properties, - NM_SETTING_CONNECTION_METERED, - PROP_METERED, - NM_TYPE_METERED, - NM_METERED_UNKNOWN, - NM_SETTING_PARAM_REAPPLY_IMMEDIATELY, - NULL, - NMSettingConnectionPrivate, - metered); + _nm_setting_property_define_direct_real_enum(properties_override, + obj_properties, + NM_SETTING_CONNECTION_METERED, + PROP_METERED, + NM_TYPE_METERED, + NM_METERED_UNKNOWN, + NM_SETTING_PARAM_REAPPLY_IMMEDIATELY, + NULL, + NMSettingConnectionPrivate, + metered); /** * NMSettingConnection:lldp: diff --git a/src/libnm-core-impl/nm-setting-generic.c b/src/libnm-core-impl/nm-setting-generic.c index 6623e71f..8a38118a 100644 --- a/src/libnm-core-impl/nm-setting-generic.c +++ b/src/libnm-core-impl/nm-setting-generic.c @@ -23,13 +23,20 @@ /*****************************************************************************/ +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingGeneric, PROP_DEVICE_HANDLER, ); + +typedef struct { + char *device_handler; +} NMSettingGenericPrivate; + /** * NMSettingGeneric: * * Generic Link Settings */ struct _NMSettingGeneric { - NMSetting parent; + NMSetting parent; + NMSettingGenericPrivate _priv; }; struct _NMSettingGenericClass { @@ -38,6 +45,82 @@ struct _NMSettingGenericClass { G_DEFINE_TYPE(NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING) +#define NM_SETTING_GENERIC_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingGeneric, NM_IS_SETTING_GENERIC, NMSetting) + +/*****************************************************************************/ + +/** + * nm_setting_generic_get_device_handler: + * @setting: the #NMSettingGeneric + * + * Returns the #NMSettingGeneric:device-handler property of the connection. + * + * Returns: the device handler name, or %NULL if no device handler is set + * + * Since: 1.46 + **/ +const char * +nm_setting_generic_get_device_handler(NMSettingGeneric *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_GENERIC(setting), NULL); + + return NM_SETTING_GENERIC_GET_PRIVATE(setting)->device_handler; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingGenericPrivate *priv = NM_SETTING_GENERIC_GET_PRIVATE(setting); + + if (priv->device_handler) { + if (NM_IN_SET(priv->device_handler[0], '\0', '.') + || !NM_STRCHAR_ALL(priv->device_handler, + ch, + g_ascii_isalnum(ch) || NM_IN_SET(ch, '-', '_', '.'))) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_GENERIC_SETTING_NAME, + NM_SETTING_GENERIC_DEVICE_HANDLER); + return FALSE; + } + + if (connection) { + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection(connection); + if (!s_con) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (!nm_setting_connection_get_interface_name(s_con)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("the property is required when %s.%s is set"), + NM_SETTING_GENERIC_SETTING_NAME, + NM_SETTING_GENERIC_DEVICE_HANDLER); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + return FALSE; + } + } + } + + return TRUE; +} + /*****************************************************************************/ static void @@ -60,7 +143,46 @@ nm_setting_generic_new(void) static void nm_setting_generic_class_init(NMSettingGenericClass *klass) { - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray *properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = _nm_setting_property_get_property_direct; + object_class->set_property = _nm_setting_property_set_property_direct; + + setting_class->verify = verify; + + /** + * NMSettingGeneric:device-handler: + * + * Name of the device handler that will be invoked to add and delete + * the device for this connection. The name can only contain ASCII + * alphanumeric characters and '-', '_', '.'. It cannot start with '.'. + * + * See the NetworkManager-dispatcher(8) man page for more details + * about how to write the device handler. + * + * By setting this property the generic connection becomes "virtual", + * meaning that it can be activated without an existing device; the device + * will be created at the time the connection is started by invoking the + * device-handler. + * + * Since: 1.46 + **/ + _nm_setting_property_define_direct_string(properties_override, + obj_properties, + NM_SETTING_GENERIC_DEVICE_HANDLER, + PROP_DEVICE_HANDLER, + NM_SETTING_PARAM_FUZZY_IGNORE + | NM_SETTING_PARAM_INFERRABLE, + NMSettingGeneric, + _priv.device_handler); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_GENERIC, NULL, NULL, 0); + _nm_setting_class_commit(setting_class, + NM_META_SETTING_TYPE_GENERIC, + NULL, + properties_override, + 0); } diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 8165cb2f..02334b54 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -6139,14 +6139,16 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) obj_properties[PROP_AUTO_ROUTE_EXT_GW], &nm_sett_info_propert_type_direct_enum, .direct_offset = - NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw)); + NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw), + .direct_data.enum_gtype = NM_TYPE_TERNARY); _nm_properties_override_gobj( properties_override, obj_properties[PROP_REPLACE_LOCAL_RULE], &nm_sett_info_propert_type_direct_enum, .direct_offset = - NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule)); + NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule), + .direct_data.enum_gtype = NM_TYPE_TERNARY); _nm_properties_override_gobj( properties_override, diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index fc0744ad..42bb2571 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -941,16 +941,16 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes * ---end--- */ - _nm_setting_property_define_direct_enum(properties_override, - obj_properties, - NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - PROP_IP6_PRIVACY, - NM_TYPE_SETTING_IP6_CONFIG_PRIVACY, - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, - NM_SETTING_PARAM_NONE, - NULL, - NMSettingIP6ConfigPrivate, - ip6_privacy); + _nm_setting_property_define_direct_real_enum(properties_override, + obj_properties, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + PROP_IP6_PRIVACY, + NM_TYPE_SETTING_IP6_CONFIG_PRIVACY, + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, + NM_SETTING_PARAM_NONE, + NULL, + NMSettingIP6ConfigPrivate, + ip6_privacy); /** * NMSettingIP6Config:addr-gen-mode: @@ -1215,7 +1215,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) NM_SETTING_PARAM_NONE, NMSettingIP6ConfigPrivate, dhcp_pd_hint, - .direct_set_fcn.set_string = + .direct_data.set_string = _set_string_fcn_dhcp_pd_hint, .direct_string_allow_empty = TRUE); diff --git a/src/libnm-core-impl/nm-setting-macsec.c b/src/libnm-core-impl/nm-setting-macsec.c index f66fc52a..763d306b 100644 --- a/src/libnm-core-impl/nm-setting-macsec.c +++ b/src/libnm-core-impl/nm-setting-macsec.c @@ -35,7 +35,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, PROP_MKA_CKN, PROP_PORT, PROP_VALIDATION, - PROP_SEND_SCI, ); + PROP_SEND_SCI, + PROP_OFFLOAD, ); typedef struct { char *parent; @@ -47,6 +48,7 @@ typedef struct { gint32 port; bool encrypt; bool send_sci; + gint32 offload; } NMSettingMacsecPrivate; /** @@ -212,6 +214,22 @@ nm_setting_macsec_get_send_sci(NMSettingMacsec *setting) return NM_SETTING_MACSEC_GET_PRIVATE(setting)->send_sci; } +/** + * nm_setting_macsec_get_offload: + * @setting: the #NMSettingMacsec + * + * Returns: the #NMSettingMacsec:offload property of the setting + * + * Since: 1.46 + **/ +NMSettingMacsecOffload +nm_setting_macsec_get_offload(NMSettingMacsec *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_OFFLOAD_DEFAULT); + + return NM_SETTING_MACSEC_GET_PRIVATE(setting)->offload; +} + static GPtrArray * need_secrets(NMSetting *setting, gboolean check_rerequest) { @@ -597,6 +615,35 @@ nm_setting_macsec_class_init(NMSettingMacsecClass *klass) NMSettingMacsecPrivate, send_sci); + /** + * NMSettingMacsec:offload: + * + * Specifies the MACsec offload mode. + * + * %NM_SETTING_MACSEC_OFFLOAD_OFF disables MACsec offload. + * + * %NM_SETTING_MACSEC_OFFLOAD_PHY and %NM_SETTING_MACSEC_OFFLOAD_MAC request offload + * respectively to the PHY or to the MAC; if the selected mode is not available, the + * connection will fail. + * + * %NM_SETTING_MACSEC_OFFLOAD_DEFAULT uses the global default value specified in + * NetworkManager configuration; if no global default is defined, the built-in + * default is %NM_SETTING_MACSEC_OFFLOAD_OFF. + * + * Since: 1.46 + **/ + _nm_setting_property_define_direct_enum(properties_override, + obj_properties, + NM_SETTING_MACSEC_OFFLOAD, + PROP_OFFLOAD, + NM_TYPE_SETTING_MACSEC_OFFLOAD, + NM_SETTING_MACSEC_OFFLOAD_DEFAULT, + NM_SETTING_PARAM_INFERRABLE + | NM_SETTING_PARAM_FUZZY_IGNORE, + NULL, + NMSettingMacsecPrivate, + offload); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit(setting_class, diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index 6bad516e..1276c903 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -904,6 +904,13 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p /*****************************************************************************/ +/* Define a direct property of type enum, but using `int` as type in the underlying + * GObject property. This is the preferred way to define enum properties because using + * real enums it is not possible to maintain backwards compatibility with clients + * using an old libnm (glib asserts against new values of the enum not being valid). + * The main difference from define_direct_real_enum is that this will accept any + * integer value, and we'll check that it's valid in #NMSetting::verify, as doing + * 'verify' is optional for clients. */ #define _nm_setting_property_define_direct_enum(properties_override, \ obj_properties, \ prop_name, \ @@ -924,6 +931,58 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p ~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \ | NM_SETTING_PARAM_INFERRABLE))); \ \ + nm_assert(G_TYPE_IS_ENUM(gtype_enum)); \ + \ + _param_spec = g_param_spec_int("" prop_name "", \ + "", \ + "", \ + G_MININT32, \ + G_MAXINT32, \ + (default_value), \ + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY \ + | G_PARAM_STATIC_STRINGS | (param_flags)); \ + \ + (obj_properties)[(prop_id)] = _param_spec; \ + _property_type = (property_type) ?: &nm_sett_info_propert_type_direct_enum; \ + \ + _nm_properties_override_gobj( \ + (properties_override), \ + _param_spec, \ + _property_type, \ + .direct_offset = \ + NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field), \ + .direct_data.enum_gtype = (gtype_enum), \ + __VA_ARGS__); \ + }) + +/*****************************************************************************/ + +/* Define an enum property using real enums in the GObject, not integers. Note that + * this is not backwards compatible because clients with old libnm will reject + * newer values of the enum. Generally you want to use define_direct_enum and use this + * one only for properties that already existed as real enums */ +#define _nm_setting_property_define_direct_real_enum(properties_override, \ + obj_properties, \ + prop_name, \ + prop_id, \ + gtype_enum, \ + default_value, \ + param_flags, \ + property_type, \ + private_struct_type, \ + private_struct_field, \ + ... /* extra NMSettInfoProperty fields */) \ + ({ \ + GParamSpec *_param_spec; \ + const NMSettInfoPropertType *_property_type; \ + \ + G_STATIC_ASSERT( \ + !NM_FLAGS_ANY((param_flags), \ + ~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \ + | NM_SETTING_PARAM_INFERRABLE))); \ + \ + nm_assert(G_TYPE_IS_ENUM(gtype_enum)); \ + \ _param_spec = g_param_spec_enum("" prop_name "", \ "", \ "", \ @@ -941,11 +1000,26 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p _property_type, \ .direct_offset = \ NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field), \ + .direct_data.enum_gtype = (gtype_enum), \ __VA_ARGS__); \ }) /*****************************************************************************/ +#define _nm_setting_property_is_valid_direct_enum(property_info) \ + ({ \ + const NMSettInfoProperty *_property_info = (property_info); \ + NMValueType direct_nmtype = _property_info->property_type->direct_type; \ + GType direct_gtype = _property_info->direct_data.enum_gtype; \ + GParamSpec *spec = _property_info->param_spec; \ + GType spec_gtype = spec ? spec->value_type : G_TYPE_INVALID; \ + \ + direct_nmtype == NM_VALUE_TYPE_ENUM &&direct_gtype &&G_TYPE_IS_ENUM(direct_gtype) \ + && NM_IN_SET(spec_gtype, G_TYPE_INT, direct_gtype); \ + }) + +/*****************************************************************************/ + #define _nm_setting_property_define_direct_ternary_enum(properties_override, \ obj_properties, \ prop_name, \ @@ -954,17 +1028,17 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p private_struct_type, \ private_struct_field, \ ...) \ - _nm_setting_property_define_direct_enum((properties_override), \ - (obj_properties), \ - prop_name, \ - (prop_id), \ - NM_TYPE_TERNARY, \ - NM_TERNARY_DEFAULT, \ - (param_flags), \ - NULL, \ - private_struct_type, \ - private_struct_field, \ - __VA_ARGS__) + _nm_setting_property_define_direct_real_enum((properties_override), \ + (obj_properties), \ + prop_name, \ + (prop_id), \ + NM_TYPE_TERNARY, \ + NM_TERNARY_DEFAULT, \ + (param_flags), \ + NULL, \ + private_struct_type, \ + private_struct_field, \ + __VA_ARGS__) /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-setting-sriov.c b/src/libnm-core-impl/nm-setting-sriov.c index b9faad56..145c2b14 100644 --- a/src/libnm-core-impl/nm-setting-sriov.c +++ b/src/libnm-core-impl/nm-setting-sriov.c @@ -9,6 +9,7 @@ #include "nm-setting-private.h" #include "nm-utils-private.h" +#include "nm-core-enum-types.h" /** * SECTION:nm-setting-sriov @@ -18,7 +19,13 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, PROP_TOTAL_VFS, PROP_VFS, PROP_AUTOPROBE_DRIVERS, ); +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, + PROP_TOTAL_VFS, + PROP_VFS, + PROP_AUTOPROBE_DRIVERS, + PROP_ESWITCH_MODE, + PROP_ESWITCH_INLINE_MODE, + PROP_ESWITCH_ENCAP_MODE, ); /** * NMSettingSriov: @@ -32,6 +39,9 @@ struct _NMSettingSriov { GPtrArray *vfs; int autoprobe_drivers; guint32 total_vfs; + int eswitch_mode; + int eswitch_inline_mode; + int eswitch_encap_mode; }; struct _NMSettingSriovClass { @@ -835,6 +845,54 @@ nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting) return setting->autoprobe_drivers; } +/** + * nm_setting_sriov_get_eswitch_mode: + * @setting: the #NMSettingSriov + * + * Returns: the value contained in the #NMSettingSriov:eswitch-mode property. + * + * Since: 1.46 + */ +NMSriovEswitchMode +nm_setting_sriov_get_eswitch_mode(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_MODE_PRESERVE); + + return setting->eswitch_mode; +} + +/** + * nm_setting_sriov_get_eswitch_inline_mode: + * @setting: the #NMSettingSriov + * + * Returns: the value contained in the #NMSettingSriov:eswitch-inline-mode property. + * + * Since: 1.46 + */ +NMSriovEswitchInlineMode +nm_setting_sriov_get_eswitch_inline_mode(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE); + + return setting->eswitch_inline_mode; +} + +/** + * nm_setting_sriov_get_eswitch_encap_mode: + * @setting: the #NMSettingSriov + * + * Returns: the value contained in the #NMSettingSriov:eswitch-encap-mode property. + * + * Since: 1.46 + */ +NMSriovEswitchEncapMode +nm_setting_sriov_get_eswitch_encap_mode(NMSettingSriov *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE); + + return setting->eswitch_encap_mode; +} + static int vf_index_compare(gconstpointer a, gconstpointer b) { @@ -1331,6 +1389,79 @@ nm_setting_sriov_class_init(NMSettingSriovClass *klass) NMSettingSriov, autoprobe_drivers); + /** + * NMSettingSriov:eswitch-mode + * + * Select the eswitch mode of the device. Currently it's only supported for + * PCI PF devices, and only if the eswitch device is managed from the same + * PCI address than the PF. + * + * If set to %NM_SRIOV_ESWITCH_MODE_PRESERVE (default) the eswitch mode won't be + * modified by NetworkManager. + * + * Since: 1.46 + */ + _nm_setting_property_define_direct_enum(properties_override, + obj_properties, + NM_SETTING_SRIOV_ESWITCH_MODE, + PROP_ESWITCH_MODE, + NM_TYPE_SRIOV_ESWITCH_MODE, + NM_SRIOV_ESWITCH_MODE_PRESERVE, + NM_SETTING_PARAM_FUZZY_IGNORE, + NULL, + NMSettingSriov, + eswitch_mode); + + /** + * NMSettingSriov:eswitch-inline-mode + * + * Select the eswitch inline-mode of the device. Some HWs need the VF driver to put + * part of the packet headers on the TX descriptor so the e-switch can do proper + * matching and steering. + * + * Currently it's only supported for PCI PF devices, and only if the eswitch device + * is managed from the same PCI address than the PF. + * + * If set to %NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE (default) the eswitch inline-mode + * won't be modified by NetworkManager. + * + * Since: 1.46 + */ + _nm_setting_property_define_direct_enum(properties_override, + obj_properties, + NM_SETTING_SRIOV_ESWITCH_INLINE_MODE, + PROP_ESWITCH_INLINE_MODE, + NM_TYPE_SRIOV_ESWITCH_INLINE_MODE, + NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE, + NM_SETTING_PARAM_FUZZY_IGNORE, + NULL, + NMSettingSriov, + eswitch_inline_mode); + + /** + * NMSettingSriov:eswitch-encap-mode + * + * Select the eswitch encapsulation support. + * + * Currently it's only supported for PCI PF devices, and only if the eswitch device + * is managed from the same PCI address than the PF. + * + * If set to %NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE (default) the eswitch encap-mode + * won't be modified by NetworkManager. + * + * Since: 1.46 + */ + _nm_setting_property_define_direct_enum(properties_override, + obj_properties, + NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE, + PROP_ESWITCH_ENCAP_MODE, + NM_TYPE_SRIOV_ESWITCH_ENCAP_MODE, + NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE, + NM_SETTING_PARAM_FUZZY_IGNORE, + NULL, + NMSettingSriov, + eswitch_encap_mode); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit(setting_class, diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c index c313d22c..4f96f742 100644 --- a/src/libnm-core-impl/nm-setting-wireguard.c +++ b/src/libnm-core-impl/nm-setting-wireguard.c @@ -2361,8 +2361,7 @@ nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass) NM_SETTING_PARAM_SECRET, NMSettingWireGuard, _priv.private_key, - .direct_set_fcn.set_string = - _set_string_fcn_public_key, + .direct_data.set_string = _set_string_fcn_public_key, .direct_string_allow_empty = TRUE); /** diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index e6e4d23b..8bc7b4bf 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -682,10 +682,10 @@ _property_direct_set_string(const NMSettInfoSetting *sett_info, + (!!property_info->direct_string_is_refstr) + (property_info->direct_set_string_mac_address_len > 0) + (property_info->direct_set_string_ip_address_addr_family != 0)) - <= (property_info->direct_set_fcn.set_string ? 0 : 1)); + <= (property_info->direct_data.set_string ? 0 : 1)); - if (property_info->direct_set_fcn.set_string) { - return property_info->direct_set_fcn.set_string(sett_info, property_info, setting, src); + if (property_info->direct_data.set_string) { + return property_info->direct_data.set_string(sett_info, property_info, setting, src); } dst = _nm_setting_get_private_field(setting, sett_info, property_info); @@ -805,7 +805,13 @@ _nm_setting_property_get_property_direct(GObject *object, { const int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info); - g_value_set_enum(value, *p_val); + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); + + if (G_TYPE_IS_ENUM(pspec->value_type)) + g_value_set_enum(value, *p_val); + else + g_value_set_int(value, *p_val); + return; } case NM_VALUE_TYPE_FLAGS: @@ -940,7 +946,13 @@ _nm_setting_property_set_property_direct(GObject *object, int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info); int v; - v = g_value_get_enum(value); + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); + + if (G_TYPE_IS_ENUM(pspec->value_type)) + v = g_value_get_enum(value); + else + v = g_value_get_int(value); + if (*p_val == v) return; *p_val = v; @@ -1076,7 +1088,13 @@ _init_direct(NMSetting *setting) int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info); int def_val; - def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec); + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); + + if (G_TYPE_IS_ENUM(property_info->param_spec->value_type)) + def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec); + else + def_val = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec); + nm_assert(NM_IN_SET(*p_val, 0, property_info->direct_is_aliased_field ? def_val : 0)); *p_val = def_val; break; @@ -1234,10 +1252,22 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_ { int val; + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); + val = *((int *) _nm_setting_get_private_field(setting, sett_info, property_info)); - if (!property_info->to_dbus_including_default - && val == NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec)) - return NULL; + + if (!property_info->to_dbus_including_default) { + int default_value; + + if (G_TYPE_IS_ENUM(property_info->param_spec->value_type)) + default_value = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec); + else + default_value = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec); + + if (val == default_value) + return NULL; + } + return nm_g_variant_maybe_singleton_i(val); } case NM_VALUE_TYPE_FLAGS: @@ -1413,7 +1443,10 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS GVariant *_value = (value); \ gboolean _success = FALSE; \ \ - nm_assert(_property_info->param_spec->value_type == _gtype); \ + nm_assert(_property_info->param_spec->value_type == _gtype \ + || (_property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM \ + && _property_info->direct_data.enum_gtype == _gtype)); \ + \ if (_property_info->property_type->from_dbus_direct_allow_transform) { \ nm_auto_unset_gvalue GValue _gvalue = G_VALUE_INIT; \ \ @@ -1564,21 +1597,20 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS } case NM_VALUE_TYPE_ENUM: { - const GParamSpecEnum *param_spec; - int *p_val; - int v; + int *p_val; + int v; - param_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec); + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); if (g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) { G_STATIC_ASSERT(sizeof(int) >= sizeof(gint32)); v = g_variant_get_int32(value); } else { - if (!_variant_get_value_transform(property_info, - value, - G_TYPE_FROM_CLASS(param_spec->enum_class), - g_value_get_flags, - &v)) + GType gtype = G_TYPE_IS_ENUM(property_info->param_spec->value_type) + ? property_info->param_spec->value_type + : G_TYPE_INT; + + if (!_variant_get_value_transform(property_info, value, gtype, g_value_get_flags, &v)) goto out_error_wrong_dbus_type; } @@ -1586,8 +1618,18 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS if (*p_val == v) goto out_unchanged; - if (!g_enum_get_value(param_spec->enum_class, v)) - goto out_error_param_spec_validation; + /* To avoid that clients with old libnm fails setting a newer value received + * from the daemon, do not validate here if the value is within range or not. + * Instead, do it in 'verify' that the client can ignore. + * However, some properties are implemented as real enums, mostly those that + * were originally implemented as such. Maintain the old behaviour on them. */ + if (G_TYPE_IS_ENUM(property_info->param_spec->value_type)) { + const GParamSpecEnum *enum_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec); + + if (!g_enum_get_value(enum_spec->enum_class, v)) + goto out_error_param_spec_validation; + } + *p_val = v; goto out_notify; } @@ -2422,7 +2464,6 @@ _verify_properties(NMSetting *setting, GError **error) case NM_VALUE_TYPE_BOOL: case NM_VALUE_TYPE_BYTES: case NM_VALUE_TYPE_STRV: - case NM_VALUE_TYPE_ENUM: case NM_VALUE_TYPE_FLAGS: case NM_VALUE_TYPE_INT32: case NM_VALUE_TYPE_INT64: @@ -2430,6 +2471,37 @@ _verify_properties(NMSetting *setting, GError **error) case NM_VALUE_TYPE_UINT32: case NM_VALUE_TYPE_UINT64: break; + case NM_VALUE_TYPE_ENUM: + { + nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL; + int *val; + + nm_assert(_nm_setting_property_is_valid_direct_enum(property_info)); + + enum_class = g_type_class_ref(property_info->direct_data.enum_gtype); + val = _nm_setting_get_private_field(setting, sett_info, property_info); + + /* We validate here that the value is within the range of the enum, and not + * in the GObject property and/or DBus setters. This way, clients using an + * old libnm can accept new values added later to the enum, because clients + * are not required to 'verify' */ + if (!g_enum_get_value(enum_class, *val)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid value %d, expected %d-%d"), + *val, + enum_class->minimum, + enum_class->maximum); + g_prefix_error(error, + "%s.%s: ", + klass->setting_info->setting_name, + property_info->name); + return FALSE; + } + + return TRUE; + } case NM_VALUE_TYPE_STRING: { const char *val; @@ -4444,6 +4516,43 @@ nm_range_from_str(const char *str, GError **error) return nm_range_new(start, end); } +/** + * nm_setting_get_enum_property_type: + * @setting_type: the GType of the NMSetting instance + * @property_name: the name of the property + * + * Get the type of the enum that defines the values that the property accepts. It is only + * useful for properties configured to accept values from certain enum type, otherwise + * it will return %G_TYPE_INVALID. Note that flags (children of G_TYPE_FLAGS) are also + * considered enums. + * + * Note that the GObject property might be implemented as an integer, actually, and not + * as enum. Find out what underlying type is used, checking the #GParamSpec, before + * setting the GObject property. + * + * Returns: the enum's GType, or %G_TYPE_INVALID if the property is not of enum type + * + * Since: 1.46 + */ +GType +nm_setting_get_enum_property_type(GType setting_type, const char *property_name) +{ + nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref(setting_type); + const NMSettInfoProperty *property_info; + GParamSpec *spec; + + g_return_val_if_fail(NM_IS_SETTING_CLASS(setting_class), G_TYPE_INVALID); + + property_info = _nm_setting_class_get_property_info(setting_class, property_name); + spec = property_info->param_spec; + + if (spec && (G_TYPE_IS_ENUM(spec->value_type) || G_TYPE_IS_FLAGS(spec->value_type))) + return property_info->param_spec->value_type; + if (property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM) + return property_info->direct_data.enum_gtype; + return G_TYPE_INVALID; +} + /*****************************************************************************/ static void diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index 72b855a5..4b5a0b6f 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -4565,7 +4565,7 @@ test_setting_metadata(void) GArray *property_types_data; guint prop_idx_val; gboolean can_set_including_default = FALSE; - gboolean can_have_direct_set_fcn = FALSE; + gboolean can_have_direct_data = FALSE; int n_special_options; g_assert(sip->name); @@ -4662,18 +4662,35 @@ test_setting_metadata(void) can_set_including_default = TRUE; } else if (sip->property_type->direct_type == NM_VALUE_TYPE_ENUM) { - const GParamSpecEnum *pspec; + nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL; + int default_value; + g_assert(_nm_setting_property_is_valid_direct_enum(sip)); + g_assert(G_TYPE_IS_ENUM(sip->direct_data.enum_gtype)); g_assert(g_variant_type_equal(sip->property_type->dbus_type, "i")); g_assert(sip->param_spec); - g_assert(g_type_is_a(sip->param_spec->value_type, G_TYPE_ENUM)); - g_assert(sip->param_spec->value_type != G_TYPE_ENUM); - pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec); - g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type); - g_assert(g_enum_get_value(pspec->enum_class, pspec->default_value)); + if (G_TYPE_IS_ENUM(sip->param_spec->value_type)) { + const GParamSpecEnum *pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec); + + g_assert(sip->param_spec->value_type != G_TYPE_ENUM); + g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type); + g_assert(sip->param_spec->value_type == sip->direct_data.enum_gtype); + + default_value = pspec->default_value; + } else if (sip->param_spec->value_type == G_TYPE_INT) { + const GParamSpecInt *pspec = NM_G_PARAM_SPEC_CAST_INT(sip->param_spec); + + default_value = pspec->default_value; + } else { + g_assert_not_reached(); + } + + enum_class = g_type_class_ref(sip->direct_data.enum_gtype); + g_assert(g_enum_get_value(enum_class, default_value)); can_set_including_default = TRUE; + can_have_direct_data = TRUE; } else if (sip->property_type->direct_type == NM_VALUE_TYPE_FLAGS) { const GParamSpecFlags *pspec; @@ -4703,7 +4720,7 @@ test_setting_metadata(void) INFINIBAND_ALEN)); } else { g_assert(g_variant_type_equal(sip->property_type->dbus_type, "s")); - can_have_direct_set_fcn = TRUE; + can_have_direct_data = TRUE; } g_assert(sip->param_spec); g_assert(sip->param_spec->value_type == G_TYPE_STRING); @@ -4744,8 +4761,8 @@ test_setting_metadata(void) g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRING); } - if (!can_have_direct_set_fcn) - g_assert(!sip->direct_set_fcn.set_string); + if (!can_have_direct_data) + g_assert(!sip->direct_data.set_string); if (sip->property_type->direct_type == NM_VALUE_TYPE_NONE) g_assert(!sip->direct_also_notify); |