2008-04-28 Dan Williams <dcbw@redhat.com>

Fix the device up/down ambiguities.  Up/down state used to be a
	conglomeration of hardware state (IFF_UP) and any device-specific things
	(supplicant, periodic timers, etc) that the device used to indicate
	readiness.  Unfortunately, if the hardware was already IFF_UP for some
	reason, then the device specific stuff wouldn't get run, and the device
	would be stuck.

	* src/nm-device.c
	  src/nm-device.h
		- Create hw_is_up, hw_bring_up, and hw_take_down
		- Rename bring_down -> take_down
		- (real_hw_is_up): check interface flags for IFF_UP
		- (nm_device_hw_is_up): let subclasses figure out their own HW state
		- (nm_device_is_up): make static; only used locally
		- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
			if the device is already up; if the device isn't up, bring it up
		- (nm_device_hw_take_down): just take down hardware
		- (nm_device_bring_up): bring up HW first, then device specific stuff
		- (nm_device_take_down): always deactivate device when called; always
			try to take hardware down too
		- (nm_device_state_changed): take device down when entering unmanaged
			state from a higher state

	* src/nm-device-802-11-wireless.c
		- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
			check IFF_UP really
		- (real_take_down, supplicant_iface_state_cb_handler, 
		   supplicant_iface_connection_state_cb_handler,
		   supplicant_mgr_state_cb_handler): fix some messages

	* src/nm-device-802-3-ethernet.c
		- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
			check IFF_UP really



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-04-29 15:36:29 +00:00
parent 982abb9f79
commit 9be3804c7f
5 changed files with 201 additions and 55 deletions

View file

@ -1,3 +1,39 @@
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
2008-04-28 Dan Williams <dcbw@redhat.com>
* src/nm-manager.c

View file

@ -48,6 +48,7 @@
#include "nm-setting-wireless.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-8021x.h"
#include "NetworkManagerSystem.h"
static gboolean impl_device_get_access_points (NMDevice80211Wireless *device,
GPtrArray **aps,
@ -729,12 +730,29 @@ out:
return TRUE;
}
static gboolean
real_hw_is_up (NMDevice *device)
{
return NM_DEVICE_CLASS (nm_device_802_11_wireless_parent_class)->hw_is_up (device);
}
static gboolean
real_hw_bring_up (NMDevice *dev)
{
return nm_system_device_set_up_down (dev, TRUE);
}
static void
real_hw_take_down (NMDevice *dev)
{
nm_system_device_set_up_down (dev, FALSE);
}
static gboolean
real_is_up (NMDevice *device)
{
/* Try device-specific tests first */
if (NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device)->periodic_source_id)
return TRUE;
if (!NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device)->periodic_source_id)
return FALSE;
return NM_DEVICE_CLASS (nm_device_802_11_wireless_parent_class)->is_up (device);
}
@ -752,9 +770,8 @@ real_bring_up (NMDevice *dev)
"state",
G_CALLBACK (supplicant_mgr_state_cb),
self);
if (nm_supplicant_manager_get_state (priv->supplicant.mgr) == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
if (nm_supplicant_manager_get_state (priv->supplicant.mgr) == NM_SUPPLICANT_MANAGER_STATE_IDLE)
init_supplicant_interface (self);
}
/* Peridoically update signal strength */
priv->periodic_source_id = g_timeout_add (6000, nm_device_802_11_periodic_update, self);
@ -816,7 +833,7 @@ device_cleanup (NMDevice80211Wireless *self)
}
static void
real_bring_down (NMDevice *dev)
real_take_down (NMDevice *dev)
{
NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (dev);
@ -1139,7 +1156,7 @@ nm_device_802_11_wireless_get_frequency (NMDevice80211Wireless *self)
if (err >= 0)
freq = iw_freq_to_uint32 (&wrq.u.freq);
else if (err == -1)
nm_warning ("(%s) error getting frequency: %s", iface, strerror (errno));
nm_warning ("(%s): error getting frequency: %s", iface, strerror (errno));
close (fd);
return freq;
@ -2045,10 +2062,10 @@ supplicant_iface_state_cb_handler (gpointer user_data)
new_state = cb_data->new_state;
old_state = cb_data->old_state;
nm_info ("(%s) supplicant interface is now in state %d (from %d).",
nm_info ("(%s): supplicant interface state change: %d -> %d.",
nm_device_get_iface (NM_DEVICE (self)),
new_state,
old_state);
old_state,
new_state);
if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
priv->scan_interval = SCAN_INTERVAL_MIN;
@ -2099,7 +2116,7 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
goto out;
}
nm_info ("(%s) Supplicant interface state change: %d -> %d",
nm_info ("(%s): supplicant connection state change: %d -> %d",
nm_device_get_iface (dev), old_state, new_state);
if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
@ -2208,7 +2225,7 @@ supplicant_mgr_state_cb_handler (gpointer user_data)
new_state = cb_data->new_state;
old_state = cb_data->old_state;
nm_info ("(%s) supplicant manager is now in state %d (from %d).",
nm_info ("(%s): supplicant manager is now in state %d (from %d).",
nm_device_get_iface (NM_DEVICE (self)),
new_state,
old_state);
@ -3068,9 +3085,12 @@ nm_device_802_11_wireless_class_init (NMDevice80211WirelessClass *klass)
parent_class->get_type_capabilities = real_get_type_capabilities;
parent_class->get_generic_capabilities = real_get_generic_capabilities;
parent_class->hw_is_up = real_hw_is_up;
parent_class->hw_bring_up = real_hw_bring_up;
parent_class->hw_take_down = real_hw_take_down;
parent_class->is_up = real_is_up;
parent_class->bring_up = real_bring_up;
parent_class->bring_down = real_bring_down;
parent_class->take_down = real_take_down;
parent_class->update_hw_address = real_update_hw_address;
parent_class->get_best_auto_connection = real_get_best_auto_connection;
parent_class->can_activate = real_can_activate;

View file

@ -312,9 +312,8 @@ nm_device_802_3_ethernet_init (NMDevice8023Ethernet * self)
static gboolean
real_is_up (NMDevice *device)
{
/* Try device-specific tests first */
if (NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (device)->supplicant.mgr)
return TRUE;
if (!NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (device)->supplicant.mgr)
return FALSE;
return NM_DEVICE_CLASS (nm_device_802_3_ethernet_parent_class)->is_up (device);
}
@ -326,11 +325,11 @@ real_bring_up (NMDevice *dev)
priv->supplicant.mgr = nm_supplicant_manager_get ();
return TRUE;
return priv->supplicant.mgr ? TRUE : FALSE;
}
static void
real_bring_down (NMDevice *dev)
real_take_down (NMDevice *dev)
{
NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (dev);
@ -340,6 +339,23 @@ real_bring_down (NMDevice *dev)
}
}
static gboolean
real_hw_is_up (NMDevice *device)
{
return NM_DEVICE_CLASS (nm_device_802_3_ethernet_parent_class)->hw_is_up (device);
}
static gboolean
real_hw_bring_up (NMDevice *dev)
{
return nm_system_device_set_up_down (dev, TRUE);
}
static void
real_hw_take_down (NMDevice *dev)
{
nm_system_device_set_up_down (dev, FALSE);
}
NMDevice8023Ethernet *
nm_device_802_3_ethernet_new (const char *udi,
@ -1365,9 +1381,12 @@ nm_device_802_3_ethernet_class_init (NMDevice8023EthernetClass *klass)
object_class->finalize = nm_device_802_3_ethernet_finalize;
parent_class->get_generic_capabilities = real_get_generic_capabilities;
parent_class->hw_is_up = real_hw_is_up;
parent_class->hw_bring_up = real_hw_bring_up;
parent_class->hw_take_down = real_hw_take_down;
parent_class->is_up = real_is_up;
parent_class->bring_up = real_bring_up;
parent_class->bring_down = real_bring_down;
parent_class->take_down = real_take_down;
parent_class->can_interrupt_activation = real_can_interrupt_activation;
parent_class->update_hw_address = real_update_hw_address;
parent_class->get_best_auto_connection = real_get_best_auto_connection;

View file

@ -100,6 +100,9 @@ static gboolean nm_device_activate (NMDeviceInterface *device,
static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self);
static void nm_device_deactivate (NMDeviceInterface *device);
static gboolean nm_device_bring_up (NMDevice *self, gboolean wait);
static gboolean nm_device_is_up (NMDevice *self);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
{
@ -195,7 +198,7 @@ error:
static gboolean
real_is_up (NMDevice *self)
real_hw_is_up (NMDevice *self)
{
struct ifreq ifr;
const char *iface;
@ -224,6 +227,17 @@ real_is_up (NMDevice *self)
return FALSE;
}
static gboolean
nm_device_hw_is_up (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (NM_DEVICE_GET_CLASS (self)->hw_is_up)
return NM_DEVICE_GET_CLASS (self)->hw_is_up (self);
return TRUE;
}
static guint32
real_get_generic_capabilities (NMDevice *dev)
{
@ -982,7 +996,7 @@ nm_device_deactivate (NMDeviceInterface *device)
g_return_if_fail (self != NULL);
nm_info ("Deactivating device %s.", nm_device_get_iface (self));
nm_info ("(%s): deactivating device.", nm_device_get_iface (self));
nm_device_deactivate_quickly (self);
@ -1392,8 +1406,7 @@ nm_device_update_ip4_address (NMDevice *self)
self->priv->ip4_address = new_address;
}
gboolean
static gboolean
nm_device_is_up (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@ -1404,64 +1417,112 @@ nm_device_is_up (NMDevice *self)
return TRUE;
}
gboolean
nm_device_bring_up (NMDevice *self, gboolean wait)
static gboolean
nm_device_hw_bring_up (NMDevice *self, gboolean wait)
{
gboolean success;
guint32 tries = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (nm_device_is_up (self))
return TRUE;
if (nm_device_hw_is_up (self))
goto out;
nm_info ("Bringing up device %s", nm_device_get_iface (self));
nm_info ("(%s): bringing up device.", nm_device_get_iface (self));
nm_system_device_set_up_down (self, TRUE);
nm_device_update_ip4_address (self);
if (NM_DEVICE_GET_CLASS (self)->hw_bring_up) {
success = NM_DEVICE_GET_CLASS (self)->hw_bring_up (self);
if (!success)
return FALSE;
}
/* Wait for the device to come up if requested */
while (wait && !nm_device_hw_is_up (self) && (tries++ < 50))
g_usleep (200);
if (!nm_device_hw_is_up (self)) {
nm_warning ("(%s): device not up after timeout!", nm_device_get_iface (self));
return FALSE;
}
out:
/* Can only get HW address of some devices when they are up */
if (NM_DEVICE_GET_CLASS (self)->update_hw_address)
NM_DEVICE_GET_CLASS (self)->update_hw_address (self);
nm_device_update_ip4_address (self);
return TRUE;
}
static void
nm_device_hw_take_down (NMDevice *self, gboolean wait)
{
guint32 tries = 0;
g_return_if_fail (NM_IS_DEVICE (self));
if (!nm_device_hw_is_up (self))
return;
nm_info ("(%s): taking down device.", nm_device_get_iface (self));
if (NM_DEVICE_GET_CLASS (self)->hw_take_down)
NM_DEVICE_GET_CLASS (self)->hw_take_down (self);
/* Wait for the device to come up if requested */
while (wait && nm_device_hw_is_up (self) && (tries++ < 50))
g_usleep (200);
}
static gboolean
real_is_up (NMDevice *self)
{
return TRUE;
}
static gboolean
nm_device_bring_up (NMDevice *self, gboolean wait)
{
gboolean success;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (!nm_device_hw_bring_up (self, wait))
return FALSE;
if (nm_device_is_up (self))
return TRUE;
nm_info ("(%s): preparing device.", nm_device_get_iface (self));
if (NM_DEVICE_GET_CLASS (self)->bring_up) {
success = NM_DEVICE_GET_CLASS (self)->bring_up (self);
if (!success)
return FALSE;
}
/* Wait for the device to come up if requested */
while (wait && !nm_device_is_up (self) && (tries++ < 50))
g_usleep (200);
return TRUE;
}
void
nm_device_bring_down (NMDevice *self, gboolean wait)
nm_device_take_down (NMDevice *self, gboolean wait)
{
NMDeviceState state;
guint32 tries = 0;
g_return_if_fail (NM_IS_DEVICE (self));
if (!nm_device_is_up (self))
return;
nm_info ("Bringing down device %s", nm_device_get_iface (self));
state = nm_device_get_state (self);
if ((state == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (self))
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (self));
if (NM_DEVICE_GET_CLASS (self)->bring_down)
NM_DEVICE_GET_CLASS (self)->bring_down (self);
if (nm_device_is_up (self)) {
nm_info ("(%s): cleaning up...", nm_device_get_iface (self));
nm_system_device_set_up_down (self, FALSE);
if (NM_DEVICE_GET_CLASS (self)->take_down)
NM_DEVICE_GET_CLASS (self)->take_down (self);
}
/* Wait for the device to come up if requested */
while (wait && nm_device_is_up (self) && (tries++ < 50))
g_usleep (200);
nm_device_hw_take_down (self, wait);
}
/*
@ -1507,7 +1568,7 @@ nm_device_dispose (GObject *object)
*/
if (self->priv->managed) {
nm_device_bring_down (self, FALSE);
nm_device_take_down (self, FALSE);
nm_device_set_ip4_config (self, NULL);
}
@ -1632,6 +1693,7 @@ nm_device_class_init (NMDeviceClass *klass)
object_class->get_property = get_property;
object_class->constructor = constructor;
klass->hw_is_up = real_hw_is_up;
klass->is_up = real_is_up;
klass->get_type_capabilities = real_get_type_capabilities;
klass->get_generic_capabilities = real_get_generic_capabilities;
@ -1719,6 +1781,10 @@ nm_info ("(%s): device state change: %d -> %d", nm_device_get_iface (device), ol
* another state change should be done below.
*/
switch (state) {
case NM_DEVICE_STATE_UNMANAGED:
if (old_state > NM_DEVICE_STATE_UNMANAGED)
nm_device_take_down (device, TRUE);
break;
case NM_DEVICE_STATE_UNAVAILABLE:
if (old_state == NM_DEVICE_STATE_UNMANAGED)
nm_device_bring_up (device, TRUE);

View file

@ -66,9 +66,17 @@ struct _NMDeviceClass
{
GObjectClass parent;
gboolean (* is_up) (NMDevice *self);
gboolean (* bring_up) (NMDevice *self);
void (* bring_down) (NMDevice *self);
/* Hardware state, ie IFF_UP */
gboolean (*hw_is_up) (NMDevice *self);
gboolean (*hw_bring_up) (NMDevice *self);
void (*hw_take_down) (NMDevice *self);
/* Additional stuff required to operate the device, like a
* connection to the supplicant, Bluez, etc
*/
gboolean (*is_up) (NMDevice *self);
gboolean (*bring_up) (NMDevice *self);
void (*take_down) (NMDevice *self);
void (* update_hw_address) (NMDevice *self);
@ -126,10 +134,7 @@ NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
gboolean nm_device_set_ip4_config (NMDevice *dev,
NMIP4Config *config);
gboolean nm_device_is_up (NMDevice *dev);
gboolean nm_device_bring_up (NMDevice *dev, gboolean wait);
void nm_device_bring_down (NMDevice *dev, gboolean wait);
void nm_device_take_down (NMDevice *dev, gboolean wait);
void * nm_device_get_system_config_data (NMDevice *dev);