Blame src/devices/ovs/nm-ovs-factory.c

Packit 5756e2
// SPDX-License-Identifier: GPL-2.0+
Packit 5756e2
/*
Packit 5756e2
 * Copyright (C) 2017 Red Hat, Inc.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
#include "nm-default.h"
Packit 5756e2
Packit 5756e2
#include "nm-manager.h"
Packit 5756e2
#include "nm-ovsdb.h"
Packit 5756e2
#include "nm-device-ovs-interface.h"
Packit 5756e2
#include "nm-device-ovs-port.h"
Packit 5756e2
#include "nm-device-ovs-bridge.h"
Packit 5756e2
#include "platform/nm-platform.h"
Packit 5756e2
#include "nm-core-internal.h"
Packit 5756e2
#include "settings/nm-settings.h"
Packit 5756e2
#include "devices/nm-device-factory.h"
Packit 5756e2
#include "devices/nm-device-private.h"
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
typedef struct {
Packit 5756e2
	NMDeviceFactory parent;
Packit 5756e2
} NMOvsFactory;
Packit 5756e2
Packit 5756e2
typedef struct {
Packit 5756e2
	NMDeviceFactoryClass parent;
Packit 5756e2
} NMOvsFactoryClass;
Packit 5756e2
Packit 5756e2
#define NM_TYPE_OVS_FACTORY            (nm_ovs_factory_get_type ())
Packit 5756e2
#define NM_OVS_FACTORY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OVS_FACTORY, NMOvsFactory))
Packit 5756e2
#define NM_OVS_FACTORY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass))
Packit 5756e2
#define NM_IS_OVS_FACTORY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OVS_FACTORY))
Packit 5756e2
#define NM_IS_OVS_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_OVS_FACTORY))
Packit 5756e2
#define NM_OVS_FACTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OVS_FACTORY, NMOvsFactoryClass))
Packit 5756e2
Packit 5756e2
static GType nm_ovs_factory_get_type (void);
Packit 5756e2
G_DEFINE_TYPE (NMOvsFactory, nm_ovs_factory, NM_TYPE_DEVICE_FACTORY)
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
#define _NMLOG_DOMAIN      LOGD_DEVICE
Packit 5756e2
#define _NMLOG(level, ifname, con_uuid, ...) \
Packit 5756e2
        G_STMT_START { \
Packit 5756e2
                nm_log ((level), _NMLOG_DOMAIN, (ifname), (con_uuid), \
Packit 5756e2
                        "ovs: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \
Packit 5756e2
                        _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
Packit 5756e2
        } G_STMT_END
Packit 5756e2
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
NM_DEVICE_FACTORY_DECLARE_TYPES (
Packit 5756e2
	NM_DEVICE_FACTORY_DECLARE_LINK_TYPES    (NM_LINK_TYPE_OPENVSWITCH)
Packit 5756e2
	NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_OVS_BRIDGE_SETTING_NAME,
Packit 5756e2
	                                         NM_SETTING_OVS_INTERFACE_SETTING_NAME,
Packit 5756e2
	                                         NM_SETTING_OVS_PORT_SETTING_NAME)
Packit 5756e2
)
Packit 5756e2
Packit 5756e2
G_MODULE_EXPORT NMDeviceFactory *
Packit 5756e2
nm_device_factory_create (GError **error)
Packit 5756e2
{
Packit 5756e2
	nm_manager_set_capability (NM_MANAGER_GET, NM_CAPABILITY_OVS);
Packit 5756e2
	return (NMDeviceFactory *) g_object_new (NM_TYPE_OVS_FACTORY, NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMDevice *
Packit 5756e2
new_device_from_type (const char *name, NMDeviceType device_type)
Packit 5756e2
{
Packit 5756e2
	GType type;
Packit 5756e2
	const char *type_desc;
Packit 5756e2
	NMLinkType link_type = NM_LINK_TYPE_NONE;
Packit 5756e2
Packit 5756e2
	if (nm_manager_get_device (NM_MANAGER_GET, name, device_type))
Packit 5756e2
		return NULL;
Packit 5756e2
Packit 5756e2
	if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) {
Packit 5756e2
		type = NM_TYPE_DEVICE_OVS_INTERFACE;
Packit 5756e2
		type_desc = "Open vSwitch Interface";
Packit 5756e2
		link_type = NM_LINK_TYPE_OPENVSWITCH;
Packit 5756e2
	} else if (device_type == NM_DEVICE_TYPE_OVS_PORT) {
Packit 5756e2
		type = NM_TYPE_DEVICE_OVS_PORT;
Packit 5756e2
		type_desc = "Open vSwitch Port";
Packit 5756e2
	} else if (device_type == NM_DEVICE_TYPE_OVS_BRIDGE) {
Packit 5756e2
		type = NM_TYPE_DEVICE_OVS_BRIDGE;
Packit 5756e2
		type_desc = "Open vSwitch Bridge";
Packit 5756e2
	} else {
Packit 5756e2
		return NULL;
Packit 5756e2
	}
Packit 5756e2
Packit 5756e2
	return g_object_new (type,
Packit 5756e2
	                     NM_DEVICE_IFACE, name,
Packit 5756e2
	                     NM_DEVICE_DRIVER, "openvswitch",
Packit 5756e2
	                     NM_DEVICE_DEVICE_TYPE, device_type,
Packit 5756e2
	                     NM_DEVICE_TYPE_DESC, type_desc,
Packit 5756e2
	                     NM_DEVICE_LINK_TYPE, link_type,
Packit 5756e2
	                     NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
ovsdb_device_added (NMOvsdb *ovsdb, const char *name, NMDeviceType device_type,
Packit 5756e2
                    NMDeviceFactory *self)
Packit 5756e2
{
Packit 5756e2
	NMDevice *device = NULL;
Packit 5756e2
Packit 5756e2
	device = new_device_from_type (name, device_type);
Packit 5756e2
	if (!device)
Packit 5756e2
		return;
Packit 5756e2
Packit 5756e2
	g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device);
Packit 5756e2
	g_object_unref (device);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
ovsdb_device_removed (NMOvsdb *ovsdb, const char *name, NMDeviceType device_type,
Packit 5756e2
                      NMDeviceFactory *self)
Packit 5756e2
{
Packit 5756e2
	NMDevice *device;
Packit 5756e2
	NMDeviceState device_state;
Packit 5756e2
Packit 5756e2
	device = nm_manager_get_device (NM_MANAGER_GET, name, device_type);
Packit 5756e2
	if (!device)
Packit 5756e2
		return;
Packit 5756e2
Packit 5756e2
	device_state = nm_device_get_state (device);
Packit 5756e2
	if (   device_type == NM_DEVICE_TYPE_OVS_INTERFACE
Packit 5756e2
	    && device_state > NM_DEVICE_STATE_DISCONNECTED
Packit 5756e2
	    && device_state < NM_DEVICE_STATE_DEACTIVATING) {
Packit 5756e2
		nm_device_state_changed (device,
Packit 5756e2
		                         NM_DEVICE_STATE_DEACTIVATING,
Packit 5756e2
		                         NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
Packit 5756e2
	} else if (device_state == NM_DEVICE_STATE_UNMANAGED) {
Packit 5756e2
		nm_device_unrealize (device, TRUE, NULL);
Packit 5756e2
	}
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
ovsdb_interface_failed (NMOvsdb *ovsdb,
Packit 5756e2
                        const char *name,
Packit 5756e2
                        const char *connection_uuid,
Packit 5756e2
                        const char *error,
Packit 5756e2
                        NMDeviceFactory *self)
Packit 5756e2
{
Packit 5756e2
	NMDevice *device = NULL;
Packit 5756e2
	NMSettingsConnection *connection = NULL;
Packit 5756e2
	NMConnection *c;
Packit 5756e2
	const char *type;
Packit 5756e2
	NMSettingOvsInterface *s_ovs_int;
Packit 5756e2
	gboolean is_patch = FALSE;
Packit 5756e2
	gboolean ignore;
Packit 5756e2
Packit 5756e2
	device = nm_manager_get_device (NM_MANAGER_GET, name, NM_DEVICE_TYPE_OVS_INTERFACE);
Packit 5756e2
	if (device && connection_uuid) {
Packit 5756e2
		connection = nm_settings_get_connection_by_uuid (nm_device_get_settings (device),
Packit 5756e2
		                                                 connection_uuid);
Packit 5756e2
	}
Packit 5756e2
Packit 5756e2
	/* The patch interface which gets created first is expected to
Packit 5756e2
	 * fail because the second patch doesn't exist yet. Ignore all
Packit 5756e2
	 * failures of patch interfaces. */
Packit 5756e2
	if (   connection
Packit 5756e2
	    && (c = nm_settings_connection_get_connection (connection))
Packit 5756e2
	    && (type = nm_connection_get_connection_type (c))
Packit 5756e2
	    && nm_streq0 (type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)
Packit 5756e2
	    && (s_ovs_int = nm_connection_get_setting_ovs_interface (c))
Packit 5756e2
	    && nm_streq0 (nm_setting_ovs_interface_get_interface_type (s_ovs_int), "patch"))
Packit 5756e2
		is_patch = TRUE;
Packit 5756e2
Packit 5756e2
	ignore = !device || is_patch;
Packit 5756e2
Packit 5756e2
	_NMLOG (ignore ? LOGL_DEBUG : LOGL_INFO,
Packit 5756e2
	        name, connection_uuid,
Packit 5756e2
	        "ovs interface \"%s\" (%s) failed%s: %s",
Packit 5756e2
	        name, connection_uuid,
Packit 5756e2
	        ignore ? " (ignored)" : "",
Packit 5756e2
	        error);
Packit 5756e2
Packit 5756e2
	if (ignore)
Packit 5756e2
		return;
Packit 5756e2
Packit 5756e2
	if (connection) {
Packit 5756e2
		nm_settings_connection_autoconnect_blocked_reason_set (connection,
Packit 5756e2
		                                                       NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit 5756e2
		                                                       TRUE);
Packit 5756e2
	}
Packit 5756e2
Packit 5756e2
	nm_device_state_changed (device,
Packit 5756e2
	                         NM_DEVICE_STATE_FAILED,
Packit 5756e2
	                         NM_DEVICE_STATE_REASON_OVSDB_FAILED);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
start (NMDeviceFactory *self)
Packit 5756e2
{
Packit 5756e2
	NMOvsdb *ovsdb;
Packit 5756e2
Packit 5756e2
	ovsdb = nm_ovsdb_get ();
Packit 5756e2
Packit 5756e2
	g_signal_connect_object (ovsdb, NM_OVSDB_DEVICE_ADDED, G_CALLBACK (ovsdb_device_added), self, (GConnectFlags) 0);
Packit 5756e2
	g_signal_connect_object (ovsdb, NM_OVSDB_DEVICE_REMOVED, G_CALLBACK (ovsdb_device_removed), self, (GConnectFlags) 0);
Packit 5756e2
	g_signal_connect_object (ovsdb, NM_OVSDB_INTERFACE_FAILED, G_CALLBACK (ovsdb_interface_failed), self, (GConnectFlags) 0);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMDevice *
Packit 5756e2
create_device (NMDeviceFactory *self,
Packit 5756e2
               const char *iface,
Packit 5756e2
               const NMPlatformLink *plink,
Packit 5756e2
               NMConnection *connection,
Packit 5756e2
               gboolean *out_ignore)
Packit 5756e2
{
Packit 5756e2
	NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN;
Packit 5756e2
	const char *connection_type = NULL;
Packit 5756e2
Packit 5756e2
	if (g_strcmp0 (iface, "ovs-system") == 0) {
Packit 5756e2
		*out_ignore = TRUE;
Packit 5756e2
		return NULL;
Packit 5756e2
	}
Packit 5756e2
Packit 5756e2
	if (connection)
Packit 5756e2
		connection_type = nm_connection_get_connection_type (connection);
Packit 5756e2
Packit 5756e2
	if (plink)
Packit 5756e2
		device_type = NM_DEVICE_TYPE_OVS_INTERFACE;
Packit 5756e2
	else if (g_strcmp0 (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0)
Packit 5756e2
		device_type = NM_DEVICE_TYPE_OVS_INTERFACE;
Packit 5756e2
	else if (g_strcmp0 (connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0)
Packit 5756e2
		device_type = NM_DEVICE_TYPE_OVS_PORT;
Packit 5756e2
	else if (g_strcmp0 (connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0)
Packit 5756e2
		device_type = NM_DEVICE_TYPE_OVS_BRIDGE;
Packit 5756e2
Packit 5756e2
	return new_device_from_type (iface, device_type);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
nm_ovs_factory_init (NMOvsFactory *self)
Packit 5756e2
{
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit 5756e2
nm_ovs_factory_class_init (NMOvsFactoryClass *klass)
Packit 5756e2
{
Packit 5756e2
	NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS (klass);
Packit 5756e2
Packit 5756e2
	factory_class->get_supported_types = get_supported_types;
Packit 5756e2
	factory_class->start = start;
Packit 5756e2
	factory_class->create_device = create_device;
Packit 5756e2
}