ovs: add support for "other_config" settings

See `man ovs-vswitchd.conf.db` for documentation of "other_config" keys.

https://bugzilla.redhat.com/show_bug.cgi?id=2151455
This commit is contained in:
Thomas Haller
2023-01-11 11:51:46 +01:00
parent 8445b96b04
commit a259303e1d
29 changed files with 978 additions and 153 deletions

View File

@@ -1273,6 +1273,7 @@ src_libnm_core_impl_lib_h_pub_real = \
src/libnm-core-public/nm-setting-ovs-dpdk.h \
src/libnm-core-public/nm-setting-ovs-external-ids.h \
src/libnm-core-public/nm-setting-ovs-interface.h \
src/libnm-core-public/nm-setting-ovs-other-config.h \
src/libnm-core-public/nm-setting-ovs-patch.h \
src/libnm-core-public/nm-setting-ovs-port.h \
src/libnm-core-public/nm-setting-ppp.h \
@@ -1353,6 +1354,7 @@ src_libnm_core_impl_lib_c_settings_real = \
src/libnm-core-impl/nm-setting-ovs-dpdk.c \
src/libnm-core-impl/nm-setting-ovs-external-ids.c \
src/libnm-core-impl/nm-setting-ovs-interface.c \
src/libnm-core-impl/nm-setting-ovs-other-config.c \
src/libnm-core-impl/nm-setting-ovs-patch.c \
src/libnm-core-impl/nm-setting-ovs-port.c \
src/libnm-core-impl/nm-setting-ppp.c \

View File

@@ -341,6 +341,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-external-ids.xml"/>
<xi:include href="xml/nm-setting-ovs-interface.xml"/>
<xi:include href="xml/nm-setting-ovs-other-config.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-ppp.xml"/>

View File

