core: add class function for device unrealization

When a device is unrealized, its class-specific properties must also be cleared
since the device is no longer valid.
This commit is contained in:
Dan Williams 2014-09-24 15:13:19 -05:00 committed by Thomas Haller
parent deb6c5f714
commit 0be66bb1eb
7 changed files with 217 additions and 9 deletions

View file

@ -727,6 +727,34 @@ setup (NMDevice *device, NMPlatformLink *plink)
update_properties (device);
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device);
NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self);
GParamSpec **properties;
guint n_properties, i;
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->unrealize (device, remove_resources);
g_clear_object (&priv->parent);
priv->parent_ifindex = 0;
g_clear_pointer (&priv->local, g_free);
g_clear_pointer (&priv->remote, g_free);
priv->ttl = 0;
priv->tos = 0;
priv->path_mtu_discovery = FALSE;
g_clear_pointer (&priv->input_key, g_free);
g_clear_pointer (&priv->output_key, g_free);
priv->encap_limit = 0;
priv->flow_label = 0;
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties);
for (i = 0; i < n_properties; i++)
g_object_notify_by_pspec (G_OBJECT (self), properties[i]);
g_free (properties);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@ -809,6 +837,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
device_class->create_and_realize = create_and_realize;
device_class->realize = realize;
device_class->setup = setup;
device_class->unrealize = unrealize;
device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME;

View file

@ -24,9 +24,9 @@
#include <string.h>
#include <sys/types.h>
#include "nm-default.h"
#include "nm-device-tun.h"
#include "nm-device-private.h"
#include "nm-default.h"
#include "nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-tun.h"
@ -265,6 +265,24 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
return TRUE;
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
GParamSpec **properties;
guint n_properties, i;
NM_DEVICE_CLASS (nm_device_tun_parent_class)->unrealize (device, remove_resources);
memset (&priv->props, 0, sizeof (NMPlatformTunProperties));
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties);
for (i = 0; i < n_properties; i++)
g_object_notify_by_pspec (G_OBJECT (self), properties[i]);
g_free (properties);
}
/**************************************************************/
static void
@ -349,6 +367,7 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->realize = realize;
device_class->unrealize = unrealize;
device_class->update_connection = update_connection;
/* properties */

View file

@ -256,6 +256,16 @@ create_and_realize (NMDevice *device,
return TRUE;
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->unrealize (device, remove_resources);
NM_DEVICE_VLAN_GET_PRIVATE (device)->vlan_id = 0;
g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID);
nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), NULL);
}
/******************************************************************/
static NMDeviceCapabilities
@ -663,6 +673,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
parent_class->create_and_realize = create_and_realize;
parent_class->realize = realize;
parent_class->setup = setup;
parent_class->unrealize = unrealize;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->bring_up = bring_up;
parent_class->act_stage1_prepare = act_stage1_prepare;

View file

@ -22,9 +22,9 @@
#include <string.h>
#include "nm-default.h"
#include "nm-device-vxlan.h"
#include "nm-device-private.h"
#include "nm-default.h"
#include "nm-manager.h"
#include "nm-platform.h"
#include "nm-utils.h"
@ -142,6 +142,23 @@ setup (NMDevice *device, NMPlatformLink *plink)
update_properties (device);
}
static void
unrealize (NMDevice *device, gboolean remove_resources)
{
NMDeviceVxlan *self = NM_DEVICE_VXLAN (device);
NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (self);
GParamSpec **properties;
guint n_properties, i;
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->unrealize (device, remove_resources);
memset (&priv->props, 0, sizeof (NMPlatformLnkVxlan));
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties);
for (i = 0; i < n_properties; i++)
g_object_notify_by_pspec (G_OBJECT (self), properties[i]);
g_free (properties);
}
/**************************************************************/
@ -231,6 +248,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
device_class->link_changed = link_changed;
device_class->setup = setup;
device_class->unrealize = unrealize;
/* properties */
g_object_class_install_property

View file

@ -1858,6 +1858,103 @@ setup (NMDevice *self, NMPlatformLink *plink)
g_object_thaw_notify (G_OBJECT (self));
}
static void
unrealize (NMDevice *self, gboolean remove_resources)
{
int ifindex;
if (remove_resources) {
ifindex = nm_device_get_ifindex (self);
if ( ifindex > 0
&& nm_device_is_software (self))
nm_platform_link_delete (NM_PLATFORM_GET, ifindex);
}
}
/**
* nm_device_unrealize():
* @self: the #NMDevice
* @remove_resources: if %TRUE, remove backing resources
* @error: location to store error, or %NULL
*
* Clears any properties that depend on backing resources (kernel devices,
* etc) and removes those resources if @remove_resources is %TRUE.
*
* Returns: %TRUE on success, %FALSE on error
*/
gboolean
nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_SOFTWARE,
"This device is not a software device or is not realized");
return FALSE;
}
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_val_if_fail (priv->iface != NULL, FALSE);
g_object_freeze_notify (G_OBJECT (self));
if (NM_DEVICE_GET_CLASS (self)->unrealize)
NM_DEVICE_GET_CLASS (self)->unrealize (self, remove_resources);
if (priv->ifindex > 0) {
priv->ifindex = 0;
g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX);
}
priv->ip_ifindex = 0;
if (priv->ip_iface) {
g_clear_pointer (&priv->ip_iface, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
}
if (priv->driver_version) {
g_clear_pointer (&priv->driver_version, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION);
}
if (priv->firmware_version) {
g_clear_pointer (&priv->firmware_version, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION);
}
if (priv->udi) {
g_clear_pointer (&priv->udi, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
}
if (priv->hw_addr) {
g_clear_pointer (&priv->hw_addr, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS);
}
if (priv->physical_port_id) {
g_clear_pointer (&priv->physical_port_id, g_free);
g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
}
g_clear_pointer (&priv->perm_hw_addr, g_free);
g_clear_pointer (&priv->initial_hw_addr, g_free);
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
priv->real = FALSE;
g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
g_object_thaw_notify (G_OBJECT (self));
nm_device_state_changed (self,
NM_DEVICE_STATE_UNMANAGED,
remove_resources ?
NM_DEVICE_STATE_REASON_USER_REQUESTED : NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
return TRUE;
}
/**
* nm_device_notify_new_device_added():
* @self: the #NMDevice
@ -6471,16 +6568,21 @@ delete_on_deactivate_link_delete (gpointer user_data)
DeleteOnDeactivateData *data = user_data;
NMDevice *self = data->device;
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
data->ifindex, data->idle_add_id);
if (data->device) {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (data->device);
gs_free_error GError *error = NULL;
g_object_remove_weak_pointer (G_OBJECT (data->device), (void **) &data->device);
priv->delete_on_deactivate_data = NULL;
}
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
data->ifindex, data->idle_add_id);
nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex);
if (!nm_device_unrealize (data->device, TRUE, &error))
_LOGD (LOGD_DEVICE, "delete_on_deactivate: unrealizing %d failed (%s)", data->ifindex, error->message);
} else
nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex);
g_free (data);
return FALSE;
}
@ -6611,6 +6713,8 @@ delete_cb (NMDevice *self,
GError *error,
gpointer user_data)
{
GError *local = NULL;
if (error) {
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, subject, error->message);
@ -6618,9 +6722,11 @@ delete_cb (NMDevice *self,
}
/* Authorized */
nm_platform_link_delete (NM_PLATFORM_GET, nm_device_get_ifindex (self));
g_dbus_method_invocation_return_value (context, NULL);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, subject, NULL);
if (nm_device_unrealize (self, TRUE, &local))
g_dbus_method_invocation_return_value (context, NULL);
else
g_dbus_method_invocation_take_error (context, local);
}
static void
@ -10219,6 +10325,7 @@ nm_device_class_init (NMDeviceClass *klass)
klass->check_connection_available = check_connection_available;
klass->can_unmanaged_external_down = can_unmanaged_external_down;
klass->setup = setup;
klass->unrealize = unrealize;
klass->is_up = is_up;
klass->bring_up = bring_up;
klass->take_down = take_down;

View file

@ -183,6 +183,17 @@ typedef struct {
*/
void (*setup) (NMDevice *self, NMPlatformLink *plink);
/**
* unrealize():
* @self: the #NMDevice
* @remove_resources: if %TRUE remove backing resources
* @error: location to store error, or %NULL
*
* Clears any properties that depend on backing resources (kernel devices,
* etc) and removes those resources if @remove_resources is %TRUE.
*/
void (*unrealize) (NMDevice *self, gboolean remove_resources);
/* Hardware state (IFF_UP) */
gboolean (*can_unmanaged_external_down) (NMDevice *self);
gboolean (*is_up) (NMDevice *self);
@ -466,6 +477,9 @@ gboolean nm_device_create_and_realize (NMDevice *self,
NMConnection *connection,
NMDevice *parent,
GError **error);
gboolean nm_device_unrealize (NMDevice *device,
gboolean remove_resources,
GError **error);
gboolean nm_device_get_autoconnect (NMDevice *device);

View file

@ -1949,10 +1949,20 @@ _platform_link_cb_idle (PlatformLinkCbData *data)
platform_link_added (self, data->ifindex, &pllink);
} else {
NMDevice *device;
GError *error = NULL;
device = nm_manager_get_device_by_ifindex (self, data->ifindex);
if (device)
if (device) {
if (nm_device_is_software (device)) {
if (!nm_device_unrealize (device, FALSE, &error)) {
nm_log_warn (LOGD_DEVICE, "(%s): failed to unrealize: %s",
nm_device_get_iface (device),
error->message);
g_clear_error (&error);
}
}
remove_device (self, device, FALSE, TRUE);
}
}
g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self);
}