device: add support for OpenVSwitch devices

This commit is contained in:
Lubomir Rintel 2017-08-01 18:27:22 +02:00
parent d0cb2050f3
commit 830a5a14cb
13 changed files with 2583 additions and 0 deletions

View file

@ -2768,6 +2768,63 @@ check_local += check-local-devices-team
endif
###############################################################################
# src/devices/ovs
###############################################################################
if WITH_OPENVSWITCH
if HAVE_SYSTEMD
systemdnmunitdir = $(systemdsystemunitdir)/NetworkManager.service.d
systemdnmunit_DATA = \
data/NetworkManager-ovs.conf
endif
core_plugins += src/devices/ovs/libnm-device-plugin-ovs.la
src_devices_ovs_libnm_device_plugin_ovs_la_SOURCES = \
src/devices/ovs/nm-ovsdb.c \
src/devices/ovs/nm-ovsdb.h \
src/devices/ovs/nm-ovs-factory.c \
src/devices/ovs/nm-device-ovs-interface.c \
src/devices/ovs/nm-device-ovs-interface.h \
src/devices/ovs/nm-device-ovs-port.c \
src/devices/ovs/nm-device-ovs-port.h \
src/devices/ovs/nm-device-ovs-bridge.c \
src/devices/ovs/nm-device-ovs-bridge.h
src_devices_ovs_libnm_device_plugin_ovs_la_CPPFLAGS = \
-I$(srcdir)/src \
-I$(builddir)/src \
-I$(srcdir)/shared \
-I$(builddir)/shared \
-I$(builddir)/libnm-core \
-I$(srcdir)/libnm-core \
\
-DG_LOG_DOMAIN=\""NetworkManager"\" \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
-DRUNSTATEDIR=\"$(runstatedir)\" \
\
$(JANSSON_CFLAGS) \
$(GLIB_CFLAGS)
src_devices_ovs_libnm_device_plugin_ovs_la_LDFLAGS = \
-module -avoid-version \
-Wl,--version-script="$(srcdir)/linker-script-devices.ver"
src_devices_ovs_libnm_device_plugin_ovs_la_LIBADD = \
introspection/libnmdbus.la \
$(JANSSON_LIBS) \
$(GLIB_LIBS)
check-local-devices-ovs: src/devices/ovs/libnm-device-plugin-ovs.la
$(srcdir)/tools/check-exports.sh $(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so "$(srcdir)/linker-script-devices.ver"
$(call check_so_symbols,$(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so)
endif
###############################################################################
# src/dnsmasq/tests
###############################################################################

View file

@ -871,6 +871,20 @@ if test "$with_dhcpcanon" != "no"; then
else
AC_DEFINE(WITH_DHCPCANON, 0, [Define if you have dhcpcanon])
fi
# OpenVSwitch integration
AC_ARG_ENABLE(ovs, AS_HELP_STRING([--enable-ovs], [enable OpenVSwitch support]))
if test "${enable_ovs}" != "no"; then
enable_ovs='yes'
if test "$have_jansson" = "no"; then
AC_MSG_ERROR(Jansson is required for ovs support)
fi
AC_DEFINE(WITH_OPENVSWITCH, 1, [Define if you have OpenVSwitch support])
else
AC_DEFINE(WITH_OPENVSWITCH, 0, [Define if you have OpenVSwitch support])
fi
AM_CONDITIONAL(WITH_OPENVSWITCH, test "${enable_ovs}" = "yes")
# DHCP client support
AC_ARG_WITH([dhclient],
AS_HELP_STRING([--with-dhclient=yes|no|path], [Enable dhclient 4.x support]))
@ -1359,6 +1373,7 @@ echo " modemmanager-1: $with_modem_manager_1"
echo " ofono: $with_ofono"
echo " concheck: $enable_concheck"
echo " libteamdctl: $enable_teamdctl"
echo " ovs: $enable_ovs"
echo " libnm-glib: $with_libnm_glib"
echo " nmcli: $build_nmcli"
echo " nmtui: $build_nmtui"

View file

@ -50,6 +50,7 @@
%bcond_without wwan
%bcond_without team
%bcond_without wifi
%bcond_without ovs
%bcond_without ppp
%bcond_without nmtui
%bcond_without regen_docs
@ -240,6 +241,19 @@ This package contains NetworkManager support for mobile broadband (WWAN)
devices.
%endif
%if %{with ovs}
%package ovs
Summary: OpenVSwitch device plugin for NetworkManager
Group: System Environment/Base
Requires: %{name}%{?_isa} = %{epoch}:%{version}-%{release}
Requires: openvswitch
%description ovs
This package contains NetworkManager support for OpenVSwitch bridges.
%endif
%if %{with ppp}
%package ppp
Summary: PPP plugin for NetworkManager
@ -608,6 +622,12 @@ fi
%{_libdir}/%{name}/libnm-wwan.so
%endif
%if %{with ovs}
%files ovs
%{_libdir}/%{name}/libnm-device-plugin-ovs.so
%{systemd_dir}/NetworkManager.service.d/NetworkManager-ovs.conf
%endif
%if %{with ppp}
%files ppp
%{_libdir}/pppd/%{ppp_version}/nm-pppd-plugin.so

View file

@ -0,0 +1,2 @@
[Unit]
After=openvswitch.service

View file

@ -0,0 +1,156 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-ovs-bridge.h"
#include "nm-device-ovs-port.h"
#include "nm-ovsdb.h"
#include "devices/nm-device-private.h"
#include "nm-active-connection.h"
#include "nm-setting-connection.h"
#include "nm-setting-ovs-bridge.h"
#include "introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h"
#include "devices/nm-device-logging.h"
_LOG_DECLARE_SELF(NMDeviceOvsBridge);
/*****************************************************************************/
struct _NMDeviceOvsBridge {
NMDevice parent;
};
struct _NMDeviceOvsBridgeClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE (NMDeviceOvsBridge, nm_device_ovs_bridge, NM_TYPE_DEVICE)
/*****************************************************************************/
static const char *
get_type_description (NMDevice *device)
{
return "ovs-bridge";
}
static gboolean
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. */
return TRUE;
}
static gboolean
unrealize (NMDevice *device, GError **error)
{
return TRUE;
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_bridge_parent_class)->check_connection_compatible (device, connection))
return FALSE;
connection_type = nm_connection_get_connection_type (connection);
if (!nm_streq0 (connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME))
return FALSE;
return TRUE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
static NMActStageReturn
act_stage3_ip6_config_start (NMDevice *device,
NMIP6Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
static gboolean
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
{
if (!configure)
return TRUE;
if (!NM_IS_DEVICE_OVS_PORT (slave))
return FALSE;
return TRUE;
}
static void
release_slave (NMDevice *device, NMDevice *slave, gboolean configure)
{
}
/*****************************************************************************/
static void
nm_device_ovs_bridge_init (NMDeviceOvsBridge *self)
{
}
static void
nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass)
{
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
device_class->connection_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
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->check_connection_compatible = check_connection_compatible;
device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
device_class->enslave_slave = enslave_slave;
device_class->release_slave = release_slave;
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_OVS_BRIDGE_SKELETON,
NULL);
}