@@ -5,14 +5,15 @@
#
#
# set and show OVS external-ids for a connection:
# set and show OVS external-ids and other-config for a connection:
#
import sys
import collections
import os
import re
import pprint
import re
import subprocess
import sys
import gi
@@ -178,14 +179,14 @@ def device_reapply(device, connection, version_id):
raise result_error[0]
def ovs_print_external_ids(prefix):
def ovs_print_config(prefix):
if not can_sudo():
_print(prefix + ": not running as root and cannot call ovs-vsctl")
return
cmds = [["ovs-vsctl", "show"]]
for typ in ["Bridge", "Port", "Interface"]:
cmds += [["ovs-vsctl", "--columns=name,external-ids", "list", typ]]
cmds += [["ovs-vsctl", "--columns=name,external-ids,other-config", "list", typ]]
out = ""
for cmd in cmds:
@@ -207,7 +208,11 @@ def usage():
)
_print(" DEVICE := [iface] STRING")
_print(" GETTER := ( KEY | ~REGEX_KEY ) [... GETTER]")
_print(" SETTER := ( + | - | -KEY | [+]KEY VALUE ) [... SETTER]")
_print(" SETTER := ( +[e:|o:] | -[e:|o:] | -KEY | [+]KEY VALUE ) [... SETTER]")
_print("")
_print(
'Prefix KEY with "e:" or "o:" to set external-ids or other-config ("e:" is the default)'
)
def die(msg, show_usage=False):
@@ -221,6 +226,24 @@ def die_usage(msg):
die(msg, show_usage=True)
DataTypeTuple = collections.namedtuple(
"DataTypeTuple", ["short", "name", "setting_type", "property_name"]
)
DataTypeE = DataTypeTuple(
"external-ids",
"ovs-external-ids",
NM.SettingOvsExternalIDs,
NM.SETTING_OVS_EXTERNAL_IDS_DATA,
)
DataTypeO = DataTypeTuple(
"other-config",
"ovs-other-config",
NM.SettingOvsOtherConfig,
NM.SETTING_OVS_OTHER_CONFIG_DATA,
)
def parse_args(argv):
args = {
"mode": MODE_GET,
@@ -274,12 +297,14 @@ def parse_args(argv):
continue
if not a:
die_usage("argument should specify a external-id but is empty string")
die_usage(
"argument should specify a external-id/other-config but is empty string"
)
if a[0] == "-":
v = (a, None)
i += 1
elif a == "+":
elif a in ["+", "+o:", "+e:"]:
v = (a, None)
i += 1
else:
@@ -294,7 +319,7 @@ def parse_args(argv):
if args["mode"] == MODE_SET:
if not args["ids_arg"]:
die_usage("Requires one or more external-ids to set or delete")
die_usage("Requires one or more external-ids/other-config to set or delete")
return args
@@ -319,9 +344,6 @@ def devices_filter(devices, select_arg):
devices = list(sorted(devices, key=device_to_str))
if not select_arg:
return devices
# we preserve the order of the selected devices. And
# if devices are selected multiple times, we return
# them multiple times.
l = []
f = select_arg
for d in devices:
@@ -342,9 +364,6 @@ def connections_filter(connections, select_arg):
connections = list(sorted(connections, key=connection_to_str))
if not select_arg:
return connections
# we preserve the order of the selected connections. And
# if connections are selected multiple times, we return
# them multiple times.
l = []
f = select_arg
for c in connections:
@@ -352,7 +371,7 @@ def connections_filter(connections, select_arg):
if f[1] == c.get_id():
l.append(c)
elif f[0] == "~id":
if re.match(f[1], c.get_id()):
if re.search(f[1], c.get_id()):
l.append(c)
elif f[0] == "uuid":
if f[1] == c.get_uuid():
@@ -361,7 +380,7 @@ def connections_filter(connections, select_arg):
if f[1] == c.get_connection_type():
l.append(c)
elif f[0] == "~type":
if re.match(f[1], c.get_connection_type()):
if re.search(f[1], c.get_connection_type()):
l.append(c)
else:
assert f[0] == "*"
@@ -384,7 +403,7 @@ def ids_select(ids, mode, ids_arg):
if mode == MODE_GET:
if d[0] == "~":
r = re.compile(d[1:])
keys.update([k for k in ids if r.match(k)])
keys.update([k for k in ids if r.search(k)])
else:
keys.update([k for k in ids if k == d])
if d not in requested:
@@ -400,44 +419,67 @@ def ids_select(ids, mode, ids_arg):
def connection_print(connection, mode, ids_arg, dbus_path, prefix=""):
sett = connection.get_setting(NM.SettingOvsExternalIDs)
def _num_str(connection, data_type):
sett = connection.get_setting(data_type.setting_type)
num_str = "none"
if sett is not None:
all_ids = list(sett.get_data_keys())
keys, requested = ids_select(all_ids, mode, ids_arg)
num_str = "%s" % (len(all_ids))
else:
keys = []
requested = []
num_str = "none"
return num_str
_print(
"%s%s [%s]" % (prefix, connection_to_str(connection, show_type=True), num_str)
"%s%s [e:%s, o:%s]"
% (
prefix,
connection_to_str(connection, show_type=True),
_num_str(connection, DataTypeE),
_num_str(connection, DataTypeO),
)
)
if dbus_path:
_print("%s %s" % (prefix, dbus_path))
for data_type in [DataTypeE, DataTypeO]:
sett = connection.get_setting(data_type.setting_type)
if sett is not None:
dd = sett.get_property(NM.SETTING_OVS_EXTERNAL_IDS_DATA)
all_ids = list(sett.get_data_keys())
keys, requested = ids_select(all_ids, mode, ids_arg)
else:
keys = []
requested = []
if sett is not None:
dd = sett.get_property(data_type.property_name)
else:
dd = {}
for k in keys:
v = sett.get_data(k)
assert v is not None
assert v == dd.get(k, None)
_print('%s "%s" = "%s"' % (prefix, k, v))
_print('%s %s: "%s" = "%s"' % (prefix, data_type.short, k, v))
for k in requested:
_print('%s "%s" = <unset>' % (prefix, k))
_print('%s %s: "%s" = <unset>' % (prefix, data_type.short, k))
def sett_update(connection, ids_arg):
sett = connection.get_setting(NM.SettingOvsExternalIDs)
for d in ids_arg:
op = d[0][0]
key = d[0][1:]
val = d[1]
if key == "o" or key.startswith("o:"):
data_type = DataTypeO
key = key[2:]
elif key == "e" or key.startswith("e:"):
data_type = DataTypeE
key = key[2:]
else:
data_type = DataTypeE
sett = connection.get_setting(data_type.setting_type)
oldval = None
if sett is not None:
oldval = sett.get_data(key)
@@ -446,15 +488,17 @@ def sett_update(connection, ids_arg):
assert val is None
if key == "":
if sett is None:
_print(" DEL: setting (ovs-external-ids group was not present)")
_print(
" DEL: setting (%s group was not present)" % (data_type.name,)
)
else:
connection.remove_setting(NM.SettingOvsExternalIDs)
connection.remove_setting(data_type.setting_type)
sett = None
_print(" DEL: setting")
_print(" DEL: setting (%s)" % (data_type.name,))
continue
if sett is None:
_print(' DEL: "%s" (ovs-external-ids group was not present)' % (key))
_print(' DEL: "%s" (%s group was not present)' % (key, data_type.name))
continue
if oldval is None:
_print(' DEL: "%s" (id was unset)' % (key))
@@ -466,21 +510,22 @@ def sett_update(connection, ids_arg):
if key == "":
assert val is None
if sett is None:
sett = NM.SettingOvsExternalIDs.new()
sett = data_type.setting_type.new()
connection.add_setting(sett)
_print(" SET: setting (external-ids group was added)")
_print(" SET: setting (%s group was added)" % (data_type.name,))
continue
_print(" SET: setting (external-ids group was present)")
_print(" SET: setting (%s group was present)" % (data_type.name,))
continue
assert val is not None
if sett is None:
sett = NM.SettingOvsExternalIDs.new()
sett = data_type.setting_type.new()
connection.add_setting(sett)
_print(
' SET: "%s" = "%s" (external-ids group was not present)' % (key, val)
' SET: "%s" = "%s" (%s group was not present)'
% (key, val, data_type.name)
)
elif oldval is None:
_print(' SET: "%s" = "%s" (new)' % (key, val))
@@ -579,7 +624,7 @@ def do_apply(nmc, device, ids_arg, do_test):
)
_print()
ovs_print_external_ids("BEFORE-OVS-VSCTL: ")
ovs_print_config("BEFORE-OVS-VSCTL: ")
_print()
connection = NM.SimpleConnection.new_clone(connection_orig)
@@ -619,7 +664,7 @@ def do_apply(nmc, device, ids_arg, do_test):
)
_print()
ovs_print_external_ids("AFTER-OVS-VSCTL: ")
ovs_print_config("AFTER-OVS-VSCTL: ")
###############################################################################
@@ -636,7 +681,7 @@ if __name__ == "__main__":
if len(devices) != 1:
_print(
"To apply the external-ids of a device, exactly one connection must be selected. Instead, %s devices matched ([%s])"
"To apply the external-ids/other-config of a device, exactly one connection must be selected. Instead, %s devices matched ([%s])"
% (len(devices), ", ".join([device_to_str(c) for c in devices]))
)
die_usage("Select unique device to apply")
@@ -649,7 +694,7 @@ if __name__ == "__main__":
if args["mode"] == MODE_SET:
if len(connections) != 1:
_print(
"To set the external-ids of a connection, exactly one connection must be selected via id|uuid. Instead, %s connection matched ([%s])"
"To set the external-ids/other-config of a connection, exactly one connection must be selected via id|uuid. Instead, %s connection matched ([%s])"
% (
len(connections),
", ".join([connection_to_str(c) for c in connections]),
@@ -659,6 +704,8 @@ if __name__ == "__main__":
do_set(nmc, connections[0], args["ids_arg"], do_test=args["do_test"])
else:
if len(connections) < 1:
_print("No connection selected for printing the external ids")
_print(
"No connection selected for printing the external ids/other-config"
)
die_usage("Select connection to get")
do_get(connections, args["ids_arg"])

View File

@@ -102,6 +102,7 @@ src/libnm-core-impl/nm-setting-olpc-mesh.c
src/libnm-core-impl/nm-setting-ovs-bridge.c
src/libnm-core-impl/nm-setting-ovs-external-ids.c
src/libnm-core-impl/nm-setting-ovs-interface.c
src/libnm-core-impl/nm-setting-ovs-other-config.c
src/libnm-core-impl/nm-setting-ovs-patch.c
src/libnm-core-impl/nm-setting-ovs-port.c
src/libnm-core-impl/nm-setting-ppp.c

View File

@@ -59,6 +59,7 @@
#include "settings/nm-settings.h"
#include "nm-setting-ethtool.h"
#include "nm-setting-ovs-external-ids.h"
#include "nm-setting-ovs-other-config.h"
#include "nm-setting-user.h"
#include "nm-auth-utils.h"
#include "nm-keep-alive.h"
@@ -12813,7 +12814,9 @@ can_reapply_change(NMDevice *self,
goto out_fail;
}
if (nm_streq(setting_name, NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME)
if (NM_IN_STRSET(setting_name,
NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)
&& NM_DEVICE_GET_CLASS(self)->can_reapply_change_ovs_external_ids) {
/* TODO: this means, you cannot reapply changes to the external-ids for
* OVS system interfaces. */

View File

@@ -16,6 +16,7 @@
#include "nm-setting-connection.h"
#include "nm-setting-ovs-bridge.h"
#include "nm-setting-ovs-external-ids.h"
#include "nm-setting-ovs-other-config.h"
#include "libnm-core-intern/nm-core-internal.h"
#define _NMLOG_DEVICE_TYPE NMDeviceOvsBridge
@@ -129,7 +130,9 @@ nm_device_ovs_reapply_connection(NMDevice *self, NMConnection *con_old, NMConnec
nm_device_get_ip_iface(self),
nm_connection_get_uuid(con_new),
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS));
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_OTHER_CONFIG),
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_OTHER_CONFIG));
}
/*****************************************************************************/

View File

