Commit 830a5a14 authored by Lubomir Rintel's avatar Lubomir Rintel 🥕

device: add support for OpenVSwitch devices

parent d0cb2050
......@@ -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
###############################################################################
......
......@@ -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"
......
......@@ -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
......
[Unit]
After=openvswitch.service
/* 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);
}
/* 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__ */
/* 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);
}
/* 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__ */
/* 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)