diff options
Diffstat (limited to 'src/core/devices/ovs/nm-ovsdb.c')
-rw-r--r-- | src/core/devices/ovs/nm-ovsdb.c | 557 |
1 files changed, 378 insertions, 179 deletions
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 8da232ab0f..d6422434c7 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -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,18 +25,26 @@ #define OVSDB_MAX_FAILURES 3 +#define OTHER_CONFIG_HWADDR "hwaddr" + /*****************************************************************************/ #if JANSSON_VERSION_HEX < 0x020400 #warning "requires at least libjansson 2.4" #endif +typedef enum { + STRDICT_TYPE_EXTERNAL_IDS, + STRDICT_TYPE_OTHER_CONFIG, +} StrdictType; + typedef struct { char *port_uuid; char *name; char *connection_uuid; GPtrArray *interfaces; /* interface uuids */ GArray *external_ids; + GArray *other_config; } OpenvswitchPort; typedef struct { @@ -44,6 +53,7 @@ typedef struct { char *connection_uuid; GPtrArray *ports; /* port uuids */ GArray *external_ids; + GArray *other_config; } OpenvswitchBridge; typedef struct { @@ -52,6 +62,7 @@ typedef struct { char *type; char *connection_uuid; GArray *external_ids; + GArray *other_config; } OpenvswitchInterface; /*****************************************************************************/ @@ -66,7 +77,7 @@ typedef enum { OVSDB_ADD_INTERFACE, OVSDB_DEL_INTERFACE, OVSDB_SET_INTERFACE_MTU, - OVSDB_SET_EXTERNAL_IDS, + OVSDB_SET_REAPPLY, } OvsdbCommand; #define CALL_ID_UNSPEC G_MAXUINT64 @@ -92,9 +103,11 @@ typedef union { NMDeviceType device_type; char *ifname; char *connection_uuid; - GHashTable *exid_old; - GHashTable *exid_new; - } set_external_ids; + GHashTable *external_ids_old; + GHashTable *external_ids_new; + GHashTable *other_config_old; + GHashTable *other_config_new; + } set_reapply; } OvsdbMethodPayload; typedef struct { @@ -223,20 +236,24 @@ static void cleanup_check_ready(NMOvsdb *self); }, \ })) -#define OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(xdevice_type, \ - xifname, \ - xconnection_uuid, \ - xexid_old, \ - xexid_new) \ - (&((const OvsdbMethodPayload){ \ - .set_external_ids = \ - { \ - .device_type = xdevice_type, \ - .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ - .connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \ - .exid_old = (xexid_old), \ - .exid_new = (xexid_new), \ - }, \ +#define OVSDB_METHOD_PAYLOAD_SET_REAPPLY(xdevice_type, \ + xifname, \ + xconnection_uuid, \ + xexternal_ids_old, \ + xexternal_ids_new, \ + xother_config_old, \ + xother_config_new) \ + (&((const OvsdbMethodPayload){ \ + .set_reapply = \ + { \ + .device_type = xdevice_type, \ + .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ + .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), \ + }, \ })) /*****************************************************************************/ @@ -291,11 +308,13 @@ _call_complete(OvsdbMethodCall *call, json_t *response, GError *error) case OVSDB_SET_INTERFACE_MTU: nm_clear_g_free(&call->payload.set_interface_mtu.ifname); break; - case OVSDB_SET_EXTERNAL_IDS: - nm_clear_g_free(&call->payload.set_external_ids.ifname); - nm_clear_g_free(&call->payload.set_external_ids.connection_uuid); - nm_clear_pointer(&call->payload.set_external_ids.exid_old, g_hash_table_destroy); - nm_clear_pointer(&call->payload.set_external_ids.exid_new, g_hash_table_destroy); + case OVSDB_SET_REAPPLY: + nm_clear_g_free(&call->payload.set_reapply.ifname); + 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; } @@ -312,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); } @@ -323,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); } @@ -334,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); } @@ -447,19 +469,22 @@ ovsdb_call_method(NMOvsdb *self, call->payload.set_interface_mtu.ifname, call->payload.set_interface_mtu.mtu); break; - case OVSDB_SET_EXTERNAL_IDS: - call->payload.set_external_ids.device_type = payload->set_external_ids.device_type; - call->payload.set_external_ids.ifname = g_strdup(payload->set_external_ids.ifname); - call->payload.set_external_ids.connection_uuid = - g_strdup(payload->set_external_ids.connection_uuid); - call->payload.set_external_ids.exid_old = - nm_g_hash_table_ref(payload->set_external_ids.exid_old); - call->payload.set_external_ids.exid_new = - nm_g_hash_table_ref(payload->set_external_ids.exid_new); + case OVSDB_SET_REAPPLY: + call->payload.set_reapply.device_type = payload->set_reapply.device_type; + call->payload.set_reapply.ifname = g_strdup(payload->set_reapply.ifname); + call->payload.set_reapply.connection_uuid = g_strdup(payload->set_reapply.connection_uuid); + call->payload.set_reapply.external_ids_old = + 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", - call->payload.set_external_ids.connection_uuid, - call->payload.set_external_ids.ifname); + "new: set external-ids/other-config con-uuid=%s, interface=%s", + call->payload.set_reapply.connection_uuid, + call->payload.set_reapply.ifname); break; } @@ -592,21 +617,30 @@ _set_bridge_ports(json_t *params, const char *ifname, json_t *new_ports) static void _set_bridge_mac(json_t *params, const char *ifname, const char *mac) { - json_array_append_new(params, - json_pack("{s:s, s:s, s:{s:[s, [[s, s]]]}, s:[[s, s, s]]}", - "op", - "update", - "table", - "Bridge", - "row", - "other_config", - "map", - "hwaddr", - mac, - "where", - "name", - "==", - ifname)); + json_array_append_new( + params, + json_pack("{s:s, s:s, s:[[s, s, [s, [s]]], [s, s, [s, [[s, s]]]]], s:[[s, s, s]]}", + "op", + "mutate", + "table", + "Bridge", + "mutations", + + "other_config", + "delete", + "set", + OTHER_CONFIG_HWADDR, + + "other_config", + "insert", + "map", + OTHER_CONFIG_HWADDR, + mac, + + "where", + "name", + "==", + ifname)); } /** @@ -668,91 +702,155 @@ _set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces) } static json_t * -_j_create_external_ids_array_new(NMConnection *connection) +_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 *external_ids = NULL; - guint n_external_ids = 0; + const char *const *strv = NULL; + guint n_strv = 0; guint i; const char *uuid; - NMSettingOvsExternalIDs *s_exid; nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS, STRDICT_TYPE_OTHER_CONFIG)); array = json_array(); - uuid = nm_connection_get_uuid(connection); - nm_assert(uuid); - json_array_append_new(array, json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, uuid)); + if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) { + uuid = nm_connection_get_uuid(connection); + 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)); + } + } - s_exid = _nm_connection_get_setting(connection, NM_TYPE_SETTING_OVS_EXTERNAL_IDS); - if (s_exid) - external_ids = nm_setting_ovs_external_ids_get_data_keys(s_exid, &n_external_ids); - for (i = 0; i < n_external_ids; i++) { - const char *k = external_ids[i]; + if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) { + s_external_ids = _nm_connection_get_setting(connection, NM_TYPE_SETTING_OVS_EXTERNAL_IDS); + if (s_external_ids) + strv = nm_setting_ovs_external_ids_get_data_keys(s_external_ids, &n_strv); + } else { + 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_exid, 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); } -static json_t * -_j_create_external_ids_array_update(const char *connection_uuid, - GHashTable *exid_old, - GHashTable *exid_new) +static void +_j_create_strv_array_update(json_t *mutations, + StrdictType strdict_type, + const char *connection_uuid, + GHashTable *hash_old, + GHashTable *hash_new) { GHashTableIter iter; - json_t *mutations; json_t *array; const char *key; const char *val; - nm_assert(connection_uuid); + /* 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. */ - mutations = json_array(); + nm_assert((!!connection_uuid) == (strdict_type == STRDICT_TYPE_EXTERNAL_IDS)); + nm_assert(NM_IN_SET(strdict_type, STRDICT_TYPE_EXTERNAL_IDS, STRDICT_TYPE_OTHER_CONFIG)); - if (exid_old) { - array = NULL; - g_hash_table_iter_init(&iter, exid_old); + array = NULL; + if (hash_old) { + g_hash_table_iter_init(&iter, hash_old); while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { - if (nm_g_hash_table_contains(exid_new, key)) + if (strdict_type == STRDICT_TYPE_OTHER_CONFIG && nm_streq(key, OTHER_CONFIG_HWADDR)) continue; - if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) + if (!array) + array = json_array(); + json_array_append_new(array, json_string(key)); + } + } + 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) array = json_array(); - json_array_append_new(array, json_string(key)); } - if (array) { - json_array_append_new( - mutations, - json_pack("[s, s, [s, o]]", "external_ids", "delete", "set", array)); + } + if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) { + if (!nm_g_hash_table_contains(hash_old, NM_OVS_EXTERNAL_ID_NM_PREFIX) + && !nm_g_hash_table_contains(hash_new, NM_OVS_EXTERNAL_ID_NM_PREFIX)) { + if (!array) + array = json_array(); + json_array_append_new(array, json_string(NM_OVS_EXTERNAL_ID_NM_PREFIX)); } } + if (array) { + json_array_append_new( + mutations, + json_pack("[s, s, [s, o]]", + strdict_type == STRDICT_TYPE_EXTERNAL_IDS ? "external_ids" : "other_config", + "delete", + "set", + array)); + } array = json_array(); - json_array_append_new( - array, - json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, connection_uuid)); - - if (exid_new) { - g_hash_table_iter_init(&iter, exid_new); + if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) { + json_array_append_new( + array, + json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, connection_uuid)); + } + if (hash_new) { + g_hash_table_iter_init(&iter, hash_new); while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { - if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) + if (strdict_type == STRDICT_TYPE_EXTERNAL_IDS) { + 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)); } } - json_array_append_new(mutations, - json_pack("[s, s, [s, o]]", "external_ids", "insert", "map", array)); - return mutations; + json_array_append_new( + mutations, + json_pack("[s, s, [s, o]]", + strdict_type == STRDICT_TYPE_EXTERNAL_IDS ? "external_ids" : "other_config", + "insert", + "map", + array)); } /** @@ -824,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", @@ -832,7 +930,9 @@ _insert_interface(json_t *params, "options", options, "external_ids", - _j_create_external_ids_array_new(interface)); + _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)); @@ -917,7 +1017,12 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces) json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port))); json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces)); - json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(port)); + json_object_set_new(row, + "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, @@ -977,13 +1082,12 @@ _insert_bridge(json_t *params, json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge))); json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports)); - json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(bridge)); - - if (cloned_mac) { - json_object_set_new(row, - "other_config", - json_pack("[s, [[s, s]]]", "map", "hwaddr", cloned_mac)); - } + json_object_set_new(row, + "external_ids", + _j_create_strdict_new(bridge, STRDICT_TYPE_EXTERNAL_IDS, NULL)); + json_object_set_new(row, + "other_config", + _j_create_strdict_new(bridge, STRDICT_TYPE_OTHER_CONFIG, cloned_mac)); /* Create a new one. */ json_array_append_new(params, @@ -1345,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", @@ -1361,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"); @@ -1411,24 +1518,38 @@ ovsdb_next_command(NMOvsdb *self) "==", call->payload.set_interface_mtu.ifname)); break; - case OVSDB_SET_EXTERNAL_IDS: + case OVSDB_SET_REAPPLY: + { + json_t *mutations; + + mutations = json_array(); + + _j_create_strv_array_update(mutations, + STRDICT_TYPE_EXTERNAL_IDS, + 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, json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}", "op", "mutate", "table", - _device_type_to_table(call->payload.set_external_ids.device_type), + _device_type_to_table(call->payload.set_reapply.device_type), "mutations", - _j_create_external_ids_array_update( - call->payload.set_external_ids.connection_uuid, - call->payload.set_external_ids.exid_old, - call->payload.set_external_ids.exid_new), + mutations, "where", "name", "==", - call->payload.set_external_ids.ifname)); + call->payload.set_reapply.ifname)); break; + } default: nm_assert_not_reached(); @@ -1513,19 +1634,18 @@ _uuids_to_array(const json_t *items) } static void -_external_ids_extract(json_t *external_ids, GArray **out_array, const char **out_connection_uuid) +_strdict_extract(json_t *strdict, GArray **out_array) { json_t *array; json_t *value; gsize index; nm_assert(out_array && !*out_array); - nm_assert(!out_connection_uuid || !*out_connection_uuid); - if (!nm_streq0("map", json_string_value(json_array_get(external_ids, 0)))) + if (!nm_streq0("map", json_string_value(json_array_get(strdict, 0)))) return; - array = json_array_get(external_ids, 1); + array = json_array_get(strdict, 1); json_array_foreach (array, index, value) { const char *key = json_string_value(json_array_get(value, 0)); @@ -1546,16 +1666,26 @@ _external_ids_extract(json_t *external_ids, GArray **out_array, const char **out .name = g_strdup(key), .value_str = g_strdup(val), }; - - if (out_connection_uuid && nm_streq(v->name, NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID)) { - *out_connection_uuid = v->value_str; - out_connection_uuid = NULL; - } } } +static const char * +_strdict_find_key(GArray *array, const char *key) +{ + gssize idx; + + idx = nm_utils_named_value_list_find(nm_g_array_first_p(array, NMUtilsNamedValue), + nm_g_array_len(array), + key, + FALSE); + if (idx < 0) + return NULL; + + return nm_g_array_index(array, NMUtilsNamedValue, idx).value_str; +} + static gboolean -_external_ids_equal(const GArray *arr1, const GArray *arr2) +_strdict_equals(const GArray *arr1, const GArray *arr2) { guint n; guint i; @@ -1568,16 +1698,16 @@ _external_ids_equal(const GArray *arr1, const GArray *arr2) const NMUtilsNamedValue *n1 = &nm_g_array_index(arr1, NMUtilsNamedValue, i); const NMUtilsNamedValue *n2 = &nm_g_array_index(arr2, NMUtilsNamedValue, i); - if (!nm_streq0(n1->name, n2->name)) + if (!nm_streq(n1->name, n2->name)) return FALSE; - if (!nm_streq0(n1->value_str, n2->value_str)) + if (!nm_streq(n1->value_str, n2->value_str)) return FALSE; } return TRUE; } static char * -_external_ids_to_string(const GArray *arr) +_strdict_to_string(const GArray *arr) { NMStrBuf strbuf; guint i; @@ -1592,9 +1722,9 @@ _external_ids_to_string(const GArray *arr) if (i > 0) nm_str_buf_append_c(&strbuf, ','); - nm_str_buf_append_printf(&strbuf, " \"%s\" = \"%s\"]", n->name, n->value_str); + nm_str_buf_append_printf(&strbuf, " \"%s\" = \"%s\" ", n->name, n->value_str); } - nm_str_buf_append(&strbuf, " ]"); + nm_str_buf_append(&strbuf, "]"); return nm_str_buf_finalize(&strbuf, NULL); } @@ -1618,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, }; @@ -1657,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, @@ -1671,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; @@ -1714,7 +1848,10 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_clear_pointer(&ovs_interface, _free_interface); } - _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + _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; @@ -1723,14 +1860,20 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) changed |= nm_strdup_reset(&ovs_interface->type, type); changed |= nm_strdup_reset(&ovs_interface->connection_uuid, connection_uuid); - if (!_external_ids_equal(ovs_interface->external_ids, external_ids_arr)) { + if (!_strdict_equals(ovs_interface->external_ids, external_ids_arr)) { 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 *strtmp = NULL; + 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, @@ -1738,10 +1881,12 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) ", ", ovs_interface->connection_uuid, ""), - (strtmp = _external_ids_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 *strtmp = NULL; + gs_free char *strtmp1 = NULL; + gs_free char *strtmp2 = NULL; ovs_interface = g_slice_new(OpenvswitchInterface); *ovs_interface = (OpenvswitchInterface){ @@ -1750,17 +1895,20 @@ 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", - key, - ovs_interface->type, - ovs_interface->name, - NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid, - ", ", - ovs_interface->connection_uuid, - ""), - (strtmp = _external_ids_to_string(ovs_interface->external_ids))); + _LOGT( + "obj[iface:%s]: added an '%s' interface: %s%s%s, external-ids=%s, other-config=%s", + key, + ovs_interface->type, + ovs_interface->name, + NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid, + ", ", + ovs_interface->connection_uuid, + ""), + (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, @@ -1781,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) { @@ -1824,7 +1975,11 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_clear_pointer(&ovs_port, _free_port); } - _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + _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); if (ovs_port) { @@ -1838,24 +1993,31 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) NM_SWAP(&ovs_port->interfaces, &interfaces); changed = TRUE; } - if (!_external_ids_equal(ovs_port->external_ids, external_ids_arr)) { + if (!_strdict_equals(ovs_port->external_ids, external_ids_arr)) { 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 *strtmp = NULL; + 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, ""), - (strtmp = _external_ids_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 *strtmp = NULL; + gs_free char *strtmp1 = NULL; + gs_free char *strtmp2 = NULL; ovs_port = g_slice_new(OpenvswitchPort); *ovs_port = (OpenvswitchPort){ @@ -1864,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, ""), - (strtmp = _external_ids_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); } } @@ -1882,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); @@ -1929,7 +2096,11 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_clear_pointer(&ovs_bridge, _free_bridge); } - _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + _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); if (ovs_bridge) { @@ -1943,24 +2114,31 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) NM_SWAP(&ovs_bridge->ports, &ports); changed = TRUE; } - if (!_external_ids_equal(ovs_bridge->external_ids, external_ids_arr)) { + if (!_strdict_equals(ovs_bridge->external_ids, external_ids_arr)) { 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 *strtmp = NULL; + 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, ""), - (strtmp = _external_ids_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 *strtmp = NULL; + gs_free char *strtmp1 = NULL; + gs_free char *strtmp2 = NULL; ovs_bridge = g_slice_new(OpenvswitchBridge); *ovs_bridge = (OpenvswitchBridge){ @@ -1969,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, ""), - (strtmp = _external_ids_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); } } @@ -2716,31 +2896,50 @@ nm_ovsdb_set_interface_mtu(NMOvsdb *self, } void -nm_ovsdb_set_external_ids(NMOvsdb *self, - NMDeviceType device_type, - const char *ifname, - const char *connection_uuid, - NMSettingOvsExternalIDs *s_exid_old, - NMSettingOvsExternalIDs *s_exid_new) +nm_ovsdb_set_reapply(NMOvsdb *self, + NMDeviceType device_type, + const char *ifname, + const char *connection_uuid, + NMSettingOvsExternalIDs *s_external_ids_old, + NMSettingOvsExternalIDs *s_external_ids_new, + NMSettingOvsOtherConfig *s_other_config_old, + NMSettingOvsOtherConfig *s_other_config_new) { - gs_unref_hashtable GHashTable *exid_old = NULL; - gs_unref_hashtable GHashTable *exid_new = NULL; - - exid_old = - s_exid_old ? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_old)) : NULL; - exid_new = - s_exid_new ? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_new)) : NULL; + 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 + ? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_external_ids_old)) + : NULL; + external_ids_new = + s_external_ids_new + ? 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, FALSE, - OVSDB_SET_EXTERNAL_IDS, - OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(device_type, - ifname, - connection_uuid, - exid_old, - exid_new)); + OVSDB_SET_REAPPLY, + OVSDB_METHOD_PAYLOAD_SET_REAPPLY(device_type, + ifname, + connection_uuid, + external_ids_old, + external_ids_new, + other_config_old, + other_config_new)); } /*****************************************************************************/ |