mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-06 14:20:16 +01:00
device: track parent device in NMDevice
Multiple subclasses have a parent/link interface (NMDeviceIPTunnel, NMDeviceVlan). Tracking the parent interface properly is midly complicated to get right. So, instead of repeating it in each subclass, track it in the parent device.
This commit is contained in:
parent
bd09decf16
commit
f703f4bb65
3 changed files with 202 additions and 0 deletions
|
|
@ -123,6 +123,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
|
|||
PROP_PHYSICAL_PORT_ID,
|
||||
PROP_IS_MASTER,
|
||||
PROP_MASTER,
|
||||
PROP_PARENT,
|
||||
PROP_HW_ADDRESS,
|
||||
PROP_PERM_HW_ADDRESS,
|
||||
PROP_HAS_PENDING_ACTION,
|
||||
|
|
@ -225,10 +226,14 @@ typedef struct _NMDevicePrivate {
|
|||
GSList *pending_actions;
|
||||
GSList *dad6_failed_addrs;
|
||||
|
||||
NMDevice *parent_device;
|
||||
|
||||
char * udi;
|
||||
char * iface; /* may change, could be renamed by user */
|
||||
int ifindex;
|
||||
|
||||
int parent_ifindex;
|
||||
|
||||
union {
|
||||
const guint8 hw_addr_len; /* read-only */
|
||||
guint8 hw_addr_len_;
|
||||
|
|
@ -874,6 +879,132 @@ _ip_iface_update (NMDevice *self, const char *ip_iface)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
nm_device_parent_get_ifindex (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), 0);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
return priv->parent_ifindex;
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
nm_device_parent_get_device (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
return priv->parent_device;
|
||||
}
|
||||
|
||||
static void
|
||||
parent_changed_notify (NMDevice *self,
|
||||
int old_ifindex,
|
||||
NMDevice *old_parent,
|
||||
int new_ifindex,
|
||||
NMDevice *new_parent)
|
||||
{
|
||||
/* empty handler to allow subclasses to always chain up the virtual function. */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_parent_set_ifindex (NMDevice *self,
|
||||
int parent_ifindex,
|
||||
gboolean force_check)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMDevice *parent_device;
|
||||
gboolean changed = FALSE;
|
||||
int old_ifindex;
|
||||
NMDevice *old_device;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (parent_ifindex <= 0)
|
||||
parent_ifindex = 0;
|
||||
|
||||
old_ifindex = priv->parent_ifindex;
|
||||
old_device = priv->parent_device;
|
||||
|
||||
if (priv->parent_ifindex == parent_ifindex) {
|
||||
if (parent_ifindex > 0) {
|
||||
if ( !force_check
|
||||
&& priv->parent_device
|
||||
&& nm_device_get_ifindex (priv->parent_device) == parent_ifindex)
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!priv->parent_device)
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
priv->parent_ifindex = parent_ifindex;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (parent_ifindex > 0) {
|
||||
parent_device = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
|
||||
if (parent_device == self)
|
||||
parent_device = NULL;
|
||||
} else
|
||||
parent_device = NULL;
|
||||
|
||||
if (parent_device != priv->parent_device) {
|
||||
priv->parent_device = parent_device;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (priv->parent_ifindex <= 0)
|
||||
_LOGD (LOGD_DEVICE, "parent: clear");
|
||||
else if (!priv->parent_device)
|
||||
_LOGD (LOGD_DEVICE, "parent: ifindex %d, no device", priv->parent_ifindex);
|
||||
else {
|
||||
_LOGD (LOGD_DEVICE, "parent: ifindex %d, device %p, %s", priv->parent_ifindex,
|
||||
priv->parent_device, nm_device_get_iface (priv->parent_device));
|
||||
}
|
||||
|
||||
NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device);
|
||||
|
||||
_notify (self, PROP_PARENT);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_parent_set_ifindex (NMDevice *self,
|
||||
int parent_ifindex)
|
||||
{
|
||||
_parent_set_ifindex (self, parent_ifindex, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_parent_notify_changed (NMDevice *self,
|
||||
NMDevice *change_candidate,
|
||||
gboolean device_removed)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
nm_assert (NM_IS_DEVICE (self));
|
||||
nm_assert (NM_IS_DEVICE (change_candidate));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->parent_ifindex > 0) {
|
||||
if ( priv->parent_device == change_candidate
|
||||
|| priv->parent_ifindex == nm_device_get_ifindex (change_candidate))
|
||||
return _parent_set_ifindex (self, priv->parent_ifindex, device_removed);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_stats_update_counters (NMDevice *self,
|
||||
guint64 tx_bytes,
|
||||
|
|
@ -2622,6 +2753,8 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
|
|||
|
||||
NM_DEVICE_GET_CLASS (self)->unrealize_notify (self);
|
||||
|
||||
_parent_set_ifindex (self, 0, FALSE);
|
||||
|
||||
if (priv->ifindex > 0) {
|
||||
priv->ifindex = 0;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
|
|
@ -12722,6 +12855,8 @@ dispose (GObject *object)
|
|||
|
||||
_LOGD (LOGD_DEVICE, "disposing");
|
||||
|
||||
_parent_set_ifindex (self, 0, FALSE);
|
||||
|
||||
platform = NM_PLATFORM_GET;
|
||||
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
|
||||
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
|
||||
|
|
@ -12758,6 +12893,11 @@ dispose (GObject *object)
|
|||
|
||||
link_disconnect_action_cancel (self);
|
||||
|
||||
if (priv->ifindex > 0) {
|
||||
priv->ifindex = 0;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
}
|
||||
|
||||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self);
|
||||
|
|
@ -13036,6 +13176,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_MASTER:
|
||||
g_value_set_object (value, nm_device_get_master (self));
|
||||
break;
|
||||
case PROP_PARENT:
|
||||
nm_utils_g_value_set_object_path (value, priv->parent_device);
|
||||
break;
|
||||
case PROP_HW_ADDRESS:
|
||||
g_value_set_string (value, priv->hw_addr);
|
||||
break;
|
||||
|
|
@ -13140,6 +13283,7 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
klass->get_ip_iface_identifier = get_ip_iface_identifier;
|
||||
klass->unmanaged_on_quit = unmanaged_on_quit;
|
||||
klass->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
|
||||
klass->parent_changed_notify = parent_changed_notify;
|
||||
|
||||
obj_properties[PROP_UDI] =
|
||||
g_param_spec_string (NM_DEVICE_UDI, "", "",
|
||||
|
|
@ -13294,6 +13438,11 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
NM_TYPE_DEVICE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_PARENT] =
|
||||
g_param_spec_string (NM_DEVICE_PARENT, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_HW_ADDRESS] =
|
||||
g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "",
|
||||
NULL,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@
|
|||
#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors"
|
||||
#define NM_DEVICE_REAL "real"
|
||||
|
||||
/* "parent" will later be exposed by some subclasses */
|
||||
#define NM_DEVICE_PARENT "parent"
|
||||
|
||||
/* the "slaves" property is internal in the parent class, but exposed
|
||||
* by the derived classes NMDeviceBond, NMDeviceBridge and NMDeviceTeam.
|
||||
* It is thus important that the property name matches. */
|
||||
|
|
@ -316,6 +319,12 @@ typedef struct {
|
|||
|
||||
void (* notify_new_device_added) (NMDevice *self, NMDevice *new_device);
|
||||
|
||||
void (* parent_changed_notify) (NMDevice *self,
|
||||
int old_ifindex,
|
||||
NMDevice *old_parent,
|
||||
int new_ifindex,
|
||||
NMDevice *new_parent);
|
||||
|
||||
/**
|
||||
* component_added:
|
||||
* @self: the #NMDevice
|
||||
|
|
@ -390,6 +399,14 @@ void nm_device_replace_vpn6_config (NMDevice *dev,
|
|||
|
||||
void nm_device_capture_initial_config (NMDevice *dev);
|
||||
|
||||
int nm_device_parent_get_ifindex (NMDevice *dev);
|
||||
NMDevice *nm_device_parent_get_device (NMDevice *dev);
|
||||
void nm_device_parent_set_ifindex (NMDevice *self,
|
||||
int parent_ifindex);
|
||||
gboolean nm_device_parent_notify_changed (NMDevice *self,
|
||||
NMDevice *change_candidate,
|
||||
gboolean device_removed);
|
||||
|
||||
/* Master */
|
||||
gboolean nm_device_is_master (NMDevice *dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -949,6 +949,26 @@ settings_startup_complete_changed (NMSettings *settings,
|
|||
check_if_startup_complete (self);
|
||||
}
|
||||
|
||||
static void
|
||||
_parent_notify_changed (NMManager *self,
|
||||
NMDevice *device,
|
||||
gboolean device_removed)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
nm_assert (NM_IS_DEVICE (device));
|
||||
nm_assert (NM_IS_MANAGER (self));
|
||||
|
||||
for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; ) {
|
||||
if (nm_device_parent_notify_changed (iter->data, device, device_removed)) {
|
||||
/* in the unlikely event that this changes anything, we start iterating
|
||||
* again, to be sure that the device list is up-to-date. */
|
||||
iter = NM_MANAGER_GET_PRIVATE (self)->devices;
|
||||
} else
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_device (NMManager *self,
|
||||
NMDevice *device,
|
||||
|
|
@ -985,6 +1005,8 @@ remove_device (NMManager *self,
|
|||
nm_settings_device_removed (priv->settings, device, quitting);
|
||||
priv->devices = g_slist_remove (priv->devices, device);
|
||||
|
||||
_parent_notify_changed (self, device, TRUE);
|
||||
|
||||
if (nm_device_is_real (device)) {
|
||||
gboolean unconfigure_ip_config = !quitting || unmanage;
|
||||
|
||||
|
|
@ -1860,6 +1882,14 @@ recheck_assume_connection_cb (NMDevice *device, gpointer user_data)
|
|||
recheck_assume_connection (user_data, device);
|
||||
}
|
||||
|
||||
static void
|
||||
device_ifindex_changed (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
NMManager *self)
|
||||
{
|
||||
_parent_notify_changed (self, device, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
device_ip_iface_changed (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
|
|
@ -1998,6 +2028,10 @@ add_device (NMManager *self, NMDevice *device, GError **error)
|
|||
G_CALLBACK (device_ip_iface_changed),
|
||||
self);
|
||||
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_IFINDEX,
|
||||
G_CALLBACK (device_ifindex_changed),
|
||||
self);
|
||||
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_IFACE,
|
||||
G_CALLBACK (device_iface_changed),
|
||||
self);
|
||||
|
|
@ -2047,6 +2081,8 @@ add_device (NMManager *self, NMDevice *device, GError **error)
|
|||
nm_device_notify_new_device_added (d, device);
|
||||
}
|
||||
|
||||
_parent_notify_changed (self, device, FALSE);
|
||||
|
||||
/* Virtual connections may refer to the new device as
|
||||
* parent device, retry to activate them.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue