diff options
Diffstat (limited to 'src/devices/ovs')
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-bridge.c | 122 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-bridge.h | 22 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-interface.c | 536 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-interface.h | 23 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-port.c | 244 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-port.h | 22 | ||||
| -rw-r--r-- | src/devices/ovs/nm-ovs-factory.c | 377 | ||||
| -rw-r--r-- | src/devices/ovs/nm-ovsdb.c | 3040 | ||||
| -rw-r--r-- | src/devices/ovs/nm-ovsdb.h | 53 |
9 files changed, 2378 insertions, 2061 deletions
diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/devices/ovs/nm-device-ovs-bridge.c index 59096803..a7b7a539 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.c +++ b/src/devices/ovs/nm-device-ovs-bridge.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -15,117 +15,111 @@ #include "nm-setting-ovs-bridge.h" #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF (NMDeviceOvsBridge); +_LOG_DECLARE_SELF(NMDeviceOvsBridge); /*****************************************************************************/ struct _NMDeviceOvsBridge { - NMDevice parent; + NMDevice parent; }; struct _NMDeviceOvsBridgeClass { - NMDeviceClass parent; + NMDeviceClass parent; }; -G_DEFINE_TYPE (NMDeviceOvsBridge, nm_device_ovs_bridge, NM_TYPE_DEVICE) +G_DEFINE_TYPE(NMDeviceOvsBridge, nm_device_ovs_bridge, NM_TYPE_DEVICE) /*****************************************************************************/ static const char * -get_type_description (NMDevice *device) +get_type_description(NMDevice *device) { - return "ovs-bridge"; + return "ovs-bridge"; } static gboolean -create_and_realize (NMDevice *device, - NMConnection *connection, - NMDevice *parent, - const NMPlatformLink **out_plink, - GError **error) +create_and_realize(NMDevice * device, + NMConnection * connection, + NMDevice * parent, + const NMPlatformLink **out_plink, + GError ** error) { - /* The actual backing resources will be created on enslavement by the port - * when it can identify the port and the bridge. */ + /* The actual backing resources will be created on enslavement by the port + * when it can identify the port and the bridge. */ - return TRUE; + return TRUE; } static gboolean -unrealize (NMDevice *device, GError **error) +unrealize(NMDevice *device, GError **error) { - return TRUE; + return TRUE; } static NMDeviceCapabilities -get_generic_capabilities (NMDevice *device) +get_generic_capabilities(NMDevice *device) { - return NM_DEVICE_CAP_IS_SOFTWARE; + return NM_DEVICE_CAP_IS_SOFTWARE; } static NMActStageReturn -act_stage3_ip_config_start (NMDevice *device, - int addr_family, - gpointer *out_config, - NMDeviceStateReason *out_failure_reason) +act_stage3_ip_config_start(NMDevice * device, + int addr_family, + gpointer * out_config, + NMDeviceStateReason *out_failure_reason) { - return NM_ACT_STAGE_RETURN_IP_FAIL; + return NM_ACT_STAGE_RETURN_IP_FAIL; } static gboolean -enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - if (!configure) - return TRUE; + if (!configure) + return TRUE; - if (!NM_IS_DEVICE_OVS_PORT (slave)) - return FALSE; + if (!NM_IS_DEVICE_OVS_PORT(slave)) + return FALSE; - return TRUE; + return TRUE; } static void -release_slave (NMDevice *device, NMDevice *slave, gboolean configure) -{ -} +release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +{} /*****************************************************************************/ static void -nm_device_ovs_bridge_init (NMDeviceOvsBridge *self) -{ -} +nm_device_ovs_bridge_init(NMDeviceOvsBridge *self) +{} static const NMDBusInterfaceInfoExtended interface_info_device_ovs_bridge = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Slaves", "ao", NM_DEVICE_SLAVES), - ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), + .legacy_property_changed = TRUE, }; static void -nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass) +nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_bridge); - - device_class->connection_type_supported = NM_SETTING_OVS_BRIDGE_SETTING_NAME; - device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME; - device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (); - - device_class->is_master = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->unrealize = unrealize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_bridge); + + device_class->connection_type_supported = NM_SETTING_OVS_BRIDGE_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); + + device_class->is_master = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->unrealize = unrealize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->enslave_slave = enslave_slave; + device_class->release_slave = release_slave; } diff --git a/src/devices/ovs/nm-device-ovs-bridge.h b/src/devices/ovs/nm-device-ovs-bridge.h index 07a1fee7..ba04bfeb 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.h +++ b/src/devices/ovs/nm-device-ovs-bridge.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -6,16 +6,20 @@ #ifndef __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ #define __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ -#define NM_TYPE_DEVICE_OVS_BRIDGE (nm_device_ovs_bridge_get_type ()) -#define NM_DEVICE_OVS_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridge)) -#define NM_DEVICE_OVS_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridgeClass)) -#define NM_IS_DEVICE_OVS_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OVS_BRIDGE)) -#define NM_IS_DEVICE_OVS_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OVS_BRIDGE)) -#define NM_DEVICE_OVS_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridgeClass)) +#define NM_TYPE_DEVICE_OVS_BRIDGE (nm_device_ovs_bridge_get_type()) +#define NM_DEVICE_OVS_BRIDGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridge)) +#define NM_DEVICE_OVS_BRIDGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridgeClass)) +#define NM_IS_DEVICE_OVS_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_OVS_BRIDGE)) +#define NM_IS_DEVICE_OVS_BRIDGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_OVS_BRIDGE)) +#define NM_DEVICE_OVS_BRIDGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_OVS_BRIDGE, NMDeviceOvsBridgeClass)) -typedef struct _NMDeviceOvsBridge NMDeviceOvsBridge; +typedef struct _NMDeviceOvsBridge NMDeviceOvsBridge; typedef struct _NMDeviceOvsBridgeClass NMDeviceOvsBridgeClass; -GType nm_device_ovs_bridge_get_type (void); +GType nm_device_ovs_bridge_get_type(void); #endif /* __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ */ diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index 83954cf0..16b6e04d 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -20,389 +20,379 @@ _LOG_DECLARE_SELF(NMDeviceOvsInterface); /*****************************************************************************/ typedef struct { - bool waiting_for_interface:1; + bool waiting_for_interface : 1; } NMDeviceOvsInterfacePrivate; struct _NMDeviceOvsInterface { - NMDevice parent; - NMDeviceOvsInterfacePrivate _priv; + NMDevice parent; + NMDeviceOvsInterfacePrivate _priv; }; struct _NMDeviceOvsInterfaceClass { - NMDeviceClass parent; + NMDeviceClass parent; }; -G_DEFINE_TYPE (NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE) +G_DEFINE_TYPE(NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE) -#define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceOvsInterface, NM_IS_DEVICE_OVS_INTERFACE, NMDevice) +#define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDeviceOvsInterface, NM_IS_DEVICE_OVS_INTERFACE, NMDevice) /*****************************************************************************/ static const char * -get_type_description (NMDevice *device) +get_type_description(NMDevice *device) { - return "ovs-interface"; + return "ovs-interface"; } static gboolean -create_and_realize (NMDevice *device, - NMConnection *connection, - NMDevice *parent, - const NMPlatformLink **out_plink, - GError **error) +create_and_realize(NMDevice * device, + NMConnection * connection, + NMDevice * parent, + const NMPlatformLink **out_plink, + GError ** error) { - /* The actual backing resources will be created once an interface is - * added to a port of ours, since there can be neither an empty port nor - * an empty bridge. */ + /* The actual backing resources will be created once an interface is + * added to a port of ours, since there can be neither an empty port nor + * an empty bridge. */ - return TRUE; + return TRUE; } static NMDeviceCapabilities -get_generic_capabilities (NMDevice *device) +get_generic_capabilities(NMDevice *device) { - return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; + return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; } static gboolean -is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - return TRUE; + return TRUE; } static gboolean -check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMSettingOvsInterface *s_ovs_iface; + NMSettingOvsInterface *s_ovs_iface; - if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection, error)) - return FALSE; + if (!NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class) + ->check_connection_compatible(device, connection, error)) + return FALSE; - s_ovs_iface = nm_connection_get_setting_ovs_interface (connection); + s_ovs_iface = nm_connection_get_setting_ovs_interface(connection); - if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface), - "dpdk", - "internal", - "patch")) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "unsupported OVS interface type in profile"); - return FALSE; - } + if (!NM_IN_STRSET(nm_setting_ovs_interface_get_interface_type(s_ovs_iface), + "dpdk", + "internal", + "patch")) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "unsupported OVS interface type in profile"); + return FALSE; + } - return TRUE; + return TRUE; } static void -link_changed (NMDevice *device, - const NMPlatformLink *pllink) +link_changed(NMDevice *device, const NMPlatformLink *pllink) { - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); - - if (!pllink || !priv->waiting_for_interface) - return; - - priv->waiting_for_interface = FALSE; - - if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { - if (!nm_device_hw_addr_set_cloned (device, - nm_device_get_applied_connection (device), - FALSE)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); - return; - } - nm_device_bring_up (device, TRUE, NULL); - nm_device_activate_schedule_stage3_ip_config_start (device); - } + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device); + + if (!pllink || !priv->waiting_for_interface) + return; + + priv->waiting_for_interface = FALSE; + + if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) { + if (!nm_device_hw_addr_set_cloned(device, + nm_device_get_applied_connection(device), + FALSE)) { + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + nm_device_bring_up(device, TRUE, NULL); + nm_device_activate_schedule_stage3_ip_config_start(device); + } } static gboolean -_is_internal_interface (NMDevice *device) +_is_internal_interface(NMDevice *device) { - NMSettingOvsInterface *s_ovs_iface; + NMSettingOvsInterface *s_ovs_iface; - s_ovs_iface = nm_device_get_applied_setting (device, NM_TYPE_SETTING_OVS_INTERFACE); + s_ovs_iface = nm_device_get_applied_setting(device, NM_TYPE_SETTING_OVS_INTERFACE); - g_return_val_if_fail (s_ovs_iface, FALSE); + g_return_val_if_fail(s_ovs_iface, FALSE); - return nm_streq (nm_setting_ovs_interface_get_interface_type (s_ovs_iface), "internal"); + return nm_streq(nm_setting_ovs_interface_get_interface_type(s_ovs_iface), "internal"); } static void -set_platform_mtu_cb (GError *error, gpointer user_data) +set_platform_mtu_cb(GError *error, gpointer user_data) { - NMDevice *device = user_data; - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); + NMDevice * device = user_data; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); - if ( error - && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { - _LOGW (LOGD_DEVICE, "could not change mtu of '%s': %s", - nm_device_get_iface (device), error->message); - } + if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + _LOGW(LOGD_DEVICE, + "could not change mtu of '%s': %s", + nm_device_get_iface(device), + error->message); + } - g_object_unref (device); + g_object_unref(device); } static gboolean -set_platform_mtu (NMDevice *device, guint32 mtu) +set_platform_mtu(NMDevice *device, guint32 mtu) { - /* - * If the MTU is not set in ovsdb, Open vSwitch will change - * the MTU of an internal interface to match the minimum of - * the other interfaces in the bridge. - */ - /* FIXME(shutdown): the function should become cancellable so - * that it doesn't need to hold a reference to the device, and - * it can be stopped during shutdown. - */ - if (_is_internal_interface (device)) { - nm_ovsdb_set_interface_mtu (nm_ovsdb_get (), - nm_device_get_ip_iface (device), - mtu, set_platform_mtu_cb, - g_object_ref (device)); - } - - return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->set_platform_mtu (device, mtu); + /* + * If the MTU is not set in ovsdb, Open vSwitch will change + * the MTU of an internal interface to match the minimum of + * the other interfaces in the bridge. + */ + /* FIXME(shutdown): the function should become cancellable so + * that it doesn't need to hold a reference to the device, and + * it can be stopped during shutdown. + */ + if (_is_internal_interface(device)) { + nm_ovsdb_set_interface_mtu(nm_ovsdb_get(), + nm_device_get_ip_iface(device), + mtu, + set_platform_mtu_cb, + g_object_ref(device)); + } + + return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)->set_platform_mtu(device, mtu); } static NMActStageReturn -act_stage3_ip_config_start (NMDevice *device, - int addr_family, - gpointer *out_config, - NMDeviceStateReason *out_failure_reason) +act_stage3_ip_config_start(NMDevice * device, + int addr_family, + gpointer * out_config, + NMDeviceStateReason *out_failure_reason) { - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); - - if (!_is_internal_interface (device)) - return NM_ACT_STAGE_RETURN_IP_FAIL; - - if (nm_device_get_ip_ifindex (device) <= 0) { - _LOGT (LOGD_DEVICE, "waiting for link to appear"); - priv->waiting_for_interface = TRUE; - return NM_ACT_STAGE_RETURN_POSTPONE; - } - - if (!nm_device_hw_addr_set_cloned (device, - nm_device_get_applied_connection (device), - FALSE)) { - *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->act_stage3_ip_config_start (device, addr_family, out_config, out_failure_reason); + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device); + + if (!_is_internal_interface(device)) + return NM_ACT_STAGE_RETURN_IP_FAIL; + + if (nm_device_get_ip_ifindex(device) <= 0) { + _LOGT(LOGD_DEVICE, "waiting for link to appear"); + priv->waiting_for_interface = TRUE; + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) { + *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class) + ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); } static gboolean -can_unmanaged_external_down (NMDevice *self) +can_unmanaged_external_down(NMDevice *self) { - return FALSE; + return FALSE; } static void -deactivate (NMDevice *device) +deactivate(NMDevice *device) { - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (self); + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); - priv->waiting_for_interface = FALSE; + priv->waiting_for_interface = FALSE; } typedef struct { - NMDeviceOvsInterface *self; - GCancellable *cancellable; - NMDeviceDeactivateCallback callback; - gpointer callback_user_data; - gulong link_changed_id; - gulong cancelled_id; - guint link_timeout_id; + NMDeviceOvsInterface * self; + GCancellable * cancellable; + NMDeviceDeactivateCallback callback; + gpointer callback_user_data; + gulong link_changed_id; + gulong cancelled_id; + guint link_timeout_id; } DeactivateData; static void -deactivate_invoke_cb (DeactivateData *data, GError *error) +deactivate_invoke_cb(DeactivateData *data, GError *error) { - NMDeviceOvsInterface *self = data->self; - - _LOGT (LOGD_CORE, - "deactivate: async callback (%s)", - error ? error->message : "success"); - data->callback (NM_DEVICE (data->self), - error, - data->callback_user_data); - - nm_clear_g_signal_handler (nm_device_get_platform (NM_DEVICE (data->self)), - &data->link_changed_id); - nm_clear_g_signal_handler (data->cancellable, - &data->cancelled_id); - nm_clear_g_source (&data->link_timeout_id); - g_object_unref (data->self); - g_object_unref (data->cancellable); - nm_g_slice_free (data); + NMDeviceOvsInterface *self = data->self; + + _LOGT(LOGD_CORE, "deactivate: async callback (%s)", error ? error->message : "success"); + data->callback(NM_DEVICE(data->self), error, data->callback_user_data); + + nm_clear_g_signal_handler(nm_device_get_platform(NM_DEVICE(data->self)), + &data->link_changed_id); + nm_clear_g_signal_handler(data->cancellable, &data->cancelled_id); + nm_clear_g_source(&data->link_timeout_id); + g_object_unref(data->self); + g_object_unref(data->cancellable); + nm_g_slice_free(data); } static void -deactivate_link_changed_cb (NMPlatform *platform, - int obj_type_i, - int ifindex, - NMPlatformLink *info, - int change_type_i, - DeactivateData *data) +deactivate_link_changed_cb(NMPlatform * platform, + int obj_type_i, + int ifindex, + NMPlatformLink *info, + int change_type_i, + DeactivateData *data) { - NMDeviceOvsInterface *self = data->self; - const NMPlatformSignalChangeType change_type = change_type_i; - - if ( change_type == NM_PLATFORM_SIGNAL_REMOVED - && nm_streq0 (info->name, nm_device_get_iface (NM_DEVICE (self)))) { - _LOGT (LOGD_DEVICE, "deactivate: link removed, proceeding"); - nm_device_update_from_platform_link (NM_DEVICE (self), NULL); - deactivate_invoke_cb (data, NULL); - return; - } + NMDeviceOvsInterface * self = data->self; + const NMPlatformSignalChangeType change_type = change_type_i; + + if (change_type == NM_PLATFORM_SIGNAL_REMOVED + && nm_streq0(info->name, nm_device_get_iface(NM_DEVICE(self)))) { + _LOGT(LOGD_DEVICE, "deactivate: link removed, proceeding"); + nm_device_update_from_platform_link(NM_DEVICE(self), NULL); + deactivate_invoke_cb(data, NULL); + return; + } } static gboolean -deactivate_link_timeout (gpointer user_data) +deactivate_link_timeout(gpointer user_data) { - DeactivateData *data = user_data; - NMDeviceOvsInterface *self = data->self; + DeactivateData * data = user_data; + NMDeviceOvsInterface *self = data->self; - _LOGT (LOGD_DEVICE, "deactivate: timeout waiting link removal"); - deactivate_invoke_cb (data, NULL); - return G_SOURCE_REMOVE; + _LOGT(LOGD_DEVICE, "deactivate: timeout waiting link removal"); + deactivate_invoke_cb(data, NULL); + return G_SOURCE_REMOVE; } static void -deactivate_cancelled_cb (GCancellable *cancellable, - gpointer user_data) +deactivate_cancelled_cb(GCancellable *cancellable, gpointer user_data) { - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; - nm_utils_error_set_cancelled (&error, FALSE, NULL); - deactivate_invoke_cb ((DeactivateData *) user_data, error); + nm_utils_error_set_cancelled(&error, FALSE, NULL); + deactivate_invoke_cb((DeactivateData *) user_data, error); } static void -deactivate_cb_on_idle (gpointer user_data, - GCancellable *cancellable) +deactivate_cb_on_idle(gpointer user_data, GCancellable *cancellable) { - DeactivateData *data = user_data; - gs_free_error GError *cancelled_error = NULL; + DeactivateData *data = user_data; + gs_free_error GError *cancelled_error = NULL; - g_cancellable_set_error_if_cancelled (data->cancellable, &cancelled_error); - deactivate_invoke_cb (data, cancelled_error); + g_cancellable_set_error_if_cancelled(data->cancellable, &cancelled_error); + deactivate_invoke_cb(data, cancelled_error); } static void -deactivate_async (NMDevice *device, - GCancellable *cancellable, - NMDeviceDeactivateCallback callback, - gpointer callback_user_data) { - - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (self); - DeactivateData *data; - - _LOGT (LOGD_CORE, "deactivate: start async"); - - /* We want to ensure that the kernel link for this device is - * removed upon disconnection so that it will not interfere with - * later activations of the same device. Unfortunately there is - * no synchronization mechanism with vswitchd, we only update - * ovsdb and wait that changes are picked up. - */ - - data = g_slice_new (DeactivateData); - *data = (DeactivateData) { - .self = g_object_ref (self), - .cancellable = g_object_ref (cancellable), - .callback = callback, - .callback_user_data = callback_user_data, - }; - - if ( !priv->waiting_for_interface - && !nm_platform_link_get_by_ifname (nm_device_get_platform (device), - nm_device_get_iface (device))) { - _LOGT (LOGD_CORE, "deactivate: link not present, proceeding"); - nm_device_update_from_platform_link (NM_DEVICE (self), NULL); - nm_utils_invoke_on_idle (cancellable, deactivate_cb_on_idle, data); - return; - } - - if (priv->waiting_for_interface) { - /* At this point we have issued an INSERT and a DELETE - * command for the interface to ovsdb. We don't know if - * vswitchd will see the two updates or only one. We - * must add a timeout to avoid waiting forever in case - * the link doesn't appear. - */ - data->link_timeout_id = g_timeout_add (6000, deactivate_link_timeout, data); - _LOGT (LOGD_DEVICE, "deactivate: waiting for link to disappear in 6 seconds"); - } else - _LOGT (LOGD_DEVICE, "deactivate: waiting for link to disappear"); - - data->cancelled_id = g_cancellable_connect (cancellable, - G_CALLBACK (deactivate_cancelled_cb), - data, - NULL); - data->link_changed_id = g_signal_connect (nm_device_get_platform (device), - NM_PLATFORM_SIGNAL_LINK_CHANGED, - G_CALLBACK (deactivate_link_changed_cb), - data); +deactivate_async(NMDevice * device, + GCancellable * cancellable, + NMDeviceDeactivateCallback callback, + gpointer callback_user_data) +{ + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + DeactivateData * data; + + _LOGT(LOGD_CORE, "deactivate: start async"); + + /* We want to ensure that the kernel link for this device is + * removed upon disconnection so that it will not interfere with + * later activations of the same device. Unfortunately there is + * no synchronization mechanism with vswitchd, we only update + * ovsdb and wait that changes are picked up. + */ + + data = g_slice_new(DeactivateData); + *data = (DeactivateData){ + .self = g_object_ref(self), + .cancellable = g_object_ref(cancellable), + .callback = callback, + .callback_user_data = callback_user_data, + }; + + if (!priv->waiting_for_interface + && !nm_platform_link_get_by_ifname(nm_device_get_platform(device), + nm_device_get_iface(device))) { + _LOGT(LOGD_CORE, "deactivate: link not present, proceeding"); + nm_device_update_from_platform_link(NM_DEVICE(self), NULL); + nm_utils_invoke_on_idle(cancellable, deactivate_cb_on_idle, data); + return; + } + + if (priv->waiting_for_interface) { + /* At this point we have issued an INSERT and a DELETE + * command for the interface to ovsdb. We don't know if + * vswitchd will see the two updates or only one. We + * must add a timeout to avoid waiting forever in case + * the link doesn't appear. + */ + data->link_timeout_id = g_timeout_add(6000, deactivate_link_timeout, data); + _LOGT(LOGD_DEVICE, "deactivate: waiting for link to disappear in 6 seconds"); + } else + _LOGT(LOGD_DEVICE, "deactivate: waiting for link to disappear"); + + data->cancelled_id = + g_cancellable_connect(cancellable, G_CALLBACK(deactivate_cancelled_cb), data, NULL); + data->link_changed_id = g_signal_connect(nm_device_get_platform(device), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(deactivate_link_changed_cb), + data); } static gboolean -can_update_from_platform_link (NMDevice *device, const NMPlatformLink *plink) +can_update_from_platform_link(NMDevice *device, const NMPlatformLink *plink) { - /* If the device is deactivating, we already sent the - * deletion command to ovsdb and we don't want to deal - * with any new link appearing from the previous - * activation. - */ - return !plink - || nm_device_get_state (device) != NM_DEVICE_STATE_DEACTIVATING; + /* If the device is deactivating, we already sent the + * deletion command to ovsdb and we don't want to deal + * with any new link appearing from the previous + * activation. + */ + return !plink || nm_device_get_state(device) != NM_DEVICE_STATE_DEACTIVATING; } /*****************************************************************************/ static void -nm_device_ovs_interface_init (NMDeviceOvsInterface *self) -{ -} +nm_device_ovs_interface_init(NMDeviceOvsInterface *self) +{} static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), + .legacy_property_changed = TRUE, }; static void -nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) +nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_interface); - - device_class->connection_type_supported = NM_SETTING_OVS_INTERFACE_SETTING_NAME; - device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; - device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_OPENVSWITCH); - - device_class->can_update_from_platform_link = can_update_from_platform_link; - device_class->deactivate = deactivate; - device_class->deactivate_async = deactivate_async; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->is_available = is_available; - device_class->check_connection_compatible = check_connection_compatible; - device_class->link_changed = link_changed; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->can_unmanaged_external_down = can_unmanaged_external_down; - device_class->set_platform_mtu = set_platform_mtu; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + + dbus_object_class->interface_infos = + NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_interface); + + device_class->connection_type_supported = NM_SETTING_OVS_INTERFACE_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH); + + device_class->can_update_from_platform_link = can_update_from_platform_link; + device_class->deactivate = deactivate; + device_class->deactivate_async = deactivate_async; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->link_changed = link_changed; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->can_unmanaged_external_down = can_unmanaged_external_down; + device_class->set_platform_mtu = set_platform_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; } diff --git a/src/devices/ovs/nm-device-ovs-interface.h b/src/devices/ovs/nm-device-ovs-interface.h index e31dac8b..902847de 100644 --- a/src/devices/ovs/nm-device-ovs-interface.h +++ b/src/devices/ovs/nm-device-ovs-interface.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -6,16 +6,21 @@ #ifndef __NETWORKMANAGER_DEVICE_OVS_INTERFACE_H__ #define __NETWORKMANAGER_DEVICE_OVS_INTERFACE_H__ -#define NM_TYPE_DEVICE_OVS_INTERFACE (nm_device_ovs_interface_get_type ()) -#define NM_DEVICE_OVS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterface)) -#define NM_DEVICE_OVS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterfaceClass)) -#define NM_IS_DEVICE_OVS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OVS_INTERFACE)) -#define NM_IS_DEVICE_OVS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OVS_INTERFACE)) -#define NM_DEVICE_OVS_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterfaceClass)) +#define NM_TYPE_DEVICE_OVS_INTERFACE (nm_device_ovs_interface_get_type()) +#define NM_DEVICE_OVS_INTERFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterface)) +#define NM_DEVICE_OVS_INTERFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterfaceClass)) +#define NM_IS_DEVICE_OVS_INTERFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_OVS_INTERFACE)) +#define NM_IS_DEVICE_OVS_INTERFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_OVS_INTERFACE)) +#define NM_DEVICE_OVS_INTERFACE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_OVS_INTERFACE, NMDeviceOvsInterfaceClass)) -typedef struct _NMDeviceOvsInterface NMDeviceOvsInterface; +typedef struct _NMDeviceOvsInterface NMDeviceOvsInterface; typedef struct _NMDeviceOvsInterfaceClass NMDeviceOvsInterfaceClass; -GType nm_device_ovs_interface_get_type (void); +GType nm_device_ovs_interface_get_type(void); #endif /* __NETWORKMANAGER_DEVICE_OVS_INTERFACE_H__ */ diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c index e0216377..de98e29e 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/devices/ovs/nm-device-ovs-port.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -16,181 +16,177 @@ #include "nm-setting-ovs-port.h" #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF (NMDeviceOvsPort); +_LOG_DECLARE_SELF(NMDeviceOvsPort); /*****************************************************************************/ struct _NMDeviceOvsPort { - NMDevice parent; + NMDevice parent; }; struct _NMDeviceOvsPortClass { - NMDeviceClass parent; + NMDeviceClass parent; }; -G_DEFINE_TYPE (NMDeviceOvsPort, nm_device_ovs_port, NM_TYPE_DEVICE) +G_DEFINE_TYPE(NMDeviceOvsPort, nm_device_ovs_port, NM_TYPE_DEVICE) /*****************************************************************************/ static const char * -get_type_description (NMDevice *device) +get_type_description(NMDevice *device) { - return "ovs-port"; + return "ovs-port"; } static gboolean -create_and_realize (NMDevice *device, - NMConnection *connection, - NMDevice *parent, - const NMPlatformLink **out_plink, - GError **error) +create_and_realize(NMDevice * device, + NMConnection * connection, + NMDevice * parent, + const NMPlatformLink **out_plink, + GError ** error) { - /* The port will be added to ovsdb when an interface is enslaved, - * because there's no such thing like an empty port. */ + /* The port will be added to ovsdb when an interface is enslaved, + * because there's no such thing like an empty port. */ - return TRUE; + return TRUE; } static NMDeviceCapabilities -get_generic_capabilities (NMDevice *device) +get_generic_capabilities(NMDevice *device) { - return NM_DEVICE_CAP_IS_SOFTWARE; + return NM_DEVICE_CAP_IS_SOFTWARE; } static NMActStageReturn -act_stage3_ip_config_start (NMDevice *device, - int addr_family, - gpointer *out_config, - NMDeviceStateReason *out_failure_reason) +act_stage3_ip_config_start(NMDevice * device, + int addr_family, + gpointer * out_config, + NMDeviceStateReason *out_failure_reason) { - return NM_ACT_STAGE_RETURN_IP_FAIL; + return NM_ACT_STAGE_RETURN_IP_FAIL; } static void -add_iface_cb (GError *error, gpointer user_data) +add_iface_cb(GError *error, gpointer user_data) { - NMDevice *slave = user_data; - - if ( error - && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { - nm_log_warn (LOGD_DEVICE, "device %s could not be added to a ovs port: %s", - nm_device_get_iface (slave), error->message); - nm_device_state_changed (slave, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_OVSDB_FAILED); - } - - g_object_unref (slave); + NMDevice *slave = user_data; + + if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + nm_log_warn(LOGD_DEVICE, + "device %s could not be added to a ovs port: %s", + nm_device_get_iface(slave), + error->message); + nm_device_state_changed(slave, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_OVSDB_FAILED); + } + + g_object_unref(slave); } static gboolean -enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT (device); - NMActiveConnection *ac_port = NULL; - NMActiveConnection *ac_bridge = NULL; - NMDevice *bridge_device; - - if (!configure) - return TRUE; - - ac_port = NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)); - ac_bridge = nm_active_connection_get_master (ac_port); - if (!ac_bridge) { - _LOGW (LOGD_DEVICE, "can't enslave %s: bridge active-connection not found", - nm_device_get_iface (slave)); - return FALSE; - } - - bridge_device = nm_active_connection_get_device (ac_bridge); - if (!bridge_device) { - _LOGW (LOGD_DEVICE, "can't enslave %s: bridge device not found", - nm_device_get_iface (slave)); - return FALSE; - } - - 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; + NMDeviceOvsPort * self = NM_DEVICE_OVS_PORT(device); + NMActiveConnection *ac_port = NULL; + NMActiveConnection *ac_bridge = NULL; + NMDevice * bridge_device; + + if (!configure) + return TRUE; + + ac_port = NM_ACTIVE_CONNECTION(nm_device_get_act_request(device)); + ac_bridge = nm_active_connection_get_master(ac_port); + if (!ac_bridge) { + _LOGW(LOGD_DEVICE, + "can't enslave %s: bridge active-connection not found", + nm_device_get_iface(slave)); + return FALSE; + } + + bridge_device = nm_active_connection_get_device(ac_bridge); + if (!bridge_device) { + _LOGW(LOGD_DEVICE, "can't enslave %s: bridge device not found", nm_device_get_iface(slave)); + return FALSE; + } + + 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; } static void -del_iface_cb (GError *error, gpointer user_data) +del_iface_cb(GError *error, gpointer user_data) { - NMDevice *slave = user_data; - - if ( error - && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { - nm_log_warn (LOGD_DEVICE, "device %s could not be removed from a ovs port: %s", - nm_device_get_iface (slave), error->message); - nm_device_state_changed (slave, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_OVSDB_FAILED); - } - - g_object_unref (slave); + NMDevice *slave = user_data; + + if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + nm_log_warn(LOGD_DEVICE, + "device %s could not be removed from a ovs port: %s", + nm_device_get_iface(slave), + error->message); + nm_device_state_changed(slave, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_OVSDB_FAILED); + } + + g_object_unref(slave); } static void -release_slave (NMDevice *device, NMDevice *slave, gboolean configure) +release_slave(NMDevice *device, NMDevice *slave, gboolean configure) { - NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT (device); - - if (configure) { - _LOGI (LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface (slave)); - nm_ovsdb_del_interface (nm_ovsdb_get (), nm_device_get_iface (slave), - del_iface_cb, g_object_ref (slave)); - /* Open VSwitch is going to delete this one. We must ignore what happens - * next with the interface. */ - if (NM_IS_DEVICE_OVS_INTERFACE (slave)) - nm_device_update_from_platform_link (slave, NULL); - } else - _LOGI (LOGD_DEVICE, "ovs interface %s was released", nm_device_get_ip_iface (slave)); + NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); + + if (configure) { + _LOGI(LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface(slave)); + nm_ovsdb_del_interface(nm_ovsdb_get(), + nm_device_get_iface(slave), + del_iface_cb, + g_object_ref(slave)); + /* Open VSwitch is going to delete this one. We must ignore what happens + * next with the interface. */ + if (NM_IS_DEVICE_OVS_INTERFACE(slave)) + nm_device_update_from_platform_link(slave, NULL); + } else + _LOGI(LOGD_DEVICE, "ovs interface %s was released", nm_device_get_ip_iface(slave)); } /*****************************************************************************/ static void -nm_device_ovs_port_init (NMDeviceOvsPort *self) -{ -} +nm_device_ovs_port_init(NMDeviceOvsPort *self) +{} static const NMDBusInterfaceInfoExtended interface_info_device_ovs_port = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_PORT, - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Slaves", "ao", NM_DEVICE_SLAVES), - ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE_DEVICE_OVS_PORT, + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), + .legacy_property_changed = TRUE, }; static void -nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass) +nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_port); - - device_class->connection_type_supported = NM_SETTING_OVS_PORT_SETTING_NAME; - device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME; - device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (); - - device_class->is_master = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_port); + + device_class->connection_type_supported = NM_SETTING_OVS_PORT_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); + + device_class->is_master = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->enslave_slave = enslave_slave; + device_class->release_slave = release_slave; } diff --git a/src/devices/ovs/nm-device-ovs-port.h b/src/devices/ovs/nm-device-ovs-port.h index 7edbf02f..3f5d7793 100644 --- a/src/devices/ovs/nm-device-ovs-port.h +++ b/src/devices/ovs/nm-device-ovs-port.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -6,16 +6,20 @@ #ifndef __NETWORKMANAGER_DEVICE_OVS_PORT_H__ #define __NETWORKMANAGER_DEVICE_OVS_PORT_H__ -#define NM_TYPE_DEVICE_OVS_PORT (nm_device_ovs_port_get_type ()) -#define NM_DEVICE_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPort)) -#define NM_DEVICE_OVS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPortClass)) -#define NM_IS_DEVICE_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OVS_PORT)) -#define NM_IS_DEVICE_OVS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OVS_PORT)) -#define NM_DEVICE_OVS_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPortClass)) +#define NM_TYPE_DEVICE_OVS_PORT (nm_device_ovs_port_get_type()) +#define NM_DEVICE_OVS_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPort)) +#define NM_DEVICE_OVS_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPortClass)) +#define NM_IS_DEVICE_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_OVS_PORT)) +#define NM_IS_DEVICE_OVS_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_OVS_PORT)) +#define NM_DEVICE_OVS_PORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_OVS_PORT, NMDeviceOvsPortClass)) -typedef struct _NMDeviceOvsPort NMDeviceOvsPort; +typedef struct _NMDeviceOvsPort NMDeviceOvsPort; typedef struct _NMDeviceOvsPortClass NMDeviceOvsPortClass; -GType nm_device_ovs_port_get_type (void); +GType nm_device_ovs_port_get_type(void); #endif /* __NETWORKMANAGER_DEVICE_OVS_PORT_H__ */ diff --git a/src/devices/ovs/nm-ovs-factory.c b/src/devices/ovs/nm-ovs-factory.c index d7bd0a09..e1feacbd 100644 --- a/src/devices/ovs/nm-ovs-factory.c +++ b/src/devices/ovs/nm-ovs-factory.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -19,228 +19,251 @@ /*****************************************************************************/ typedef struct { - NMDeviceFactory parent; + NMDeviceFactory parent; } NMOvsFactory; typedef struct { - NMDeviceFactoryClass parent; + NMDeviceFactoryClass parent; } NMOvsFactoryClass; -#define NM_TYPE_OVS_FACTORY (nm_ovs_factory_get_type ()) -#define NM_OVS_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OVS_FACTORY, NMOvsFactory)) -#define NM_OVS_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass)) -#define NM_IS_OVS_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OVS_FACTORY)) -#define NM_IS_OVS_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_OVS_FACTORY)) -#define NM_OVS_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass)) +#define NM_TYPE_OVS_FACTORY (nm_ovs_factory_get_type()) +#define NM_OVS_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_OVS_FACTORY, NMOvsFactory)) +#define NM_OVS_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass)) +#define NM_IS_OVS_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_OVS_FACTORY)) +#define NM_IS_OVS_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_OVS_FACTORY)) +#define NM_OVS_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass)) -static GType nm_ovs_factory_get_type (void); -G_DEFINE_TYPE (NMOvsFactory, nm_ovs_factory, NM_TYPE_DEVICE_FACTORY) +static GType nm_ovs_factory_get_type(void); +G_DEFINE_TYPE(NMOvsFactory, nm_ovs_factory, NM_TYPE_DEVICE_FACTORY) /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG(level, ifname, con_uuid, ...) \ - G_STMT_START { \ - nm_log ((level), _NMLOG_DOMAIN, (ifname), (con_uuid), \ - "ovs: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END - +#define _NMLOG_DOMAIN LOGD_DEVICE +#define _NMLOG(level, ifname, con_uuid, ...) \ + G_STMT_START \ + { \ + nm_log((level), \ + _NMLOG_DOMAIN, \ + (ifname), \ + (con_uuid), \ + "ovs: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END /*****************************************************************************/ -NM_DEVICE_FACTORY_DECLARE_TYPES ( - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_OPENVSWITCH) - NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME) -) +NM_DEVICE_FACTORY_DECLARE_TYPES( + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * -nm_device_factory_create (GError **error) + nm_device_factory_create(GError **error) { - nm_manager_set_capability (NM_MANAGER_GET, NM_CAPABILITY_OVS); - return (NMDeviceFactory *) g_object_new (NM_TYPE_OVS_FACTORY, NULL); + nm_manager_set_capability(NM_MANAGER_GET, NM_CAPABILITY_OVS); + return (NMDeviceFactory *) g_object_new(NM_TYPE_OVS_FACTORY, NULL); } static NMDevice * -new_device_from_type (const char *name, NMDeviceType device_type) +new_device_from_type(const char *name, NMDeviceType device_type) { - GType type; - const char *type_desc; - NMLinkType link_type = NM_LINK_TYPE_NONE; - - if (nm_manager_get_device (NM_MANAGER_GET, name, device_type)) - return NULL; - - if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) { - type = NM_TYPE_DEVICE_OVS_INTERFACE; - type_desc = "Open vSwitch Interface"; - link_type = NM_LINK_TYPE_OPENVSWITCH; - } else if (device_type == NM_DEVICE_TYPE_OVS_PORT) { - type = NM_TYPE_DEVICE_OVS_PORT; - type_desc = "Open vSwitch Port"; - } else if (device_type == NM_DEVICE_TYPE_OVS_BRIDGE) { - type = NM_TYPE_DEVICE_OVS_BRIDGE; - type_desc = "Open vSwitch Bridge"; - } else { - return NULL; - } - - return g_object_new (type, - NM_DEVICE_IFACE, name, - NM_DEVICE_DRIVER, "openvswitch", - NM_DEVICE_DEVICE_TYPE, device_type, - NM_DEVICE_TYPE_DESC, type_desc, - NM_DEVICE_LINK_TYPE, link_type, - NULL); + GType type; + const char *type_desc; + NMLinkType link_type = NM_LINK_TYPE_NONE; + + if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) + return NULL; + + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) { + type = NM_TYPE_DEVICE_OVS_INTERFACE; + type_desc = "Open vSwitch Interface"; + link_type = NM_LINK_TYPE_OPENVSWITCH; + } else if (device_type == NM_DEVICE_TYPE_OVS_PORT) { + type = NM_TYPE_DEVICE_OVS_PORT; + type_desc = "Open vSwitch Port"; + } else if (device_type == NM_DEVICE_TYPE_OVS_BRIDGE) { + type = NM_TYPE_DEVICE_OVS_BRIDGE; + type_desc = "Open vSwitch Bridge"; + } else { + return NULL; + } + + return g_object_new(type, + NM_DEVICE_IFACE, + name, + NM_DEVICE_DRIVER, + "openvswitch", + NM_DEVICE_DEVICE_TYPE, + device_type, + NM_DEVICE_TYPE_DESC, + type_desc, + NM_DEVICE_LINK_TYPE, + link_type, + NULL); } static void -ovsdb_device_added (NMOvsdb *ovsdb, const char *name, NMDeviceType device_type, - NMDeviceFactory *self) +ovsdb_device_added(NMOvsdb * ovsdb, + const char * name, + NMDeviceType device_type, + NMDeviceFactory *self) { - NMDevice *device = NULL; + NMDevice *device = NULL; - device = new_device_from_type (name, device_type); - if (!device) - return; + device = new_device_from_type(name, device_type); + if (!device) + return; - g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); - g_object_unref (device); + g_signal_emit_by_name(self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); + g_object_unref(device); } static void -ovsdb_device_removed (NMOvsdb *ovsdb, const char *name, NMDeviceType device_type, - NMDeviceFactory *self) +ovsdb_device_removed(NMOvsdb * ovsdb, + const char * name, + NMDeviceType device_type, + NMDeviceFactory *self) { - NMDevice *device; - NMDeviceState device_state; - - device = nm_manager_get_device (NM_MANAGER_GET, name, device_type); - if (!device) - return; - - device_state = nm_device_get_state (device); - if ( device_type == NM_DEVICE_TYPE_OVS_INTERFACE - && device_state > NM_DEVICE_STATE_DISCONNECTED - && device_state < NM_DEVICE_STATE_DEACTIVATING) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DEACTIVATING, - NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); - } else if (device_state == NM_DEVICE_STATE_UNMANAGED) { - nm_device_unrealize (device, TRUE, NULL); - } + NMDevice * device; + NMDeviceState device_state; + + device = nm_manager_get_device(NM_MANAGER_GET, name, device_type); + if (!device) + return; + + device_state = nm_device_get_state(device); + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && device_state > NM_DEVICE_STATE_DISCONNECTED + && device_state < NM_DEVICE_STATE_DEACTIVATING) { + nm_device_state_changed(device, + NM_DEVICE_STATE_DEACTIVATING, + NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); + } else if (device_state == NM_DEVICE_STATE_UNMANAGED) { + nm_device_unrealize(device, TRUE, NULL); + } } static void -ovsdb_interface_failed (NMOvsdb *ovsdb, - const char *name, - const char *connection_uuid, - const char *error, - NMDeviceFactory *self) +ovsdb_interface_failed(NMOvsdb * ovsdb, + const char * name, + const char * connection_uuid, + const char * error, + NMDeviceFactory *self) { - NMDevice *device = NULL; - NMSettingsConnection *connection = NULL; - NMConnection *c; - const char *type; - NMSettingOvsInterface *s_ovs_int; - gboolean is_patch = FALSE; - gboolean ignore; - - device = nm_manager_get_device (NM_MANAGER_GET, name, NM_DEVICE_TYPE_OVS_INTERFACE); - if (device && connection_uuid) { - connection = nm_settings_get_connection_by_uuid (nm_device_get_settings (device), - connection_uuid); - } - - /* The patch interface which gets created first is expected to - * fail because the second patch doesn't exist yet. Ignore all - * failures of patch interfaces. */ - if ( connection - && (c = nm_settings_connection_get_connection (connection)) - && (type = nm_connection_get_connection_type (c)) - && nm_streq0 (type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) - && (s_ovs_int = nm_connection_get_setting_ovs_interface (c)) - && nm_streq0 (nm_setting_ovs_interface_get_interface_type (s_ovs_int), "patch")) - is_patch = TRUE; - - ignore = !device || is_patch; - - _NMLOG (ignore ? LOGL_DEBUG : LOGL_INFO, - name, connection_uuid, - "ovs interface \"%s\" (%s) failed%s: %s", - name, connection_uuid, - ignore ? " (ignored)" : "", - error); - - if (ignore) - return; - - if (connection) { - nm_settings_connection_autoconnect_blocked_reason_set (connection, - NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, - TRUE); - } - - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_OVSDB_FAILED); + NMDevice * device = NULL; + NMSettingsConnection * connection = NULL; + NMConnection * c; + const char * type; + NMSettingOvsInterface *s_ovs_int; + gboolean is_patch = FALSE; + gboolean ignore; + + device = nm_manager_get_device(NM_MANAGER_GET, name, NM_DEVICE_TYPE_OVS_INTERFACE); + if (device && connection_uuid) { + connection = + nm_settings_get_connection_by_uuid(nm_device_get_settings(device), connection_uuid); + } + + /* The patch interface which gets created first is expected to + * fail because the second patch doesn't exist yet. Ignore all + * failures of patch interfaces. */ + if (connection && (c = nm_settings_connection_get_connection(connection)) + && (type = nm_connection_get_connection_type(c)) + && nm_streq0(type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) + && (s_ovs_int = nm_connection_get_setting_ovs_interface(c)) + && nm_streq0(nm_setting_ovs_interface_get_interface_type(s_ovs_int), "patch")) + is_patch = TRUE; + + ignore = !device || is_patch; + + _NMLOG(ignore ? LOGL_DEBUG : LOGL_INFO, + name, + connection_uuid, + "ovs interface \"%s\" (%s) failed%s: %s", + name, + connection_uuid, + ignore ? " (ignored)" : "", + error); + + if (ignore) + return; + + if (connection) { + nm_settings_connection_autoconnect_blocked_reason_set( + connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, + TRUE); + } + + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_OVSDB_FAILED); } static void -start (NMDeviceFactory *self) +start(NMDeviceFactory *self) { - NMOvsdb *ovsdb; - - ovsdb = nm_ovsdb_get (); - - g_signal_connect_object (ovsdb, NM_OVSDB_DEVICE_ADDED, G_CALLBACK (ovsdb_device_added), self, (GConnectFlags) 0); - g_signal_connect_object (ovsdb, NM_OVSDB_DEVICE_REMOVED, G_CALLBACK (ovsdb_device_removed), self, (GConnectFlags) 0); - g_signal_connect_object (ovsdb, NM_OVSDB_INTERFACE_FAILED, G_CALLBACK (ovsdb_interface_failed), self, (GConnectFlags) 0); + NMOvsdb *ovsdb; + + ovsdb = nm_ovsdb_get(); + + g_signal_connect_object(ovsdb, + NM_OVSDB_DEVICE_ADDED, + G_CALLBACK(ovsdb_device_added), + self, + (GConnectFlags) 0); + g_signal_connect_object(ovsdb, + NM_OVSDB_DEVICE_REMOVED, + G_CALLBACK(ovsdb_device_removed), + self, + (GConnectFlags) 0); + g_signal_connect_object(ovsdb, + NM_OVSDB_INTERFACE_FAILED, + G_CALLBACK(ovsdb_interface_failed), + self, + (GConnectFlags) 0); } static NMDevice * -create_device (NMDeviceFactory *self, - const char *iface, - const NMPlatformLink *plink, - NMConnection *connection, - gboolean *out_ignore) +create_device(NMDeviceFactory * self, + const char * iface, + const NMPlatformLink *plink, + NMConnection * connection, + gboolean * out_ignore) { - NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN; - const char *connection_type = NULL; - - if (g_strcmp0 (iface, "ovs-system") == 0) { - *out_ignore = TRUE; - return NULL; - } - - if (connection) - connection_type = nm_connection_get_connection_type (connection); - - if (plink) - device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0 (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) - device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0 (connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0) - device_type = NM_DEVICE_TYPE_OVS_PORT; - else if (g_strcmp0 (connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0) - device_type = NM_DEVICE_TYPE_OVS_BRIDGE; - - return new_device_from_type (iface, device_type); + NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN; + const char * connection_type = NULL; + + if (g_strcmp0(iface, "ovs-system") == 0) { + *out_ignore = TRUE; + return NULL; + } + + if (connection) + connection_type = nm_connection_get_connection_type(connection); + + if (plink) + device_type = NM_DEVICE_TYPE_OVS_INTERFACE; + else if (g_strcmp0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + device_type = NM_DEVICE_TYPE_OVS_INTERFACE; + else if (g_strcmp0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0) + device_type = NM_DEVICE_TYPE_OVS_PORT; + else if (g_strcmp0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0) + device_type = NM_DEVICE_TYPE_OVS_BRIDGE; + + return new_device_from_type(iface, device_type); } static void -nm_ovs_factory_init (NMOvsFactory *self) -{ -} +nm_ovs_factory_init(NMOvsFactory *self) +{} static void -nm_ovs_factory_class_init (NMOvsFactoryClass *klass) +nm_ovs_factory_class_init(NMOvsFactoryClass *klass) { - NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS (klass); + NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass); - factory_class->get_supported_types = get_supported_types; - factory_class->start = start; - factory_class->create_device = create_device; + factory_class->get_supported_types = get_supported_types; + factory_class->start = start; + factory_class->create_device = create_device; } diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index 0b3fa3fd..9826c1b7 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -18,163 +18,161 @@ /*****************************************************************************/ #if JANSSON_VERSION_HEX < 0x020400 -#warning "requires at least libjansson 2.4" + #warning "requires at least libjansson 2.4" #endif typedef struct { - char *name; - char *connection_uuid; - GPtrArray *interfaces; /* interface uuids */ + char * name; + char * connection_uuid; + GPtrArray *interfaces; /* interface uuids */ } OpenvswitchPort; typedef struct { - char *name; - char *connection_uuid; - GPtrArray *ports; /* port uuids */ + char * name; + char * connection_uuid; + GPtrArray *ports; /* port uuids */ } OpenvswitchBridge; typedef struct { - char *name; - char *type; - char *connection_uuid; + char *name; + char *type; + char *connection_uuid; } OpenvswitchInterface; /*****************************************************************************/ -enum { - DEVICE_ADDED, - DEVICE_REMOVED, - INTERFACE_FAILED, - LAST_SIGNAL -}; +enum { DEVICE_ADDED, DEVICE_REMOVED, INTERFACE_FAILED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = {0}; typedef struct { - GSocketClient *client; - GSocketConnection *conn; - GCancellable *cancellable; - char buf[4096]; /* Input buffer */ - size_t bufp; /* Last decoded byte in the input buffer. */ - GString *input; /* JSON stream waiting for decoding. */ - GString *output; /* JSON stream to be sent. */ - gint64 seq; - GArray *calls; /* Method calls waiting for a response. */ - GHashTable *interfaces; /* interface uuid => OpenvswitchInterface */ - GHashTable *ports; /* port uuid => OpenvswitchPort */ - GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ - char *db_uuid; - guint num_failures; + GSocketClient * client; + GSocketConnection *conn; + GCancellable * cancellable; + char buf[4096]; /* Input buffer */ + size_t bufp; /* Last decoded byte in the input buffer. */ + GString * input; /* JSON stream waiting for decoding. */ + GString * output; /* JSON stream to be sent. */ + gint64 seq; + GArray * calls; /* Method calls waiting for a response. */ + GHashTable * interfaces; /* interface uuid => OpenvswitchInterface */ + GHashTable * ports; /* port uuid => OpenvswitchPort */ + GHashTable * bridges; /* bridge uuid => OpenvswitchBridge */ + char * db_uuid; + guint num_failures; } NMOvsdbPrivate; struct _NMOvsdb { - GObject parent; - NMOvsdbPrivate _priv; + GObject parent; + NMOvsdbPrivate _priv; }; struct _NMOvsdbClass { - GObjectClass parent; + GObjectClass parent; }; -G_DEFINE_TYPE (NMOvsdb, nm_ovsdb, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMOvsdb, nm_ovsdb, G_TYPE_OBJECT) -#define NM_OVSDB_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMOvsdb, NM_IS_OVSDB) +#define NM_OVSDB_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMOvsdb, NM_IS_OVSDB) #define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__) +#define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__) -NM_DEFINE_SINGLETON_GETTER (NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB); +NM_DEFINE_SINGLETON_GETTER(NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB); /*****************************************************************************/ -static void ovsdb_try_connect (NMOvsdb *self); -static void ovsdb_disconnect (NMOvsdb *self, gboolean retry, gboolean is_disposing); -static void ovsdb_read (NMOvsdb *self); -static void ovsdb_write (NMOvsdb *self); -static void ovsdb_next_command (NMOvsdb *self); +static void ovsdb_try_connect(NMOvsdb *self); +static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing); +static void ovsdb_read(NMOvsdb *self); +static void ovsdb_write(NMOvsdb *self); +static void ovsdb_next_command(NMOvsdb *self); /*****************************************************************************/ /* ovsdb command abstraction. */ -typedef void (*OvsdbMethodCallback) (NMOvsdb *self, json_t *response, - GError *error, gpointer user_data); +typedef void (*OvsdbMethodCallback)(NMOvsdb *self, + json_t * response, + GError * error, + gpointer user_data); typedef enum { - OVSDB_MONITOR, - OVSDB_ADD_INTERFACE, - OVSDB_DEL_INTERFACE, - OVSDB_SET_INTERFACE_MTU, + OVSDB_MONITOR, + OVSDB_ADD_INTERFACE, + OVSDB_DEL_INTERFACE, + OVSDB_SET_INTERFACE_MTU, } OvsdbCommand; typedef struct { - gint64 id; -#define COMMAND_PENDING -1 /* id not yet assigned */ - OvsdbCommand command; - OvsdbMethodCallback callback; - gpointer user_data; - union { - struct { - char *ifname; - guint32 mtu; - }; - struct { - NMConnection *bridge; - NMConnection *port; - NMConnection *interface; - NMDevice *bridge_device; - NMDevice *interface_device; - }; - }; + gint64 id; +#define COMMAND_PENDING -1 /* id not yet assigned */ + OvsdbCommand command; + OvsdbMethodCallback callback; + gpointer user_data; + union { + struct { + char * ifname; + guint32 mtu; + }; + struct { + NMConnection *bridge; + NMConnection *port; + NMConnection *interface; + NMDevice * bridge_device; + NMDevice * interface_device; + }; + }; } OvsdbMethodCall; -#define OVSDB_MAX_FAILURES 3 +#define OVSDB_MAX_FAILURES 3 static void -_LOGT_call_do (const char *comment, OvsdbMethodCall *call, json_t *msg) +_LOGT_call_do(const char *comment, OvsdbMethodCall *call, json_t *msg) { - gs_free char *str = NULL; - - if (msg) - str = json_dumps (msg, 0); - - switch (call->command) { - case OVSDB_MONITOR: - _LOGT ("%s: monitor%s%s", - comment, - msg ? ": " : "", - msg ? str : ""); - break; - case OVSDB_ADD_INTERFACE: - _LOGT ("%s: add-iface bridge=%s port=%s interface=%s%s%s", - comment, - nm_connection_get_interface_name (call->bridge), - nm_connection_get_interface_name (call->port), - nm_connection_get_interface_name (call->interface), - msg ? ": " : "", - msg ? str : ""); - break; - case OVSDB_DEL_INTERFACE: - _LOGT ("%s: del-iface interface=%s%s%s", - comment, call->ifname, - msg ? ": " : "", - msg ? str : ""); - break; - case OVSDB_SET_INTERFACE_MTU: - _LOGT ("%s: set-iface-mtu interface=%s%s%s mtu=%u", - comment, call->ifname, - msg ? ": " : "", - msg ? str : "", - call->mtu); - break; - } + gs_free char *str = NULL; + + if (msg) + str = json_dumps(msg, 0); + + switch (call->command) { + case OVSDB_MONITOR: + _LOGT("%s: monitor%s%s", comment, msg ? ": " : "", msg ? str : ""); + break; + case OVSDB_ADD_INTERFACE: + _LOGT("%s: add-iface bridge=%s port=%s interface=%s%s%s", + comment, + nm_connection_get_interface_name(call->bridge), + nm_connection_get_interface_name(call->port), + nm_connection_get_interface_name(call->interface), + msg ? ": " : "", + msg ? str : ""); + break; + case OVSDB_DEL_INTERFACE: + _LOGT("%s: del-iface interface=%s%s%s", + comment, + call->ifname, + msg ? ": " : "", + msg ? str : ""); + break; + case OVSDB_SET_INTERFACE_MTU: + _LOGT("%s: set-iface-mtu interface=%s%s%s mtu=%u", + comment, + call->ifname, + msg ? ": " : "", + msg ? str : "", + call->mtu); + break; + } } -#define _LOGT_call(comment, call, message) \ - G_STMT_START { \ - if (_LOGT_ENABLED ()) \ - _LOGT_call_do ((comment), (call), (message)); \ - } G_STMT_END +#define _LOGT_call(comment, call, message) \ + G_STMT_START \ + { \ + if (_LOGT_ENABLED()) \ + _LOGT_call_do((comment), (call), (message)); \ + } \ + G_STMT_END /** * ovsdb_call_method: @@ -183,53 +181,59 @@ _LOGT_call_do (const char *comment, OvsdbMethodCall *call, json_t *msg) * there's no command pending completion. */ static void -ovsdb_call_method (NMOvsdb *self, OvsdbCommand command, - const char *ifname, - NMConnection *bridge, NMConnection *port, NMConnection *interface, - NMDevice *bridge_device, NMDevice *interface_device, - guint32 mtu, OvsdbMethodCallback callback, gpointer user_data, - gboolean add_first) +ovsdb_call_method(NMOvsdb * self, + OvsdbCommand command, + const char * ifname, + NMConnection * bridge, + NMConnection * port, + NMConnection * interface, + NMDevice * bridge_device, + NMDevice * interface_device, + guint32 mtu, + OvsdbMethodCallback callback, + gpointer user_data, + gboolean add_first) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - OvsdbMethodCall *call; - - /* Ensure we're not unsynchronized before we queue the method call. */ - ovsdb_try_connect (self); - - if (add_first) { - g_array_prepend_val (priv->calls, (OvsdbMethodCall) {}); - call = &g_array_index (priv->calls, OvsdbMethodCall, 0); - } else { - g_array_set_size (priv->calls, priv->calls->len + 1); - call = &g_array_index (priv->calls, OvsdbMethodCall, priv->calls->len - 1); - } - call->id = COMMAND_PENDING; - call->command = command; - call->callback = callback; - call->user_data = user_data; - - switch (call->command) { - case OVSDB_MONITOR: - break; - case OVSDB_ADD_INTERFACE: - 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); - break; - case OVSDB_SET_INTERFACE_MTU: - call->ifname = g_strdup (ifname); - call->mtu = mtu; - break; - } - - _LOGT_call ("enqueue", call, NULL); - - ovsdb_next_command (self); + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + OvsdbMethodCall *call; + + /* Ensure we're not unsynchronized before we queue the method call. */ + ovsdb_try_connect(self); + + if (add_first) { + g_array_prepend_val(priv->calls, (OvsdbMethodCall){}); + call = &g_array_index(priv->calls, OvsdbMethodCall, 0); + } else { + g_array_set_size(priv->calls, priv->calls->len + 1); + call = &g_array_index(priv->calls, OvsdbMethodCall, priv->calls->len - 1); + } + call->id = COMMAND_PENDING; + call->command = command; + call->callback = callback; + call->user_data = user_data; + + switch (call->command) { + case OVSDB_MONITOR: + break; + case OVSDB_ADD_INTERFACE: + 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); + break; + case OVSDB_SET_INTERFACE_MTU: + call->ifname = g_strdup(ifname); + call->mtu = mtu; + break; + } + + _LOGT_call("enqueue", call, NULL); + + ovsdb_next_command(self); } /*****************************************************************************/ @@ -245,15 +249,30 @@ ovsdb_call_method (NMOvsdb *self, OvsdbCommand command, * at the same time. */ static void -_expect_ovs_bridges (json_t *params, const char *db_uuid, json_t *bridges) +_expect_ovs_bridges(json_t *params, const char *db_uuid, json_t *bridges) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, [s, s]]]}", - "op", "wait", "table", "Open_vSwitch", - "timeout", 0, "columns", "bridges", - "until", "==", "rows", "bridges", "set", bridges, - "where", "_uuid", "==", "uuid", db_uuid) - ); + json_array_append_new( + params, + json_pack("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, [s, s]]]}", + "op", + "wait", + "table", + "Open_vSwitch", + "timeout", + 0, + "columns", + "bridges", + "until", + "==", + "rows", + "bridges", + "set", + bridges, + "where", + "_uuid", + "==", + "uuid", + db_uuid)); } /** @@ -263,14 +282,23 @@ _expect_ovs_bridges (json_t *params, const char *db_uuid, json_t *bridges) * database to @new_bridges. */ static void -_set_ovs_bridges (json_t *params, const char *db_uuid, json_t *new_bridges) +_set_ovs_bridges(json_t *params, const char *db_uuid, json_t *new_bridges) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, [s, s]]]}", - "op", "update", "table", "Open_vSwitch", - "row", "bridges", "set", new_bridges, - "where", "_uuid", "==", "uuid", db_uuid) - ); + json_array_append_new(params, + json_pack("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, [s, s]]]}", + "op", + "update", + "table", + "Open_vSwitch", + "row", + "bridges", + "set", + new_bridges, + "where", + "_uuid", + "==", + "uuid", + db_uuid)); } /** @@ -282,15 +310,28 @@ _set_ovs_bridges (json_t *params, const char *db_uuid, json_t *new_bridges) * bridge ports at the same time. */ static void -_expect_bridge_ports (json_t *params, const char *ifname, json_t *ports) +_expect_bridge_ports(json_t *params, const char *ifname, json_t *ports) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, s]]}", - "op", "wait", "table", "Bridge", - "timeout", 0, "columns", "ports", - "until", "==", "rows", "ports", "set", ports, - "where", "name", "==", ifname) - ); + json_array_append_new(params, + json_pack("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, s]]}", + "op", + "wait", + "table", + "Bridge", + "timeout", + 0, + "columns", + "ports", + "until", + "==", + "rows", + "ports", + "set", + ports, + "where", + "name", + "==", + ifname)); } /** @@ -300,26 +341,42 @@ _expect_bridge_ports (json_t *params, const char *ifname, json_t *ports) * @ifname to @new_ports. */ static void -_set_bridge_ports (json_t *params, const char *ifname, json_t *new_ports) +_set_bridge_ports(json_t *params, const char *ifname, json_t *new_ports) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, s]]}", - "op", "update", "table", "Bridge", - "row", "ports", "set", new_ports, - "where", "name", "==", ifname) - ); + json_array_append_new(params, + json_pack("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, s]]}", + "op", + "update", + "table", + "Bridge", + "row", + "ports", + "set", + new_ports, + "where", + "name", + "==", + ifname)); } static void -_set_bridge_mac (json_t *params, const char *ifname, const char *mac) +_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]]}", + "op", + "update", + "table", + "Bridge", + "row", + "other_config", + "map", + "hwaddr", + mac, + "where", + "name", + "==", + ifname)); } /** @@ -331,15 +388,28 @@ _set_bridge_mac (json_t *params, const char *ifname, const char *mac) * or removing port interfaces at the same time. */ static void -_expect_port_interfaces (json_t *params, const char *ifname, json_t *interfaces) +_expect_port_interfaces(json_t *params, const char *ifname, json_t *interfaces) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, s]]}", - "op", "wait", "table", "Port", - "timeout", 0, "columns", "interfaces", - "until", "==", "rows", "interfaces", "set", interfaces, - "where", "name", "==", ifname) - ); + json_array_append_new(params, + json_pack("{s:s, s:s, s:i, s:[s], s:s, s:[{s:[s, O]}], s:[[s, s, s]]}", + "op", + "wait", + "table", + "Port", + "timeout", + 0, + "columns", + "interfaces", + "until", + "==", + "rows", + "interfaces", + "set", + interfaces, + "where", + "name", + "==", + ifname)); } /** @@ -349,14 +419,22 @@ _expect_port_interfaces (json_t *params, const char *ifname, json_t *interfaces) * to @new_interfaces. */ static void -_set_port_interfaces (json_t *params, const char *ifname, json_t *new_interfaces) +_set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces) { - json_array_append_new (params, - json_pack ("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, s]]}", - "op", "update", "table", "Port", - "row", "interfaces", "set", new_interfaces, - "where", "name", "==", ifname) - ); + json_array_append_new(params, + json_pack("{s:s, s:s, s:{s:[s, O]}, s:[[s, s, s]]}", + "op", + "update", + "table", + "Port", + "row", + "interfaces", + "set", + new_interfaces, + "where", + "name", + "==", + ifname)); } /** @@ -365,69 +443,78 @@ _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, - NMDevice *interface_device, - const char *cloned_mac) +_insert_interface(json_t * params, + NMConnection *interface, + NMDevice * interface_device, + const char * cloned_mac) { - const char *type = NULL; - NMSettingOvsInterface *s_ovs_iface; - NMSettingOvsDpdk *s_ovs_dpdk; - NMSettingOvsPatch *s_ovs_patch; - json_t *options = json_array (); - json_t *row; - guint32 mtu = 0; - - 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_streq0 (type, "internal")) { - NMSettingWired *s_wired; - - s_wired = _nm_connection_get_setting (interface, NM_TYPE_SETTING_WIRED); - if (s_wired) - mtu = nm_setting_wired_get_mtu (s_wired); - } - - json_array_append_new (options, json_string ("map")); - - s_ovs_dpdk = (NMSettingOvsDpdk *) nm_connection_get_setting (interface, - NM_TYPE_SETTING_OVS_DPDK); - if (!s_ovs_dpdk) - s_ovs_patch = nm_connection_get_setting_ovs_patch (interface); - - if (s_ovs_dpdk) { - json_array_append_new (options, json_pack ("[[s, s]]", - "dpdk-devargs", - nm_setting_ovs_dpdk_get_devargs (s_ovs_dpdk))); - } else if (s_ovs_patch) { - json_array_append_new (options, json_pack ("[[s, s]]", - "peer", - nm_setting_ovs_patch_get_peer (s_ovs_patch))); - } else { - 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)); - - if (mtu != 0) - json_object_set_new (row, "mtu_request", json_integer (mtu)); - - json_array_append_new (params, - json_pack ("{s:s, s:s, s:o, s:s}", - "op", "insert", - "table", "Interface", - "row", row, - "uuid-name", "rowInterface")); + const char * type = NULL; + NMSettingOvsInterface *s_ovs_iface; + NMSettingOvsDpdk * s_ovs_dpdk; + NMSettingOvsPatch * s_ovs_patch; + json_t * options = json_array(); + json_t * row; + guint32 mtu = 0; + + 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_streq0(type, "internal")) { + NMSettingWired *s_wired; + + s_wired = _nm_connection_get_setting(interface, NM_TYPE_SETTING_WIRED); + if (s_wired) + mtu = nm_setting_wired_get_mtu(s_wired); + } + + json_array_append_new(options, json_string("map")); + + s_ovs_dpdk = + (NMSettingOvsDpdk *) nm_connection_get_setting(interface, NM_TYPE_SETTING_OVS_DPDK); + if (!s_ovs_dpdk) + s_ovs_patch = nm_connection_get_setting_ovs_patch(interface); + + if (s_ovs_dpdk) { + json_array_append_new( + options, + json_pack("[[s, s]]", "dpdk-devargs", nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk))); + } else if (s_ovs_patch) { + json_array_append_new( + options, + json_pack("[[s, s]]", "peer", nm_setting_ovs_patch_get_peer(s_ovs_patch))); + } else { + 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)); + + if (mtu != 0) + json_object_set_new(row, "mtu_request", json_integer(mtu)); + + json_array_append_new(params, + json_pack("{s:s, s:s, s:o, s:s}", + "op", + "insert", + "table", + "Interface", + "row", + row, + "uuid-name", + "rowInterface")); } /** @@ -436,53 +523,61 @@ _insert_interface (json_t *params, * Returns an commands that adds new port from a given connection. */ static void -_insert_port (json_t *params, NMConnection *port, json_t *new_interfaces) +_insert_port(json_t *params, NMConnection *port, json_t *new_interfaces) { - NMSettingOvsPort *s_ovs_port; - const char *vlan_mode = NULL; - guint tag = 0; - const char *lacp = NULL; - const char *bond_mode = NULL; - guint bond_updelay = 0; - guint bond_downdelay = 0; - json_t *row; - - s_ovs_port = nm_connection_get_setting_ovs_port (port); - - row = json_object (); - - if (s_ovs_port) { - vlan_mode = nm_setting_ovs_port_get_vlan_mode (s_ovs_port); - tag = nm_setting_ovs_port_get_tag (s_ovs_port); - lacp = nm_setting_ovs_port_get_lacp (s_ovs_port); - bond_mode = nm_setting_ovs_port_get_bond_mode (s_ovs_port); - bond_updelay = nm_setting_ovs_port_get_bond_updelay (s_ovs_port); - bond_downdelay = nm_setting_ovs_port_get_bond_downdelay (s_ovs_port); - } - - if (vlan_mode) - json_object_set_new (row, "vlan_mode", json_string (vlan_mode)); - if (tag) - json_object_set_new (row, "tag", json_integer (tag)); - if (lacp) - json_object_set_new (row, "lacp", json_string (lacp)); - if (bond_mode) - json_object_set_new (row, "bond_mode", json_string (bond_mode)); - if (bond_updelay) - json_object_set_new (row, "bond_updelay", json_integer (bond_updelay)); - if (bond_downdelay) - json_object_set_new (row, "bond_downdelay", json_integer (bond_downdelay)); - - 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", - json_pack ("[s, [[s, s]]]", "map", - "NM.connection.uuid", nm_connection_get_uuid (port))); - - /* Create a new one. */ - json_array_append_new (params, - json_pack ("{s:s, s:s, s:o, s:s}", "op", "insert", "table", "Port", - "row", row, "uuid-name", "rowPort")); + NMSettingOvsPort *s_ovs_port; + const char * vlan_mode = NULL; + guint tag = 0; + const char * lacp = NULL; + const char * bond_mode = NULL; + guint bond_updelay = 0; + guint bond_downdelay = 0; + json_t * row; + + s_ovs_port = nm_connection_get_setting_ovs_port(port); + + row = json_object(); + + if (s_ovs_port) { + vlan_mode = nm_setting_ovs_port_get_vlan_mode(s_ovs_port); + tag = nm_setting_ovs_port_get_tag(s_ovs_port); + lacp = nm_setting_ovs_port_get_lacp(s_ovs_port); + bond_mode = nm_setting_ovs_port_get_bond_mode(s_ovs_port); + bond_updelay = nm_setting_ovs_port_get_bond_updelay(s_ovs_port); + bond_downdelay = nm_setting_ovs_port_get_bond_downdelay(s_ovs_port); + } + + if (vlan_mode) + json_object_set_new(row, "vlan_mode", json_string(vlan_mode)); + if (tag) + json_object_set_new(row, "tag", json_integer(tag)); + if (lacp) + json_object_set_new(row, "lacp", json_string(lacp)); + if (bond_mode) + json_object_set_new(row, "bond_mode", json_string(bond_mode)); + if (bond_updelay) + json_object_set_new(row, "bond_updelay", json_integer(bond_updelay)); + if (bond_downdelay) + json_object_set_new(row, "bond_downdelay", json_integer(bond_downdelay)); + + 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", + json_pack("[s, [[s, s]]]", "map", "NM.connection.uuid", nm_connection_get_uuid(port))); + + /* Create a new one. */ + json_array_append_new(params, + json_pack("{s:s, s:s, s:o, s:s}", + "op", + "insert", + "table", + "Port", + "row", + row, + "uuid-name", + "rowPort")); } /** @@ -491,59 +586,67 @@ _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, - NMDevice *bridge_device, - json_t *new_ports, - const char *cloned_mac) +_insert_bridge(json_t * params, + NMConnection *bridge, + NMDevice * bridge_device, + json_t * new_ports, + const char * cloned_mac) { - NMSettingOvsBridge *s_ovs_bridge; - const char *fail_mode = NULL; - gboolean mcast_snooping_enable = FALSE; - gboolean rstp_enable = FALSE; - gboolean stp_enable = FALSE; - const char *datapath_type = NULL; - json_t *row; - - s_ovs_bridge = nm_connection_get_setting_ovs_bridge (bridge); - - row = json_object (); - - if (s_ovs_bridge) { - fail_mode = nm_setting_ovs_bridge_get_fail_mode (s_ovs_bridge); - mcast_snooping_enable = nm_setting_ovs_bridge_get_mcast_snooping_enable (s_ovs_bridge); - rstp_enable = nm_setting_ovs_bridge_get_rstp_enable (s_ovs_bridge); - stp_enable = nm_setting_ovs_bridge_get_stp_enable (s_ovs_bridge); - datapath_type = nm_setting_ovs_bridge_get_datapath_type (s_ovs_bridge); - } - - if (fail_mode) - json_object_set_new (row, "fail_mode", json_string (fail_mode)); - if (mcast_snooping_enable) - json_object_set_new (row, "mcast_snooping_enable", json_boolean (mcast_snooping_enable)); - if (rstp_enable) - json_object_set_new (row, "rstp_enable", json_boolean (rstp_enable)); - if (stp_enable) - json_object_set_new (row, "stp_enable", json_boolean (stp_enable)); - if (datapath_type) - json_object_set_new (row, "datapath_type", json_string (datapath_type)); - - 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", - 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", - "row", row, "uuid-name", "rowBridge")); + NMSettingOvsBridge *s_ovs_bridge; + const char * fail_mode = NULL; + gboolean mcast_snooping_enable = FALSE; + gboolean rstp_enable = FALSE; + gboolean stp_enable = FALSE; + const char * datapath_type = NULL; + json_t * row; + + s_ovs_bridge = nm_connection_get_setting_ovs_bridge(bridge); + + row = json_object(); + + if (s_ovs_bridge) { + fail_mode = nm_setting_ovs_bridge_get_fail_mode(s_ovs_bridge); + mcast_snooping_enable = nm_setting_ovs_bridge_get_mcast_snooping_enable(s_ovs_bridge); + rstp_enable = nm_setting_ovs_bridge_get_rstp_enable(s_ovs_bridge); + stp_enable = nm_setting_ovs_bridge_get_stp_enable(s_ovs_bridge); + datapath_type = nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge); + } + + if (fail_mode) + json_object_set_new(row, "fail_mode", json_string(fail_mode)); + if (mcast_snooping_enable) + json_object_set_new(row, "mcast_snooping_enable", json_boolean(mcast_snooping_enable)); + if (rstp_enable) + json_object_set_new(row, "rstp_enable", json_boolean(rstp_enable)); + if (stp_enable) + json_object_set_new(row, "stp_enable", json_boolean(stp_enable)); + if (datapath_type) + json_object_set_new(row, "datapath_type", json_string(datapath_type)); + + 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", + 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", + "row", + row, + "uuid-name", + "rowBridge")); } /** @@ -553,12 +656,22 @@ _insert_bridge (json_t *params, * of the transaction it is in. */ static json_t * -_inc_next_cfg (const char *db_uuid) +_inc_next_cfg(const char *db_uuid) { - return json_pack ("{s:s, s:s, s:[[s, s, i]], s:[[s, s, [s, s]]]}", - "op", "mutate", "table", "Open_vSwitch", - "mutations", "next_cfg", "+=", 1, - "where", "_uuid", "==", "uuid", db_uuid); + return json_pack("{s:s, s:s, s:[[s, s, i]], s:[[s, s, [s, s]]]}", + "op", + "mutate", + "table", + "Open_vSwitch", + "mutations", + "next_cfg", + "+=", + 1, + "where", + "_uuid", + "==", + "uuid", + db_uuid); } /** @@ -568,160 +681,165 @@ _inc_next_cfg (const char *db_uuid) * a parent @port and @bridge if needed. */ static void -_add_interface (NMOvsdb *self, json_t *params, - NMConnection *bridge, NMConnection *port, NMConnection *interface, - NMDevice *bridge_device, NMDevice *interface_device) +_add_interface(NMOvsdb * self, + json_t * params, + NMConnection *bridge, + NMConnection *port, + NMConnection *interface, + NMDevice * bridge_device, + NMDevice * interface_device) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GHashTableIter iter; - const char *bridge_uuid; - const char *port_uuid; - const char *interface_uuid; - const char *bridge_name; - const char *port_name; - const char *interface_name; - OpenvswitchBridge *ovs_bridge = NULL; - OpenvswitchPort *ovs_port = NULL; - OpenvswitchInterface *ovs_interface = NULL; - nm_auto_decref_json json_t *bridges = NULL; - nm_auto_decref_json json_t *new_bridges = NULL; - nm_auto_decref_json json_t *ports = NULL; - nm_auto_decref_json json_t *new_ports = NULL; - nm_auto_decref_json json_t *interfaces = NULL; - nm_auto_decref_json json_t *new_interfaces = NULL; - gboolean has_interface = FALSE; - gboolean interface_is_internal; - gs_free char *bridge_cloned_mac = NULL; - gs_free char *interface_cloned_mac = NULL; - GError *error = NULL; - int pi; - int ii; - - bridges = json_array (); - ports = json_array (); - interfaces = json_array (); - new_bridges = json_array (); - new_ports = json_array (); - new_interfaces = json_array (); - - bridge_name = nm_connection_get_interface_name (bridge); - port_name = nm_connection_get_interface_name (port); - interface_name = nm_connection_get_interface_name (interface); - interface_is_internal = nm_streq0 (bridge_name, interface_name); - - /* Determine cloned MAC addresses */ - if (!nm_device_hw_addr_get_cloned (bridge_device, - bridge, - FALSE, - &bridge_cloned_mac, - NULL, - &error)) { - _LOGW ("Cannot determine cloned mac for OVS %s '%s': %s", - "bridge", - bridge_name, - error->message); - g_clear_error (&error); - } - - if (!nm_device_hw_addr_get_cloned (interface_device, - interface, - FALSE, - &interface_cloned_mac, - NULL, - &error)) { - _LOGW ("Cannot determine cloned mac for OVS %s '%s': %s", - "interface", - interface_name, - error->message); - g_clear_error (&error); - } - - if ( interface_is_internal - && !bridge_cloned_mac - && interface_cloned_mac) { - _LOGT ("'%s' is a local ovs-interface, the MAC will be set on ovs-bridge '%s'", - interface_name, bridge_name); - bridge_cloned_mac = g_steal_pointer (&interface_cloned_mac); - } - - g_hash_table_iter_init (&iter, priv->bridges); - while (g_hash_table_iter_next (&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { - json_array_append_new (bridges, json_pack ("[s, s]", "uuid", bridge_uuid)); - - if ( g_strcmp0 (ovs_bridge->name, bridge_name) != 0 - || g_strcmp0 (ovs_bridge->connection_uuid, nm_connection_get_uuid (bridge)) != 0) - continue; - - for (pi = 0; pi < ovs_bridge->ports->len; pi++) { - port_uuid = g_ptr_array_index (ovs_bridge->ports, pi); - ovs_port = g_hash_table_lookup (priv->ports, port_uuid); - - json_array_append_new (ports, json_pack ("[s, s]", "uuid", port_uuid)); - - if (!ovs_port) { - /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW ("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); - continue; - } else if ( strcmp (ovs_port->name, port_name) != 0 - || g_strcmp0 (ovs_port->connection_uuid, nm_connection_get_uuid (port)) != 0) { - continue; - } - - for (ii = 0; ii < ovs_port->interfaces->len; ii++) { - interface_uuid = g_ptr_array_index (ovs_port->interfaces, ii); - ovs_interface = g_hash_table_lookup (priv->interfaces, interface_uuid); - - json_array_append_new (interfaces, json_pack ("[s, s]", "uuid", interface_uuid)); - - if (!ovs_interface) { - /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW ("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); - } else if ( strcmp (ovs_interface->name, interface_name) == 0 - && g_strcmp0 (ovs_interface->connection_uuid, nm_connection_get_uuid (interface)) == 0) { - has_interface = TRUE; - } - } - - break; - } - - break; - } - - json_array_extend (new_bridges, bridges); - json_array_extend (new_ports, ports); - json_array_extend (new_interfaces, interfaces); - - if (json_array_size (interfaces) == 0) { - /* Need to create a port. */ - if (json_array_size (ports) == 0) { - /* Need to create a bridge. */ - _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, bridge_device, new_ports, bridge_cloned_mac); - } else { - /* Bridge already exists. */ - g_return_if_fail (ovs_bridge); - _expect_bridge_ports (params, ovs_bridge->name, ports); - _set_bridge_ports (params, bridge_name, new_ports); - if (bridge_cloned_mac && interface_is_internal) - _set_bridge_mac (params, bridge_name, bridge_cloned_mac); - } - - json_array_append_new (new_ports, json_pack ("[s, s]", "named-uuid", "rowPort")); - _insert_port (params, port, new_interfaces); - } else { - /* Port already exists */ - g_return_if_fail (ovs_port); - _expect_port_interfaces (params, ovs_port->name, interfaces); - _set_port_interfaces (params, port_name, new_interfaces); - } - - if (!has_interface) { - _insert_interface (params, interface, interface_device, interface_cloned_mac); - json_array_append_new (new_interfaces, json_pack ("[s, s]", "named-uuid", "rowInterface")); - } + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + GHashTableIter iter; + const char * bridge_uuid; + const char * port_uuid; + const char * interface_uuid; + const char * bridge_name; + const char * port_name; + const char * interface_name; + OpenvswitchBridge * ovs_bridge = NULL; + OpenvswitchPort * ovs_port = NULL; + OpenvswitchInterface *ovs_interface = NULL; + nm_auto_decref_json json_t *bridges = NULL; + nm_auto_decref_json json_t *new_bridges = NULL; + nm_auto_decref_json json_t *ports = NULL; + nm_auto_decref_json json_t *new_ports = NULL; + nm_auto_decref_json json_t *interfaces = NULL; + nm_auto_decref_json json_t *new_interfaces = NULL; + gboolean has_interface = FALSE; + gboolean interface_is_internal; + gs_free char * bridge_cloned_mac = NULL; + gs_free char * interface_cloned_mac = NULL; + GError * error = NULL; + int pi; + int ii; + + bridges = json_array(); + ports = json_array(); + interfaces = json_array(); + new_bridges = json_array(); + new_ports = json_array(); + new_interfaces = json_array(); + + bridge_name = nm_connection_get_interface_name(bridge); + port_name = nm_connection_get_interface_name(port); + interface_name = nm_connection_get_interface_name(interface); + interface_is_internal = nm_streq0(bridge_name, interface_name); + + /* Determine cloned MAC addresses */ + if (!nm_device_hw_addr_get_cloned(bridge_device, + bridge, + FALSE, + &bridge_cloned_mac, + NULL, + &error)) { + _LOGW("Cannot determine cloned mac for OVS %s '%s': %s", + "bridge", + bridge_name, + error->message); + g_clear_error(&error); + } + + if (!nm_device_hw_addr_get_cloned(interface_device, + interface, + FALSE, + &interface_cloned_mac, + NULL, + &error)) { + _LOGW("Cannot determine cloned mac for OVS %s '%s': %s", + "interface", + interface_name, + error->message); + g_clear_error(&error); + } + + if (interface_is_internal && !bridge_cloned_mac && interface_cloned_mac) { + _LOGT("'%s' is a local ovs-interface, the MAC will be set on ovs-bridge '%s'", + interface_name, + bridge_name); + bridge_cloned_mac = g_steal_pointer(&interface_cloned_mac); + } + + g_hash_table_iter_init(&iter, priv->bridges); + while (g_hash_table_iter_next(&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { + json_array_append_new(bridges, json_pack("[s, s]", "uuid", bridge_uuid)); + + if (g_strcmp0(ovs_bridge->name, bridge_name) != 0 + || g_strcmp0(ovs_bridge->connection_uuid, nm_connection_get_uuid(bridge)) != 0) + continue; + + for (pi = 0; pi < ovs_bridge->ports->len; pi++) { + port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); + ovs_port = g_hash_table_lookup(priv->ports, port_uuid); + + json_array_append_new(ports, json_pack("[s, s]", "uuid", port_uuid)); + + if (!ovs_port) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); + continue; + } else if (strcmp(ovs_port->name, port_name) != 0 + || g_strcmp0(ovs_port->connection_uuid, nm_connection_get_uuid(port)) != 0) { + continue; + } + + for (ii = 0; ii < ovs_port->interfaces->len; ii++) { + interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); + ovs_interface = g_hash_table_lookup(priv->interfaces, interface_uuid); + + json_array_append_new(interfaces, json_pack("[s, s]", "uuid", interface_uuid)); + + if (!ovs_interface) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); + } else if (strcmp(ovs_interface->name, interface_name) == 0 + && g_strcmp0(ovs_interface->connection_uuid, + nm_connection_get_uuid(interface)) + == 0) { + has_interface = TRUE; + } + } + + break; + } + + break; + } + + json_array_extend(new_bridges, bridges); + json_array_extend(new_ports, ports); + json_array_extend(new_interfaces, interfaces); + + if (json_array_size(interfaces) == 0) { + /* Need to create a port. */ + if (json_array_size(ports) == 0) { + /* Need to create a bridge. */ + _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, bridge_device, new_ports, bridge_cloned_mac); + } else { + /* Bridge already exists. */ + g_return_if_fail(ovs_bridge); + _expect_bridge_ports(params, ovs_bridge->name, ports); + _set_bridge_ports(params, bridge_name, new_ports); + if (bridge_cloned_mac && interface_is_internal) + _set_bridge_mac(params, bridge_name, bridge_cloned_mac); + } + + json_array_append_new(new_ports, json_pack("[s, s]", "named-uuid", "rowPort")); + _insert_port(params, port, new_interfaces); + } else { + /* Port already exists */ + g_return_if_fail(ovs_port); + _expect_port_interfaces(params, ovs_port->name, interfaces); + _set_port_interfaces(params, port_name, new_interfaces); + } + + if (!has_interface) { + _insert_interface(params, interface, interface_device, interface_cloned_mac); + json_array_append_new(new_interfaces, json_pack("[s, s]", "named-uuid", "rowInterface")); + } } /** @@ -731,104 +849,104 @@ _add_interface (NMOvsdb *self, json_t *params, * if last item is removed from them. */ static void -_delete_interface (NMOvsdb *self, json_t *params, const char *ifname) +_delete_interface(NMOvsdb *self, json_t *params, const char *ifname) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GHashTableIter iter; - char *bridge_uuid; - char *port_uuid; - char *interface_uuid; - OpenvswitchBridge *ovs_bridge; - OpenvswitchPort *ovs_port; - OpenvswitchInterface *ovs_interface; - nm_auto_decref_json json_t *bridges = NULL; - nm_auto_decref_json json_t *new_bridges = NULL; - gboolean bridges_changed; - gboolean ports_changed; - gboolean interfaces_changed; - int pi; - int ii; - - bridges = json_array (); - new_bridges = json_array (); - bridges_changed = FALSE; - - g_hash_table_iter_init (&iter, priv->bridges); - while (g_hash_table_iter_next (&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { - nm_auto_decref_json json_t *ports = NULL; - nm_auto_decref_json json_t *new_ports = NULL; - - ports = json_array (); - new_ports = json_array (); - ports_changed = FALSE; - - json_array_append_new (bridges, json_pack ("[s,s]", "uuid", bridge_uuid)); - - for (pi = 0; pi < ovs_bridge->ports->len; pi++) { - nm_auto_decref_json json_t *interfaces = NULL; - nm_auto_decref_json json_t *new_interfaces = NULL; - - interfaces = json_array (); - new_interfaces = json_array (); - port_uuid = g_ptr_array_index (ovs_bridge->ports, pi); - ovs_port = g_hash_table_lookup (priv->ports, port_uuid); - - json_array_append_new (ports, json_pack ("[s,s]", "uuid", port_uuid)); - - interfaces_changed = FALSE; - - if (!ovs_port) { - /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW ("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); - continue; - } - - for (ii = 0; ii < ovs_port->interfaces->len; ii++) { - interface_uuid = g_ptr_array_index (ovs_port->interfaces, ii); - ovs_interface = g_hash_table_lookup (priv->interfaces, interface_uuid); - - json_array_append_new (interfaces, json_pack ("[s,s]", "uuid", interface_uuid)); - - if (ovs_interface) { - if (strcmp (ovs_interface->name, ifname) == 0) { - /* skip the interface */ - interfaces_changed = TRUE; - continue; - } - } else { - /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW ("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); - } - - json_array_append_new (new_interfaces, json_pack ("[s,s]", "uuid", interface_uuid)); - } - - if (json_array_size (new_interfaces) == 0) { - ports_changed = TRUE; - } else { - if (interfaces_changed) { - _expect_port_interfaces (params, ovs_port->name, interfaces); - _set_port_interfaces (params, ovs_port->name, new_interfaces); - } - json_array_append_new (new_ports, json_pack ("[s,s]", "uuid", port_uuid)); - } - } - - if (json_array_size (new_ports) == 0) { - bridges_changed = TRUE; - } else { - if (ports_changed) { - _expect_bridge_ports (params, ovs_bridge->name, ports); - _set_bridge_ports (params, ovs_bridge->name, new_ports); - } - json_array_append_new (new_bridges, json_pack ("[s,s]", "uuid", bridge_uuid)); - } - } - - if (bridges_changed) { - _expect_ovs_bridges (params, priv->db_uuid, bridges); - _set_ovs_bridges (params, priv->db_uuid, new_bridges); - } + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + GHashTableIter iter; + char * bridge_uuid; + char * port_uuid; + char * interface_uuid; + OpenvswitchBridge * ovs_bridge; + OpenvswitchPort * ovs_port; + OpenvswitchInterface *ovs_interface; + nm_auto_decref_json json_t *bridges = NULL; + nm_auto_decref_json json_t *new_bridges = NULL; + gboolean bridges_changed; + gboolean ports_changed; + gboolean interfaces_changed; + int pi; + int ii; + + bridges = json_array(); + new_bridges = json_array(); + bridges_changed = FALSE; + + g_hash_table_iter_init(&iter, priv->bridges); + while (g_hash_table_iter_next(&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { + nm_auto_decref_json json_t *ports = NULL; + nm_auto_decref_json json_t *new_ports = NULL; + + ports = json_array(); + new_ports = json_array(); + ports_changed = FALSE; + + json_array_append_new(bridges, json_pack("[s,s]", "uuid", bridge_uuid)); + + for (pi = 0; pi < ovs_bridge->ports->len; pi++) { + nm_auto_decref_json json_t *interfaces = NULL; + nm_auto_decref_json json_t *new_interfaces = NULL; + + interfaces = json_array(); + new_interfaces = json_array(); + port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); + ovs_port = g_hash_table_lookup(priv->ports, port_uuid); + + json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid)); + + interfaces_changed = FALSE; + + if (!ovs_port) { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); + continue; + } + + for (ii = 0; ii < ovs_port->interfaces->len; ii++) { + interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); + ovs_interface = g_hash_table_lookup(priv->interfaces, interface_uuid); + + json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid)); + + if (ovs_interface) { + if (strcmp(ovs_interface->name, ifname) == 0) { + /* skip the interface */ + interfaces_changed = TRUE; + continue; + } + } else { + /* This would be a violation of ovsdb's reference integrity (a bug). */ + _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); + } + + json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid)); + } + + if (json_array_size(new_interfaces) == 0) { + ports_changed = TRUE; + } else { + if (interfaces_changed) { + _expect_port_interfaces(params, ovs_port->name, interfaces); + _set_port_interfaces(params, ovs_port->name, new_interfaces); + } + json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); + } + } + + if (json_array_size(new_ports) == 0) { + bridges_changed = TRUE; + } else { + if (ports_changed) { + _expect_bridge_ports(params, ovs_bridge->name, ports); + _set_bridge_ports(params, ovs_bridge->name, new_ports); + } + json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", bridge_uuid)); + } + } + + if (bridges_changed) { + _expect_ovs_bridges(params, priv->db_uuid, bridges); + _set_ovs_bridges(params, priv->db_uuid, new_bridges); + } } /** @@ -842,87 +960,111 @@ _delete_interface (NMOvsdb *self, json_t *params, const char *ifname) * include an up to date bridge list in their transactions to rule out races). */ static void -ovsdb_next_command (NMOvsdb *self) +ovsdb_next_command(NMOvsdb *self) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - OvsdbMethodCall *call = NULL; - char *cmd; - nm_auto_decref_json json_t *msg = NULL; - json_t *params; - - if (!priv->conn) - return; - if (!priv->calls->len) - return; - call = &g_array_index (priv->calls, OvsdbMethodCall, 0); - if (call->id != COMMAND_PENDING) - return; - call->id = priv->seq++; - - 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:[]}]" - "}]}", - "id", call->id, - "method", "monitor", "params", "Open_vSwitch", - "Bridge", "columns", "name", "ports", "external_ids", - "Port", "columns", "name", "interfaces", "external_ids", - "Interface", "columns", "name", "type", "external_ids", "error", - "Open_vSwitch", "columns"); - break; - case OVSDB_ADD_INTERFACE: - params = json_array (); - 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, - call->bridge_device, call->interface_device); - - msg = json_pack ("{s:i, s:s, s:o}", - "id", call->id, - "method", "transact", "params", params); - break; - case OVSDB_DEL_INTERFACE: - params = json_array (); - json_array_append_new (params, json_string ("Open_vSwitch")); - json_array_append_new (params, _inc_next_cfg (priv->db_uuid)); - - _delete_interface (self, params, call->ifname); - - msg = json_pack ("{s:i, s:s, s:o}", - "id", call->id, - "method", "transact", "params", params); - break; - case OVSDB_SET_INTERFACE_MTU: - params = json_array (); - json_array_append_new (params, json_string ("Open_vSwitch")); - json_array_append_new (params, _inc_next_cfg (priv->db_uuid)); - - json_array_append_new (params, - json_pack ("{s:s, s:s, s:{s: i}, s:[[s, s, s]]}", - "op", "update", - "table", "Interface", - "row", "mtu_request", call->mtu, - "where", "name", "==", call->ifname)); - - msg = json_pack ("{s:i, s:s, s:o}", - "id", call->id, - "method", "transact", "params", params); - break; - } - - g_return_if_fail (msg); - _LOGT_call ("send", call, msg); - cmd = json_dumps (msg, 0); - - g_string_append (priv->output, cmd); - free (cmd); - - ovsdb_write (self); + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + OvsdbMethodCall * call = NULL; + char * cmd; + nm_auto_decref_json json_t *msg = NULL; + json_t * params; + + if (!priv->conn) + return; + if (!priv->calls->len) + return; + call = &g_array_index(priv->calls, OvsdbMethodCall, 0); + if (call->id != COMMAND_PENDING) + return; + call->id = priv->seq++; + + 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:[]}]" + "}]}", + "id", + call->id, + "method", + "monitor", + "params", + "Open_vSwitch", + "Bridge", + "columns", + "name", + "ports", + "external_ids", + "Port", + "columns", + "name", + "interfaces", + "external_ids", + "Interface", + "columns", + "name", + "type", + "external_ids", + "error", + "Open_vSwitch", + "columns"); + break; + case OVSDB_ADD_INTERFACE: + params = json_array(); + 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, + call->bridge_device, + call->interface_device); + + msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); + break; + case OVSDB_DEL_INTERFACE: + params = json_array(); + json_array_append_new(params, json_string("Open_vSwitch")); + json_array_append_new(params, _inc_next_cfg(priv->db_uuid)); + + _delete_interface(self, params, call->ifname); + + msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); + break; + case OVSDB_SET_INTERFACE_MTU: + params = json_array(); + json_array_append_new(params, json_string("Open_vSwitch")); + json_array_append_new(params, _inc_next_cfg(priv->db_uuid)); + + json_array_append_new(params, + json_pack("{s:s, s:s, s:{s: i}, s:[[s, s, s]]}", + "op", + "update", + "table", + "Interface", + "row", + "mtu_request", + call->mtu, + "where", + "name", + "==", + call->ifname)); + + msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); + break; + } + + g_return_if_fail(msg); + _LOGT_call("send", call, msg); + cmd = json_dumps(msg, 0); + + g_string_append(priv->output, cmd); + free(cmd); + + ovsdb_write(self); } /** @@ -939,48 +1081,50 @@ ovsdb_next_command (NMOvsdb *self) * [ "uuid", "185c93f6-0b39-424e-8587-77d074aa7ce0" ], ... ] ] */ static void -_uuids_to_array (GPtrArray *array, const json_t *items) +_uuids_to_array(GPtrArray *array, const json_t *items) { - const char *key; - json_t *value; - size_t index = 0; - json_t *set_value; - size_t set_index; - - while (index < json_array_size (items)) { - key = json_string_value (json_array_get (items, index)); - index++; - value = json_array_get (items, index); - index++; - - if (!value) - return; - - if (g_strcmp0 (key, "uuid") == 0 && json_is_string (value)) { - g_ptr_array_add (array, g_strdup (json_string_value (value))); - } else if (g_strcmp0 (key, "set") == 0 && json_is_array (value)) { - json_array_foreach (value, set_index, set_value) { - _uuids_to_array (array, set_value); - } - } - } + const char *key; + json_t * value; + size_t index = 0; + json_t * set_value; + size_t set_index; + + while (index < json_array_size(items)) { + key = json_string_value(json_array_get(items, index)); + index++; + value = json_array_get(items, index); + index++; + + if (!value) + return; + + if (g_strcmp0(key, "uuid") == 0 && json_is_string(value)) { + g_ptr_array_add(array, g_strdup(json_string_value(value))); + } else if (g_strcmp0(key, "set") == 0 && json_is_array(value)) { + json_array_foreach(value, set_index, set_value) + { + _uuids_to_array(array, set_value); + } + } + } } static char * -_connection_uuid_from_external_ids (json_t *external_ids) +_connection_uuid_from_external_ids(json_t *external_ids) { - json_t *value; - size_t index; + json_t *value; + size_t index; - if (g_strcmp0 ("map", json_string_value (json_array_get (external_ids, 0))) != 0) - return NULL; + if (g_strcmp0("map", json_string_value(json_array_get(external_ids, 0))) != 0) + return NULL; - json_array_foreach (json_array_get (external_ids, 1), index, value) { - if (g_strcmp0 ("NM.connection.uuid", json_string_value (json_array_get (value, 0))) == 0) - return g_strdup (json_string_value (json_array_get (value, 1))); - } + json_array_foreach(json_array_get(external_ids, 1), index, value) + { + if (g_strcmp0("NM.connection.uuid", json_string_value(json_array_get(value, 0))) == 0) + return g_strdup(json_string_value(json_array_get(value, 1))); + } - return NULL; + return NULL; } /** @@ -991,205 +1135,266 @@ _connection_uuid_from_external_ids (json_t *external_ids) * whether the changes are done by us or externally. */ static void -ovsdb_got_update (NMOvsdb *self, json_t *msg) +ovsdb_got_update(NMOvsdb *self, json_t *msg) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - json_t *ovs = NULL; - json_t *bridge = NULL; - json_t *port = NULL; - json_t *interface = NULL; - json_t *items; - json_t *external_ids; - json_error_t json_error = { 0, }; - void *iter; - const char *name; - const char *key; - const char *type; - json_t *value; - OpenvswitchBridge *ovs_bridge; - OpenvswitchPort *ovs_port; - OpenvswitchInterface *ovs_interface; - - if (json_unpack_ex (msg, &json_error, 0, "{s?:o, s?:o, s?:o, s?:o}", - "Open_vSwitch", &ovs, - "Bridge", &bridge, - "Port", &port, - "Interface", &interface) == -1) { - /* This doesn't really have to be an error; the key might - * be missing if there really are no bridges present. */ - _LOGD ("Bad update: %s", json_error.text); - } - - if (ovs) { - iter = json_object_iter (ovs); - priv->db_uuid = iter ? g_strdup (json_object_iter_key (iter)) : NULL; - } - - /* Interfaces */ - json_object_foreach (interface, key, value) { - json_t *error = NULL; - gboolean old = FALSE; - gboolean new = FALSE; - - if (json_unpack (value, "{s:{}}", "old") == 0) - old = TRUE; - - if (json_unpack (value, "{s:{s:s, s:s, s?:o, s:o}}", "new", - "name", &name, - "type", &type, - "error", &error, - "external_ids", &external_ids) == 0) - new = TRUE; - - if (old) { - ovs_interface = g_hash_table_lookup (priv->interfaces, key); - if (!ovs_interface) { - _LOGW ("Interface '%s' was not seen", key); - } else if (!new || strcmp (ovs_interface->name, name) != 0) { - old = FALSE; - _LOGT ("removed an '%s' interface: %s%s%s", - ovs_interface->type, ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - if (g_strcmp0 (ovs_interface->type, "internal") == 0) { - /* Currently the factory only creates NMDevices for - * internal interfaces. Ignore the rest. */ - g_signal_emit (self, signals[DEVICE_REMOVED], 0, - ovs_interface->name, NM_DEVICE_TYPE_OVS_INTERFACE); - } - } - g_hash_table_remove (priv->interfaces, key); - } - - if (new) { - ovs_interface = g_slice_new (OpenvswitchInterface); - ovs_interface->name = g_strdup (name); - ovs_interface->type = g_strdup (type); - ovs_interface->connection_uuid = _connection_uuid_from_external_ids (external_ids); - g_hash_table_insert (priv->interfaces, g_strdup (key), ovs_interface); - if (old) { - _LOGT ("changed an '%s' interface: %s%s%s", type, ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - } else { - _LOGT ("added an '%s' interface: %s%s%s", - ovs_interface->type, ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - if (g_strcmp0 (ovs_interface->type, "internal") == 0) { - /* Currently the factory only creates NMDevices for - * internal interfaces. Ignore the rest. */ - g_signal_emit (self, signals[DEVICE_ADDED], 0, - ovs_interface->name, NM_DEVICE_TYPE_OVS_INTERFACE); - } - } - /* The error is a string. No error is indicated by an empty set, - * because why the fuck not: [ "set": [] ] */ - if (error && json_is_string (error)) { - g_signal_emit (self, signals[INTERFACE_FAILED], 0, - ovs_interface->name, - ovs_interface->connection_uuid, - json_string_value (error)); - } - } - } - - /* Ports */ - json_object_foreach (port, key, value) { - gboolean old = FALSE; - gboolean new = FALSE; - - if (json_unpack (value, "{s:{}}", "old") == 0) - old = TRUE; - - if (json_unpack (value, "{s:{s:s, s:o, s:o}}", "new", - "name", &name, - "external_ids", &external_ids, - "interfaces", &items) == 0) - new = TRUE; - - if (old) { - ovs_port = g_hash_table_lookup (priv->ports, key); - if (!new || g_strcmp0 (ovs_port->name, name) != 0) { - old = FALSE; - _LOGT ("removed a port: %s%s%s", ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - g_signal_emit (self, signals[DEVICE_REMOVED], 0, - ovs_port->name, NM_DEVICE_TYPE_OVS_PORT); - } - g_hash_table_remove (priv->ports, key); - } - - if (new) { - ovs_port = g_slice_new (OpenvswitchPort); - ovs_port->name = g_strdup (name); - ovs_port->connection_uuid = _connection_uuid_from_external_ids (external_ids); - ovs_port->interfaces = g_ptr_array_new_with_free_func (g_free); - _uuids_to_array (ovs_port->interfaces, items); - g_hash_table_insert (priv->ports, g_strdup (key), ovs_port); - if (old) { - _LOGT ("changed a port: %s%s%s", ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - } else { - _LOGT ("added a port: %s%s%s", ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - g_signal_emit (self, signals[DEVICE_ADDED], 0, - ovs_port->name, NM_DEVICE_TYPE_OVS_PORT); - } - } - } - - /* Bridges */ - json_object_foreach (bridge, key, value) { - gboolean old = FALSE; - gboolean new = FALSE; - - if (json_unpack (value, "{s:{}}", "old") == 0) - old = TRUE; - - if (json_unpack (value, "{s:{s:s, s:o, s:o}}", "new", - "name", &name, - "external_ids", &external_ids, - "ports", &items) == 0) - new = TRUE; - - if (old) { - ovs_bridge = g_hash_table_lookup (priv->bridges, key); - if (!new || g_strcmp0 (ovs_bridge->name, name) != 0) { - old = FALSE; - _LOGT ("removed a bridge: %s%s%s", ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - g_signal_emit (self, signals[DEVICE_REMOVED], 0, - ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE); - } - g_hash_table_remove (priv->bridges, key); - } - - if (new) { - ovs_bridge = g_slice_new (OpenvswitchBridge); - ovs_bridge->name = g_strdup (name); - ovs_bridge->connection_uuid = _connection_uuid_from_external_ids (external_ids); - ovs_bridge->ports = g_ptr_array_new_with_free_func (g_free); - _uuids_to_array (ovs_bridge->ports, items); - g_hash_table_insert (priv->bridges, g_strdup (key), ovs_bridge); - if (old) { - _LOGT ("changed a bridge: %s%s%s", ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - } else { - _LOGT ("added a bridge: %s%s%s", ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - g_signal_emit (self, signals[DEVICE_ADDED], 0, - ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE); - } - } - } - + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + json_t * ovs = NULL; + json_t * bridge = NULL; + json_t * port = NULL; + json_t * interface = NULL; + json_t * items; + json_t * external_ids; + json_error_t json_error = { + 0, + }; + void * iter; + const char * name; + const char * key; + const char * type; + json_t * value; + OpenvswitchBridge * ovs_bridge; + OpenvswitchPort * ovs_port; + OpenvswitchInterface *ovs_interface; + + if (json_unpack_ex(msg, + &json_error, + 0, + "{s?:o, s?:o, s?:o, s?:o}", + "Open_vSwitch", + &ovs, + "Bridge", + &bridge, + "Port", + &port, + "Interface", + &interface) + == -1) { + /* This doesn't really have to be an error; the key might + * be missing if there really are no bridges present. */ + _LOGD("Bad update: %s", json_error.text); + } + + if (ovs) { + iter = json_object_iter(ovs); + priv->db_uuid = iter ? g_strdup(json_object_iter_key(iter)) : NULL; + } + + /* Interfaces */ + json_object_foreach(interface, key, value) + { + json_t * error = NULL; + gboolean old = FALSE; + gboolean new = FALSE; + + if (json_unpack(value, "{s:{}}", "old") == 0) + old = TRUE; + + if (json_unpack(value, + "{s:{s:s, s:s, s?:o, s:o}}", + "new", + "name", + &name, + "type", + &type, + "error", + &error, + "external_ids", + &external_ids) + == 0) + new = TRUE; + + if (old) { + ovs_interface = g_hash_table_lookup(priv->interfaces, key); + if (!ovs_interface) { + _LOGW("Interface '%s' was not seen", key); + } else if (!new || strcmp(ovs_interface->name, name) != 0) { + old = FALSE; + _LOGT("removed an '%s' interface: %s%s%s", + ovs_interface->type, + ovs_interface->name, + ovs_interface->connection_uuid ? ", " : "", + ovs_interface->connection_uuid ?: ""); + if (g_strcmp0(ovs_interface->type, "internal") == 0) { + /* Currently, the factory only creates NMDevices for + * internal interfaces. Ignore the rest. */ + g_signal_emit(self, + signals[DEVICE_REMOVED], + 0, + ovs_interface->name, + NM_DEVICE_TYPE_OVS_INTERFACE); + } + } + g_hash_table_remove(priv->interfaces, key); + } + + if (new) { + ovs_interface = g_slice_new(OpenvswitchInterface); + ovs_interface->name = g_strdup(name); + ovs_interface->type = g_strdup(type); + ovs_interface->connection_uuid = _connection_uuid_from_external_ids(external_ids); + g_hash_table_insert(priv->interfaces, g_strdup(key), ovs_interface); + if (old) { + _LOGT("changed an '%s' interface: %s%s%s", + type, + ovs_interface->name, + ovs_interface->connection_uuid ? ", " : "", + ovs_interface->connection_uuid ?: ""); + } else { + _LOGT("added an '%s' interface: %s%s%s", + ovs_interface->type, + ovs_interface->name, + ovs_interface->connection_uuid ? ", " : "", + ovs_interface->connection_uuid ?: ""); + if (g_strcmp0(ovs_interface->type, "internal") == 0) { + /* Currently, the factory only creates NMDevices for + * internal interfaces. Ignore the rest. */ + g_signal_emit(self, + signals[DEVICE_ADDED], + 0, + ovs_interface->name, + NM_DEVICE_TYPE_OVS_INTERFACE); + } + } + /* The error is a string. No error is indicated by an empty set, + * because why the fuck not: [ "set": [] ] */ + if (error && json_is_string(error)) { + g_signal_emit(self, + signals[INTERFACE_FAILED], + 0, + ovs_interface->name, + ovs_interface->connection_uuid, + json_string_value(error)); + } + } + } + + /* Ports */ + json_object_foreach(port, key, value) + { + gboolean old = FALSE; + gboolean new = FALSE; + + if (json_unpack(value, "{s:{}}", "old") == 0) + old = TRUE; + + if (json_unpack(value, + "{s:{s:s, s:o, s:o}}", + "new", + "name", + &name, + "external_ids", + &external_ids, + "interfaces", + &items) + == 0) + new = TRUE; + + if (old) { + ovs_port = g_hash_table_lookup(priv->ports, key); + if (!new || g_strcmp0(ovs_port->name, name) != 0) { + old = FALSE; + _LOGT("removed a port: %s%s%s", + ovs_port->name, + ovs_port->connection_uuid ? ", " : "", + ovs_port->connection_uuid ?: ""); + g_signal_emit(self, + signals[DEVICE_REMOVED], + 0, + ovs_port->name, + NM_DEVICE_TYPE_OVS_PORT); + } + g_hash_table_remove(priv->ports, key); + } + + if (new) { + ovs_port = g_slice_new(OpenvswitchPort); + ovs_port->name = g_strdup(name); + ovs_port->connection_uuid = _connection_uuid_from_external_ids(external_ids); + ovs_port->interfaces = g_ptr_array_new_with_free_func(g_free); + _uuids_to_array(ovs_port->interfaces, items); + g_hash_table_insert(priv->ports, g_strdup(key), ovs_port); + if (old) { + _LOGT("changed a port: %s%s%s", + ovs_port->name, + ovs_port->connection_uuid ? ", " : "", + ovs_port->connection_uuid ?: ""); + } else { + _LOGT("added a port: %s%s%s", + ovs_port->name, + ovs_port->connection_uuid ? ", " : "", + ovs_port->connection_uuid ?: ""); + g_signal_emit(self, + signals[DEVICE_ADDED], + 0, + ovs_port->name, + NM_DEVICE_TYPE_OVS_PORT); + } + } + } + + /* Bridges */ + json_object_foreach(bridge, key, value) + { + gboolean old = FALSE; + gboolean new = FALSE; + + if (json_unpack(value, "{s:{}}", "old") == 0) + old = TRUE; + + if (json_unpack(value, + "{s:{s:s, s:o, s:o}}", + "new", + "name", + &name, + "external_ids", + &external_ids, + "ports", + &items) + == 0) + new = TRUE; + + if (old) { + ovs_bridge = g_hash_table_lookup(priv->bridges, key); + if (!new || g_strcmp0(ovs_bridge->name, name) != 0) { + old = FALSE; + _LOGT("removed a bridge: %s%s%s", + ovs_bridge->name, + ovs_bridge->connection_uuid ? ", " : "", + ovs_bridge->connection_uuid ?: ""); + g_signal_emit(self, + signals[DEVICE_REMOVED], + 0, + ovs_bridge->name, + NM_DEVICE_TYPE_OVS_BRIDGE); + } + g_hash_table_remove(priv->bridges, key); + } + + if (new) { + ovs_bridge = g_slice_new(OpenvswitchBridge); + ovs_bridge->name = g_strdup(name); + ovs_bridge->connection_uuid = _connection_uuid_from_external_ids(external_ids); + ovs_bridge->ports = g_ptr_array_new_with_free_func(g_free); + _uuids_to_array(ovs_bridge->ports, items); + g_hash_table_insert(priv->bridges, g_strdup(key), ovs_bridge); + if (old) { + _LOGT("changed a bridge: %s%s%s", + ovs_bridge->name, + ovs_bridge->connection_uuid ? ", " : "", + ovs_bridge->connection_uuid ?: ""); + } else { + _LOGT("added a bridge: %s%s%s", + ovs_bridge->name, + ovs_bridge->connection_uuid ? ", " : "", + ovs_bridge->connection_uuid ?: ""); + g_signal_emit(self, + signals[DEVICE_ADDED], + 0, + ovs_bridge->name, + NM_DEVICE_TYPE_OVS_BRIDGE); + } + } + } } /** @@ -1199,123 +1404,138 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg) * seen doing this. */ static void -ovsdb_got_echo (NMOvsdb *self, json_int_t id, json_t *data) +ovsdb_got_echo(NMOvsdb *self, json_int_t id, json_t *data) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - nm_auto_decref_json json_t *msg = NULL; - char *reply; - gboolean output_was_empty; + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + nm_auto_decref_json json_t *msg = NULL; + char * reply; + gboolean output_was_empty; - output_was_empty = priv->output->len == 0; + output_was_empty = priv->output->len == 0; - msg = json_pack ("{s:I, s:O}", "id", id, "result", data); - reply = json_dumps (msg, 0); - g_string_append (priv->output, reply); - free (reply); + msg = json_pack("{s:I, s:O}", "id", id, "result", data); + reply = json_dumps(msg, 0); + g_string_append(priv->output, reply); + free(reply); - if (output_was_empty) - ovsdb_write (self); + if (output_was_empty) + ovsdb_write(self); } /** * ovsdb_got_msg:: * - * Called when when a complete JSON object was seen and unmarshalled. + * Called when a complete JSON object was seen and unmarshalled. * Either finishes a method call or processes a method call. */ static void -ovsdb_got_msg (NMOvsdb *self, json_t *msg) +ovsdb_got_msg(NMOvsdb *self, json_t *msg) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - json_error_t json_error = { 0, }; - json_t *json_id = NULL; - gint64 id = -1; - const char *method = NULL; - json_t *params = NULL; - json_t *result = NULL; - json_t *error = NULL; - OvsdbMethodCall *call = NULL; - OvsdbMethodCallback callback; - gpointer user_data; - gs_free_error GError *local = NULL; - - if (json_unpack_ex (msg, &json_error, 0, "{s?:o, s?:s, s?:o, s?:o, s?:o}", - "id", &json_id, - "method", &method, - "params", ¶ms, - "result", &result, - "error", &error) == -1) { - _LOGW ("couldn't grok the message: %s", json_error.text); - ovsdb_disconnect (self, FALSE, FALSE); - return; - } - - if (json_is_number (json_id)) - id = json_integer_value (json_id); - - if (method) { - /* It's a method call! */ - if (!params) { - _LOGW ("a method call with no params: '%s'", method); - ovsdb_disconnect (self, FALSE, FALSE); - return; - } - - if (g_strcmp0 (method, "update") == 0) { - /* This is a update method call. */ - ovsdb_got_update (self, json_array_get (params, 1)); - } else if (g_strcmp0 (method, "echo") == 0) { - /* This is an echo request. */ - ovsdb_got_echo (self, id, params); - } else { - _LOGW ("got an unknown method call: '%s'", method); - } - return; - } - - if (id > -1) { - /* This is a response to a method call. */ - if (!priv->calls->len) { - _LOGE ("there are no queued calls expecting response %" G_GUINT64_FORMAT, id); - ovsdb_disconnect (self, FALSE, FALSE); - return; - } - call = &g_array_index (priv->calls, OvsdbMethodCall, 0); - if (call->id != id) { - _LOGE ("expected a response to call %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT, call->id, id); - ovsdb_disconnect (self, FALSE, FALSE); - return; - } - /* Cool, we found a corresponding call. Finish it. */ - - _LOGT_call ("response", call, msg); - - if (!json_is_null (error)) { - /* The response contains an error. */ - g_set_error (&local, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error call to OVSDB returned an error: %s", - json_string_value (error)); - } - - callback = call->callback; - user_data = call->user_data; - g_array_remove_index (priv->calls, 0); - callback (self, result, local, user_data); - priv->num_failures = 0; - - /* Don't progress further commands in case the callback hit an error - * and disconnected us. */ - if (!priv->conn) - return; - - /* Now we're free to serialize and send the next command, if any. */ - ovsdb_next_command (self); - - return; - } - - /* This is a message we are not interested in. */ - _LOGW ("got an unknown message, ignoring"); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + json_error_t json_error = { + 0, + }; + json_t * json_id = NULL; + gint64 id = -1; + const char * method = NULL; + json_t * params = NULL; + json_t * result = NULL; + json_t * error = NULL; + OvsdbMethodCall * call = NULL; + OvsdbMethodCallback callback; + gpointer user_data; + gs_free_error GError *local = NULL; + + if (json_unpack_ex(msg, + &json_error, + 0, + "{s?:o, s?:s, s?:o, s?:o, s?:o}", + "id", + &json_id, + "method", + &method, + "params", + ¶ms, + "result", + &result, + "error", + &error) + == -1) { + _LOGW("couldn't grok the message: %s", json_error.text); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + + if (json_is_number(json_id)) + id = json_integer_value(json_id); + + if (method) { + /* It's a method call! */ + if (!params) { + _LOGW("a method call with no params: '%s'", method); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + + if (g_strcmp0(method, "update") == 0) { + /* This is a update method call. */ + ovsdb_got_update(self, json_array_get(params, 1)); + } else if (g_strcmp0(method, "echo") == 0) { + /* This is an echo request. */ + ovsdb_got_echo(self, id, params); + } else { + _LOGW("got an unknown method call: '%s'", method); + } + return; + } + + if (id > -1) { + /* This is a response to a method call. */ + if (!priv->calls->len) { + _LOGE("there are no queued calls expecting response %" G_GUINT64_FORMAT, id); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + call = &g_array_index(priv->calls, OvsdbMethodCall, 0); + if (call->id != id) { + _LOGE("expected a response to call %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT, + call->id, + id); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + /* Cool, we found a corresponding call. Finish it. */ + + _LOGT_call("response", call, msg); + + if (!json_is_null(error)) { + /* The response contains an error. */ + g_set_error(&local, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Error call to OVSDB returned an error: %s", + json_string_value(error)); + } + + callback = call->callback; + user_data = call->user_data; + g_array_remove_index(priv->calls, 0); + callback(self, result, local, user_data); + priv->num_failures = 0; + + /* Don't progress further commands in case the callback hit an error + * and disconnected us. */ + if (!priv->conn) + return; + + /* Now we're free to serialize and send the next command, if any. */ + ovsdb_next_command(self); + + return; + } + + /* This is a message we are not interested in. */ + _LOGW("got an unknown message, ignoring"); } /*****************************************************************************/ @@ -1324,21 +1544,21 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg) * ovsdb socket. */ static size_t -_json_callback (void *buffer, size_t buflen, void *user_data) +_json_callback(void *buffer, size_t buflen, void *user_data) { - NMOvsdb *self = NM_OVSDB (user_data); - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); + NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - if (priv->bufp == priv->input->len) { - /* No more bytes buffered for decoding. */ - return 0; - } + if (priv->bufp == priv->input->len) { + /* No more bytes buffered for decoding. */ + return 0; + } - /* Pass one more byte to the JSON decoder. */ - *(char *)buffer = priv->input->str[priv->bufp]; - priv->bufp++; + /* Pass one more byte to the JSON decoder. */ + *(char *) buffer = priv->input->str[priv->bufp]; + priv->bufp++; - return (size_t)1; + return (size_t) 1; } /** @@ -1348,100 +1568,110 @@ _json_callback (void *buffer, size_t buflen, void *user_data) * the JSON. If we see a complete object, pass it upwards to ovsdb_got_msg(). */ static void -ovsdb_read_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +ovsdb_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMOvsdb *self = NM_OVSDB (user_data); - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GInputStream *stream = G_INPUT_STREAM (source_object); - GError *error = NULL; - gssize size; - json_t *msg; - json_error_t json_error = { 0, }; - - size = g_input_stream_read_finish (stream, res, &error); - if (size == -1) { - /* ovsdb-server was possibly restarted */ - _LOGW ("short read from ovsdb: %s", error->message); - priv->num_failures++; - g_clear_error (&error); - ovsdb_disconnect (self, priv->num_failures <= OVSDB_MAX_FAILURES, FALSE); - return; - } - - g_string_append_len (priv->input, priv->buf, size); - do { - priv->bufp = 0; - /* The callback always eats up only up to a single byte. This makes - * it possible for us to identify complete JSON objects in spite of - * us not knowing the length in advance. */ - msg = json_load_callback (_json_callback, self, JSON_DISABLE_EOF_CHECK, &json_error); - if (msg) { - ovsdb_got_msg (self, msg); - g_string_erase (priv->input, 0, priv->bufp); - } - json_decref (msg); - } while (msg); - - if (!priv->conn) - return; - - if (size) - ovsdb_read (self); + NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GInputStream * stream = G_INPUT_STREAM(source_object); + GError * error = NULL; + gssize size; + json_t * msg; + json_error_t json_error = { + 0, + }; + + size = g_input_stream_read_finish(stream, res, &error); + if (size == -1) { + /* ovsdb-server was possibly restarted */ + _LOGW("short read from ovsdb: %s", error->message); + priv->num_failures++; + g_clear_error(&error); + ovsdb_disconnect(self, priv->num_failures <= OVSDB_MAX_FAILURES, FALSE); + return; + } + + g_string_append_len(priv->input, priv->buf, size); + do { + priv->bufp = 0; + /* The callback always eats up only up to a single byte. This makes + * it possible for us to identify complete JSON objects in spite of + * us not knowing the length in advance. */ + msg = json_load_callback(_json_callback, self, JSON_DISABLE_EOF_CHECK, &json_error); + if (msg) { + ovsdb_got_msg(self, msg); + g_string_erase(priv->input, 0, priv->bufp); + } + json_decref(msg); + } while (msg); + + if (!priv->conn) + return; + + if (size) + ovsdb_read(self); } static void -ovsdb_read (NMOvsdb *self) +ovsdb_read(NMOvsdb *self) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - - g_input_stream_read_async (g_io_stream_get_input_stream (G_IO_STREAM (priv->conn)), - priv->buf, sizeof(priv->buf), - G_PRIORITY_DEFAULT, NULL, ovsdb_read_cb, self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + + g_input_stream_read_async(g_io_stream_get_input_stream(G_IO_STREAM(priv->conn)), + priv->buf, + sizeof(priv->buf), + G_PRIORITY_DEFAULT, + NULL, + ovsdb_read_cb, + self); } static void -ovsdb_write_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +ovsdb_write_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GOutputStream *stream = G_OUTPUT_STREAM (source_object); - NMOvsdb *self = NM_OVSDB (user_data); - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GError *error = NULL; - gssize size; - - size = g_output_stream_write_finish (stream, res, &error); - if (size == -1) { - /* ovsdb-server was possibly restarted */ - _LOGW ("short write to ovsdb: %s", error->message); - priv->num_failures++; - g_clear_error (&error); - ovsdb_disconnect (self, priv->num_failures <= OVSDB_MAX_FAILURES, FALSE); - return; - } - - if (!priv->conn) - return; - - g_string_erase (priv->output, 0, size); - - ovsdb_write (self); + GOutputStream * stream = G_OUTPUT_STREAM(source_object); + NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GError * error = NULL; + gssize size; + + size = g_output_stream_write_finish(stream, res, &error); + if (size == -1) { + /* ovsdb-server was possibly restarted */ + _LOGW("short write to ovsdb: %s", error->message); + priv->num_failures++; + g_clear_error(&error); + ovsdb_disconnect(self, priv->num_failures <= OVSDB_MAX_FAILURES, FALSE); + return; + } + + if (!priv->conn) + return; + + g_string_erase(priv->output, 0, size); + + ovsdb_write(self); } static void -ovsdb_write (NMOvsdb *self) +ovsdb_write(NMOvsdb *self) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GOutputStream *stream; - - if (!priv->output->len) - return; - - stream = g_io_stream_get_output_stream (G_IO_STREAM (priv->conn)); - if (g_output_stream_has_pending (stream)) - return; - - g_output_stream_write_async (stream, - priv->output->str, priv->output->len, - G_PRIORITY_DEFAULT, NULL, ovsdb_write_cb, self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GOutputStream * stream; + + if (!priv->output->len) + return; + + stream = g_io_stream_get_output_stream(G_IO_STREAM(priv->conn)); + if (g_output_stream_has_pending(stream)) + return; + + g_output_stream_write_async(stream, + priv->output->str, + priv->output->len, + G_PRIORITY_DEFAULT, + NULL, + ovsdb_write_cb, + self); } /*****************************************************************************/ @@ -1457,89 +1687,89 @@ ovsdb_write (NMOvsdb *self) * puts us back in sync. */ static void -ovsdb_disconnect (NMOvsdb *self, gboolean retry, gboolean is_disposing) +ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - OvsdbMethodCall *call; - OvsdbMethodCallback callback; - gpointer user_data; - gs_free_error GError *error = NULL; - - nm_assert (!retry || !is_disposing); - - if (!priv->client) - return; - - _LOGD ("disconnecting from ovsdb, retry %d", retry); - - if (retry) { - if (priv->calls->len != 0) - g_array_index (priv->calls, OvsdbMethodCall, 0).id = COMMAND_PENDING; - } else { - nm_utils_error_set_cancelled (&error, is_disposing, "NMOvsdb"); - - while (priv->calls->len) { - call = &g_array_index (priv->calls, OvsdbMethodCall, priv->calls->len - 1); - callback = call->callback; - user_data = call->user_data; - g_array_remove_index (priv->calls, priv->calls->len - 1); - callback (self, NULL, error, user_data); - } - } - - priv->bufp = 0; - g_string_truncate (priv->input, 0); - g_string_truncate (priv->output, 0); - g_clear_object (&priv->client); - g_clear_object (&priv->conn); - nm_clear_g_free (&priv->db_uuid); - nm_clear_g_cancellable (&priv->cancellable); - - if (retry) - ovsdb_try_connect (self); + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + OvsdbMethodCall * call; + OvsdbMethodCallback callback; + gpointer user_data; + gs_free_error GError *error = NULL; + + nm_assert(!retry || !is_disposing); + + if (!priv->client) + return; + + _LOGD("disconnecting from ovsdb, retry %d", retry); + + if (retry) { + if (priv->calls->len != 0) + g_array_index(priv->calls, OvsdbMethodCall, 0).id = COMMAND_PENDING; + } else { + nm_utils_error_set_cancelled(&error, is_disposing, "NMOvsdb"); + + while (priv->calls->len) { + call = &g_array_index(priv->calls, OvsdbMethodCall, priv->calls->len - 1); + callback = call->callback; + user_data = call->user_data; + g_array_remove_index(priv->calls, priv->calls->len - 1); + callback(self, NULL, error, user_data); + } + } + + priv->bufp = 0; + g_string_truncate(priv->input, 0); + g_string_truncate(priv->output, 0); + g_clear_object(&priv->client); + g_clear_object(&priv->conn); + nm_clear_g_free(&priv->db_uuid); + nm_clear_g_cancellable(&priv->cancellable); + + if (retry) + ovsdb_try_connect(self); } static void -_monitor_bridges_cb (NMOvsdb *self, json_t *result, GError *error, gpointer user_data) +_monitor_bridges_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { - if (error) { - if (!nm_utils_error_is_cancelled_or_disposing (error)) { - _LOGI ("%s", error->message); - ovsdb_disconnect (self, FALSE, FALSE); - } - return; - } - - /* Treat the first response the same as the subsequent "update" - * messages we eventually get. */ - ovsdb_got_update (self, result); + if (error) { + if (!nm_utils_error_is_cancelled_or_disposing(error)) { + _LOGI("%s", error->message); + ovsdb_disconnect(self, FALSE, FALSE); + } + return; + } + + /* Treat the first response the same as the subsequent "update" + * messages we eventually get. */ + ovsdb_got_update(self, result); } static void -_client_connect_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +_client_connect_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GSocketClient *client = G_SOCKET_CLIENT (source_object); - NMOvsdb *self = NM_OVSDB (user_data); - NMOvsdbPrivate *priv; - GError *error = NULL; - GSocketConnection *conn; - - conn = g_socket_client_connect_finish (client, res, &error); - if (conn == NULL) { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - _LOGI ("%s", error->message); - - ovsdb_disconnect (self, FALSE, FALSE); - g_clear_error (&error); - return; - } - - priv = NM_OVSDB_GET_PRIVATE (self); - priv->conn = conn; - g_clear_object (&priv->cancellable); - - ovsdb_read (self); - ovsdb_next_command (self); + GSocketClient * client = G_SOCKET_CLIENT(source_object); + NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdbPrivate * priv; + GError * error = NULL; + GSocketConnection *conn; + + conn = g_socket_client_connect_finish(client, res, &error); + if (conn == NULL) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + _LOGI("%s", error->message); + + ovsdb_disconnect(self, FALSE, FALSE); + g_clear_error(&error); + return; + } + + priv = NM_OVSDB_GET_PRIVATE(self); + priv->conn = conn; + g_clear_object(&priv->cancellable); + + ovsdb_read(self); + ovsdb_next_command(self); } /** @@ -1550,28 +1780,40 @@ _client_connect_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat * sync when other commands are issued. */ static void -ovsdb_try_connect (NMOvsdb *self) +ovsdb_try_connect(NMOvsdb *self) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - GSocketAddress *addr; - - if (priv->client) - return; - - /* XXX: This should probably be made configurable via NetworkManager.conf */ - addr = g_unix_socket_address_new (RUNSTATEDIR "/openvswitch/db.sock"); - - priv->client = g_socket_client_new (); - priv->cancellable = g_cancellable_new (); - g_socket_client_connect_async (priv->client, G_SOCKET_CONNECTABLE (addr), - priv->cancellable, _client_connect_cb, self); - g_object_unref (addr); - - /* 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, NULL, NULL, 0, - _monitor_bridges_cb, NULL, TRUE); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GSocketAddress *addr; + + if (priv->client) + return; + + /* TODO: This should probably be made configurable via NetworkManager.conf */ + addr = g_unix_socket_address_new(RUNSTATEDIR "/openvswitch/db.sock"); + + priv->client = g_socket_client_new(); + priv->cancellable = g_cancellable_new(); + g_socket_client_connect_async(priv->client, + G_SOCKET_CONNECTABLE(addr), + priv->cancellable, + _client_connect_cb, + self); + g_object_unref(addr); + + /* 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, + NULL, + NULL, + 0, + _monitor_bridges_cb, + NULL, + TRUE); } /*****************************************************************************/ @@ -1580,209 +1822,259 @@ ovsdb_try_connect (NMOvsdb *self) * their ovsdb entries without having to deal with ovsdb complexities themselves. */ typedef struct { - NMOvsdbCallback callback; - gpointer user_data; + NMOvsdbCallback callback; + gpointer user_data; } OvsdbCall; static void -_transact_cb (NMOvsdb *self, json_t *result, GError *error, gpointer user_data) +_transact_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { - OvsdbCall *call = user_data; - const char *err; - const char *err_details; - size_t index; - json_t *value; - - if (error) - goto out; - - json_array_foreach (result, index, value) { - if (json_unpack (value, "{s:s, s:s}", "error", &err, "details", &err_details) == 0) { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error running the transaction: %s: %s", err, err_details); - goto out; - } - } + OvsdbCall * call = user_data; + const char *err; + const char *err_details; + size_t index; + json_t * value; + + if (error) + goto out; + + json_array_foreach(result, index, value) + { + if (json_unpack(value, "{s:s, s:s}", "error", &err, "details", &err_details) == 0) { + g_set_error(&error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Error running the transaction: %s: %s", + err, + err_details); + goto out; + } + } out: - call->callback (error, call->user_data); - g_slice_free (OvsdbCall, call); + call->callback(error, call->user_data); + g_slice_free(OvsdbCall, call); } static OvsdbCall * -ovsdb_call_new (NMOvsdbCallback callback, gpointer user_data) +ovsdb_call_new(NMOvsdbCallback callback, gpointer user_data) { - OvsdbCall *call; + OvsdbCall *call; - call = g_slice_new (OvsdbCall); - call->callback = callback; - call->user_data = user_data; + call = g_slice_new(OvsdbCall); + call->callback = callback; + call->user_data = user_data; - return call; + return call; } void -nm_ovsdb_add_interface (NMOvsdb *self, - NMConnection *bridge, NMConnection *port, NMConnection *interface, - NMDevice *bridge_device, NMDevice *interface_device, - NMOvsdbCallback callback, gpointer user_data) +nm_ovsdb_add_interface(NMOvsdb * self, + NMConnection * bridge, + NMConnection * port, + NMConnection * interface, + NMDevice * bridge_device, + NMDevice * interface_device, + NMOvsdbCallback callback, + gpointer user_data) { - ovsdb_call_method (self, OVSDB_ADD_INTERFACE, NULL, - bridge, port, interface, - bridge_device, interface_device, - 0, - _transact_cb, - ovsdb_call_new (callback, user_data), - FALSE); + ovsdb_call_method(self, + OVSDB_ADD_INTERFACE, + NULL, + bridge, + port, + interface, + bridge_device, + interface_device, + 0, + _transact_cb, + ovsdb_call_new(callback, user_data), + FALSE); } void -nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname, - NMOvsdbCallback callback, gpointer user_data) +nm_ovsdb_del_interface(NMOvsdb * self, + const char * ifname, + NMOvsdbCallback callback, + gpointer user_data) { - ovsdb_call_method (self, OVSDB_DEL_INTERFACE, ifname, - NULL, NULL, NULL, NULL, NULL, 0, - _transact_cb, - ovsdb_call_new (callback, user_data), - FALSE); + ovsdb_call_method(self, + OVSDB_DEL_INTERFACE, + ifname, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + _transact_cb, + ovsdb_call_new(callback, user_data), + FALSE); } -void nm_ovsdb_set_interface_mtu (NMOvsdb *self, const char *ifname, guint32 mtu, - NMOvsdbCallback callback, gpointer user_data) +void +nm_ovsdb_set_interface_mtu(NMOvsdb * self, + const char * ifname, + guint32 mtu, + NMOvsdbCallback callback, + gpointer user_data) { - ovsdb_call_method (self, OVSDB_SET_INTERFACE_MTU, ifname, - NULL, NULL, NULL, NULL, NULL, mtu, - _transact_cb, - ovsdb_call_new (callback, user_data), - FALSE); + ovsdb_call_method(self, + OVSDB_SET_INTERFACE_MTU, + ifname, + NULL, + NULL, + NULL, + NULL, + NULL, + mtu, + _transact_cb, + ovsdb_call_new(callback, user_data), + FALSE); } /*****************************************************************************/ static void -_clear_call (gpointer data) +_clear_call(gpointer data) { - OvsdbMethodCall *call = data; - - switch (call->command) { - case OVSDB_MONITOR: - break; - case OVSDB_ADD_INTERFACE: - 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: - case OVSDB_SET_INTERFACE_MTU: - nm_clear_g_free (&call->ifname); - break; - } + OvsdbMethodCall *call = data; + + switch (call->command) { + case OVSDB_MONITOR: + break; + case OVSDB_ADD_INTERFACE: + 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: + case OVSDB_SET_INTERFACE_MTU: + nm_clear_g_free(&call->ifname); + break; + } } static void -_free_bridge (gpointer data) +_free_bridge(gpointer data) { - OpenvswitchBridge *ovs_bridge = data; + OpenvswitchBridge *ovs_bridge = data; - g_free (ovs_bridge->name); - g_free (ovs_bridge->connection_uuid); - g_ptr_array_free (ovs_bridge->ports, TRUE); - g_slice_free (OpenvswitchBridge, ovs_bridge); + g_free(ovs_bridge->name); + g_free(ovs_bridge->connection_uuid); + g_ptr_array_free(ovs_bridge->ports, TRUE); + g_slice_free(OpenvswitchBridge, ovs_bridge); } static void -_free_port (gpointer data) +_free_port(gpointer data) { - OpenvswitchPort *ovs_port = data; + OpenvswitchPort *ovs_port = data; - g_free (ovs_port->name); - g_free (ovs_port->connection_uuid); - g_ptr_array_free (ovs_port->interfaces, TRUE); - g_slice_free (OpenvswitchPort, ovs_port); + g_free(ovs_port->name); + g_free(ovs_port->connection_uuid); + g_ptr_array_free(ovs_port->interfaces, TRUE); + g_slice_free(OpenvswitchPort, ovs_port); } static void -_free_interface (gpointer data) +_free_interface(gpointer data) { - OpenvswitchInterface *ovs_interface = data; + OpenvswitchInterface *ovs_interface = data; - g_free (ovs_interface->name); - g_free (ovs_interface->connection_uuid); - g_free (ovs_interface->type); - g_slice_free (OpenvswitchInterface, ovs_interface); + g_free(ovs_interface->name); + g_free(ovs_interface->connection_uuid); + g_free(ovs_interface->type); + g_slice_free(OpenvswitchInterface, ovs_interface); } static void -nm_ovsdb_init (NMOvsdb *self) +nm_ovsdb_init(NMOvsdb *self) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - priv->calls = g_array_new (FALSE, TRUE, sizeof (OvsdbMethodCall)); - g_array_set_clear_func (priv->calls, _clear_call); - priv->input = g_string_new (NULL); - priv->output = g_string_new (NULL); - priv->bridges = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, _free_bridge); - priv->ports = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, _free_port); - priv->interfaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, _free_interface); + priv->calls = g_array_new(FALSE, TRUE, sizeof(OvsdbMethodCall)); + g_array_set_clear_func(priv->calls, _clear_call); + priv->input = g_string_new(NULL); + priv->output = g_string_new(NULL); + priv->bridges = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_bridge); + priv->ports = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_port); + priv->interfaces = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_interface); - ovsdb_try_connect (self); + ovsdb_try_connect(self); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMOvsdb *self = NM_OVSDB (object); - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - - ovsdb_disconnect (self, FALSE, TRUE); - - if (priv->input) { - g_string_free (priv->input, TRUE); - priv->input = NULL; - } - if (priv->output) { - g_string_free (priv->output, TRUE); - priv->output = NULL; - } - if (priv->calls) { - g_array_free (priv->calls, TRUE); - priv->calls = NULL; - } - - nm_clear_pointer (&priv->bridges, g_hash_table_destroy); - nm_clear_pointer (&priv->ports, g_hash_table_destroy); - nm_clear_pointer (&priv->interfaces, g_hash_table_destroy); - - G_OBJECT_CLASS (nm_ovsdb_parent_class)->dispose (object); + NMOvsdb * self = NM_OVSDB(object); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + + ovsdb_disconnect(self, FALSE, TRUE); + + if (priv->input) { + g_string_free(priv->input, TRUE); + priv->input = NULL; + } + if (priv->output) { + g_string_free(priv->output, TRUE); + priv->output = NULL; + } + if (priv->calls) { + g_array_free(priv->calls, TRUE); + priv->calls = NULL; + } + + nm_clear_pointer(&priv->bridges, g_hash_table_destroy); + nm_clear_pointer(&priv->ports, g_hash_table_destroy); + nm_clear_pointer(&priv->interfaces, g_hash_table_destroy); + + G_OBJECT_CLASS(nm_ovsdb_parent_class)->dispose(object); } static void -nm_ovsdb_class_init (NMOvsdbClass *klass) +nm_ovsdb_class_init(NMOvsdbClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - - signals[DEVICE_ADDED] = - g_signal_new (NM_OVSDB_DEVICE_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT); - - signals[DEVICE_REMOVED] = - g_signal_new (NM_OVSDB_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT); - - signals[INTERFACE_FAILED] = - g_signal_new (NM_OVSDB_INTERFACE_FAILED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->dispose = dispose; + + signals[DEVICE_ADDED] = g_signal_new(NM_OVSDB_DEVICE_ADDED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_UINT); + + signals[DEVICE_REMOVED] = g_signal_new(NM_OVSDB_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_UINT); + + signals[INTERFACE_FAILED] = g_signal_new(NM_OVSDB_INTERFACE_FAILED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); } diff --git a/src/devices/ovs/nm-ovsdb.h b/src/devices/ovs/nm-ovsdb.h index 72a2dc73..c9eee19c 100644 --- a/src/devices/ovs/nm-ovsdb.h +++ b/src/devices/ovs/nm-ovsdb.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -6,35 +6,44 @@ #ifndef __NETWORKMANAGER_OVSDB_H__ #define __NETWORKMANAGER_OVSDB_H__ -#define NM_TYPE_OVSDB (nm_ovsdb_get_type ()) -#define NM_OVSDB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OVSDB, NMOvsdb)) -#define NM_OVSDB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OVSDB, NMOvsdbClass)) -#define NM_IS_OVSDB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OVSDB)) -#define NM_IS_OVSDB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_OVSDB)) -#define NM_OVSDB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OVSDB, NMOvsdbClass)) +#define NM_TYPE_OVSDB (nm_ovsdb_get_type()) +#define NM_OVSDB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_OVSDB, NMOvsdb)) +#define NM_OVSDB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_OVSDB, NMOvsdbClass)) +#define NM_IS_OVSDB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_OVSDB)) +#define NM_IS_OVSDB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_OVSDB)) +#define NM_OVSDB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_OVSDB, NMOvsdbClass)) -#define NM_OVSDB_DEVICE_ADDED "device-added" -#define NM_OVSDB_DEVICE_REMOVED "device-removed" -#define NM_OVSDB_INTERFACE_FAILED "interface-failed" +#define NM_OVSDB_DEVICE_ADDED "device-added" +#define NM_OVSDB_DEVICE_REMOVED "device-removed" +#define NM_OVSDB_INTERFACE_FAILED "interface-failed" -typedef struct _NMOvsdb NMOvsdb; +typedef struct _NMOvsdb NMOvsdb; typedef struct _NMOvsdbClass NMOvsdbClass; -typedef void (*NMOvsdbCallback) (GError *error, gpointer user_data); +typedef void (*NMOvsdbCallback)(GError *error, gpointer user_data); -NMOvsdb *nm_ovsdb_get (void); +NMOvsdb *nm_ovsdb_get(void); -GType nm_ovsdb_get_type (void); +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_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, - NMOvsdbCallback callback, gpointer user_data); +void nm_ovsdb_del_interface(NMOvsdb * self, + const char * ifname, + NMOvsdbCallback callback, + gpointer user_data); -void nm_ovsdb_set_interface_mtu (NMOvsdb *self, const char *ifname, guint32 mtu, - NMOvsdbCallback callback, gpointer user_data); +void nm_ovsdb_set_interface_mtu(NMOvsdb * self, + const char * ifname, + guint32 mtu, + NMOvsdbCallback callback, + gpointer user_data); #endif /* __NETWORKMANAGER_OVSDB_H__ */ |