Re: [PATCH 1/2] wifi: add a disconnected timer

2010-10-27 Thread Kalle Valo
Samuel Ortiz  writes:

> Hi Kalle,

Hi Samuel,

> On Tue, Oct 26, 2010 at 07:30:53PM +0300, Kalle Valo wrote:
>> In a big network, for example at Ubuntu Developer Summit which has >10 APs,
>> connman and wpasupplicant got out of sync very easily. connman claimed it
>> was connected even though wpasupplicant (and the kernel driver) was actually
>> connected to the AP.
>
> Did you mean connman claimed it was _disconnected_ ?

Yes, that's what I mean. Sorry for the confusion.

Just to be clear: connman claimed that wifi connection was disconnected,
but 'iw wlan0 link' showed that I was connected to Ubuntu network.

>> The problem is that while roaming between APs inside ESS
>> wpasupplicant states go like this:
>> 
>> COMPLETED -> DISCONNECTED -> SCANNING -> AUTHENTICATING ... -> COMPLETED
>> 
>> So what happens is that connman unnecessarily marks the network disconnected
>> even though wpasupplicant is just roaming to a different AP within ESS.
>
> Well it really got disconnected from the AP, so ConnMan should just track
> that.

Well, it depends how we want to handle intra-ESS roaming. I see two
choises:

1) wpasupplicant manages roaming, connman just provides SSID and other settings
2) connman manages roaming

We should definitely go with option 1, it's faster and wpasupplicant has
the best information to choose which AP to connect to. So roaming between
APs on an ESS would be transparent from connman point of view.

> I'm really not a big fan of trying to be smarter than wpa_supplicant. In my
> experience, it's the shortest paths to new bugs

The problem here is that when wpasupplicant is roaming between APs it
goes to the disconnected state and then immediately to the scanning
state. The connman wifi plugin doesn't handle this properly.

>> To fix this add a timer which waits 10 seconds after a disconnected state.
>> If wpasupplicant hasn't connected to a network at time only then set the
>> network disconnected.
>
> It looks a bit like a hack to me, the fundamental issue (ConnMan not tracking
> the wpa_supplicant states properly, it seems) is not fixed.