View file

@ -0,0 +1,35 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#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))
typedef struct _NMDeviceOvsBridge NMDeviceOvsBridge;
typedef struct _NMDeviceOvsBridgeClass NMDeviceOvsBridgeClass;
GType nm_device_ovs_bridge_get_type (void);
#endif /* __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ */

View file

@ -0,0 +1,191 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-ovs-interface.h"
#include "nm-ovsdb.h"
#include "devices/nm-device-private.h"
#include "nm-active-connection.h"
#include "nm-setting-connection.h"
#include "nm-setting-ovs-interface.h"
#include "nm-setting-ovs-port.h"
#include "introspection/org.freedesktop.NetworkManager.Device.OvsInterface.h"
#include "devices/nm-device-logging.h"
_LOG_DECLARE_SELF(NMDeviceOvsInterface);
/*****************************************************************************/
struct _NMDeviceOvsInterface {
NMDevice parent;
};
struct _NMDeviceOvsInterfaceClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE (NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE)
/*****************************************************************************/
static const char *
get_type_description (NMDevice *device)
{
return "ovs-interface";
}
static gboolean
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. */
return TRUE;
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
return TRUE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
NMSettingOvsInterface *s_ovs_iface;
if (!NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_ovs_iface = nm_connection_get_setting_ovs_interface (connection);
if (!s_ovs_iface)
return FALSE;
if (!NM_IN_STRSET (nm_setting_ovs_interface_get_interface_type (s_ovs_iface),
"internal", "patch")) {
return FALSE;
}
s_con = nm_connection_get_setting_connection (connection);
if (g_strcmp0 (nm_setting_connection_get_connection_type (s_con),
NM_SETTING_OVS_INTERFACE_SETTING_NAME) != 0) {
return FALSE;
}
return TRUE;
}
static void
link_changed (NMDevice *device,
const NMPlatformLink *pllink)
{
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
nm_device_bring_up (device, TRUE, NULL);
nm_device_activate_schedule_stage3_ip_config_start (device);
}
}
static gboolean
_is_internal_interface (NMDevice *device)
{
NMConnection *connection = nm_device_get_applied_connection (device);
NMSettingOvsInterface *s_ovs_iface = nm_connection_get_setting_ovs_interface (connection);
g_return_val_if_fail (s_ovs_iface, FALSE);
return strcmp (nm_setting_ovs_interface_get_interface_type (s_ovs_iface), "internal") == 0;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
if (!_is_internal_interface (device))
return NM_ACT_STAGE_RETURN_IP_FAIL;
if (!nm_device_get_ip_ifindex (device))
return NM_ACT_STAGE_RETURN_POSTPONE;
return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason);
}
static NMActStageReturn
act_stage3_ip6_config_start (NMDevice *device,
NMIP6Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
if (!_is_internal_interface (device))
return NM_ACT_STAGE_RETURN_IP_FAIL;
if (!nm_device_get_ip_ifindex (device))
return NM_ACT_STAGE_RETURN_POSTPONE;
return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason);
}
static gboolean
can_unmanaged_external_down (NMDevice *self)
{
return FALSE;
}
/*****************************************************************************/
static void
nm_device_ovs_interface_init (NMDeviceOvsInterface *self)
{
}
static void
nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass)
{
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_OPENVSWITCH);
device_class->connection_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME;
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_ip4_config_start = act_stage3_ip4_config_start;
device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_OVS_INTERFACE_SKELETON,
NULL);
}

View file

@ -0,0 +1,35 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#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))
typedef struct _NMDeviceOvsInterface NMDeviceOvsInterface;
typedef struct _NMDeviceOvsInterfaceClass NMDeviceOvsInterfaceClass;
GType nm_device_ovs_interface_get_type (void);
#endif /* __NETWORKMANAGER_DEVICE_OVS_INTERFACE_H__ */

View file

@ -0,0 +1,201 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-ovs-port.h"
#include "nm-ovsdb.h"
#include "devices/nm-device-private.h"
#include "nm-active-connection.h"
#include "nm-setting-connection.h"
#include "nm-setting-ovs-port.h"
#include "nm-setting-ovs-port.h"
#include "introspection/org.freedesktop.NetworkManager.Device.OvsPort.h"
#include "devices/nm-device-logging.h"
_LOG_DECLARE_SELF(NMDeviceOvsPort);
/*****************************************************************************/
struct _NMDeviceOvsPort {
NMDevice parent;
};
struct _NMDeviceOvsPortClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE (NMDeviceOvsPort, nm_device_ovs_port, NM_TYPE_DEVICE)
/*****************************************************************************/
static const char *
get_type_description (NMDevice *device)
{
return "ovs-port";
}
static gboolean
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. */
return TRUE;
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingConnection *s_con;
const char *connection_type;
if (!NM_DEVICE_CLASS (nm_device_ovs_port_parent_class)->check_connection_compatible (device, connection))
return FALSE;
s_con = nm_connection_get_setting_connection (connection);
connection_type = nm_setting_connection_get_connection_type (s_con);
if (!connection_type)
return FALSE;
if (strcmp (connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0)
return TRUE;
return FALSE;
}
static NMActStageReturn
act_stage3_ip4_config_start (NMDevice *device,
NMIP4Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
static NMActStageReturn
act_stage3_ip6_config_start (NMDevice *device,
NMIP6Config **out_config,
NMDeviceStateReason *out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
static void
add_iface_cb (GError *error, gpointer user_data)
{
NMDevice *slave = user_data;
if (error) {
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)
{
NMActiveConnection *ac_port = NULL;
NMActiveConnection *ac_bridge = NULL;
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)
ac_bridge = ac_port;
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),
add_iface_cb, g_object_ref (slave));
return TRUE;
}
static void
del_iface_cb (GError *error, gpointer user_data)
{
NMDevice *slave = user_data;
if (error) {
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)
{
nm_ovsdb_del_interface (nm_ovsdb_get (), nm_device_get_iface (slave),
del_iface_cb, g_object_ref (slave));
}
/*****************************************************************************/
static void
nm_device_ovs_port_init (NMDeviceOvsPort *self)
{
}
static void
nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass)
{
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
device_class->connection_type = NM_SETTING_OVS_PORT_SETTING_NAME;
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->check_connection_compatible = check_connection_compatible;
device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
device_class->enslave_slave = enslave_slave;
device_class->release_slave = release_slave;
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_OVS_PORT_SKELETON,
NULL);
}

