mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-22 10:46:59 +00:00
libnm: add NMSettingOvsExternalIDs
This commit is contained in:
parent
0d083f5dab
commit
6100b52e5c
|
@ -954,6 +954,7 @@ libnm_core_lib_h_pub_real = \
|
|||
libnm-core/nm-setting-olpc-mesh.h \
|
||||
libnm-core/nm-setting-ovs-bridge.h \
|
||||
libnm-core/nm-setting-ovs-dpdk.h \
|
||||
libnm-core/nm-setting-ovs-external-ids.h \
|
||||
libnm-core/nm-setting-ovs-interface.h \
|
||||
libnm-core/nm-setting-ovs-patch.h \
|
||||
libnm-core/nm-setting-ovs-port.h \
|
||||
|
@ -1027,6 +1028,7 @@ libnm_core_lib_c_settings_real = \
|
|||
libnm-core/nm-setting-olpc-mesh.c \
|
||||
libnm-core/nm-setting-ovs-bridge.c \
|
||||
libnm-core/nm-setting-ovs-dpdk.c \
|
||||
libnm-core/nm-setting-ovs-external-ids.c \
|
||||
libnm-core/nm-setting-ovs-interface.c \
|
||||
libnm-core/nm-setting-ovs-patch.c \
|
||||
libnm-core/nm-setting-ovs-port.c \
|
||||
|
|
|
@ -784,6 +784,8 @@
|
|||
<property name="devargs"
|
||||
description="Open vSwitch DPDK device arguments." />
|
||||
</setting>
|
||||
<setting name="ovs-external-ids" >
|
||||
</setting>
|
||||
<setting name="ovs-interface" >
|
||||
<property name="type"
|
||||
description="The interface type. Either "internal", "system", "patch", "dpdk", or empty." />
|
||||
|
|
|
@ -7946,6 +7946,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
|
|||
#define SETTING_PRETTY_NAME_OLPC_MESH N_("OLPC Mesh connection")
|
||||
#define SETTING_PRETTY_NAME_OVS_BRIDGE N_("Open vSwitch bridge settings")
|
||||
#define SETTING_PRETTY_NAME_OVS_DPDK N_("Open vSwitch DPDK interface settings")
|
||||
#define SETTING_PRETTY_NAME_OVS_EXTERNAL_IDS N_("OVS External IDs")
|
||||
#define SETTING_PRETTY_NAME_OVS_INTERFACE N_("Open vSwitch interface settings")
|
||||
#define SETTING_PRETTY_NAME_OVS_PATCH N_("Open vSwitch patch interface settings")
|
||||
#define SETTING_PRETTY_NAME_OVS_PORT N_("Open vSwitch port settings")
|
||||
|
@ -8129,6 +8130,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
|
|||
),
|
||||
),
|
||||
SETTING_INFO (OVS_DPDK),
|
||||
SETTING_INFO_EMPTY (OVS_EXTERNAL_IDS),
|
||||
SETTING_INFO (OVS_INTERFACE,
|
||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
||||
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
||||
|
|
|
@ -294,6 +294,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_RSTP_ENABLE N_("Enable or disable RSTP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_STP_ENABLE N_("Enable or disable STP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_DPDK_DEVARGS N_("Open vSwitch DPDK device arguments.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_EXTERNAL_IDS_DATA N_("A dictionary of key/value pairs with exernal-ids for OVS.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_TYPE N_("The interface type. Either \"internal\", \"system\", \"patch\", \"dpdk\", or empty.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_PEER N_("Specifies the name of the interface for the other side of the patch. The patch on the other side must also set this interface as peer.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_DOWNDELAY N_("The time port must be inactive in order to be considered down.")
|
||||
|
|
|
@ -338,6 +338,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
|
|||
<xi:include href="xml/nm-setting-ovs-dpdk.xml"/>
|
||||
<xi:include href="xml/nm-setting-ovs-patch.xml"/>
|
||||
<xi:include href="xml/nm-setting-ovs-port.xml"/>
|
||||
<xi:include href="xml/nm-setting-ovs-external-ids.xml"/>
|
||||
<xi:include href="xml/nm-setting-ppp.xml"/>
|
||||
<xi:include href="xml/nm-setting-pppoe.xml"/>
|
||||
<xi:include href="xml/nm-setting-proxy.xml"/>
|
||||
|
|
|
@ -43,8 +43,9 @@ libnm_core_headers = files(
|
|||
'nm-setting-match.h',
|
||||
'nm-setting-olpc-mesh.h',
|
||||
'nm-setting-ovs-bridge.h',
|
||||
'nm-setting-ovs-interface.h',
|
||||
'nm-setting-ovs-dpdk.h',
|
||||
'nm-setting-ovs-external-ids.h',
|
||||
'nm-setting-ovs-interface.h',
|
||||
'nm-setting-ovs-patch.h',
|
||||
'nm-setting-ovs-port.h',
|
||||
'nm-setting-ppp.h',
|
||||
|
@ -143,8 +144,9 @@ libnm_core_settings_sources = files(
|
|||
'nm-setting-match.c',
|
||||
'nm-setting-olpc-mesh.c',
|
||||
'nm-setting-ovs-bridge.c',
|
||||
'nm-setting-ovs-interface.c',
|
||||
'nm-setting-ovs-dpdk.c',
|
||||
'nm-setting-ovs-external-ids.c',
|
||||
'nm-setting-ovs-interface.c',
|
||||
'nm-setting-ovs-patch.c',
|
||||
'nm-setting-ovs-port.c',
|
||||
'nm-setting-ppp.c',
|
||||
|
|
|
@ -476,6 +476,10 @@ GSList *_nm_vpn_plugin_info_list_load_dir(const char * dirname,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
GHashTable *_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
gboolean numeric;
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef struct _NMSettingMatch NMSettingMatch;
|
|||
typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh;
|
||||
typedef struct _NMSettingOvsBridge NMSettingOvsBridge;
|
||||
typedef struct _NMSettingOvsDpdk NMSettingOvsDpdk;
|
||||
typedef struct _NMSettingOvsExternalIDs NMSettingOvsExternalIDs;
|
||||
typedef struct _NMSettingOvsInterface NMSettingOvsInterface;
|
||||
typedef struct _NMSettingOvsPatch NMSettingOvsPatch;
|
||||
typedef struct _NMSettingOvsPort NMSettingOvsPort;
|
||||
|
|
|
@ -24,9 +24,14 @@
|
|||
#include "nm-core-internal.h"
|
||||
#include "nm-keyfile.h"
|
||||
#include "nm-setting-user.h"
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
|
||||
#include "nm-keyfile-utils.h"
|
||||
|
||||
#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options"
|
||||
|
||||
#define OVS_EXTERNAL_IDS_DATA_PREFIX "data."
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _ParseInfoProperty ParseInfoProperty;
|
||||
|
@ -989,6 +994,44 @@ ip_routing_rule_parser_full(KeyfileReaderInfo * info,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_parser_full_ovs_external_ids_data(KeyfileReaderInfo * info,
|
||||
const NMMetaSettingInfo * setting_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
const ParseInfoProperty * pip,
|
||||
NMSetting * setting)
|
||||
{
|
||||
const char * setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME;
|
||||
gs_strfreev char **keys = NULL;
|
||||
gsize n_keys;
|
||||
gsize i;
|
||||
|
||||
nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting));
|
||||
nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA));
|
||||
nm_assert(nm_streq(setting_name, setting_info->setting_name));
|
||||
nm_assert(nm_streq(setting_name, nm_setting_get_name(setting)));
|
||||
|
||||
keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL);
|
||||
|
||||
for (i = 0; i < n_keys; i++) {
|
||||
const char * key = keys[i];
|
||||
gs_free char *name_to_free = NULL;
|
||||
gs_free char *value = NULL;
|
||||
const char * name;
|
||||
|
||||
if (!NM_STR_HAS_PREFIX(key, OVS_EXTERNAL_IDS_DATA_PREFIX))
|
||||
continue;
|
||||
|
||||
value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL);
|
||||
if (!value)
|
||||
continue;
|
||||
|
||||
name = &key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)];
|
||||
name = nm_keyfile_key_decode(name, &name_to_free);
|
||||
nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
|
@ -2214,8 +2257,6 @@ bridge_vlan_writer(KeyfileWriterInfo *info,
|
|||
}
|
||||
}
|
||||
|
||||
#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options"
|
||||
|
||||
static void
|
||||
wired_s390_options_parser_full(KeyfileReaderInfo * info,
|
||||
const NMMetaSettingInfo * setting_info,
|
||||
|
@ -2360,6 +2401,60 @@ tfilter_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, con
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_writer_full_ovs_external_ids_data(KeyfileWriterInfo * info,
|
||||
const NMMetaSettingInfo * setting_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
const ParseInfoProperty * pip,
|
||||
NMSetting * setting)
|
||||
{
|
||||
GHashTable * hash;
|
||||
NMUtilsNamedValue data_static[300u / sizeof(NMUtilsNamedValue)];
|
||||
gs_free NMUtilsNamedValue *data_free = NULL;
|
||||
const NMUtilsNamedValue * data;
|
||||
guint data_len;
|
||||
char full_key_static[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + 300u];
|
||||
guint i;
|
||||
|
||||
nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting));
|
||||
nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA));
|
||||
|
||||
hash = _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting));
|
||||
if (!hash)
|
||||
return;
|
||||
|
||||
data = nm_utils_named_values_from_strdict(hash, &data_len, data_static, &data_free);
|
||||
if (data_len == 0)
|
||||
return;
|
||||
|
||||
memcpy(full_key_static, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX));
|
||||
|
||||
for (i = 0; i < data_len; i++) {
|
||||
const char * key = data[i].name;
|
||||
const char * val = data[i].value_str;
|
||||
gs_free char *escaped_key_to_free = NULL;
|
||||
const char * escaped_key;
|
||||
gsize len;
|
||||
gs_free char *full_key_free = NULL;
|
||||
char * full_key = full_key_static;
|
||||
|
||||
escaped_key = nm_keyfile_key_encode(key, &escaped_key_to_free);
|
||||
|
||||
len = strlen(escaped_key) + 1u;
|
||||
if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)) {
|
||||
full_key_free = g_new(char, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + len);
|
||||
full_key = full_key_free;
|
||||
memcpy(full_key, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX));
|
||||
}
|
||||
memcpy(&full_key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)], escaped_key, len);
|
||||
|
||||
nm_keyfile_plugin_kf_set_string(info->keyfile,
|
||||
NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
|
||||
full_key,
|
||||
val);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_hash_of_string(GKeyFile *file, NMSetting *setting, const char *key, const GValue *value)
|
||||
{
|
||||
|
@ -2799,6 +2894,14 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
|
|||
.writer_full = ip_routing_rule_writer_full,
|
||||
.has_parser_full = TRUE,
|
||||
.has_writer_full = TRUE, ), ), ),
|
||||
PARSE_INFO_SETTING(
|
||||
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||
PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_EXTERNAL_IDS_DATA,
|
||||
.parser_no_check_key = TRUE,
|
||||
.parser_full = _parser_full_ovs_external_ids_data,
|
||||
.writer_full = _writer_full_ovs_external_ids_data,
|
||||
.has_parser_full = TRUE,
|
||||
.has_writer_full = TRUE, ), ), ),
|
||||
PARSE_INFO_SETTING(NM_META_SETTING_TYPE_SERIAL,
|
||||
PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SERIAL_PARITY,
|
||||
.parser = parity_parser, ), ), ),
|
||||
|
|
|
@ -98,6 +98,10 @@ gboolean nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_OVS_EXTERNAL_ID_NM_PREFIX "NM."
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_setting_ip_config_get_addr_family(NMSettingIPConfig *s_ip)
|
||||
{
|
||||
|
|
536
libnm-core/nm-setting-ovs-external-ids.c
Normal file
536
libnm-core/nm-setting-ovs-external-ids.c
Normal file
|
@ -0,0 +1,536 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/*
|
||||
* Copyright (C) 2017 - 2020 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
|
||||
#include "nm-setting-private.h"
|
||||
#include "nm-utils-private.h"
|
||||
#include "nm-connection-private.h"
|
||||
|
||||
#define MAX_NUM_KEYS 256
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* SECTION:nm-setting-ovs-external-ids
|
||||
* @short_description: External-IDs for OVS database
|
||||
*
|
||||
* The #NMSettingOvsExternalIDs object is a #NMSetting subclass that allow to
|
||||
* configure external ids for OVS.
|
||||
**/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsExternalIDs, PROP_DATA, );
|
||||
|
||||
typedef struct {
|
||||
GHashTable * data;
|
||||
const char **data_keys;
|
||||
} NMSettingOvsExternalIDsPrivate;
|
||||
|
||||
/**
|
||||
* NMSettingOvsExternalIDs:
|
||||
*
|
||||
* OVS External IDs Settings
|
||||
*/
|
||||
struct _NMSettingOvsExternalIDs {
|
||||
NMSetting parent;
|
||||
NMSettingOvsExternalIDsPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMSettingOvsExternalIDsClass {
|
||||
NMSettingClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMSettingOvsExternalIDs, nm_setting_ovs_external_ids, NM_TYPE_SETTING)
|
||||
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self) \
|
||||
_NM_GET_PRIVATE(self, NMSettingOvsExternalIDs, NM_IS_SETTING_OVS_EXTERNAL_IDS)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_exid_key_char_is_regular(char ch)
|
||||
{
|
||||
/* allow words of printable characters, plus some
|
||||
* special characters, for example to support base64 encoding. */
|
||||
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
|
||||
|| NM_IN_SET(ch, '-', '_', '+', '/', '=', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_check_key:
|
||||
* @key: (allow-none): the key to check
|
||||
* @error: a #GError, %NULL to ignore.
|
||||
*
|
||||
* Checks whether @key is a valid key for OVS' external-ids.
|
||||
* This means, the key cannot be %NULL, not too large and valid ASCII.
|
||||
* Also, only digits and numbers are allowed with a few special
|
||||
* characters. They key must also not start with "NM.".
|
||||
*
|
||||
* Since: 1.30
|
||||
*
|
||||
* Returns: %TRUE if @key is a valid user data key.
|
||||
*/
|
||||
gboolean
|
||||
nm_setting_ovs_external_ids_check_key(const char *key, GError **error)
|
||||
{
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail(!error || !*error, FALSE);
|
||||
|
||||
if (!key || !key[0]) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("missing key"));
|
||||
return FALSE;
|
||||
}
|
||||
len = strlen(key);
|
||||
if (len > 255u) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("key is too long"));
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_utf8_validate(key, len, NULL)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("key must be UTF8"));
|
||||
return FALSE;
|
||||
}
|
||||
if (!NM_STRCHAR_ALL(key, ch, _exid_key_char_is_regular(ch))) {
|
||||
/* Probably OVS is more forgiving about what makes a valid key for
|
||||
* an external-id. However, we are strict (at least, for now). */
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("key contains invalid characters"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) {
|
||||
/* these keys are reserved. */
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("key cannot start with \"NM.\""));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_check_val:
|
||||
* @val: (allow-none): the value to check
|
||||
* @error: a #GError, %NULL to ignore.
|
||||
*
|
||||
* Checks whether @val is a valid user data value. This means,
|
||||
* value is not %NULL, not too large and valid UTF-8.
|
||||
*
|
||||
* Since: 1.30
|
||||
*
|
||||
* Returns: %TRUE if @val is a valid user data value.
|
||||
*/
|
||||
gboolean
|
||||
nm_setting_ovs_external_ids_check_val(const char *val, GError **error)
|
||||
{
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail(!error || !*error, FALSE);
|
||||
|
||||
if (!val) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("value is missing"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
len = strlen(val);
|
||||
if (len > (8u * 1024u)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("value is too large"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_utf8_validate(val, len, NULL)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("value is not valid UTF8"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static GHashTable *
|
||||
_create_data_hash(void)
|
||||
{
|
||||
return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
|
||||
}
|
||||
|
||||
GHashTable *
|
||||
_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self)
|
||||
{
|
||||
return NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self)->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_get_data_keys:
|
||||
* @setting: the #NMSettingOvsExternalIDs
|
||||
* @out_len: (out): the length of the returned array
|
||||
*
|
||||
* Returns: (array length=out_len) (transfer none): a
|
||||
* %NULL-terminated array containing each key from the table.
|
||||
**/
|
||||
const char *const *
|
||||
nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guint *out_len)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = setting;
|
||||
NMSettingOvsExternalIDsPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL);
|
||||
|
||||
priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
if (priv->data_keys) {
|
||||
NM_SET_OUT(out_len, g_hash_table_size(priv->data));
|
||||
return priv->data_keys;
|
||||
}
|
||||
|
||||
priv->data_keys = nm_utils_strdict_get_keys(priv->data, TRUE, out_len);
|
||||
|
||||
/* don't return %NULL, but hijack the @data_keys fields as a pseudo
|
||||
* empty strv array. */
|
||||
return priv->data_keys ?: ((const char **) &priv->data_keys);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_get_data:
|
||||
* @setting: the #NMSettingOvsExternalIDs instance
|
||||
* @key: the external-id to lookup
|
||||
*
|
||||
* Since: 1.30
|
||||
*
|
||||
* Returns: (transfer none): the value associated with @key or %NULL if no such
|
||||
* value exists.
|
||||
*/
|
||||
const char *
|
||||
nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = setting;
|
||||
NMSettingOvsExternalIDsPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL);
|
||||
g_return_val_if_fail(key, NULL);
|
||||
|
||||
priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
if (!priv->data)
|
||||
return NULL;
|
||||
|
||||
return g_hash_table_lookup(priv->data, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_set_data:
|
||||
* @setting: the #NMSettingOvsExternalIDs instance
|
||||
* @key: the key to set
|
||||
* @val: (allow-none): the value to set or %NULL to clear a key.
|
||||
*
|
||||
* Since: 1.30
|
||||
*/
|
||||
void
|
||||
nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting,
|
||||
const char * key,
|
||||
const char * val)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = setting;
|
||||
NMSettingOvsExternalIDsPrivate *priv;
|
||||
|
||||
g_return_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self));
|
||||
|
||||
priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
if (!val) {
|
||||
if (priv->data && g_hash_table_remove(priv->data, key))
|
||||
goto out_changed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->data) {
|
||||
const char *val2;
|
||||
|
||||
if (g_hash_table_lookup_extended(priv->data, key, NULL, (gpointer *) &val2)) {
|
||||
if (nm_streq(val, val2))
|
||||
return;
|
||||
}
|
||||
} else
|
||||
priv->data = _create_data_hash();
|
||||
|
||||
g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val));
|
||||
|
||||
out_changed:
|
||||
nm_clear_g_free(&priv->data_keys);
|
||||
_notify(self, PROP_DATA);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
verify(NMSetting *setting, NMConnection *connection, GError **error)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(setting);
|
||||
NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
if (priv->data) {
|
||||
gs_free_error GError *local = NULL;
|
||||
GHashTableIter iter;
|
||||
const char * key;
|
||||
const char * val;
|
||||
|
||||
g_hash_table_iter_init(&iter, priv->data);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) {
|
||||
if (!nm_setting_ovs_external_ids_check_key(key, &local)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid key \"%s\": %s"),
|
||||
key,
|
||||
local->message);
|
||||
} else if (!nm_setting_ovs_external_ids_check_val(val, &local)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_FAILED,
|
||||
_("invalid value for \"%s\": %s"),
|
||||
key,
|
||||
local->message);
|
||||
} else
|
||||
continue;
|
||||
g_prefix_error(error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
|
||||
NM_SETTING_OVS_EXTERNAL_IDS_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("maximum number of user data entries reached (%u instead of %u)"),
|
||||
g_hash_table_size(priv->data),
|
||||
(unsigned) MAX_NUM_KEYS);
|
||||
g_prefix_error(error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
|
||||
NM_SETTING_OVS_EXTERNAL_IDS_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (connection) {
|
||||
const char *type;
|
||||
|
||||
type = nm_connection_get_connection_type(connection);
|
||||
if (!type) {
|
||||
NMSetting *s_base;
|
||||
|
||||
s_base = _nm_connection_find_base_type_setting(connection);
|
||||
if (s_base)
|
||||
type = nm_setting_get_name(s_base);
|
||||
}
|
||||
if (!NM_IN_STRSET(type,
|
||||
NM_SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||
NM_SETTING_OVS_PORT_SETTING_NAME,
|
||||
NM_SETTING_OVS_INTERFACE_SETTING_NAME)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("OVS external IDs can only be added to a profile of type OVS "
|
||||
"bridge/port/interface"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NMTernary
|
||||
compare_property(const NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
NMConnection * con_a,
|
||||
NMSetting * set_a,
|
||||
NMConnection * con_b,
|
||||
NMSetting * set_b,
|
||||
NMSettingCompareFlags flags)
|
||||
{
|
||||
NMSettingOvsExternalIDsPrivate *priv;
|
||||
NMSettingOvsExternalIDsPrivate *pri2;
|
||||
|
||||
if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)) {
|
||||
if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
|
||||
return NM_TERNARY_DEFAULT;
|
||||
|
||||
if (!set_b)
|
||||
return TRUE;
|
||||
|
||||
priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_a));
|
||||
pri2 = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(NM_SETTING_OVS_EXTERNAL_IDS(set_b));
|
||||
return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal);
|
||||
}
|
||||
|
||||
return NM_SETTING_CLASS(nm_setting_ovs_external_ids_parent_class)
|
||||
->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object);
|
||||
NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
GHashTableIter iter;
|
||||
GHashTable * data;
|
||||
const char * key;
|
||||
const char * val;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DATA:
|
||||
data = _create_data_hash();
|
||||
if (priv->data) {
|
||||
g_hash_table_iter_init(&iter, priv->data);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val))
|
||||
g_hash_table_insert(data, g_strdup(key), g_strdup(val));
|
||||
}
|
||||
g_value_take_boxed(value, data);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object);
|
||||
NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DATA:
|
||||
{
|
||||
gs_unref_hashtable GHashTable *old = NULL;
|
||||
GHashTableIter iter;
|
||||
GHashTable * data;
|
||||
const char * key;
|
||||
const char * val;
|
||||
|
||||
nm_clear_g_free(&priv->data_keys);
|
||||
|
||||
old = g_steal_pointer(&priv->data);
|
||||
|
||||
data = g_value_get_boxed(value);
|
||||
if (nm_g_hash_table_size(data) <= 0)
|
||||
return;
|
||||
|
||||
priv->data = _create_data_hash();
|
||||
g_hash_table_iter_init(&iter, data);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val))
|
||||
g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_setting_ovs_external_ids_init(NMSettingOvsExternalIDs *self)
|
||||
{}
|
||||
|
||||
/**
|
||||
* nm_setting_ovs_external_ids_new:
|
||||
*
|
||||
* Creates a new #NMSettingOvsExternalIDs object with default values.
|
||||
*
|
||||
* Returns: (transfer full) (type NMSettingOvsExternalIDs): the new empty
|
||||
* #NMSettingOvsExternalIDs object
|
||||
*
|
||||
* Since: 1.30
|
||||
*/
|
||||
gpointer
|
||||
nm_setting_ovs_external_ids_new(void)
|
||||
{
|
||||
return g_object_new(NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize(GObject *object)
|
||||
{
|
||||
NMSettingOvsExternalIDs * self = NM_SETTING_OVS_EXTERNAL_IDS(object);
|
||||
NMSettingOvsExternalIDsPrivate *priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);
|
||||
|
||||
g_free(priv->data_keys);
|
||||
if (priv->data)
|
||||
g_hash_table_unref(priv->data);
|
||||
|
||||
G_OBJECT_CLASS(nm_setting_ovs_external_ids_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_setting_ovs_external_ids_class_init(NMSettingOvsExternalIDsClass *klass)
|
||||
{
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(klass);
|
||||
NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
|
||||
GArray * properties_override = _nm_sett_info_property_override_create_array();
|
||||
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->verify = verify;
|
||||
|
||||
/**
|
||||
* NMSettingOvsExternalIDs:data: (type GHashTable(utf8,utf8))
|
||||
*
|
||||
* A dictionary of key/value pairs with exernal-ids for OVS.
|
||||
*
|
||||
* Since: 1.30
|
||||
**/
|
||||
obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_OVS_EXTERNAL_IDS_DATA,
|
||||
"",
|
||||
"",
|
||||
G_TYPE_HASH_TABLE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
_nm_properties_override_gobj(properties_override,
|
||||
obj_properties[PROP_DATA],
|
||||
&nm_sett_info_propert_type_strdict);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
_nm_setting_class_commit_full(setting_class,
|
||||
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||
NULL,
|
||||
properties_override);
|
||||
}
|
68
libnm-core/nm-setting-ovs-external-ids.h
Normal file
68
libnm-core/nm-setting-ovs-external-ids.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/*
|
||||
* Copyright (C) 2017 - 2020 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_SETTING_OVS_EXTERNAL_IDS_H__
|
||||
#define __NM_SETTING_OVS_EXTERNAL_IDS_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_TYPE_SETTING_OVS_EXTERNAL_IDS (nm_setting_ovs_external_ids_get_type())
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NMSettingOvsExternalIDs))
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \
|
||||
NMSettingOvsExternalIDsClass))
|
||||
#define NM_IS_SETTING_OVS_EXTERNAL_IDS(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_EXTERNAL_IDS))
|
||||
#define NM_IS_SETTING_OVS_EXTERNAL_IDS_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_EXTERNAL_IDS))
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
NM_TYPE_SETTING_OVS_EXTERNAL_IDS, \
|
||||
NMSettingOvsExternalIDsClass))
|
||||
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME "ovs-external-ids"
|
||||
|
||||
#define NM_SETTING_OVS_EXTERNAL_IDS_DATA "data"
|
||||
|
||||
typedef struct _NMSettingOvsExternalIDsClass NMSettingOvsExternalIDsClass;
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
GType nm_setting_ovs_external_ids_get_type(void);
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
void *nm_setting_ovs_external_ids_new(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
const char *const *nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting,
|
||||
guint * out_len);
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
const char *nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *setting, const char *key);
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
void nm_setting_ovs_external_ids_set_data(NMSettingOvsExternalIDs *setting,
|
||||
const char * key,
|
||||
const char * val);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_AVAILABLE_IN_1_30
|
||||
gboolean nm_setting_ovs_external_ids_check_key(const char *key, GError **error);
|
||||
NM_AVAILABLE_IN_1_30
|
||||
gboolean nm_setting_ovs_external_ids_check_val(const char *val, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_SETTING_OVS_EXTERNAL_IDS_H__ */
|
|
@ -1766,5 +1766,12 @@ global:
|
|||
nm_keyfile_read;
|
||||
nm_keyfile_warn_severity_get_type;
|
||||
nm_keyfile_write;
|
||||
nm_setting_ovs_external_ids_check_key;
|
||||
nm_setting_ovs_external_ids_check_val;
|
||||
nm_setting_ovs_external_ids_get_data;
|
||||
nm_setting_ovs_external_ids_get_data_keys;
|
||||
nm_setting_ovs_external_ids_get_type;
|
||||
nm_setting_ovs_external_ids_new;
|
||||
nm_setting_ovs_external_ids_set_data;
|
||||
nm_utils_print;
|
||||
} libnm_1_28_0;
|
||||
|
|
|
@ -82,6 +82,7 @@ libnm-core/nm-setting-macvlan.c
|
|||
libnm-core/nm-setting-match.c
|
||||
libnm-core/nm-setting-olpc-mesh.c
|
||||
libnm-core/nm-setting-ovs-bridge.c
|
||||
libnm-core/nm-setting-ovs-external-ids.c
|
||||
libnm-core/nm-setting-ovs-interface.c
|
||||
libnm-core/nm-setting-ovs-patch.c
|
||||
libnm-core/nm-setting-ovs-port.c
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nm-setting-ovs-bridge.h"
|
||||
#include "nm-setting-ovs-interface.h"
|
||||
#include "nm-setting-ovs-dpdk.h"
|
||||
#include "nm-setting-ovs-external-ids.h"
|
||||
#include "nm-setting-ovs-patch.h"
|
||||
#include "nm-setting-ovs-port.h"
|
||||
#include "nm-setting-ppp.h"
|
||||
|
@ -312,6 +313,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
|||
.setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME,
|
||||
.get_setting_gtype = nm_setting_ovs_dpdk_get_type,
|
||||
},
|
||||
[NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] =
|
||||
{
|
||||
.meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||
.setting_priority = NM_SETTING_PRIORITY_AUX,
|
||||
.setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
|
||||
.get_setting_gtype = nm_setting_ovs_external_ids_get_type,
|
||||
},
|
||||
[NM_META_SETTING_TYPE_OVS_INTERFACE] =
|
||||
{
|
||||
.meta_type = NM_META_SETTING_TYPE_OVS_INTERFACE,
|
||||
|
|
|
@ -128,6 +128,7 @@ typedef enum {
|
|||
NM_META_SETTING_TYPE_MATCH,
|
||||
NM_META_SETTING_TYPE_OVS_BRIDGE,
|
||||
NM_META_SETTING_TYPE_OVS_DPDK,
|
||||
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||
NM_META_SETTING_TYPE_OVS_INTERFACE,
|
||||
NM_META_SETTING_TYPE_OVS_PATCH,
|
||||
NM_META_SETTING_TYPE_OVS_PORT,
|
||||
|
|
Loading…
Reference in a new issue