@@ -17,6 +17,7 @@
#include "devices/nm-device.h"
#include "nm-manager.h"
#include "nm-setting-ovs-external-ids.h"
#include "nm-setting-ovs-other-config.h"
#include "nm-priv-helper-call.h"
#include "libnm-platform/nm-platform.h"
@@ -24,6 +25,8 @@
#define OVSDB_MAX_FAILURES 3
#define OTHER_CONFIG_HWADDR "hwaddr"
/*****************************************************************************/
#if JANSSON_VERSION_HEX < 0x020400
@@ -32,6 +35,7 @@
typedef enum {
STRDICT_TYPE_EXTERNAL_IDS,
STRDICT_TYPE_OTHER_CONFIG,
} StrdictType;
typedef struct {
@@ -40,6 +44,7 @@ typedef struct {
char *connection_uuid;
GPtrArray *interfaces; /* interface uuids */
GArray *external_ids;
GArray *other_config;
} OpenvswitchPort;
typedef struct {
@@ -48,6 +53,7 @@ typedef struct {
char *connection_uuid;
GPtrArray *ports; /* port uuids */
GArray *external_ids;
GArray *other_config;
} OpenvswitchBridge;
typedef struct {
@@ -56,6 +62,7 @@ typedef struct {
char *type;
char *connection_uuid;
GArray *external_ids;
GArray *other_config;
} OpenvswitchInterface;
/*****************************************************************************/
@@ -98,6 +105,8 @@ typedef union {
char *connection_uuid;
GHashTable *external_ids_old;
GHashTable *external_ids_new;
GHashTable *other_config_old;
GHashTable *other_config_new;
} set_reapply;
} OvsdbMethodPayload;
@@ -231,7 +240,9 @@ static void cleanup_check_ready(NMOvsdb *self);
xifname, \
xconnection_uuid, \
xexternal_ids_old, \
xexternal_ids_new) \
xexternal_ids_new, \
xother_config_old, \
xother_config_new) \
(&((const OvsdbMethodPayload){ \
.set_reapply = \
{ \
@@ -240,6 +251,8 @@ static void cleanup_check_ready(NMOvsdb *self);
.connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \
.external_ids_old = (xexternal_ids_old), \
.external_ids_new = (xexternal_ids_new), \
.other_config_old = (xother_config_old), \
.other_config_new = (xother_config_new), \
}, \
}))
@@ -300,6 +313,8 @@ _call_complete(OvsdbMethodCall *call, json_t *response, GError *error)
nm_clear_g_free(&call->payload.set_reapply.connection_uuid);
nm_clear_pointer(&call->payload.set_reapply.external_ids_old, g_hash_table_destroy);
nm_clear_pointer(&call->payload.set_reapply.external_ids_new, g_hash_table_destroy);
nm_clear_pointer(&call->payload.set_reapply.other_config_old, g_hash_table_destroy);
nm_clear_pointer(&call->payload.set_reapply.other_config_new, g_hash_table_destroy);
break;
}
@@ -316,6 +331,7 @@ _free_bridge(OpenvswitchBridge *ovs_bridge)
g_free(ovs_bridge->connection_uuid);
g_ptr_array_free(ovs_bridge->ports, TRUE);
nm_g_array_unref(ovs_bridge->external_ids);
nm_g_array_unref(ovs_bridge->other_config);
nm_g_slice_free(ovs_bridge);
}
@@ -327,6 +343,7 @@ _free_port(OpenvswitchPort *ovs_port)
g_free(ovs_port->connection_uuid);
g_ptr_array_free(ovs_port->interfaces, TRUE);
nm_g_array_unref(ovs_port->external_ids);
nm_g_array_unref(ovs_port->other_config);
nm_g_slice_free(ovs_port);
}
@@ -338,6 +355,7 @@ _free_interface(OpenvswitchInterface *ovs_interface)
g_free(ovs_interface->connection_uuid);
g_free(ovs_interface->type);
nm_g_array_unref(ovs_interface->external_ids);
nm_g_array_unref(ovs_interface->other_config);
nm_g_slice_free(ovs_interface);
}
@@ -459,8 +477,12 @@ ovsdb_call_method(NMOvsdb *self,
nm_g_hash_table_ref(payload->set_reapply.external_ids_old);
call->payload.set_reapply.external_ids_new =
nm_g_hash_table_ref(payload->set_reapply.external_ids_new);
call->payload.set_reapply.other_config_old =
nm_g_hash_table_ref(payload->set_reapply.other_config_old);
call->payload.set_reapply.other_config_new =
nm_g_hash_table_ref(payload->set_reapply.other_config_new);
_LOGT_call(call,
"new: set-external-ids con-uuid=%s, interface=%s",
"new: set external-ids/other-config con-uuid=%s, interface=%s",
call->payload.set_reapply.connection_uuid,
call->payload.set_reapply.ifname);
break;
@@ -607,12 +629,12 @@ _set_bridge_mac(json_t *params, const char *ifname, const char *mac)
"other_config",
"delete",
"set",
"hwaddr",
OTHER_CONFIG_HWADDR,
"other_config",
"insert",
"map",
"hwaddr",
OTHER_CONFIG_HWADDR,
mac,
"where",
@@ -680,8 +702,11 @@ _set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces)
}
static json_t *
_j_create_strdict_new(NMConnection *connection, StrdictType strdict_type)
_j_create_strdict_new(NMConnection *connection,
StrdictType strdict_type,
const char *other_config_hwaddr)
{
NMSettingOvsOtherConfig *s_other_config = NULL;
NMSettingOvsExternalIDs *s_external_ids = NULL;
json_t *array;
const char *const *strv = NULL;
@@ -690,7 +715,7 @@ _j_create_strdict_new(NMConnection *connection, StrdictType strdict_type)
const char *uuid;
nm_assert(NM_IS_CONNECTION(connection));
nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS));
nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS, STRDICT_TYPE_OTHER_CONFIG));
array = json_array();
@@ -699,6 +724,11 @@ _j_create_strdict_new(NMConnection *connection, StrdictType strdict_type)
nm_assert(uuid);
json_array_append_new(array,
json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, uuid));
} else {
if (other_config_hwaddr) {
json_array_append_new(array,
json_pack("[s, s]", OTHER_CONFIG_HWADDR, other_config_hwaddr));
}
}
if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) {
@@ -706,15 +736,27 @@ _j_create_strdict_new(NMConnection *connection, StrdictType strdict_type)
if (s_external_ids)
strv = nm_setting_ovs_external_ids_get_data_keys(s_external_ids, &n_strv);
} else {
nm_assert_not_reached();
s_other_config = _nm_connection_get_setting(connection, NM_TYPE_SETTING_OVS_OTHER_CONFIG);
if (s_other_config)
strv = nm_setting_ovs_other_config_get_data_keys(s_other_config, &n_strv);
}
for (i = 0; i < n_strv; i++) {
const char *k = strv[i];
if (strdict_type == STRDICT_TYPE_OTHER_CONFIG && other_config_hwaddr
&& nm_streq(k, OTHER_CONFIG_HWADDR)) {
/* "hwaddr" is explicitly overwritten. */
continue;
}
json_array_append_new(
array,
json_pack("[s, s]", k, nm_setting_ovs_external_ids_get_data(s_external_ids, k)));
json_pack("[s, s]",
k,
strdict_type == STRDICT_TYPE_EXTERNAL_IDS
? nm_setting_ovs_external_ids_get_data(s_external_ids, k)
: nm_setting_ovs_other_config_get_data(s_other_config, k)));
}
return json_pack("[s, o]", "map", array);
@@ -732,13 +774,21 @@ _j_create_strv_array_update(json_t *mutations,
const char *key;
const char *val;
/* This is called during reapply. We accept reapplying all settings,
* except other_config:hwaddr. That one cannot change and is specially
* handled below. The reason is that we knew the correct "hwaddr" during
* _j_create_strdict_new(), but we don't do now. At least not easily,
* and it's not clear that reapply of the MAC address is really useful. */
nm_assert((!!connection_uuid) == (strdict_type == STRDICT_TYPE_EXTERNAL_IDS));
nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS));
nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS, STRDICT_TYPE_OTHER_CONFIG));
array = NULL;
if (hash_old) {
g_hash_table_iter_init(&iter, hash_old);
while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) {
if (strdict_type == STRDICT_TYPE_OTHER_CONFIG && nm_streq(key, OTHER_CONFIG_HWADDR))
continue;
if (!array)
array = json_array();
json_array_append_new(array, json_string(key));
@@ -747,6 +797,8 @@ _j_create_strv_array_update(json_t *mutations,
if (hash_new) {
g_hash_table_iter_init(&iter, hash_new);
while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) {
if (strdict_type == STRDICT_TYPE_OTHER_CONFIG && nm_streq(key, OTHER_CONFIG_HWADDR))
continue;
if (nm_g_hash_table_contains(hash_old, key))
continue;
if (!array)
@@ -786,6 +838,8 @@ _j_create_strv_array_update(json_t *mutations,
if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX))
continue;
}
if (strdict_type == STRDICT_TYPE_OTHER_CONFIG && nm_streq(key, OTHER_CONFIG_HWADDR))
continue;
json_array_append_new(array, json_pack("[s, s]", key, val));
}
}
@@ -868,7 +922,7 @@ _insert_interface(json_t *params,
json_array_append_new(options, json_array());
}
row = json_pack("{s:s, s:s, s:o, s:o}",
row = json_pack("{s:s, s:s, s:o, s:o, s:o}",
"name",
nm_connection_get_interface_name(interface),
"type",
@@ -876,7 +930,9 @@ _insert_interface(json_t *params,
"options",
options,
"external_ids",
_j_create_strdict_new(interface, STRDICT_TYPE_EXTERNAL_IDS));
_j_create_strdict_new(interface, STRDICT_TYPE_EXTERNAL_IDS, NULL),
"other_config",
_j_create_strdict_new(interface, STRDICT_TYPE_OTHER_CONFIG, NULL));
if (cloned_mac)
json_object_set_new(row, "mac", json_string(cloned_mac));
@@ -963,7 +1019,10 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces));
json_object_set_new(row,
"external_ids",
_j_create_strdict_new(port, STRDICT_TYPE_EXTERNAL_IDS));
_j_create_strdict_new(port, STRDICT_TYPE_EXTERNAL_IDS, NULL));
json_object_set_new(row,
"other_config",
_j_create_strdict_new(port, STRDICT_TYPE_OTHER_CONFIG, NULL));
/* Create a new one. */
json_array_append_new(params,
@@ -1025,13 +1084,10 @@ _insert_bridge(json_t *params,
json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports));
json_object_set_new(row,
"external_ids",
_j_create_strdict_new(bridge, STRDICT_TYPE_EXTERNAL_IDS));
if (cloned_mac) {
_j_create_strdict_new(bridge, STRDICT_TYPE_EXTERNAL_IDS, NULL));
json_object_set_new(row,
"other_config",
json_pack("[s, [[s, s]]]", "map", "hwaddr", cloned_mac));
}
_j_create_strdict_new(bridge, STRDICT_TYPE_OTHER_CONFIG, cloned_mac));
/* Create a new one. */
json_array_append_new(params,
@@ -1393,9 +1449,9 @@ ovsdb_next_command(NMOvsdb *self)
switch (call->command) {
case OVSDB_MONITOR:
msg = json_pack("{s:I, s:s, s:[s, n, {"
" s:[{s:[s, s, s]}],"
" s:[{s:[s, s, s]}],"
" s:[{s:[s, s, s, s]}],"
" s:[{s:[s, s, s, s]}],"
" s:[{s:[s, s, s, s, s]}],"
" s:[{s:[]}]"
"}]}",
"id",
@@ -1409,16 +1465,19 @@ ovsdb_next_command(NMOvsdb *self)
"name",
"ports",
"external_ids",
"other_config",
"Port",
"columns",
"name",
"interfaces",
"external_ids",
"other_config",
"Interface",
"columns",
"name",
"type",
"external_ids",
"other_config",
"error",
"Open_vSwitch",
"columns");
@@ -1470,6 +1529,11 @@ ovsdb_next_command(NMOvsdb *self)
call->payload.set_reapply.connection_uuid,
call->payload.set_reapply.external_ids_old,
call->payload.set_reapply.external_ids_new);
_j_create_strv_array_update(mutations,
STRDICT_TYPE_OTHER_CONFIG,
NULL,
call->payload.set_reapply.other_config_old,
call->payload.set_reapply.other_config_new);
json_array_append_new(
params,
@@ -1684,6 +1748,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
json_t *interface = NULL;
json_t *items;
json_t *external_ids;
json_t *other_config;
json_error_t json_error = {
0,
};
@@ -1723,12 +1788,13 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
json_object_foreach (interface, key, value) {
OpenvswitchInterface *ovs_interface;
gs_unref_array GArray *external_ids_arr = NULL;
gs_unref_array GArray *other_config_arr = NULL;
const char *connection_uuid = NULL;
json_t *error = NULL;
int r;
r = json_unpack(value,
"{s:{s:s, s:s, s?:o, s:o}}",
"{s:{s:s, s:s, s?:o, s:o, s:o}}",
"new",
"name",
&name,
@@ -1737,7 +1803,9 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
"error",
&error,
"external_ids",
&external_ids);
&external_ids,
"other_config",
&other_config);
if (r != 0) {
gpointer unused;
@@ -1783,6 +1851,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
_strdict_extract(external_ids, &external_ids_arr);
connection_uuid =
_strdict_find_key(external_ids_arr, NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID);
_strdict_extract(other_config, &other_config_arr);
if (ovs_interface) {
gboolean changed = FALSE;
@@ -1795,10 +1864,16 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
NM_SWAP(&ovs_interface->external_ids, &external_ids_arr);
changed = TRUE;
}
if (!_strdict_equals(ovs_interface->other_config, other_config_arr)) {
NM_SWAP(&ovs_interface->other_config, &other_config_arr);
changed = TRUE;
}
if (changed) {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
_LOGT("obj[iface:%s]: changed an '%s' interface: %s%s%s, external-ids=%s",
_LOGT("obj[iface:%s]: changed an '%s' interface: %s%s%s, external-ids=%s, "
"other-config=%s",
key,
type,
ovs_interface->name,
@@ -1806,10 +1881,12 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
", ",
ovs_interface->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_interface->external_ids)));
(strtmp1 = _strdict_to_string(ovs_interface->external_ids)),
(strtmp2 = _strdict_to_string(ovs_interface->other_config)));
}
} else {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
ovs_interface = g_slice_new(OpenvswitchInterface);
*ovs_interface = (OpenvswitchInterface){
@@ -1818,9 +1895,11 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
.type = g_strdup(type),
.connection_uuid = g_strdup(connection_uuid),
.external_ids = g_steal_pointer(&external_ids_arr),
.other_config = g_steal_pointer(&other_config_arr),
};
g_hash_table_add(priv->interfaces, ovs_interface);
_LOGT("obj[iface:%s]: added an '%s' interface: %s%s%s, external-ids=%s",
_LOGT(
"obj[iface:%s]: added an '%s' interface: %s%s%s, external-ids=%s, other-config=%s",
key,
ovs_interface->type,
ovs_interface->name,
@@ -1828,7 +1907,8 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
", ",
ovs_interface->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_interface->external_ids)));
(strtmp1 = _strdict_to_string(ovs_interface->external_ids)),
(strtmp2 = _strdict_to_string(ovs_interface->other_config)));
_signal_emit_device_added(self,
ovs_interface->name,
NM_DEVICE_TYPE_OVS_INTERFACE,
@@ -1849,16 +1929,19 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
gs_unref_ptrarray GPtrArray *interfaces = NULL;
OpenvswitchPort *ovs_port;
gs_unref_array GArray *external_ids_arr = NULL;
gs_unref_array GArray *other_config_arr = NULL;
const char *connection_uuid = NULL;
int r;
r = json_unpack(value,
"{s:{s:s, s:o, s:o}}",
"{s:{s:s, s:o, s:o, s:o}}",
"new",
"name",
&name,
"external_ids",
&external_ids,
"other_config",
&other_config,
"interfaces",
&items);
if (r != 0) {
@@ -1895,6 +1978,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
_strdict_extract(external_ids, &external_ids_arr);
connection_uuid =
_strdict_find_key(external_ids_arr, NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID);
_strdict_extract(other_config, &other_config_arr);
interfaces = _uuids_to_array(items);
@@ -1913,20 +1997,27 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
NM_SWAP(&ovs_port->external_ids, &external_ids_arr);
changed = TRUE;
}
if (!_strdict_equals(ovs_port->other_config, other_config_arr)) {
NM_SWAP(&ovs_port->other_config, &other_config_arr);
changed = TRUE;
}
if (changed) {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
_LOGT("obj[port:%s]: changed a port: %s%s%s, external-ids=%s",
_LOGT("obj[port:%s]: changed a port: %s%s%s, external-ids=%s, other-config=%s",
key,
ovs_port->name,
NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid,
", ",
ovs_port->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_port->external_ids)));
(strtmp1 = _strdict_to_string(ovs_port->external_ids)),
(strtmp2 = _strdict_to_string(ovs_port->other_config)));
}
} else {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
ovs_port = g_slice_new(OpenvswitchPort);
*ovs_port = (OpenvswitchPort){
@@ -1935,16 +2026,18 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
.connection_uuid = g_strdup(connection_uuid),
.interfaces = g_steal_pointer(&interfaces),
.external_ids = g_steal_pointer(&external_ids_arr),
.other_config = g_steal_pointer(&other_config_arr),
};
g_hash_table_add(priv->ports, ovs_port);
_LOGT("obj[port:%s]: added a port: %s%s%s, external-ids=%s",
_LOGT("obj[port:%s]: added a port: %s%s%s, external-ids=%s, other-config=%s",
key,
ovs_port->name,
NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid,
", ",
ovs_port->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_port->external_ids)));
(strtmp1 = _strdict_to_string(ovs_port->external_ids)),
(strtmp2 = _strdict_to_string(ovs_port->other_config)));
_signal_emit_device_added(self, ovs_port->name, NM_DEVICE_TYPE_OVS_PORT, NULL);
}
}
@@ -1953,16 +2046,19 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
gs_unref_ptrarray GPtrArray *ports = NULL;
OpenvswitchBridge *ovs_bridge;
gs_unref_array GArray *external_ids_arr = NULL;
gs_unref_array GArray *other_config_arr = NULL;
const char *connection_uuid = NULL;
int r;
r = json_unpack(value,
"{s:{s:s, s:o, s:o}}",
"{s:{s:s, s:o, s:o, s:o}}",
"new",
"name",
&name,
"external_ids",
&external_ids,
"other_config",
&other_config,
"ports",
&items);
@@ -2003,6 +2099,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
_strdict_extract(external_ids, &external_ids_arr);
connection_uuid =
_strdict_find_key(external_ids_arr, NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID);
_strdict_extract(other_config, &other_config_arr);
ports = _uuids_to_array(items);
@@ -2021,20 +2118,27 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
NM_SWAP(&ovs_bridge->external_ids, &external_ids_arr);
changed = TRUE;
}
if (!_strdict_equals(ovs_bridge->other_config, other_config_arr)) {
NM_SWAP(&ovs_bridge->other_config, &other_config_arr);
changed = TRUE;
}
if (changed) {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
_LOGT("obj[bridge:%s]: changed a bridge: %s%s%s, external-ids=%s",
_LOGT("obj[bridge:%s]: changed a bridge: %s%s%s, external-ids=%s, other-config=%s",
key,
ovs_bridge->name,
NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid,
", ",
ovs_bridge->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_bridge->external_ids)));
(strtmp1 = _strdict_to_string(ovs_bridge->external_ids)),
(strtmp2 = _strdict_to_string(ovs_bridge->external_ids)));
}
} else {
gs_free char *strtmp1 = NULL;
gs_free char *strtmp2 = NULL;
ovs_bridge = g_slice_new(OpenvswitchBridge);
*ovs_bridge = (OpenvswitchBridge){
@@ -2043,16 +2147,18 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg)
.connection_uuid = g_strdup(connection_uuid),
.ports = g_steal_pointer(&ports),
.external_ids = g_steal_pointer(&external_ids_arr),
.other_config = g_steal_pointer(&other_config_arr),
};
g_hash_table_add(priv->bridges, ovs_bridge);
_LOGT("obj[bridge:%s]: added a bridge: %s%s%s, external-ids=%s",
_LOGT("obj[bridge:%s]: added a bridge: %s%s%s, external-ids=%s, other-config=%s",
key,
ovs_bridge->name,
NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid,
", ",
ovs_bridge->connection_uuid,
""),
(strtmp1 = _strdict_to_string(ovs_bridge->external_ids)));
(strtmp1 = _strdict_to_string(ovs_bridge->external_ids)),
(strtmp2 = _strdict_to_string(ovs_bridge->other_config)));
_signal_emit_device_added(self, ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE, NULL);
}
}
@@ -2795,10 +2901,14 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
const char *ifname,
const char *connection_uuid,
NMSettingOvsExternalIDs *s_external_ids_old,
NMSettingOvsExternalIDs *s_external_ids_new)
NMSettingOvsExternalIDs *s_external_ids_new,
NMSettingOvsOtherConfig *s_other_config_old,
NMSettingOvsOtherConfig *s_other_config_new)
{
gs_unref_hashtable GHashTable *external_ids_old = NULL;
gs_unref_hashtable GHashTable *external_ids_new = NULL;
gs_unref_hashtable GHashTable *other_config_old = NULL;
gs_unref_hashtable GHashTable *other_config_new = NULL;
external_ids_old =
s_external_ids_old
@@ -2809,6 +2919,15 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_external_ids_new))
: NULL;
other_config_old =
s_other_config_old
? nm_strdict_clone(_nm_setting_ovs_other_config_get_data(s_other_config_old))
: NULL;
other_config_new =
s_other_config_new
? nm_strdict_clone(_nm_setting_ovs_other_config_get_data(s_other_config_new))
: NULL;
ovsdb_call_method(self,
NULL,
NULL,
@@ -2818,7 +2937,9 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
ifname,
connection_uuid,
external_ids_old,
external_ids_new));
external_ids_new,
other_config_old,
other_config_new));
}
/*****************************************************************************/

View File

@@ -47,14 +47,14 @@ void nm_ovsdb_set_interface_mtu(NMOvsdb *self,
NMOvsdbCallback callback,
gpointer user_data);
struct _NMSettingOvsExternalIDs;
void nm_ovsdb_set_reapply(NMOvsdb *self,
NMDeviceType device_type,
const char *ifname,
const char *connection_uuid,
struct _NMSettingOvsExternalIDs *s_external_ids_old,
struct _NMSettingOvsExternalIDs *s_external_ids_new);
NMSettingOvsExternalIDs *s_external_ids_old,
NMSettingOvsExternalIDs *s_external_ids_new,
NMSettingOvsOtherConfig *s_other_config_old,
NMSettingOvsOtherConfig *s_other_config_new);
gboolean nm_ovsdb_is_ready(NMOvsdb *self);

View File

@@ -1894,6 +1894,7 @@ global:
nm_range_ref;
nm_range_to_str;
nm_range_unref;
nm_setting_ip_config_get_auto_route_ext_gw;
nm_setting_ip_config_get_dhcp_iaid;
nm_setting_ip_config_get_dhcp_iaid;
nm_setting_ip_tunnel_get_fwmark;
@@ -1901,6 +1902,11 @@ global:
nm_setting_loopback_get_type;
nm_setting_loopback_new;
nm_setting_ovs_interface_get_ofport_request;
nm_setting_ovs_other_config_get_data;
nm_setting_ovs_other_config_get_data_keys;
nm_setting_ovs_other_config_get_type;
nm_setting_ovs_other_config_new;
nm_setting_ovs_other_config_set_data;
nm_setting_ovs_port_add_trunk;
nm_setting_ovs_port_clear_trunks;
nm_setting_ovs_port_get_num_trunks;
@@ -1908,7 +1914,6 @@ global:
nm_setting_ovs_port_remove_trunk;
nm_setting_ovs_port_remove_trunk_by_value;
nm_setting_vlan_get_protocol;
nm_setting_ip_config_get_auto_route_ext_gw;
nm_utils_ensure_gtypes;
nm_version_info_capability_get_type;
} libnm_1_40_0;

View File

@@ -630,3 +630,104 @@ nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free)
*out_free = s;
return s;
}
/*****************************************************************************/
/**
* nm_setting_ovs_other_config_check_key:
* @key: (allow-none): the key to check
* @error: a #GError, %NULL to ignore.
*
* Checks whether @key is a valid key for OVS' other-config.
* 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.
*
* Returns: %TRUE if @key is a valid user data key.
*/
gboolean
nm_setting_ovs_other_config_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, nm_ascii_is_regular_char(ch))) {
/* Probably OVS is more forgiving about what makes a valid key for
* an other-key. 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;
}
return TRUE;
}
/**
* nm_setting_ovs_other_config_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.
*
* Returns: %TRUE if @val is a valid user data value.
*/
gboolean
nm_setting_ovs_other_config_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 > (2u * 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;
}

View File

@@ -308,4 +308,9 @@ const char *nm_utils_dnsname_construct(int ad
const char *nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free);
/*****************************************************************************/
gboolean nm_setting_ovs_other_config_check_key(const char *key, GError **error);
gboolean nm_setting_ovs_other_config_check_val(const char *val, GError **error);
#endif /* __NM_LIBNM_SHARED_UTILS_H__ */

View File

@@ -1879,6 +1879,14 @@
gprop-type="gchararray"
/>
</setting>
<setting name="ovs-other-config"
gtype="NMSettingOvsOtherConfig"
>
<property name="data"
dbus-type="a{ss}"
gprop-type="GHashTable"
/>
</setting>
<setting name="ovs-patch"
gtype="NMSettingOvsPatch"
>

View File

@@ -33,6 +33,7 @@ libnm_core_settings_sources = files(
'nm-setting-ovs-dpdk.c',
'nm-setting-ovs-external-ids.c',
'nm-setting-ovs-interface.c',
'nm-setting-ovs-other-config.c',
'nm-setting-ovs-patch.c',
'nm-setting-ovs-port.c',
'nm-setting-ppp.c',

View File

@@ -28,12 +28,14 @@
#include "nm-setting-private.h"
#include "nm-setting-user.h"
#include "nm-setting-ovs-external-ids.h"
#include "nm-setting-ovs-other-config.h"
#include "libnm-core-intern/nm-keyfile-utils.h"
#define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options"
#define OVS_EXTERNAL_IDS_DATA_PREFIX "data."
/* used for "ovs-external-ids.data" and "ovs-other-config.data". */
#define STRDICT_DATA_PREFIX "data."
/*****************************************************************************/
@@ -1060,23 +1062,29 @@ ip_routing_rule_parser_full(KeyfileReaderInfo *info,
}
static void
_parser_full_ovs_external_ids_data(KeyfileReaderInfo *info,
_parser_full_strdict_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;
gboolean is_exid;
nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting));
if (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)));
is_exid = TRUE;
} else {
nm_assert(NM_IS_SETTING_OVS_OTHER_CONFIG(setting));
nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_OTHER_CONFIG_DATA));
is_exid = FALSE;
}
keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL);
nm_assert(nm_streq(setting_info->setting_name, nm_setting_get_name(setting)));
keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_info->setting_name, &n_keys, NULL);
for (i = 0; i < n_keys; i++) {
const char *key = keys[i];
@@ -1084,16 +1092,20 @@ _parser_full_ovs_external_ids_data(KeyfileReaderInfo *info,
gs_free char *value = NULL;
const char *name;
if (!NM_STR_HAS_PREFIX(key, OVS_EXTERNAL_IDS_DATA_PREFIX))
if (!NM_STR_HAS_PREFIX(key, STRDICT_DATA_PREFIX))
continue;
value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL);
value =
nm_keyfile_plugin_kf_get_string(info->keyfile, setting_info->setting_name, key, NULL);
if (!value)
continue;
name = &key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)];
name = &key[NM_STRLEN(STRDICT_DATA_PREFIX)];
name = nm_keyfile_key_decode(name, &name_to_free);
if (is_exid)
nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value);
else
nm_setting_ovs_other_config_set_data(NM_SETTING_OVS_OTHER_CONFIG(setting), name, value);
}
}
@@ -2569,7 +2581,7 @@ tfilter_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, con
}
static void
_writer_full_ovs_external_ids_data(KeyfileWriterInfo *info,
_writer_full_strdict_data(KeyfileWriterInfo *info,
const NMMetaSettingInfo *setting_info,
const NMSettInfoProperty *property_info,
const ParseInfoProperty *pip,
@@ -2580,13 +2592,21 @@ _writer_full_ovs_external_ids_data(KeyfileWriterInfo *info,
gs_free NMUtilsNamedValue *data_free = NULL;
const NMUtilsNamedValue *data;
guint data_len;
char full_key_static[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + 300u];
char full_key_static[NM_STRLEN(STRDICT_DATA_PREFIX) + 300u];
guint i;
gboolean is_exid;
nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting));
if (NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)) {
nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA));
is_exid = TRUE;
} else {
nm_assert(NM_IS_SETTING_OVS_OTHER_CONFIG(setting));
nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_OTHER_CONFIG_DATA));
is_exid = FALSE;
}
hash = _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting));
hash = is_exid ? _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting))
: _nm_setting_ovs_other_config_get_data(NM_SETTING_OVS_OTHER_CONFIG(setting));
if (!hash)
return;
@@ -2594,7 +2614,7 @@ _writer_full_ovs_external_ids_data(KeyfileWriterInfo *info,
if (data_len == 0)
return;
memcpy(full_key_static, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX));
memcpy(full_key_static, STRDICT_DATA_PREFIX, NM_STRLEN(STRDICT_DATA_PREFIX));
for (i = 0; i < data_len; i++) {
const char *key = data[i].name;
@@ -2608,15 +2628,16 @@ _writer_full_ovs_external_ids_data(KeyfileWriterInfo *info,
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);
if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(STRDICT_DATA_PREFIX)) {
full_key_free = g_new(char, NM_STRLEN(STRDICT_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, STRDICT_DATA_PREFIX, NM_STRLEN(STRDICT_DATA_PREFIX));
}
memcpy(&full_key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)], escaped_key, len);
memcpy(&full_key[NM_STRLEN(STRDICT_DATA_PREFIX)], escaped_key, len);
nm_keyfile_plugin_kf_set_string(info->keyfile,
NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME,
is_exid ? NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME
: NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME,
full_key,
val);
}
@@ -3077,8 +3098,16 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
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,
.parser_full = _parser_full_strdict_data,
.writer_full = _writer_full_strdict_data,
.has_parser_full = TRUE,
.has_writer_full = TRUE, ), ), ),
PARSE_INFO_SETTING(
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_OTHER_CONFIG_DATA,
.parser_no_check_key = TRUE,
.parser_full = _parser_full_strdict_data,
.writer_full = _writer_full_strdict_data,
.has_parser_full = TRUE,
.has_writer_full = TRUE, ), ), ),
PARSE_INFO_SETTING(NM_META_SETTING_TYPE_SERIAL,

View File

@@ -40,9 +40,10 @@
#include "nm-setting-match.h"
#include "nm-setting-olpc-mesh.h"
#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-interface.h"
#include "nm-setting-ovs-other-config.h"
#include "nm-setting-ovs-patch.h"
#include "nm-setting-ovs-port.h"
#include "nm-setting-ppp.h"
@@ -410,6 +411,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_OTHER_CONFIG] =
{
.meta_type = NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
.setting_priority = NM_SETTING_PRIORITY_AUX,
.setting_name = NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME,
.get_setting_gtype = nm_setting_ovs_other_config_get_type,
},
[NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] =
{
.meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
@@ -654,6 +662,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_ETHTOOL,
NM_META_SETTING_TYPE_MATCH,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
NM_META_SETTING_TYPE_PPP,
NM_META_SETTING_TYPE_PPPOE,
NM_META_SETTING_TYPE_TEAM_PORT,

View File

@@ -10,6 +10,7 @@
#include "nm-setting-private.h"
#include "nm-utils-private.h"
#include "nm-connection-private.h"
#include "nm-setting-ovs-other-config.h"
#define MAX_NUM_KEYS 256
@@ -126,7 +127,7 @@ _nm_setting_ovs_verify_connection_type(GType gtype, NMConnection *connection, GE
const char *slave_type;
nm_assert(!connection || NM_IS_CONNECTION(connection));
nm_assert(NM_IN_SET(gtype, NM_TYPE_SETTING_OVS_EXTERNAL_IDS));
nm_assert(NM_IN_SET(gtype, NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NM_TYPE_SETTING_OVS_OTHER_CONFIG));
nm_assert(!error || !*error);
if (!connection) {
@@ -245,6 +246,8 @@ nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guin
NMSettingOvsExternalIDs *self = setting;
NMSettingOvsExternalIDsPrivate *priv;
NM_SET_OUT(out_len, 0);
g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL);
priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self);

View File

@@ -0,0 +1,403 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2017 - 2020, 2022 Red Hat, Inc.
*/
#include "libnm-core-impl/nm-default-libnm-core.h"
#include "nm-setting-ovs-other-config.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-other-config
* @short_description: Other-config settings for OVS
*
* The #NMSettingOvsOtherConfig object is a #NMSetting subclass that allows to
* configure other_config settings for OVS. See also "other_config" in the
* "ovs-vswitchd.conf.db" manual for the keys that OVS supports.
**/
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsOtherConfig, PROP_DATA, );
typedef struct {
GHashTable *data;
const char **data_keys;
} NMSettingOvsOtherConfigPrivate;
/**
* NMSettingOvsOtherConfig:
*
* OVS Other Config Settings
*
* Since: 1.42
*/
struct _NMSettingOvsOtherConfig {
NMSetting parent;
NMSettingOvsOtherConfigPrivate _priv;
};
struct _NMSettingOvsOtherConfigClass {
NMSettingClass parent;
};
G_DEFINE_TYPE(NMSettingOvsOtherConfig, nm_setting_ovs_other_config, NM_TYPE_SETTING)
#define NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMSettingOvsOtherConfig, NM_IS_SETTING_OVS_OTHER_CONFIG)
/*****************************************************************************/
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_other_config_get_data(NMSettingOvsOtherConfig *self)
{
return NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self)->data;
}
/**
* nm_setting_ovs_other_config_get_data_keys:
* @setting: the #NMSettingOvsOtherConfig
* @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.
*
* Since: 1.42
**/
const char *const *
nm_setting_ovs_other_config_get_data_keys(NMSettingOvsOtherConfig *setting, guint *out_len)
{
NMSettingOvsOtherConfig *self = setting;
NMSettingOvsOtherConfigPrivate *priv;
NM_SET_OUT(out_len, 0);
g_return_val_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self), NULL);
priv = NM_SETTING_OVS_OTHER_CONFIG_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_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_other_config_get_data:
* @setting: the #NMSettingOvsOtherConfig instance
* @key: the other-config to lookup
*
* Since: 1.42
*
* Returns: (transfer none): the value associated with @key or %NULL if no such
* value exists.
*/
const char *
nm_setting_ovs_other_config_get_data(NMSettingOvsOtherConfig *setting, const char *key)
{
NMSettingOvsOtherConfig *self = setting;
NMSettingOvsOtherConfigPrivate *priv;
g_return_val_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self), NULL);
g_return_val_if_fail(key, NULL);
priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self);
if (!priv->data)
return NULL;
return g_hash_table_lookup(priv->data, key);
}
/**
* nm_setting_ovs_other_config_set_data:
* @setting: the #NMSettingOvsOtherConfig instance
* @key: the key to set
* @val: (allow-none): the value to set or %NULL to clear a key.
*
* Since: 1.42
*/
void
nm_setting_ovs_other_config_set_data(NMSettingOvsOtherConfig *setting,
const char *key,
const char *val)
{
NMSettingOvsOtherConfig *self = setting;
NMSettingOvsOtherConfigPrivate *priv;
g_return_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self));
priv = NM_SETTING_OVS_OTHER_CONFIG_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)
{
NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(setting);
NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self);
if (priv->data) {
gs_free_error GError *local = NULL;
const char *const *keys;
guint len;
guint i;
keys = nm_setting_ovs_other_config_get_data_keys(self, &len);
for (i = 0; i < len; i++) {
const char *key = keys[i];
const char *val = g_hash_table_lookup(priv->data, key);
if (!nm_setting_ovs_other_config_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_other_config_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_OTHER_CONFIG_SETTING_NAME,
NM_SETTING_OVS_OTHER_CONFIG_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 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_OTHER_CONFIG_SETTING_NAME,
NM_SETTING_OVS_OTHER_CONFIG_DATA);
return FALSE;
}
if (!_nm_setting_ovs_verify_connection_type(NM_TYPE_SETTING_OVS_OTHER_CONFIG,
connection,
error))
return FALSE;
return TRUE;
}
static NMTernary
compare_fcn_data(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil)
{
NMSettingOvsOtherConfigPrivate *priv;
NMSettingOvsOtherConfigPrivate *pri2;
if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
return NM_TERNARY_DEFAULT;
if (!set_b)
return TRUE;
priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(NM_SETTING_OVS_OTHER_CONFIG(set_a));
pri2 = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(NM_SETTING_OVS_OTHER_CONFIG(set_b));
return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal);
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object);
NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_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)
{
NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object);
NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_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_other_config_init(NMSettingOvsOtherConfig *self)
{}
/**
* nm_setting_ovs_other_config_new:
*
* Creates a new #NMSettingOvsOtherConfig object with default values.
*
* Returns: (transfer full) (type NMSettingOvsOtherConfig): the new empty
* #NMSettingOvsOtherConfig object
*
* Since: 1.42
*/
NMSetting *
nm_setting_ovs_other_config_new(void)
{
return g_object_new(NM_TYPE_SETTING_OVS_OTHER_CONFIG, NULL);
}
static void
finalize(GObject *object)
{
NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object);
NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self);
g_free(priv->data_keys);
if (priv->data)
g_hash_table_unref(priv->data);
G_OBJECT_CLASS(nm_setting_ovs_other_config_parent_class)->finalize(object);
}
static void
nm_setting_ovs_other_config_class_init(NMSettingOvsOtherConfigClass *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->verify = verify;
/**
* NMSettingOvsOtherConfig:data: (type GHashTable(utf8,utf8))
*
* A dictionary of key/value pairs with other_config settings for OVS.
* See also "other_config" in the "ovs-vswitchd.conf.db" manual for the keys
* that OVS supports.
*
* Since: 1.42
**/
obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_OVS_OTHER_CONFIG_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_GPROP(NM_G_VARIANT_TYPE("a{ss}"),
.typdata_from_dbus.gprop_fcn = _nm_utils_strdict_from_dbus,
.typdata_to_dbus.gprop_type =
NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_STRDICT,
.compare_fcn = compare_fcn_data,
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
.from_dbus_is_full = TRUE));
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit(setting_class,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
NULL,
properties_override,
0);
}

View File

@@ -121,7 +121,7 @@ test_nm_meta_setting_types_by_priority(void)
G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM
== G_N_ELEMENTS(nm_meta_setting_types_by_priority));
G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == 53);
G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == 54);
arr = g_ptr_array_new_with_free_func(g_object_unref);

View File

@@ -395,6 +395,7 @@ GSList *_nm_vpn_plugin_info_list_load_dir(const char *dirname,
/*****************************************************************************/
GHashTable *_nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self);
GHashTable *_nm_setting_ovs_other_config_get_data(NMSettingOvsOtherConfig *self);
/*****************************************************************************/

View File

@@ -135,6 +135,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_OVS_DPDK,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_INTERFACE,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
NM_META_SETTING_TYPE_OVS_PATCH,
NM_META_SETTING_TYPE_OVS_PORT,
NM_META_SETTING_TYPE_PPP,

View File

@@ -38,6 +38,7 @@ libnm_core_headers = files(
'nm-setting-ovs-dpdk.h',
'nm-setting-ovs-external-ids.h',
'nm-setting-ovs-interface.h',
'nm-setting-ovs-other-config.h',
'nm-setting-ovs-patch.h',
'nm-setting-ovs-port.h',
'nm-setting-ppp.h',

View File

@@ -42,6 +42,7 @@ typedef struct _NMSettingMatch NMSettingMatch;
typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh;
typedef struct _NMSettingOvsBridge NMSettingOvsBridge;
typedef struct _NMSettingOvsDpdk NMSettingOvsDpdk;
typedef struct _NMSettingOvsOtherConfig NMSettingOvsOtherConfig;
typedef struct _NMSettingOvsExternalIDs NMSettingOvsExternalIDs;
typedef struct _NMSettingOvsInterface NMSettingOvsInterface;
typedef struct _NMSettingOvsPatch NMSettingOvsPatch;

View File

@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2017 - 2020, 2022 Red Hat, Inc.
*/
#ifndef __NM_SETTING_OVS_OTHER_CONFIG_H__
#define __NM_SETTING_OVS_OTHER_CONFIG_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_OTHER_CONFIG (nm_setting_ovs_other_config_get_type())
#define NM_SETTING_OVS_OTHER_CONFIG(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_OVS_OTHER_CONFIG, NMSettingOvsOtherConfig))
#define NM_SETTING_OVS_OTHER_CONFIG_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
NM_TYPE_SETTING_OVS_OTHER_CONFIG, \
NMSettingOvsOtherConfigClass))
#define NM_IS_SETTING_OVS_OTHER_CONFIG(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_OVS_OTHER_CONFIG))
#define NM_IS_SETTING_OVS_OTHER_CONFIG_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_OVS_OTHER_CONFIG))
#define NM_SETTING_OVS_OTHER_CONFIG_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
NM_TYPE_SETTING_OVS_OTHER_CONFIG, \
NMSettingOvsOtherConfigClass))
#define NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME "ovs-other-config"
#define NM_SETTING_OVS_OTHER_CONFIG_DATA "data"
typedef struct _NMSettingOvsOtherConfigClass NMSettingOvsOtherConfigClass;
NM_AVAILABLE_IN_1_42
GType nm_setting_ovs_other_config_get_type(void);
NM_AVAILABLE_IN_1_42
NMSetting *nm_setting_ovs_other_config_new(void);
/*****************************************************************************/
NM_AVAILABLE_IN_1_42
const char *const *nm_setting_ovs_other_config_get_data_keys(NMSettingOvsOtherConfig *setting,
guint *out_len);
NM_AVAILABLE_IN_1_42
const char *nm_setting_ovs_other_config_get_data(NMSettingOvsOtherConfig *setting, const char *key);
NM_AVAILABLE_IN_1_42
void nm_setting_ovs_other_config_set_data(NMSettingOvsOtherConfig *setting,
const char *key,
const char *val);
/*****************************************************************************/
G_END_DECLS
#endif /* __NM_SETTING_OVS_OTHER_CONFIG_H__ */