View file

@ -0,0 +1,35 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#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))
typedef struct _NMDeviceOvsPort NMDeviceOvsPort;
typedef struct _NMDeviceOvsPortClass NMDeviceOvsPortClass;
GType nm_device_ovs_port_get_type (void);
#endif /* __NETWORKMANAGER_DEVICE_OVS_PORT_H__ */

View file

@ -0,0 +1,195 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-manager.h"
#include "nm-ovsdb.h"
#include "nm-device-ovs-interface.h"
#include "nm-device-ovs-port.h"
#include "nm-device-ovs-bridge.h"
#include "platform/nm-platform.h"
#include "nm-core-internal.h"
#include "devices/nm-device-factory.h"
/*****************************************************************************/
typedef struct {
NMDeviceFactory parent;
} NMOvsFactory;
typedef struct {
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))
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, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "ovs", __VA_ARGS__)
/*****************************************************************************/
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)
{
return (NMDeviceFactory *) g_object_new (NM_TYPE_OVS_FACTORY, NULL);
}
static NMDevice *
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 = "OpenVSwitch Interface";
link_type = NM_LINK_TYPE_OPENVSWITCH;
} else if (device_type == NM_DEVICE_TYPE_OVS_PORT) {
type = NM_TYPE_DEVICE_OVS_PORT;
type_desc = "OpenVSwitch Port";
} else if (device_type == NM_DEVICE_TYPE_OVS_BRIDGE) {
type = NM_TYPE_DEVICE_OVS_BRIDGE;
type_desc = "OpenVSwitch 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)
{
NMDevice *device = NULL;
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);
}
static void
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_REMOVED);
} else if (device_state == NM_DEVICE_STATE_UNMANAGED) {
nm_device_unrealize (device, TRUE, NULL);
}
}
static void
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);
}
static NMDevice *
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);
}
static void
nm_ovs_factory_init (NMOvsFactory *self)
{
}
static void
nm_ovs_factory_class_init (NMOvsFactoryClass *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;
}

1591
src/devices/ovs/nm-ovsdb.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#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_OVSDB_DEVICE_ADDED "device-added"
#define NM_OVSDB_DEVICE_REMOVED "device-removed"
#define NM_OVSDB_DEVICE_CHANGED "device-changed"
typedef struct _NMOvsdb NMOvsdb;
typedef struct _NMOvsdbClass NMOvsdbClass;
typedef void (*NMOvsdbCallback) (GError *error, gpointer user_data);
NMOvsdb *nm_ovsdb_get (void);
GType nm_ovsdb_get_type (void);
void nm_ovsdb_add_interface (NMOvsdb *self,
NMConnection *bridge, NMConnection *port, NMConnection *interface,
NMOvsdbCallback callback, gpointer user_data);
void nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname,
NMOvsdbCallback callback, gpointer user_data);
#endif /* __NETWORKMANAGER_OVSDB_H__ */