Commit d1dfeb4a authored by Beniamino Galvani's avatar Beniamino Galvani
Browse files

ovs: allow changing mac address of bridges and interfaces

Allow changing the cloned MAC address for OVS bridges and
interfaces. The MAC address set on the bridge is propagated by ovs to
the local interface (the one with the same name as the bridge), while
all other internal interfaces use the address defined in the interface
connection.

https://bugzilla.redhat.com/show_bug.cgi?id=1763734
https://bugzilla.redhat.com/show_bug.cgi?id=1740557

!321
(cherry picked from commit 101e65d2)
(cherry picked from commit b366234a)
(cherry picked from commit 5a4a5f63)
(cherry picked from commit 46bb51d3)
parent 0301b55a
Pipeline #97464 passed with stage
in 9 minutes and 52 seconds
......@@ -8136,6 +8136,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
NM_META_SETTING_VALID_PART_ITEM (OVS_BRIDGE, TRUE),
NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE),
),
),
SETTING_INFO (OVS_INTERFACE,
......
......@@ -108,6 +108,7 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboo
{
NMActiveConnection *ac_port = NULL;
NMActiveConnection *ac_bridge = NULL;
NMDevice *bridge_device;
if (!configure)
return TRUE;
......@@ -117,10 +118,14 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboo
if (!ac_bridge)
ac_bridge = ac_port;
bridge_device = nm_active_connection_get_device (ac_bridge);
nm_ovsdb_add_interface (nm_ovsdb_get (),
nm_active_connection_get_applied_connection (ac_bridge),
nm_device_get_applied_connection (device),
nm_device_get_applied_connection (slave),
bridge_device,
slave,
add_iface_cb, g_object_ref (slave));
return TRUE;
......
......@@ -29,6 +29,7 @@
#include "devices/nm-device.h"
#include "platform/nm-platform.h"
#include "nm-core-internal.h"
#include "devices/nm-device.h"
/*****************************************************************************/
......@@ -132,6 +133,8 @@ typedef struct {
NMConnection *bridge;
NMConnection *port;
NMConnection *interface;
NMDevice *bridge_device;
NMDevice *interface_device;
};
};
} OvsdbMethodCall;
......@@ -184,6 +187,7 @@ static void
ovsdb_call_method (NMOvsdb *self, OvsdbCommand command,
const char *ifname,
NMConnection *bridge, NMConnection *port, NMConnection *interface,
NMDevice *bridge_device, NMDevice *interface_device,
OvsdbMethodCallback callback, gpointer user_data)
{
NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self);
......@@ -206,6 +210,8 @@ ovsdb_call_method (NMOvsdb *self, OvsdbCommand command,
call->bridge = nm_simple_connection_new_clone (bridge);
call->port = nm_simple_connection_new_clone (port);
call->interface = nm_simple_connection_new_clone (interface);
call->bridge_device = g_object_ref (bridge_device);
call->interface_device = g_object_ref (interface_device);
break;
case OVSDB_DEL_INTERFACE:
call->ifname = g_strdup (ifname);
......@@ -338,17 +344,32 @@ _set_port_interfaces (json_t *params, const char *ifname, json_t *new_interfaces
* Returns an commands that adds new interface from a given connection.
*/
static void
_insert_interface (json_t *params, NMConnection *interface)
_insert_interface (json_t *params, NMConnection *interface, NMDevice *interface_device)
{
const char *type = NULL;
NMSettingOvsInterface *s_ovs_iface;
NMSettingOvsPatch *s_ovs_patch;
json_t *options = json_array ();
gs_free char *cloned_mac = NULL;
gs_free_error GError *error = NULL;
json_t *row;
s_ovs_iface = nm_connection_get_setting_ovs_interface (interface);
if (s_ovs_iface)
type = nm_setting_ovs_interface_get_interface_type (s_ovs_iface);
if (!nm_device_hw_addr_get_cloned (interface_device,
interface,
FALSE,
&cloned_mac,
NULL,
&error)) {
_LOGW ("Cannot determine cloned mac for OVS %s '%s': %s",
"interface",
nm_connection_get_interface_name (interface),
error->message);
}
json_array_append_new (options, json_string ("map"));
s_ovs_patch = nm_connection_get_setting_ovs_patch (interface);
if (s_ovs_patch) {
......@@ -359,14 +380,22 @@ _insert_interface (json_t *params, NMConnection *interface)
json_array_append_new (options, json_array ());
}
row = json_pack ("{s:s, s:s, s:o, s:[s, [[s, s]]]}",
"name", nm_connection_get_interface_name (interface),
"type", type ?: "",
"options", options,
"external_ids", "map",
"NM.connection.uuid", nm_connection_get_uuid (interface));
if (cloned_mac)
json_object_set_new (row, "mac", json_string (cloned_mac));
json_array_append_new (params,
json_pack ("{s:s, s:s, s:{s:s, s:s, s:o, s:[s, [[s, s]]]}, s:s}",
"op", "insert", "table", "Interface", "row",
"name", nm_connection_get_interface_name (interface),
"type", type ?: "",
"options", options,
"external_ids", "map", "NM.connection.uuid", nm_connection_get_uuid (interface),
"uuid-name", "rowInterface"));
json_pack ("{s:s, s:s, s:o, s:s}",
"op", "insert",
"table", "Interface",
"row", row,
"uuid-name", "rowInterface"));
}
/**
......@@ -430,7 +459,7 @@ _insert_port (json_t *params, NMConnection *port, json_t *new_interfaces)
* Returns an commands that adds new bridge from a given connection.
*/
static void
_insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports)
_insert_bridge (json_t *params, NMConnection *bridge, NMDevice *bridge_device, json_t *new_ports)
{
NMSettingOvsBridge *s_ovs_bridge;
const char *fail_mode = NULL;
......@@ -438,9 +467,23 @@ _insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports)
gboolean rstp_enable = FALSE;
gboolean stp_enable = FALSE;
json_t *row;
gs_free_error GError *error = NULL;
gs_free char *cloned_mac = NULL;
s_ovs_bridge = nm_connection_get_setting_ovs_bridge (bridge);
if (!nm_device_hw_addr_get_cloned (bridge_device,
bridge,
FALSE,
&cloned_mac,
NULL,
&error)) {
_LOGW ("Cannot determine cloned mac for OVS %s '%s': %s",
"bridge",
nm_connection_get_interface_name (bridge),
error->message);
}
row = json_object ();
if (s_ovs_bridge) {
......@@ -465,6 +508,12 @@ _insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports)
json_pack ("[s, [[s, s]]]", "map",
"NM.connection.uuid", nm_connection_get_uuid (bridge)));
if (cloned_mac) {
json_object_set_new (row, "other_config",
json_pack ("[s, [[s, s]]]", "map",
"hwaddr", cloned_mac));
}
/* Create a new one. */
json_array_append_new (params,
json_pack ("{s:s, s:s, s:o, s:s}", "op", "insert", "table", "Bridge",
......@@ -494,7 +543,8 @@ _inc_next_cfg (const char *db_uuid)
*/
static void
_add_interface (NMOvsdb *self, json_t *params,
NMConnection *bridge, NMConnection *port, NMConnection *interface)
NMConnection *bridge, NMConnection *port, NMConnection *interface,
NMDevice *bridge_device, NMDevice *interface_device)
{
NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self);
GHashTableIter iter;
......@@ -567,7 +617,7 @@ _add_interface (NMOvsdb *self, json_t *params,
_expect_ovs_bridges (params, priv->db_uuid, bridges);
json_array_append_new (new_bridges, json_pack ("[s, s]", "named-uuid", "rowBridge"));
_set_ovs_bridges (params, priv->db_uuid, new_bridges);
_insert_bridge (params, bridge, new_ports);
_insert_bridge (params, bridge, bridge_device, new_ports);
} else {
/* Bridge already exists. */
g_return_if_fail (ovs_bridge);
......@@ -585,7 +635,7 @@ _add_interface (NMOvsdb *self, json_t *params,
}
if (!has_interface) {
_insert_interface (params, interface);
_insert_interface (params, interface, interface_device);
json_array_append_new (new_interfaces, json_pack ("[s, s]", "named-uuid", "rowInterface"));
}
}
......@@ -734,7 +784,8 @@ ovsdb_next_command (NMOvsdb *self)
json_array_append_new (params, json_string ("Open_vSwitch"));
json_array_append_new (params, _inc_next_cfg (priv->db_uuid));
_add_interface (self, params, call->bridge, call->port, call->interface);
_add_interface (self, params, call->bridge, call->port, call->interface,
call->bridge_device, call->interface_device);
msg = json_pack ("{s:i, s:s, s:o}",
"id", call->id,
......@@ -1386,7 +1437,7 @@ ovsdb_try_connect (NMOvsdb *self)
/* Queue a monitor call before any other command, ensuring that we have an up
* to date view of existing bridged that we need for add and remove ops. */
ovsdb_call_method (self, OVSDB_MONITOR, NULL,
NULL, NULL, NULL, _monitor_bridges_cb, NULL);
NULL, NULL, NULL, NULL, NULL, _monitor_bridges_cb, NULL);
}
/*****************************************************************************/
......@@ -1427,6 +1478,7 @@ out:
void
nm_ovsdb_add_interface (NMOvsdb *self,
NMConnection *bridge, NMConnection *port, NMConnection *interface,
NMDevice *bridge_device, NMDevice *interface_device,
NMOvsdbCallback callback, gpointer user_data)
{
OvsdbCall *call;
......@@ -1436,7 +1488,9 @@ nm_ovsdb_add_interface (NMOvsdb *self,
call->user_data = user_data;
ovsdb_call_method (self, OVSDB_ADD_INTERFACE, NULL,
bridge, port, interface, _transact_cb, call);
bridge, port, interface,
bridge_device, interface_device,
_transact_cb, call);
}
void
......@@ -1450,7 +1504,7 @@ nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname,
call->user_data = user_data;
ovsdb_call_method (self, OVSDB_DEL_INTERFACE, ifname,
NULL, NULL, NULL, _transact_cb, call);
NULL, NULL, NULL, NULL, NULL, _transact_cb, call);
}
/*****************************************************************************/
......@@ -1467,6 +1521,8 @@ _clear_call (gpointer data)
g_clear_object (&call->bridge);
g_clear_object (&call->port);
g_clear_object (&call->interface);
g_clear_object (&call->bridge_device);
g_clear_object (&call->interface_device);
break;
case OVSDB_DEL_INTERFACE:
g_clear_pointer (&call->ifname, g_free);
......
......@@ -42,6 +42,7 @@ GType nm_ovsdb_get_type (void);
void nm_ovsdb_add_interface (NMOvsdb *self,
NMConnection *bridge, NMConnection *port, NMConnection *interface,
NMDevice *bridge_device, NMDevice *interface_device,
NMOvsdbCallback callback, gpointer user_data);
void nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment