NetworkManager/src/devices/nm-device-infiniband.c

481 lines
16 KiB
C
Raw Normal View History

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* 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 2011 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-infiniband.h"
#include <linux/if_infiniband.h>
#include "NetworkManagerUtils.h"
#include "nm-device-private.h"
#include "nm-act-request.h"
#include "nm-ip4-config.h"
#include "platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-core-internal.h"
#include "introspection/org.freedesktop.NetworkManager.Device.Infiniband.h"
#define NM_DEVICE_INFINIBAND_IS_PARTITION "is-partition"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
PROP_IS_PARTITION,
);
typedef struct {
gboolean is_partition;
int parent_ifindex;
int p_key;
} NMDeviceInfinibandPrivate;
struct _NMDeviceInfiniband {
NMDevice parent;
NMDeviceInfinibandPrivate _priv;
};
struct _NMDeviceInfinibandClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE)
#define NM_DEVICE_INFINIBAND_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceInfiniband, NM_IS_DEVICE_INFINIBAND)
/*****************************************************************************/
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
guint32 caps = NM_DEVICE_CAP_CARRIER_DETECT;
if (NM_DEVICE_INFINIBAND_GET_PRIVATE ((NMDeviceInfiniband *) device)->is_partition)
caps |= NM_DEVICE_CAP_IS_SOFTWARE;
return caps;
}
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
nm_auto_close int dirfd = -1;
NMActStageReturn ret;
NMSettingInfiniband *s_infiniband;
char ifname_verified[IFNAMSIZ];
const char *transport_mode;
gboolean ok, no_firmware = FALSE;
ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (device, out_failure_reason);
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
return ret;
s_infiniband = (NMSettingInfiniband *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_INFINIBAND);
g_return_val_if_fail (s_infiniband, NM_ACT_STAGE_RETURN_FAILURE);
transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);
dirfd = nm_platform_sysctl_open_netdir (nm_device_get_platform (device), nm_device_get_ifindex (device), ifname_verified);
if (dirfd < 0) {
if (!strcmp (transport_mode, "datagram"))
return NM_ACT_STAGE_RETURN_SUCCESS;
else {
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_INFINIBAND_MODE);
return NM_ACT_STAGE_RETURN_FAILURE;
}
}
/* With some drivers the interface must be down to set transport mode */
nm_device_take_down (device, TRUE);
ok = nm_platform_sysctl_set (nm_device_get_platform (device), NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "mode"), transport_mode);
nm_device_bring_up (device, TRUE, &no_firmware);
if (!ok) {
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static guint32
get_configured_mtu (NMDevice *device, gboolean *out_is_user_config)
{
NMSettingInfiniband *setting;
gint64 mtu_default;
guint32 mtu;
nm_assert (NM_IS_DEVICE (device));
nm_assert (out_is_user_config);
setting = NM_SETTING_INFINIBAND (nm_device_get_applied_setting (device, NM_TYPE_SETTING_INFINIBAND));
if (!setting)
g_return_val_if_reached (0);
mtu = nm_setting_infiniband_get_mtu (setting);
if (mtu == 0) {
mtu_default = nm_device_get_configured_mtu_from_connection_default (device, "infiniband.mtu");
if (mtu_default >= 0) {
*out_is_user_config = TRUE;
return (guint32) mtu_default;
}
}
*out_is_user_config = (mtu != 0);
return mtu;
}
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
NMSettingInfiniband *s_infiniband;
if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection))
return FALSE;
if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME))
return FALSE;
s_infiniband = nm_connection_get_setting_infiniband (connection);
if (!s_infiniband)
return FALSE;
if (nm_device_is_real (device)) {
const char *mac;
const char *hw_addr;
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
if (mac) {
hw_addr = nm_device_get_permanent_hw_address (device);
if ( !hw_addr
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
return FALSE;
}
}
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
const char *specific_object,
const GSList *existing_connections,
GError **error)
{
NMSettingInfiniband *s_infiniband;
const char *setting_mac;
const char *hw_address;
nm_utils_complete_generic (nm_device_get_platform (device),
connection,
NM_SETTING_INFINIBAND_SETTING_NAME,
existing_connections,
NULL,
_("InfiniBand connection"),
NULL,
TRUE);
s_infiniband = nm_connection_get_setting_infiniband (connection);
if (!s_infiniband) {
s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new ();
nm_connection_add_setting (connection, NM_SETTING (s_infiniband));
}
setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
hw_address = nm_device_get_permanent_hw_address (device);
if (setting_mac) {
/* Make sure the setting MAC (if any) matches the device's MAC */
if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) {
g_set_error_literal (error,
libnm-core: merge NMSetting*Error into NMConnectionError Each setting type was defining its own error type, but most of them had exactly the same three errors ("unknown", "missing property", and "invalid property"), and none of the other values was of much use programmatically anyway. So, this commit merges NMSettingError, NMSettingAdslError, etc, all into NMConnectionError. (The reason for merging into NMConnectionError rather than NMSettingError is that we also already have "NMSettingsError", for errors related to the settings service, so "NMConnectionError" is a less-confusable name for settings/connection errors than "NMSettingError".) Also, make sure that all of the affected error messages are localized, and (where appropriate) prefix them with the relevant property name. Renamed error codes: NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET Remapped error codes: NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY Dropped error codes (were previously defined but unused): NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("connection does not match device"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_MAC_ADDRESS);
return FALSE;
}
} else {
/* Lock the connection to this device by default */
g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_MAC_ADDRESS, hw_address, NULL);
}
if (!nm_setting_infiniband_get_transport_mode (s_infiniband))
g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL);
return TRUE;
}
static void
update_connection (NMDevice *device, NMConnection *connection)
{
NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection);
const char *mac = nm_device_get_permanent_hw_address (device);
const char *transport_mode = "datagram";
int ifindex;
if (!s_infiniband) {
s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new ();
nm_connection_add_setting (connection, (NMSetting *) s_infiniband);
}
if (mac && !nm_utils_hwaddr_matches (mac, -1, NULL, INFINIBAND_ALEN))
g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
ifindex = nm_device_get_ifindex (device);
if (ifindex > 0) {
if (!nm_platform_link_infiniband_get_properties (nm_device_get_platform (device), ifindex, NULL, NULL, &transport_mode))
transport_mode = "datagram";
}
g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, transport_mode, NULL);
}
static gboolean
create_and_realize (NMDevice *device,
NMConnection *connection,
NMDevice *parent,
const NMPlatformLink **out_plink,
GError **error)
{
NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE ((NMDeviceInfiniband *) device);
NMSettingInfiniband *s_infiniband;
NMPlatformError plerr;
s_infiniband = nm_connection_get_setting_infiniband (connection);
g_assert (s_infiniband);
/* Can only create partitions at this time */
priv->p_key = nm_setting_infiniband_get_p_key (s_infiniband);
if (priv->p_key < 0) {
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"only InfiniBand partitions can be created");
return FALSE;
}
device: check for a parent device The device creation can be attempted if the name can be determined. It alone is doesn't mean that there's a parent device -- the name could just have been hardcoded in the connection. NetworkManager[21519]: nm_device_get_ifindex: assertion 'NM_IS_DEVICE (self)' failed Program received signal SIGTRAP, Trace/breakpoint trap. g_logv (log_domain=0x5555557fb2e5 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd3d0) at gmessages.c:1046 1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth)); (gdb) bt #0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557fb2e5 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd3d0) at gmessages.c:1046 #1 0x00007ffff4ec8a3f in g_log (log_domain=<optimized out>, log_level=<optimized out>, format=<optimized out>) at gmessages.c:1079 #2 0x00005555555d2090 in nm_device_get_ifindex (self=0x0) at devices/nm-device.c:562 #3 0x00005555555ef77a in nm_device_supports_vlans (self=0x0) at devices/nm-device.c:9865 #4 0x00005555555bf2f9 in create_and_realize (device=0x555555c549b0 [NMDeviceVlan], connection=0x555555b451e0, parent=0x0, out_plink=0x7fffffffd5f8, error=0x7fffffffd700) at devices/nm-device-vlan.c:225 #5 0x00005555555d5757 in nm_device_create_and_realize (self=0x555555c549b0 [NMDeviceVlan], connection=0x555555b451e0, parent=0x0, error=0x7fffffffd700) at devices/nm-device.c:1783 #6 0x0000555555688601 in system_create_virtual_device (self=0x555555af51c0 [NMManager], connection=0x555555b451e0) at nm-manager.c:1120 #7 0x000055555568894e in connection_changed (settings=0x555555ae8220 [NMSettings], connection=0x555555b451e0, manager=0x555555af51c0 [NMManager]) at nm-manager.c:1172 #8 0x0000555555693448 in nm_manager_start (self=0x555555af51c0 [NMManager], error=0x7fffffffda30) at nm-manager.c:4466 #9 0x00005555555d166f in main (argc=1, argv=0x7fffffffdba8) at main.c:454 (gdb) Fixes: 332994f1b19ded7cb343ef573443916bab05aaec
2016-04-19 12:02:02 +02:00
if (!parent) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_MISSING_DEPENDENCIES,
device: check for a parent device The device creation can be attempted if the name can be determined. It alone is doesn't mean that there's a parent device -- the name could just have been hardcoded in the connection. NetworkManager[21519]: nm_device_get_ifindex: assertion 'NM_IS_DEVICE (self)' failed Program received signal SIGTRAP, Trace/breakpoint trap. g_logv (log_domain=0x5555557fb2e5 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd3d0) at gmessages.c:1046 1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth)); (gdb) bt #0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557fb2e5 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd3d0) at gmessages.c:1046 #1 0x00007ffff4ec8a3f in g_log (log_domain=<optimized out>, log_level=<optimized out>, format=<optimized out>) at gmessages.c:1079 #2 0x00005555555d2090 in nm_device_get_ifindex (self=0x0) at devices/nm-device.c:562 #3 0x00005555555ef77a in nm_device_supports_vlans (self=0x0) at devices/nm-device.c:9865 #4 0x00005555555bf2f9 in create_and_realize (device=0x555555c549b0 [NMDeviceVlan], connection=0x555555b451e0, parent=0x0, out_plink=0x7fffffffd5f8, error=0x7fffffffd700) at devices/nm-device-vlan.c:225 #5 0x00005555555d5757 in nm_device_create_and_realize (self=0x555555c549b0 [NMDeviceVlan], connection=0x555555b451e0, parent=0x0, error=0x7fffffffd700) at devices/nm-device.c:1783 #6 0x0000555555688601 in system_create_virtual_device (self=0x555555af51c0 [NMManager], connection=0x555555b451e0) at nm-manager.c:1120 #7 0x000055555568894e in connection_changed (settings=0x555555ae8220 [NMSettings], connection=0x555555b451e0, manager=0x555555af51c0 [NMManager]) at nm-manager.c:1172 #8 0x0000555555693448 in nm_manager_start (self=0x555555af51c0 [NMManager], error=0x7fffffffda30) at nm-manager.c:4466 #9 0x00005555555d166f in main (argc=1, argv=0x7fffffffdba8) at main.c:454 (gdb) Fixes: 332994f1b19ded7cb343ef573443916bab05aaec
2016-04-19 12:02:02 +02:00
"InfiniBand partitions can not be created without a parent interface");
return FALSE;
}
if (!NM_IS_DEVICE_INFINIBAND (parent)) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_MISSING_DEPENDENCIES,
"Parent interface %s must be an InfiniBand interface",
nm_device_get_iface (parent));
return FALSE;
}
priv->parent_ifindex = nm_device_get_ifindex (parent);
if (priv->parent_ifindex <= 0) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_MISSING_DEPENDENCIES,
"failed to get InfiniBand parent %s ifindex",
nm_device_get_iface (parent));
return FALSE;
}
plerr = nm_platform_link_infiniband_add (nm_device_get_platform (device), priv->parent_ifindex, priv->p_key, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
nm_device_get_iface (device),
nm_connection_get_id (connection),
nm_platform_error_to_string_a (plerr));
return FALSE;
}
priv->is_partition = TRUE;
return TRUE;
}
static gboolean
unrealize (NMDevice *device, GError **error)
{
NMDeviceInfinibandPrivate *priv;
NMPlatformError plerr;
g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), FALSE);
priv = NM_DEVICE_INFINIBAND_GET_PRIVATE ((NMDeviceInfiniband *) device);
if (priv->p_key < 0) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Only InfiniBand partitions can be removed");
return FALSE;
}
plerr = nm_platform_link_infiniband_delete (nm_device_get_platform (device), priv->parent_ifindex, priv->p_key);
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to remove InfiniBand P_Key interface '%s': %s",
nm_device_get_iface (device),
nm_platform_error_to_string_a (plerr));
return FALSE;
}
return TRUE;
}
/*****************************************************************************/
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
switch (prop_id) {
case PROP_IS_PARTITION:
g_value_set_boolean (value, NM_DEVICE_INFINIBAND_GET_PRIVATE ((NMDeviceInfiniband *) object)->is_partition);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
switch (prop_id) {
case PROP_IS_PARTITION:
NM_DEVICE_INFINIBAND_GET_PRIVATE ((NMDeviceInfiniband *) object)->is_partition = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_device_infiniband_init (NMDeviceInfiniband * self)
{
}
static void
nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND)
object_class->get_property = get_property;
object_class->set_property = set_property;
parent_class->create_and_realize = create_and_realize;
parent_class->unrealize = unrealize;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
parent_class->update_connection = update_connection;
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->get_configured_mtu = get_configured_mtu;
obj_properties[PROP_IS_PARTITION] =
g_param_spec_boolean (NM_DEVICE_INFINIBAND_IS_PARTITION, "", "",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_INFINIBAND_SKELETON,
NULL);
}
/*****************************************************************************/
#define NM_TYPE_INFINIBAND_DEVICE_FACTORY (nm_infiniband_device_factory_get_type ())
#define NM_INFINIBAND_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INFINIBAND_DEVICE_FACTORY, NMInfinibandDeviceFactory))
static NMDevice *
create_device (NMDeviceFactory *factory,
const char *iface,
const NMPlatformLink *plink,
NMConnection *connection,
gboolean *out_ignore)
{
gboolean is_partition = FALSE;
if (plink)
is_partition = (plink->parent > 0 || plink->parent == NM_PLATFORM_LINK_OTHER_NETNS);
else if (connection) {
NMSettingInfiniband *s_infiniband;
s_infiniband = nm_connection_get_setting_infiniband (connection);
g_return_val_if_fail (s_infiniband, NULL);
is_partition = !!nm_setting_infiniband_get_parent (s_infiniband)
|| ( nm_setting_infiniband_get_p_key (s_infiniband) >= 0
&& nm_setting_infiniband_get_mac_address (s_infiniband));
}
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "InfiniBand",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_INFINIBAND,
/* NOTE: Partition should probably be a different link type! */
NM_DEVICE_INFINIBAND_IS_PARTITION, is_partition,
NULL);
}
static const char *
get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
{
NMSettingInfiniband *s_infiniband;
g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME), NULL);
s_infiniband = nm_connection_get_setting_infiniband (connection);
g_assert (s_infiniband);
return nm_setting_infiniband_get_parent (s_infiniband);
}
static char *
get_connection_iface (NMDeviceFactory *factory,
NMConnection *connection,
const char *parent_iface)
{
NMSettingInfiniband *s_infiniband;
g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME), NULL);
s_infiniband = nm_connection_get_setting_infiniband (connection);
g_assert (s_infiniband);
if (!parent_iface)
return NULL;
g_return_val_if_fail (g_strcmp0 (parent_iface, nm_setting_infiniband_get_parent (s_infiniband)) == 0, NULL);
return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband));
}
NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME),
factory_class->create_device = create_device;
factory_class->get_connection_parent = get_connection_parent;
factory_class->get_connection_iface = get_connection_iface;
);