diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2020-02-26 16:25:55 +0100 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2020-02-26 16:25:55 +0100 |
| commit | ee7b95167028fdbb2a4bd32aa686e27817d8dfe0 (patch) | |
| tree | f7a1abab0400789979f860dda724247a9bbbdef1 /src/devices | |
| parent | c1b3616485604f3fddfad9521cb8818cd8eece2b (diff) | |
| parent | e536d40eaea5dcdc0743b0a5e8e17faa46608a50 (diff) | |
Merge branch 'upstream/latest' of https://salsa.debian.org/utopia-team/network-manager into upstream/latest
Diffstat (limited to 'src/devices')
| -rw-r--r-- | src/devices/nm-device-factory.c | 8 | ||||
| -rw-r--r-- | src/devices/nm-device.c | 230 | ||||
| -rw-r--r-- | src/devices/nm-device.h | 7 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-interface.c | 168 | ||||
| -rw-r--r-- | src/devices/team/nm-device-team.c | 19 | ||||
| -rw-r--r-- | src/devices/wifi/nm-device-olpc-mesh.c | 4 | ||||
| -rw-r--r-- | src/devices/wwan/nm-device-modem.c | 4 |
7 files changed, 358 insertions, 82 deletions
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 232e69ef..1c1d5eaa 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -143,14 +143,6 @@ nm_device_factory_get_connection_iface (NMDeviceFactory *factory, return NULL; } - if (!nm_utils_is_valid_iface_name (ifname, error)) { - g_prefix_error (error, - "failed to determine interface name: name \"%s\" is invalid", - ifname); - g_free (ifname); - return NULL; - } - return ifname; } diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index e7a4a059..3bbc9757 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -76,7 +76,20 @@ _LOG_DECLARE_SELF (NMDevice); /*****************************************************************************/ #define DEFAULT_AUTOCONNECT TRUE -#define DHCP_GRACE_PERIOD_SEC 480 + +static guint32 +dhcp_grace_period_from_timeout (guint32 timeout) +{ +#define DHCP_GRACE_PERIOD_MULTIPLIER 2U + + nm_assert (timeout > 0); + nm_assert (timeout < G_MAXINT32); + + if (timeout < G_MAXUINT32 / DHCP_GRACE_PERIOD_MULTIPLIER) + return timeout * DHCP_GRACE_PERIOD_MULTIPLIER; + + return G_MAXUINT32; +} #define CARRIER_WAIT_TIME_MS 6000 #define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000 @@ -463,12 +476,13 @@ typedef struct _NMDevicePrivate { /* DHCPv4 tracking */ struct { NMDhcpClient * client; - gulong state_sigid; NMDhcp4Config * config; char * pac_url; char * root_path; - bool was_active; + gulong state_sigid; guint grace_id; + bool was_active:1; + bool grace_pending:1; } dhcp4; struct { @@ -533,17 +547,18 @@ typedef struct _NMDevicePrivate { struct { NMDhcpClient * client; - NMNDiscDHCPLevel mode; - gulong state_sigid; - gulong prefix_sigid; NMDhcp6Config * config; /* IP6 config from DHCP */ AppliedConfig ip6_config; /* Event ID of the current IP6 config from DHCP */ char * event_id; + gulong state_sigid; + gulong prefix_sigid; + NMNDiscDHCPLevel mode; guint needed_prefixes; - bool was_active; guint grace_id; + bool was_active:1; + bool grace_pending:1; } dhcp6; gboolean needs_ip6_subnet; @@ -4240,6 +4255,12 @@ nm_device_create_and_realize (NMDevice *self, return TRUE; } +static gboolean +can_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink) +{ + return TRUE; +} + void nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink) { @@ -4248,6 +4269,9 @@ nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink int ifindex; guint32 mtu; + if (!NM_DEVICE_GET_CLASS (self)->can_update_from_platform_link (self, plink)) + return; + g_return_if_fail (plink == NULL || link_type_compatible (self, plink->type, NULL, NULL)); str = plink ? nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex) : NULL; @@ -7474,6 +7498,51 @@ ensure_con_ip_config (NMDevice *self, int addr_family) /*****************************************************************************/ /* DHCPv4 stuff */ +static guint32 +get_dhcp_timeout (NMDevice *self, int addr_family) +{ + NMDeviceClass *klass; + NMConnection *connection; + int timeout_i; + guint32 timeout; + + nm_assert (NM_IS_DEVICE (self)); + nm_assert_addr_family (addr_family); + + connection = nm_device_get_applied_connection (self); + + timeout_i = nm_setting_ip_config_get_dhcp_timeout (nm_connection_get_setting_ip_config (connection, addr_family)); + nm_assert (timeout_i >= 0 && timeout_i <= G_MAXINT32); + + timeout = (guint32) timeout_i; + if (timeout) + goto out; + + timeout = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + addr_family == AF_INET + ? NM_CON_DEFAULT ("ipv4.dhcp-timeout") + : NM_CON_DEFAULT ("ipv6.dhcp-timeout"), + self, + 0, G_MAXINT32, 0); + if (timeout) + goto out; + + klass = NM_DEVICE_GET_CLASS (self); + if (klass->get_dhcp_timeout_for_device) { + timeout = klass->get_dhcp_timeout_for_device (self, addr_family); + if (timeout) + goto out; + } + + timeout = NM_DHCP_TIMEOUT_DEFAULT; + +out: + G_STATIC_ASSERT_EXPR (G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY); + nm_assert (timeout > 0); + nm_assert (timeout <= G_MAXINT32); + return timeout; +} + static void dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { @@ -7481,6 +7550,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) priv->dhcp4.was_active = FALSE; nm_clear_g_source (&priv->dhcp4.grace_id); + priv->dhcp4.grace_pending = FALSE; g_clear_pointer (&priv->dhcp4.pac_url, g_free); g_clear_pointer (&priv->dhcp4.root_path, g_free); @@ -7723,9 +7793,10 @@ ip_config_merge_and_apply (NMDevice *self, } static gboolean -dhcp4_lease_change (NMDevice *self, NMIP4Config *config) +dhcp4_lease_change (NMDevice *self, NMIP4Config *config, gboolean bound) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gs_free_error GError *error = NULL; g_return_val_if_fail (config, FALSE); @@ -7736,6 +7807,15 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) return FALSE; } + /* TODO: we should perform DAD again whenever we obtain a + * new lease after an expiry. But what should we do if + * a duplicate address is detected? Fail the connection; + * restart DHCP; continue without an address? */ + if (bound && !nm_dhcp_client_accept (priv->dhcp4.client, &error)) { + _LOGW (LOGD_DHCP4, "error accepting lease: %s", error->message); + return FALSE; + } + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE, self, NULL, @@ -7751,6 +7831,7 @@ dhcp4_grace_period_expired (gpointer user_data) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp4.grace_id = 0; + priv->dhcp4.grace_pending = FALSE; _LOGI (LOGD_DHCP4, "DHCPv4: grace period expired"); nm_device_ip_method_failed (self, AF_INET, @@ -7798,13 +7879,26 @@ dhcp4_fail (NMDevice *self, NMDhcpState dhcp_state) /* In any other case (expired lease, assumed connection, etc.), * wait for some time before failing the IP method. */ - if (!priv->dhcp4.grace_id) { - priv->dhcp4.grace_id = g_timeout_add_seconds (DHCP_GRACE_PERIOD_SEC, - dhcp4_grace_period_expired, - self); - _LOGI (LOGD_DHCP4, - "DHCPv4: %u seconds grace period started", - DHCP_GRACE_PERIOD_SEC); + if (!priv->dhcp4.grace_pending) { + guint32 timeout; + + /* Start a grace period equal to the DHCP timeout multiplied + * by a constant factor. */ + timeout = get_dhcp_timeout (self, AF_INET); + if (timeout == NM_DHCP_TIMEOUT_INFINITY) { + _LOGI (LOGD_DHCP4, "DHCPv4: trying to acquire a new lease"); + } else { + timeout = dhcp_grace_period_from_timeout (timeout); + _LOGI (LOGD_DHCP4, + "DHCPv4: trying to acquire a new lease within %u seconds", + timeout); + nm_assert (!priv->dhcp4.grace_id); + priv->dhcp4.grace_id = g_timeout_add_seconds (timeout, + dhcp4_grace_period_expired, + self); + } + + priv->dhcp4.grace_pending = TRUE; goto clear_config; } return; @@ -7853,6 +7947,7 @@ dhcp4_state_changed (NMDhcpClient *client, switch (state) { case NM_DHCP_STATE_BOUND: + case NM_DHCP_STATE_EXTENDED: if (!ip4_config) { _LOGW (LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event."); dhcp4_fail (self, state); @@ -7860,6 +7955,7 @@ dhcp4_state_changed (NMDhcpClient *client, } nm_clear_g_source (&priv->dhcp4.grace_id); + priv->dhcp4.grace_pending = FALSE; /* After some failures, we have been able to renew the lease: * update the ip state @@ -7895,7 +7991,8 @@ dhcp4_state_changed (NMDhcpClient *client, ipv4_dad_start (self, configs, dhcp4_dad_cb); } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { - if (dhcp4_lease_change (self, ip4_config)) + if (dhcp4_lease_change (self, ip4_config, + state == NM_DHCP_STATE_BOUND)) nm_device_update_metered (self); else dhcp4_fail (self, state); @@ -7919,41 +8016,6 @@ dhcp4_state_changed (NMDhcpClient *client, } } -static int -get_dhcp_timeout (NMDevice *self, int addr_family) -{ - NMDeviceClass *klass; - NMConnection *connection; - NMSettingIPConfig *s_ip; - guint32 timeout; - - nm_assert (NM_IS_DEVICE (self)); - nm_assert_addr_family (addr_family); - - connection = nm_device_get_applied_connection (self); - - s_ip = nm_connection_get_setting_ip_config (connection, addr_family); - - timeout = nm_setting_ip_config_get_dhcp_timeout (s_ip); - if (timeout) - return timeout; - - timeout = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, - addr_family == AF_INET - ? NM_CON_DEFAULT ("ipv4.dhcp-timeout") - : NM_CON_DEFAULT ("ipv6.dhcp-timeout"), - self, - 0, G_MAXINT32, 0); - if (timeout) - return timeout; - - klass = NM_DEVICE_GET_CLASS (self); - if (klass->get_dhcp_timeout) - timeout = klass->get_dhcp_timeout (self, addr_family); - - return timeout ?: NM_DHCP_TIMEOUT_DEFAULT; -} - /** * dhcp_get_iaid: * @self: the #NMDevice @@ -8520,6 +8582,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) applied_config_clear (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); nm_clear_g_source (&priv->dhcp6.grace_id); + priv->dhcp6.grace_pending = FALSE; if (priv->dhcp6.client) { nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.state_sigid); @@ -8575,6 +8638,7 @@ dhcp6_grace_period_expired (gpointer user_data) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp6.grace_id = 0; + priv->dhcp6.grace_pending = FALSE; _LOGI (LOGD_DHCP6, "DHCPv6: grace period expired"); nm_device_ip_method_failed (self, AF_INET6, @@ -8626,13 +8690,26 @@ dhcp6_fail (NMDevice *self, NMDhcpState dhcp_state) /* In any other case (expired lease, assumed connection, etc.), * wait for some time before failing the IP method. */ - if (!priv->dhcp6.grace_id) { - priv->dhcp6.grace_id = g_timeout_add_seconds (DHCP_GRACE_PERIOD_SEC, - dhcp6_grace_period_expired, - self); - _LOGI (LOGD_DHCP6, - "DHCPv6: %u seconds grace period started", - DHCP_GRACE_PERIOD_SEC); + if (!priv->dhcp6.grace_pending) { + guint32 timeout; + + /* Start a grace period equal to the DHCP timeout multiplied + * by a constant factor. */ + timeout = get_dhcp_timeout (self, AF_INET6); + if (timeout == NM_DHCP_TIMEOUT_INFINITY) + _LOGI (LOGD_DHCP6, "DHCPv6: trying to acquire a new lease"); + else { + timeout = dhcp_grace_period_from_timeout (timeout); + _LOGI (LOGD_DHCP6, + "DHCPv6: trying to acquire a new lease within %u seconds", + timeout); + nm_assert (!priv->dhcp6.grace_id); + priv->dhcp6.grace_id = g_timeout_add_seconds (timeout, + dhcp6_grace_period_expired, + self); + } + + priv->dhcp6.grace_pending = TRUE; goto clear_config; } } else { @@ -8670,7 +8747,9 @@ dhcp6_state_changed (NMDhcpClient *client, switch (state) { case NM_DHCP_STATE_BOUND: + case NM_DHCP_STATE_EXTENDED: nm_clear_g_source (&priv->dhcp6.grace_id); + priv->dhcp6.grace_pending = FALSE; /* If the server sends multiple IPv6 addresses, we receive a state * changed event for each of them. Use the event ID to merge IPv6 * addresses from the same transaction into a single configuration. @@ -10016,7 +10095,7 @@ addrconf6_start_with_link_ready (NMDevice *self) G_CALLBACK (ndisc_config_changed), self); priv->ndisc_timeout_id = g_signal_connect (priv->ndisc, - NM_NDISC_RA_TIMEOUT, + NM_NDISC_RA_TIMEOUT_SIGNAL, G_CALLBACK (ndisc_ra_timeout), self); @@ -10035,6 +10114,28 @@ ndisc_node_type (NMDevice *self) return NM_NDISC_NODE_TYPE_HOST; } +static gint32 +get_ra_timeout (NMDevice *self) +{ + NMConnection *connection; + gint32 timeout; + + G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_DEFAULT == 0); + G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_INFINITY == G_MAXINT32); + + connection = nm_device_get_applied_connection (self); + + timeout = nm_setting_ip6_config_get_ra_timeout (NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection))); + nm_assert (timeout >= 0); + if (timeout) + return timeout; + + return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + NM_CON_DEFAULT ("ipv6.ra-timeout"), + self, + 0, G_MAXINT32, 0); +} + static gboolean addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) { @@ -10065,6 +10166,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) stable_id, nm_setting_ip6_config_get_addr_gen_mode (s_ip6), ndisc_node_type (self), + get_ra_timeout (self), &error); if (!priv->ndisc) { _LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message); @@ -15515,6 +15617,12 @@ _set_state_full (NMDevice *self, reason_to_string_a (reason), _sys_iface_state_to_str (priv->sys_iface_state)); + /* in order to prevent triggering any callback caused + * by the device not having any pending action anymore + * we add one here that gets removed at the end of the function */ + nm_device_add_pending_action (self, + NM_PENDING_ACTION_IN_STATE_CHANGE, + TRUE); priv->in_state_changed = TRUE; priv->state = state; @@ -15821,6 +15929,9 @@ _set_state_full (NMDevice *self, g_object_unref (req); priv->in_state_changed = FALSE; + nm_device_remove_pending_action (self, + NM_PENDING_ACTION_IN_STATE_CHANGE, + TRUE); if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED)) _notify (self, PROP_MANAGED); @@ -17507,6 +17618,7 @@ nm_device_class_init (NMDeviceClass *klass) klass->get_type_description = get_type_description; klass->can_auto_connect = can_auto_connect; + klass->can_update_from_platform_link = can_update_from_platform_link; klass->check_connection_compatible = check_connection_compatible; klass->check_connection_available = check_connection_available; klass->can_unmanaged_external_down = can_unmanaged_external_down; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 518c66ca..8c6c856e 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -53,6 +53,7 @@ nm_device_state_reason_check (NMDeviceStateReason reason) } #define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate" +#define NM_PENDING_ACTION_IN_STATE_CHANGE "in-state-change" #define NM_PENDING_ACTION_RECHECK_AVAILABLE "recheck-available" #define NM_PENDING_ACTION_CARRIER_WAIT "carrier-wait" #define NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT "waiting-for-supplicant" @@ -436,11 +437,13 @@ typedef struct _NMDeviceClass { NMConnection *con_old, NMConnection *con_new); - guint32 (* get_dhcp_timeout) (NMDevice *self, - int addr_family); + guint32 (* get_dhcp_timeout_for_device) (NMDevice *self, + int addr_family); gboolean (* get_guessed_metered) (NMDevice *self); + gboolean (* can_update_from_platform_link) (NMDevice *self, const NMPlatformLink *plink); + /* Controls, whether to call act_stage2_config() callback also for assuming * a device or for external activations. In this case, act_stage2_config() must * take care not to touch the device's configuration. */ diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index 726e9901..2868dee0 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -98,10 +98,12 @@ link_changed (NMDevice *device, { NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); - if ( pllink - && priv->waiting_for_interface - && nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { - priv->waiting_for_interface = FALSE; + if (!pllink || !priv->waiting_for_interface) + return; + + priv->waiting_for_interface = FALSE; + + if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { nm_device_bring_up (device, TRUE, NULL); nm_device_activate_schedule_stage3_ip_config_start (device); } @@ -125,12 +127,14 @@ act_stage3_ip_config_start (NMDevice *device, gpointer *out_config, NMDeviceStateReason *out_failure_reason) { + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); if (!_is_internal_interface (device)) return NM_ACT_STAGE_RETURN_IP_FAIL; if (nm_device_get_ip_ifindex (device) <= 0) { + _LOGT (LOGD_DEVICE, "waiting for link to appear"); priv->waiting_for_interface = TRUE; return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -153,6 +157,160 @@ deactivate (NMDevice *device) priv->waiting_for_interface = FALSE; } +typedef struct { + NMDeviceOvsInterface *self; + GCancellable *cancellable; + NMDeviceDeactivateCallback callback; + gpointer callback_user_data; + gulong link_changed_id; + gulong cancelled_id; + guint link_timeout_id; +} DeactivateData; + +static void +deactivate_invoke_cb (DeactivateData *data, GError *error) +{ + NMDeviceOvsInterface *self = data->self; + + _LOGT (LOGD_CORE, + "deactivate: async callback (%s)", + error ? error->message : "success"); + data->callback (NM_DEVICE (data->self), + error, + data->callback_user_data); + + nm_clear_g_signal_handler (nm_device_get_platform (NM_DEVICE (data->self)), + &data->link_changed_id); + nm_clear_g_signal_handler (data->cancellable, + &data->cancelled_id); + nm_clear_g_source (&data->link_timeout_id); + g_object_unref (data->self); + g_object_unref (data->cancellable); + nm_g_slice_free (data); +} + +static void +deactivate_link_changed_cb (NMPlatform *platform, + int obj_type_i, + int ifindex, + NMPlatformLink *info, + int change_type_i, + DeactivateData *data) +{ + NMDeviceOvsInterface *self = data->self; + const NMPlatformSignalChangeType change_type = change_type_i; + + if ( change_type == NM_PLATFORM_SIGNAL_REMOVED + && nm_streq0 (info->name, nm_device_get_iface (NM_DEVICE (self)))) { + _LOGT (LOGD_DEVICE, "deactivate: link removed, proceeding"); + nm_device_update_from_platform_link (NM_DEVICE (self), NULL); + deactivate_invoke_cb (data, NULL); + return; + } +} + +static gboolean +deactivate_link_timeout (gpointer user_data) +{ + DeactivateData *data = user_data; + NMDeviceOvsInterface *self = data->self; + + _LOGT (LOGD_DEVICE, "deactivate: timeout waiting link removal"); + deactivate_invoke_cb (data, NULL); + return G_SOURCE_REMOVE; +} + +static void +deactivate_cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + gs_free_error GError *error = NULL; + + nm_utils_error_set_cancelled (&error, FALSE, NULL); + deactivate_invoke_cb ((DeactivateData *) user_data, error); +} + +static void +deactivate_cb_on_idle (gpointer user_data, + GCancellable *cancellable) +{ + DeactivateData *data = user_data; + gs_free_error GError *cancelled_error = NULL; + + g_cancellable_set_error_if_cancelled (data->cancellable, &cancelled_error); + deactivate_invoke_cb (data, cancelled_error); +} + +static void +deactivate_async (NMDevice *device, + GCancellable *cancellable, + NMDeviceDeactivateCallback callback, + gpointer callback_user_data) { + + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (self); + DeactivateData *data; + + _LOGT (LOGD_CORE, "deactivate: start async"); + + /* We want to ensure that the kernel link for this device is + * removed upon disconnection so that it will not interfere with + * later activations of the same device. Unfortunately there is + * no synchronization mechanism with vswitchd, we only update + * ovsdb and wait that changes are picked up. + */ + + data = g_slice_new (DeactivateData); + *data = (DeactivateData) { + .self = g_object_ref (self), + .cancellable = g_object_ref (cancellable), + .callback = callback, + .callback_user_data = callback_user_data, + }; + + if ( !priv->waiting_for_interface + && !nm_platform_link_get_by_ifname (nm_device_get_platform (device), + nm_device_get_iface (device))) { + _LOGT (LOGD_CORE, "deactivate: link not present, proceeding"); + nm_device_update_from_platform_link (NM_DEVICE (self), NULL); + nm_utils_invoke_on_idle (deactivate_cb_on_idle, data, cancellable); + return; + } + + if (priv->waiting_for_interface) { + /* At this point we have issued an INSERT and a DELETE + * command for the interface to ovsdb. We don't know if + * vswitchd will see the two updates or only one. We + * must add a timeout to avoid waiting forever in case + * the link doesn't appear. + */ + data->link_timeout_id = g_timeout_add (6000, deactivate_link_timeout, data); + _LOGT (LOGD_DEVICE, "deactivate: waiting for link to disappear in 6 seconds"); + } else + _LOGT (LOGD_DEVICE, "deactivate: waiting for link to disappear"); + + data->cancelled_id = g_cancellable_connect (cancellable, + G_CALLBACK (deactivate_cancelled_cb), + data, + NULL); + data->link_changed_id = g_signal_connect (nm_device_get_platform (device), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (deactivate_link_changed_cb), + data); +} + +static gboolean +can_update_from_platform_link (NMDevice *device, const NMPlatformLink *plink) +{ + /* If the device is deactivating, we already sent the + * deletion command to ovsdb and we don't want to deal + * with any new link appearing from the previous + * activation. + */ + return !plink + || nm_device_get_state (device) != NM_DEVICE_STATE_DEACTIVATING; +} + /*****************************************************************************/ static void @@ -182,7 +340,9 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_OPENVSWITCH); + device_class->can_update_from_platform_link = can_update_from_platform_link; device_class->deactivate = deactivate; + device_class->deactivate_async = deactivate_async; device_class->get_type_description = get_type_description; device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index fb9c9c69..a0749c21 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -356,6 +356,12 @@ teamd_dbus_appeared (GDBusConnection *connection, _LOGI (LOGD_TEAM, "teamd appeared on D-Bus"); nm_device_queue_recheck_assume (device); + if (priv->kill_in_progress) { + /* If we are currently killing teamd, we are not + * interested in knowing when it becomes ready. */ + return; + } + /* If another teamd grabbed the bus name while our teamd was starting, * just ignore the death of our teamd and run with the existing one. */ @@ -380,11 +386,14 @@ teamd_dbus_appeared (GDBusConnection *connection, if (pid != priv->teamd_pid) teamd_cleanup (self, FALSE); } else { - _LOGW (LOGD_TEAM, "failed to determine D-Bus name owner"); - /* If we can't determine the bus name owner, don't kill our - * teamd instance. Hopefully another existing teamd just died and - * our instance will be able to grab the bus name. - */ + /* The process that registered on the bus died. If it's + * the teamd instance we just started, ignore the event + * as we already detect the failure through the process + * watch. If it's a previous instance that got killed, + * also ignore that as our new instance will register + * again. */ + _LOGD (LOGD_TEAM, "failed to determine D-Bus name owner, ignoring"); + return; } } diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index c19ec766..516dc78b 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -405,7 +405,7 @@ state_changed (NMDevice *device, } static guint32 -get_dhcp_timeout (NMDevice *device, int addr_family) +get_dhcp_timeout_for_device (NMDevice *device, int addr_family) { /* shorter timeout for mesh connectivity */ return 20; @@ -521,7 +521,7 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; device_class->state_changed = state_changed; - device_class->get_dhcp_timeout = get_dhcp_timeout; + device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; obj_properties[PROP_COMPANION] = g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION, "", "", diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 3e6ccc8f..3de5ae07 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -732,7 +732,7 @@ set_modem (NMDeviceModem *self, NMModem *modem) } static guint32 -get_dhcp_timeout (NMDevice *device, int addr_family) +get_dhcp_timeout_for_device (NMDevice *device, int addr_family) { /* DHCP is always done by the modem firmware, not by the network, and * by the time we get around to DHCP the firmware should already know @@ -897,7 +897,7 @@ nm_device_modem_class_init (NMDeviceModemClass *klass) device_class->is_available = is_available; device_class->get_ip_iface_identifier = get_ip_iface_identifier; device_class->get_configured_mtu = nm_modem_get_configured_mtu; - device_class->get_dhcp_timeout = get_dhcp_timeout; + device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; device_class->state_changed = device_state_changed; |