View File

@@ -40,9 +40,10 @@
#include "nm-setting-match.h"
#include "nm-setting-olpc-mesh.h"
#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-interface.h"
#include "nm-setting-ovs-other-config.h"
#include "nm-setting-ovs-patch.h"
#include "nm-setting-ovs-port.h"
#include "nm-setting-ppp.h"
@@ -410,6 +411,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_OTHER_CONFIG] =
{
.meta_type = NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
.setting_priority = NM_SETTING_PRIORITY_AUX,
.setting_name = NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME,
.get_setting_gtype = nm_setting_ovs_other_config_get_type,
},
[NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] =
{
.meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
@@ -654,6 +662,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_ETHTOOL,
NM_META_SETTING_TYPE_MATCH,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
NM_META_SETTING_TYPE_PPP,
NM_META_SETTING_TYPE_PPPOE,
NM_META_SETTING_TYPE_TEAM_PORT,

View File

@@ -135,6 +135,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_OVS_DPDK,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_INTERFACE,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
NM_META_SETTING_TYPE_OVS_PATCH,
NM_META_SETTING_TYPE_OVS_PORT,
NM_META_SETTING_TYPE_PPP,

View File

@@ -8413,6 +8413,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_OTHER_CONFIG N_("OVS Other Config")
#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")
@@ -8611,6 +8612,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
NM_META_SETTING_VALID_PART_ITEM (OVS_DPDK, TRUE),
),
),
SETTING_INFO_EMPTY (OVS_OTHER_CONFIG),
SETTING_INFO_EMPTY (OVS_EXTERNAL_IDS),
SETTING_INFO (OVS_INTERFACE,
.valid_parts = NM_META_SETTING_VALID_PARTS (

View File

@@ -438,5 +438,6 @@
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT N_("If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to NM_TERNARY_FALSE (0), the hostname can be set from this device even if it doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_FALSE (0).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_PRIORITY N_("The relative priority of this connection to determine the system hostname. A lower numerical value is better (higher priority). A connection with higher priority is considered before connections with lower priority. If the value is zero, it can be overridden by a global value from NetworkManager configuration. If the property doesn't have a value in the global configuration, the value is assumed to be 100. Negative values have the special effect of excluding other connections with a greater numerical priority value; so in presence of at least one negative priority, only connections with the lowest priority value will be used to determine the hostname.")
#define DESCRIBE_DOC_NM_SETTING_LOOPBACK_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
#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_EXTERNAL_IDS_DATA N_("A dictionary of key/value pairs with external-ids for OVS.")
#define DESCRIBE_DOC_NM_SETTING_OVS_OTHER_CONFIG_DATA N_("A dictionary of key/value pairs with other_config settings for OVS. See also \"other_config\" in the \"ovs-vswitchd.conf.db\" manual for the keys that OVS supports.")
#define DESCRIBE_DOC_NM_SETTING_VETH_PEER N_("This property specifies the peer interface name of the veth. This property is mandatory.")

View File

@@ -848,6 +848,8 @@
<property name="ofport-request"
description="Open vSwitch openflow port number. Defaults to zero which means that port number will not be specified and it will be chosen randomly by ovs. OpenFlow ports are the network interfaces for passing packets between OpenFlow processing and the rest of the network. OpenFlow switches connect logically to each other via their OpenFlow ports." />
</setting>
<setting name="ovs-other-config" >
</setting>
<setting name="ovs-patch" >
<property name="peer"
description="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." />

View File

@@ -88,6 +88,7 @@ F1_EXTRA="
xml/annotation-glossary.xml
xml/api-index-full.xml
xml/nm-setting-ovs-external-ids.xml
xml/nm-setting-ovs-other-config.xml
xml/nm-version-macros.xml
xml/nm-secret-agent-old.xml
xml/nm-vpn-plugin-old.xml