diff --git a/src/nm-device.c b/src/nm-device.c index 7b5cad515..0e553f507 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -163,6 +163,9 @@ typedef struct { /* inhibit autoconnect feature */ gboolean autoconnect_inhibit; + + /* master interface for bridge, bond, vlan, etc */ + NMDevice * master; } NMDevicePrivate; static gboolean check_connection_compatible (NMDeviceInterface *device, @@ -502,6 +505,24 @@ nm_device_get_type_desc (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->type_desc; } +NMDevice * +nm_device_get_master (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->master; +} + +void +nm_device_set_master (NMDevice *self, NMDevice *master) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (priv->master) + g_object_unref (priv->master); + priv->master = master ? g_object_ref (master) : NULL; +} + /* * nm_device_get_act_request * @@ -3324,6 +3345,9 @@ finalize (GObject *object) if (priv->dhcp_anycast_address) g_byte_array_free (priv->dhcp_anycast_address, TRUE); + /* release master reference it still exists */ + nm_device_set_master (self, NULL); + G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); } diff --git a/src/nm-device.h b/src/nm-device.h index 6af2d5e41..d27f64f26 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -151,6 +151,9 @@ NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *dev); NMIP4Config * nm_device_get_ip4_config (NMDevice *dev); NMIP6Config * nm_device_get_ip6_config (NMDevice *dev); +NMDevice * nm_device_get_master (NMDevice *self); +void nm_device_set_master (NMDevice *self, NMDevice *master); + NMActRequest * nm_device_get_act_request (NMDevice *dev); gboolean nm_device_is_available (NMDevice *dev); diff --git a/src/nm-manager.c b/src/nm-manager.c index f75523acd..7205c7ae3 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -366,6 +366,24 @@ nm_manager_get_device_by_path (NMManager *manager, const char *path) return NULL; } +NMDevice * +nm_manager_get_device_by_master (NMManager *manager, const char *master, const char *driver) +{ + GSList *iter; + + g_return_val_if_fail (master != NULL, NULL); + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + + if (!strcmp (nm_device_get_iface (device), master) && + (!driver || !strcmp (nm_device_get_driver (device), driver))) + return device; + } + + return NULL; +} + static gboolean manager_sleeping (NMManager *self) { diff --git a/src/nm-manager.h b/src/nm-manager.h index b044971f0..4e8d67e49 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -84,6 +84,10 @@ void nm_manager_start (NMManager *manager); GSList *nm_manager_get_devices (NMManager *manager); +NMDevice *nm_manager_get_device_by_master (NMManager *manager, + const char *master, + const char *driver); + const char * nm_manager_activate_connection (NMManager *manager, NMConnection *connection, const char *specific_object, diff --git a/src/nm-policy.c b/src/nm-policy.c index 923ad4d93..d0f98a5d8 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -730,6 +730,33 @@ activate_data_free (ActivateData *data) g_free (data); } +static NMActStageReturn +check_master_dependency (NMManager *manager, NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMDevice *master_device; + const char *master; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + master = nm_setting_connection_get_master (s_con); + + /* no master defined, proceed with activation */ + if (!master) + return TRUE; + + master_device = nm_manager_get_device_by_master (manager, master, NULL); + + /* If master device is not yet present, postpone activation until later */ + if (!master_device) + return FALSE; + + nm_device_set_master (device, master_device); + + return TRUE; +} + static gboolean auto_activate_device (gpointer user_data) { @@ -786,6 +813,12 @@ auto_activate_device (gpointer user_data) if (best_connection) { GError *error = NULL; + if (!check_master_dependency (data->policy->manager, data->device, best_connection)) { + nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation postponed: master not available", + nm_connection_get_id (best_connection)); + goto postpone; + } + nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.", nm_connection_get_id (best_connection)); if (!nm_manager_activate_connection (policy->manager, @@ -800,6 +833,7 @@ auto_activate_device (gpointer user_data) } } + postpone: g_slist_free (connections); out: