summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/nm-device-bond.c2
-rw-r--r--src/devices/nm-device-bridge.c2
-rw-r--r--src/devices/nm-device-ethernet.c2
-rw-r--r--src/devices/nm-device-generic.c2
-rw-r--r--src/devices/nm-device-infiniband.c2
-rw-r--r--src/devices/nm-device-ip-tunnel.c7
-rw-r--r--src/devices/nm-device-macvlan.c2
-rw-r--r--src/devices/nm-device-private.h7
-rw-r--r--src/devices/nm-device-tun.c2
-rw-r--r--src/devices/nm-device-veth.c2
-rw-r--r--src/devices/nm-device-vlan.c2
-rw-r--r--src/devices/nm-device-vxlan.c2
-rw-r--r--src/devices/nm-device.c73
-rw-r--r--src/devices/nm-device.h2
-rw-r--r--src/devices/team/nm-device-team.c2
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c2
-rw-r--r--src/devices/wifi/nm-device-wifi.c2
-rw-r--r--src/nm-manager.c37
-rw-r--r--src/nm-types.h2
19 files changed, 125 insertions, 29 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 359b3c4abf..033c57214f 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -529,7 +529,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate));
- parent_class->connection_type = NM_SETTING_BOND_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BOND_SETTING_NAME, NM_LINK_TYPE_BOND)
/* virtual methods */
object_class->get_property = get_property;
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index 2a2f234c16..e152bb38b9 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -475,7 +475,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate));
- parent_class->connection_type = NM_SETTING_BRIDGE_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BRIDGE_SETTING_NAME, NM_LINK_TYPE_BRIDGE)
/* virtual methods */
object_class->get_property = get_property;
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 6f0c3e8881..65f8716d8e 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -1706,7 +1706,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate));
- parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET)
/* virtual methods */
object_class->constructor = constructor;
diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c
index 70ae48c678..0be55d54f0 100644
--- a/src/devices/nm-device-generic.c
+++ b/src/devices/nm-device-generic.c
@@ -196,7 +196,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate));
- parent_class->connection_type = NM_SETTING_GENERIC_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_GENERIC_SETTING_NAME, NM_LINK_TYPE_ANY)
object_class->constructor = constructor;
object_class->dispose = dispose;
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index e0c3c62d76..95f69c93c3 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -327,6 +327,8 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND)
+
/* virtual methods */
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
index 64c3a52146..84ab7cd69d 100644
--- a/src/devices/nm-device-ip-tunnel.c
+++ b/src/devices/nm-device-ip-tunnel.c
@@ -852,7 +852,12 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
device_class->setup_start = setup_start;
device_class->unrealize = unrealize;
- device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass,
+ NM_SETTING_IP_TUNNEL_SETTING_NAME,
+ NM_LINK_TYPE_GRE,
+ NM_LINK_TYPE_IP6TNL,
+ NM_LINK_TYPE_IPIP,
+ NM_LINK_TYPE_SIT);
/* properties */
g_object_class_install_property
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index e2dd891c1a..aed28816ff 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -143,6 +143,8 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceMacvlanPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP)
+
object_class->constructed = constructed;
object_class->get_property = get_property;
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index 33f51bfb6e..5010e90655 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -106,4 +106,11 @@ void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config);
gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value);
+#define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \
+ NM_DEVICE_CLASS (klass)->connection_type = conn_type; \
+ { \
+ static const NMLinkType link_types[] = { __VA_ARGS__, NM_LINK_TYPE_NONE }; \
+ NM_DEVICE_CLASS (klass)->link_types = link_types; \
+ }
+
#endif /* NM_DEVICE_PRIVATE_H */
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index 46d4d391e8..af37c3184d 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -364,6 +364,8 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP)
+
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index 9c22ad1e5c..1fd2a5a834 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -153,6 +153,8 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH)
+
object_class->get_property = get_property;
object_class->dispose = dispose;
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index 58263c5d0c..734a483bdc 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -667,7 +667,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
- parent_class->connection_type = NM_SETTING_VLAN_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN)
g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate));
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index 65b3950dd4..ad2f2ba44f 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -244,6 +244,8 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVxlanPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN)
+
object_class->get_property = get_property;
device_class->link_changed = link_changed;
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 63df7b71aa..5435440e2d 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1634,20 +1634,69 @@ link_changed (NMDevice *self, NMPlatformLink *info)
nm_device_set_carrier (self, info->connected);
}
+static gboolean
+link_type_compatible (NMDevice *self,
+ NMLinkType link_type,
+ gboolean *out_compatible,
+ GError **error)
+{
+ NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
+ guint i = 0;
+
+ if (!klass->link_types) {
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device does not support platform links");
+ return FALSE;
+ }
+
+ for (i = 0; klass->link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
+ if (klass->link_types[i] == link_type)
+ return TRUE;
+ if (klass->link_types[i] == NM_LINK_TYPE_ANY)
+ return TRUE;
+ }
+
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device does not support platform link type 0x%X",
+ link_type);
+ return FALSE;
+}
+
/**
* nm_device_realize():
* @self: the #NMDevice
* @plink: an existing platform link or %NULL
+ * @out_compatible: %TRUE on return if @self is compatible with @plink
* @error: location to store error, or %NULL
*
* Initializes and sets up the device using existing backing resources. Before
* the device is ready for use nm_device_setup_finish() must be called.
+ * @out_compatible will only be set if @plink is not %NULL, and
*
* Returns: %TRUE on success, %FALSE on error
*/
gboolean
-nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error)
+nm_device_realize (NMDevice *self,
+ NMPlatformLink *plink,
+ gboolean *out_compatible,
+ GError **error)
{
+ NM_SET_OUT (out_compatible, TRUE);
+
+ if (plink) {
+ if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) {
+ NM_SET_OUT (out_compatible, FALSE);
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Device interface name does not match platform link");
+ return FALSE;
+ }
+
+ if (!link_type_compatible (self, plink->type, out_compatible, error))
+ return FALSE;
+ }
+
/* Try to realize the device from existing resources */
if (NM_DEVICE_GET_CLASS (self)->realize) {
if (!NM_DEVICE_GET_CLASS (self)->realize (self, plink, error))
@@ -1766,7 +1815,7 @@ setup_start (NMDevice *self, NMPlatformLink *plink)
g_object_freeze_notify (G_OBJECT (self));
if (plink) {
- g_return_if_fail (priv->iface == NULL || strcmp (plink->name, priv->iface) == 0);
+ g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL));
update_device_from_platform_link (self, plink);
}
@@ -1871,6 +1920,8 @@ setup_finish (NMDevice *self, NMPlatformLink *plink)
void
nm_device_setup_finish (NMDevice *self, NMPlatformLink *plink)
{
+ g_return_if_fail (!plink || link_type_compatible (self, plink->type, NULL, NULL));
+
NM_DEVICE_GET_CLASS (self)->setup_finish (self, plink);
NM_DEVICE_GET_PRIVATE (self)->real = TRUE;
@@ -10073,6 +10124,7 @@ set_property (GObject *object, guint prop_id,
const char *hw_addr, *p;
guint count;
gboolean val_bool;
+ const NMPlatformLink *pllink;
switch (prop_id) {
case PROP_UDI:
@@ -10082,12 +10134,19 @@ set_property (GObject *object, guint prop_id,
}
break;
case PROP_IFACE:
- if (g_value_get_string (value)) {
+ p = g_value_get_string (value);
+ if (p) {
+
g_free (priv->iface);
- priv->iface = g_value_dup_string (value);
- priv->ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->iface);
- if (priv->ifindex > 0)
- priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
+ priv->iface = g_strdup (p);
+
+ pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
+ if (pllink) {
+ if (link_type_compatible (self, pllink->type, NULL, NULL)) {
+ priv->ifindex = pllink->ifindex;
+ priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex);
+ }
+ }
}
break;
case PROP_DRIVER:
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 268ed06294..55f05c4fab 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -123,6 +123,7 @@ typedef struct {
NMExportedObjectClass parent;
const char *connection_type;
+ const NMLinkType *link_types;
void (*state_changed) (NMDevice *device,
NMDeviceState new_state,
@@ -485,6 +486,7 @@ gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps);
gboolean nm_device_realize (NMDevice *device,
NMPlatformLink *plink,
+ gboolean *out_compatible,
GError **error);
gboolean nm_device_create_and_realize (NMDevice *self,
NMConnection *connection,
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 4bbe4c9ce7..fdc603364d 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -802,7 +802,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate));
- parent_class->connection_type = NM_SETTING_TEAM_SETTING_NAME;
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM)
/* virtual methods */
object_class->constructed = constructed;
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index 38f1f88dd4..8898c59cd6 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -511,6 +511,8 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH)
+
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index bb73e8c456..72540efed4 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -3034,6 +3034,8 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate));
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
+
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
diff --git a/src/nm-manager.c b/src/nm-manager.c
index eb0ec6fffc..ba926157f8 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1818,7 +1818,7 @@ factory_device_added_cb (NMDeviceFactory *factory,
{
GError *error = NULL;
- if (nm_device_realize (device, NULL, &error)) {
+ if (nm_device_realize (device, NULL, NULL, &error)) {
add_device (NM_MANAGER (user_data), device);
nm_device_setup_finish (device, NULL);
} else {
@@ -1878,22 +1878,29 @@ platform_link_added (NMManager *self,
device = find_device_by_iface (self, plink->name);
if (device) {
- if (!nm_device_is_real (device)) {
- if (nm_device_realize (device, plink, &error))
- nm_device_setup_finish (device, plink);
- else {
- nm_log_warn (LOGD_DEVICE, "(%s): %s", plink->name, error->message);
- g_clear_error (&error);
- remove_device (self, device, FALSE, FALSE);
- }
+ gboolean compatible = FALSE;
+
+ if (nm_device_is_real (device))
return;
- } else if (!nm_device_realize (device, plink, &error)) {
- nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s",
- plink->name, error->message);
- g_clear_error (&error);
+
+ if (nm_device_realize (device, plink, &compatible, &error)) {
+ /* Success */
+ nm_device_setup_finish (device, plink);
return;
}
- return;
+
+ nm_log_warn (LOGD_DEVICE, "(%s): %s", plink->name, error->message);
+ remove_device (self, device, FALSE, FALSE);
+ g_clear_error (&error);
+
+ if (compatible) {
+ /* Device compatible with platform link, but some other fatal error
+ * happened during realization.
+ */
+ return;
+ }
+
+ /* Fall through and create new compatible device for the link */
}
/* Try registered device factories */
@@ -1932,7 +1939,7 @@ platform_link_added (NMManager *self,
if (device) {
if (nm_plugin_missing)
nm_device_set_nm_plugin_missing (device, TRUE);
- if (nm_device_realize (device, plink, &error)) {
+ if (nm_device_realize (device, plink, NULL, &error)) {
add_device (self, device);
nm_device_setup_finish (device, plink);
} else {
diff --git a/src/nm-types.h b/src/nm-types.h
index 16ae6fa7b4..65d6193be2 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -126,6 +126,8 @@ typedef enum {
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
NM_LINK_TYPE_BOND,
NM_LINK_TYPE_TEAM,
+
+ NM_LINK_TYPE_ANY = G_MAXUINT32,
} NMLinkType;
typedef enum {