I agree my patch is a bit hackish, but it makes a huge difference here
at UDS. Without these two patches (and Mohamed's busy loop fix) connman
is unusable with a large wifi network.

Currently wifi plugin makes wrong assumptions how wpasupplicant works
and what the different wpasupplicant states mean. The proper fix would
be to change wpasupplicant to not use disconnected state when roaming.
The disconnected state should be used only when wpasupplicant is certain
that it cannot connect to the ESS anymore, for example after scanning
two times and not finding any suitable APs.

I think I can work on changing wpasupplicant at some point, but it will
take few months before I can find the time. My short term goal is to
make connman wifi reliable enough for the users.

Thank you for the comments.

-- 
Kalle Valo
___
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman


Re: [PATCH 1/2] wifi: add a disconnected timer

2010-10-26 Thread Samuel Ortiz
Hi Kalle,

On Tue, Oct 26, 2010 at 07:30:53PM +0300, Kalle Valo wrote:
> In a big network, for example at Ubuntu Developer Summit which has >10 APs,
> connman and wpasupplicant got out of sync very easily. connman claimed it
> was connected even though wpasupplicant (and the kernel driver) was actually
> connected to the AP.
Did you mean connman claimed it was _disconnected_ ?



> The problem is that while roaming between APs inside ESS wpasupplicant states
> go like this:
> 
> COMPLETED -> DISCONNECTED -> SCANNING -> AUTHENTICATING ... -> COMPLETED
> 
> So what happens is that connman unnecessarily marks the network disconnected
> even though wpasupplicant is just roaming to a different AP within ESS.
Well it really got disconnected from the AP, so ConnMan should just track
that.
I'm really not a big fan of trying to be smarter than wpa_supplicant. In my
experience, it's the shortest paths to new bugs


> To fix this add a timer which waits 10 seconds after a disconnected state.
> If wpasupplicant hasn't connected to a network at time only then set the
> network disconnected.
It looks a bit like a hack to me, the fundamental issue (ConnMan not tracking
the wpa_supplicant states properly, it seems) is not fixed.

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
___
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman


[PATCH 1/2] wifi: add a disconnected timer

2010-10-26 Thread Kalle Valo
In a big network, for example at Ubuntu Developer Summit which has >10 APs,
connman and wpasupplicant got out of sync very easily. connman claimed it
was connected even though wpasupplicant (and the kernel driver) was actually
connected to the AP.

The problem is that while roaming between APs inside ESS wpasupplicant states
go like this:

COMPLETED -> DISCONNECTED -> SCANNING -> AUTHENTICATING ... -> COMPLETED

So what happens is that connman unnecessarily marks the network disconnected
even though wpasupplicant is just roaming to a different AP within ESS.

To fix this add a timer which waits 10 seconds after a disconnected state.
If wpasupplicant hasn't connected to a network at time only then set the
network disconnected.
---
 plugins/wifi.c |   71 ++-
 1 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/plugins/wifi.c b/plugins/wifi.c
index 37f6e32..d036a92 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -61,6 +61,7 @@ struct wifi_data {
int index;
unsigned flags;
unsigned int watch;
+   guint disconnect_timer;
 };
 
 static int get_bssid(struct connman_device *device,
@@ -309,6 +310,61 @@ static const gchar *state2str(GSupplicantState state)
return "UNKNOWN";
 }
 
+static gboolean disconnected_timeout(gpointer user_data)
+{
+   GSupplicantInterface *interface;
+   struct connman_network *network;
+   struct wifi_data *wifi;
+
+   DBG("");
+
+   interface = user_data;
+
+   wifi = g_supplicant_interface_get_data(interface);
+
+   if (wifi == NULL)
+   return FALSE;
+
+   network = wifi->network;
+
+   connman_network_set_associating(network, FALSE);
+   connman_network_set_connected(network, FALSE);
+
+   connman_network_unref(wifi->network);
+   wifi->network = NULL;
+
+   return FALSE;
+}
+
+static void start_disconnected_timer(GSupplicantInterface *interface)
+{
+   struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
+
+   if (wifi == NULL)
+   return;
+
+   if (wifi->disconnect_timer != 0)
+   return;
+
+   wifi->disconnect_timer = g_timeout_add(1, disconnected_timeout,
+   interface);
+}
+
+static void stop_disconnected_timer(GSupplicantInterface *interface)
+{
+   struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
+
+   if (wifi == NULL)
+   return;
+
+   if (wifi->disconnect_timer == 0)
+   return;
+
+   g_source_remove(wifi->disconnect_timer);
+   wifi->disconnect_timer = 0;
+}
+
+
 static void interface_state(GSupplicantInterface *interface)
 {
struct connman_network *network;
@@ -328,8 +384,10 @@ static void interface_state(GSupplicantInterface 
*interface)
network = wifi->network;
device = wifi->device;
 
-   if (device == NULL || network == NULL)
+   if (device == NULL || network == NULL) {
+   stop_disconnected_timer(interface);
return;
+   }
 
switch (state) {
case G_SUPPLICANT_STATE_SCANNING:
@@ -345,6 +403,8 @@ static void interface_state(GSupplicantInterface *interface)
/* reset scan trigger and schedule background scan */
connman_device_schedule_scan(device);
 
+   stop_disconnected_timer(interface);
+
if (get_bssid(device, bssid, &bssid_len) == 0)
connman_network_set_address(network,
bssid, bssid_len);
@@ -352,12 +412,7 @@ static void interface_state(GSupplicantInterface 
*interface)
break;
 
case G_SUPPLICANT_STATE_DISCONNECTED:
-   connman_network_set_associating(network, FALSE);
-   connman_network_set_connected(network, FALSE);
-
-   connman_network_unref(wifi->network);
-   wifi->network = NULL;
-
+   start_disconnected_timer(interface);
break;
 
case G_SUPPLICANT_STATE_INACTIVE:
@@ -640,6 +695,8 @@ static int network_disconnect(struct connman_network 
*network)
 
connman_network_set_associating(network, FALSE);
 
+   stop_disconnected_timer(wifi->interface);
+
return g_supplicant_interface_disconnect(wifi->interface,
disconnect_callback, wifi);
 }
-- 
1.7.1

___
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman