diff --git a/ChangeLog b/ChangeLog index 35281a5d4..685e1e592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2005-05-05 Dan Williams + + Suggestion from Bill Moss: + * src/NetworkManagerSystem.c + - (nm_system_device_set_up_down_with_iface): ignore ENODEV + + + * src/NetworkManager.c + - (nm_data_free): move destruction of the various managers after + release of device list, because deactivating and freeing a device + requires at least the named manager + - (nm_poll_and_update_wireless_link_state): + (nm_device_link_activated): + (nm_device_link_deactivated): + don't grab the device list lock when actually updating device + link status or strength, since nm_device_set_link_active() + needs to call nm_get_active_device(), which also locks the device list. + + * src/NetworkManagerDevice.c + - (nm_device_set_link_active): if a device's link switches from off->on, + and it's wired, and the active device is wireless (or there is no + active device), activate the new device whose link just came on + - (link_to_specific_ap): try to smooth over intermittency in wireless links + my only calling the link to the current ap "failed" when more than 2 + consecutive link checks have failed + 2005-05-04 Dan Williams * src/NetworkManagerDevice.c diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 9443a3263..5fc72f314 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -466,10 +466,6 @@ static void nm_data_free (NMData *data) { g_return_if_fail (data != NULL); - nm_vpn_manager_dispose (data->vpn_manager); - nm_dhcp_manager_dispose (data->dhcp_manager); - g_object_unref (data->named_manager); - /* Stop and destroy all devices */ nm_lock_mutex (data->dev_list_mutex, __FUNCTION__); g_slist_foreach (data->dev_list, (GFunc) device_stop_and_free, NULL); @@ -481,6 +477,10 @@ static void nm_data_free (NMData *data) nm_ap_list_unref (data->allowed_ap_list); nm_ap_list_unref (data->invalid_ap_list); + nm_vpn_manager_dispose (data->vpn_manager); + nm_dhcp_manager_dispose (data->dhcp_manager); + g_object_unref (data->named_manager); + g_main_loop_unref (data->main_loop); g_main_context_unref (data->main_context); @@ -542,39 +542,48 @@ static void nm_print_usage (void) */ gboolean nm_poll_and_update_wireless_link_state (NMData *data) { - GSList *elt; + GSList * elt; + GSList * copy = NULL; + NMDevice * dev; g_return_val_if_fail (data != NULL, TRUE); if ((data->wireless_enabled == FALSE) || (data->asleep == TRUE)) return (TRUE); - /* Attempt to acquire mutex for device list iteration. - * If the acquire fails, just ignore the device deletion entirely. - */ - if (!nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) + /* Copy device list and ref devices to keep them around */ + if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { - nm_warning ("could not acquire device list mutex." ); - return TRUE; + for (elt = data->dev_list; elt; elt = g_slist_next (elt)) + { + if ((dev = (NMDevice *)(elt->data))) + { + nm_device_ref (dev); + copy = g_slist_append (copy, dev); + } + } + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); } - for (elt = data->dev_list; elt; elt = g_slist_next (elt)) + for (elt = copy; elt; elt = g_slist_next (elt)) { - NMDevice *dev = (NMDevice *)(elt->data); - - if (dev && nm_device_is_wireless (dev) && !nm_device_is_activating (dev)) + if ((dev = (NMDevice *)(elt->data))) { - nm_device_set_link_active (dev, nm_device_probe_link_state (dev)); - nm_device_update_signal_strength (dev); + if (nm_device_is_wireless (dev) && !nm_device_is_activating (dev)) + { + nm_device_set_link_active (dev, nm_device_probe_link_state (dev)); + nm_device_update_signal_strength (dev); + } + nm_device_unref (dev); } } - nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + + g_slist_free (copy); - return (TRUE); + return TRUE; } -static void -nm_monitor_wireless_link_state (NMData *data) +static void nm_monitor_wireless_link_state (NMData *data) { GSource *link_source; link_source = g_timeout_source_new (NM_WIRELESS_LINK_STATE_POLL_INTERVAL); @@ -585,46 +594,52 @@ nm_monitor_wireless_link_state (NMData *data) g_source_unref (link_source); } -static void -nm_wired_link_activated (NmNetlinkMonitor *monitor, - const gchar *interface_name, - NMData *data) +static void nm_device_link_activated (NmNetlinkMonitor *monitor, const gchar *interface_name, NMData *data) { + NMDevice *dev = NULL; + if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { - NMDevice *dev = nm_get_device_by_iface (data, interface_name); + if ((dev = nm_get_device_by_iface (data, interface_name))) + nm_device_ref (dev); + nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + } - /* Don't do anything if we already have a link */ - if ( dev - && nm_device_is_wired (dev) - && !nm_device_has_active_link (dev)) + /* Don't do anything if we already have a link */ + if (dev) + { + if (nm_device_is_wired (dev) && !nm_device_has_active_link (dev)) { NMDevice *act_dev = NULL; nm_device_set_link_active (dev, TRUE); nm_policy_schedule_device_change_check (data); } - nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + nm_device_unref (dev); } } -static void -nm_wired_link_deactivated (NmNetlinkMonitor *monitor, - const gchar *interface_name, - NMData *data) +static void nm_device_link_deactivated (NmNetlinkMonitor *monitor, const gchar *interface_name, NMData *data) { + NMDevice *dev = NULL; + if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) { - NMDevice *dev = nm_get_device_by_iface (data, interface_name); - - if ((dev != NULL) && nm_device_is_wired (dev)) - nm_device_set_link_active (dev, FALSE); + if ((dev = nm_get_device_by_iface (data, interface_name))) + nm_device_ref (dev); nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); } + + if (dev) + { + if (nm_device_is_wired (dev)) + nm_device_set_link_active (dev, FALSE); + nm_device_unref (dev); + } } static void -nm_error_monitoring_wired_link_state (NmNetlinkMonitor *monitor, +nm_error_monitoring_device_link_state (NmNetlinkMonitor *monitor, GError *error, NMData *data) { @@ -655,13 +670,13 @@ nm_monitor_wired_link_state (NMData *data) } g_signal_connect (G_OBJECT (monitor), "interface-connected", - G_CALLBACK (nm_wired_link_activated), data); + G_CALLBACK (nm_device_link_activated), data); g_signal_connect (G_OBJECT (monitor), "interface-disconnected", - G_CALLBACK (nm_wired_link_deactivated), data); + G_CALLBACK (nm_device_link_deactivated), data); g_signal_connect (G_OBJECT (monitor), "error", - G_CALLBACK (nm_error_monitoring_wired_link_state), + G_CALLBACK (nm_error_monitoring_device_link_state), data); nm_netlink_monitor_attach (monitor, data->main_context); diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 3696834dc..8266978ef 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -51,7 +51,7 @@ static gboolean nm_device_wireless_scan (gpointer user_data); static gboolean supports_mii_carrier_detect (NMDevice *dev); static gboolean supports_ethtool_carrier_detect (NMDevice *dev); static gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable); -static gboolean link_to_specific_ap (NMDevice *dev, NMAccessPoint *ap); +static gboolean link_to_specific_ap (NMDevice *dev, NMAccessPoint *ap, gboolean default_link); static void nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req); static void nm_device_activate_schedule_stage2_device_config (NMActRequest *req); @@ -664,13 +664,38 @@ gboolean nm_device_has_active_link (NMDevice *dev) void nm_device_set_link_active (NMDevice *dev, const gboolean link_active) { g_return_if_fail (dev != NULL); + g_return_if_fail (dev->app_data != NULL); if (dev->link_active != link_active) { dev->link_active = link_active; - if (!link_active) + + /* Deactivate a currently active device */ + if (!link_active && nm_device_get_act_request (dev)) + { nm_device_deactivate (dev, FALSE); - nm_policy_schedule_device_change_check (dev->app_data); + nm_policy_schedule_device_change_check (dev->app_data); + } + else if (link_active && !nm_device_get_act_request (dev)) + { + NMDevice *act_dev = nm_get_active_device (dev->app_data); + + /* If there is no currently active device, or the currently active device + * is wireless, and the device that's had the link change->active is wired, + * activate the wired device. + */ + if ( nm_device_is_wired (dev) + && ((act_dev && nm_device_is_wireless (act_dev)) || !act_dev)) + { + NMActRequest *act_req = nm_act_request_new (dev->app_data, dev, NULL, TRUE); /* TRUE = user requested */ + + if (act_req) + { + nm_info ("Will activate wired connection '%s' because it now has a link.", nm_device_get_iface (dev)); + nm_policy_schedule_device_activation (act_req); + } + } + } } } @@ -782,7 +807,7 @@ static gboolean nm_device_probe_wireless_link_state (NMDevice *dev) if ((best_ap = nm_device_get_best_ap (dev))) { - link = link_to_specific_ap (dev, best_ap); + link = link_to_specific_ap (dev, best_ap, TRUE); nm_ap_unref (best_ap); } @@ -827,7 +852,7 @@ static gboolean nm_device_probe_wired_link_state (NMDevice *dev) if (dev->options.wired.has_carrier_detect != TRUE) link = TRUE; - return (link); + return link; } @@ -1836,6 +1861,7 @@ gboolean nm_device_activation_handle_cancel (NMActRequest *req) dev->act_request = NULL; nm_act_request_unref (req); } + nm_schedule_state_change_signal_broadcast (dev->app_data); nm_info ("Activation (%s) cancellation handled.", nm_device_get_iface (dev)); return FALSE; @@ -2048,6 +2074,8 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap) g_return_val_if_fail (nm_ap_get_essid (ap) != NULL, FALSE); g_return_val_if_fail (nm_ap_get_auth_method (ap) != NM_DEVICE_AUTH_METHOD_UNKNOWN, FALSE); + dev->options.wireless.failed_link_count = 0; + /* Force the card into Managed/Infrastructure mode */ nm_device_bring_down_wait (dev, 0); nm_device_bring_up_wait (dev, 0); @@ -3304,17 +3332,32 @@ NMAccessPointList *nm_device_ap_list_get (NMDevice *dev) } -static gboolean link_to_specific_ap (NMDevice *dev, NMAccessPoint *ap) +static gboolean link_to_specific_ap (NMDevice *dev, NMAccessPoint *ap, gboolean default_link) { gboolean link = FALSE; + /* Checking hardware's ESSID during a scan is doesn't work. */ + nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); + if (nm_device_wireless_is_associated (dev)) { char * dev_essid = nm_device_get_essid (dev); char * ap_essid = nm_ap_get_essid (ap); - if (dev_essid && ap_essid) - link = (strcmp (dev_essid, ap_essid) == 0); + if (dev_essid && ap_essid && !strcmp (dev_essid, ap_essid)) + { + dev->options.wireless.failed_link_count = 0; + link = TRUE; + } + } + + nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); + + if (!link) + { + dev->options.wireless.failed_link_count++; + if (dev->options.wireless.failed_link_count < 3) + link = default_link; } return link; @@ -3366,14 +3409,8 @@ NMAccessPoint * nm_device_get_best_ap (NMDevice *dev) keep = TRUE; else if (nm_act_request_get_user_requested (req)) keep = TRUE; - else - { - /* Checking hardware's ESSID during a scan is doesn't work. */ - nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); - if (link_to_specific_ap (dev, cur_ap)) - keep = TRUE; - nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); - } + else if (link_to_specific_ap (dev, cur_ap, TRUE)) + keep = TRUE; /* Only keep if its not in the invalid list and its _is_ in our scaned list */ if ( keep diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index 19066945b..a7817d313 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -43,6 +43,8 @@ typedef struct NMDeviceWirelessOptions iwqual max_qual; iwqual avg_qual; + guint failed_link_count; + gint8 num_freqs; double freqs[IW_MAX_FREQUENCIES]; diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index d3fc5a873..ef9bdaf48 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -291,7 +291,10 @@ gboolean nm_system_device_set_up_down_with_iface (NMDevice *dev, const char *ifa ifr.ifr_flags &= ~IFF_UP; ifr.ifr_flags |= IFF_UP & flags; if (ioctl (nm_dev_sock_get_fd (sk), SIOCSIFFLAGS, &ifr) == -1) - nm_warning ("nm_system_device_set_up_down_with_iface() could not bring device %s %s. errno = %d", iface, (up ? "up" : "down"), errno); + { + if (errno != ENODEV) + nm_warning ("nm_system_device_set_up_down_with_iface() could not bring device %s %s. errno = %d", iface, (up ? "up" : "down"), errno); + } } }