mesh: Fix inactivity timer for 32 bit system
authorMasashi Honma <masashi.honma@gmail.com>
Wed, 4 Feb 2015 02:26:51 +0000 (11:26 +0900)
committerJouni Malinen <j@w1.fi>
Sat, 7 Feb 2015 20:20:45 +0000 (22:20 +0200)
Commit 5a2a6de6a5fec58dcfdb4320e4ec2b69d183a4c1 ('mesh: Make inactivity
timer configurable') has a problem on 32 bit systems. Setting
NL80211_MESHCONF_PLINK_TIMEOUT to 0xffffffff causes expiration of STA in
a minute by NL80211_CMD_DEL_STATION event. this is the kernel rule for
STA expiration:

(current jiffies) > (frame Rx jiffies + NL80211_MESHCONF_PLINK_TIMEOUT * 250)

On a 32 bit system, the right side could overflow and be unexpected
small value if NL80211_MESHCONF_PLINK_TIMEOUT is sufficiently large. STA
expiration occurs by this reason.

This patch solves the problem by disabling the STA expiration
functionality in mac80211. However, old kernel does not support
disabling it. If so, this patch sets mac80211 inactivity timer 60
seconds into future from the wpa_supplicant inactivity timer.

And I mis-understood that mesh_max_inactivity=0 disables inactivity
timer in wpa_supplicant. This commit fixes it also.

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
src/drivers/driver_nl80211.c

index d681ea6..7785fbc 100644 (file)
@@ -7849,16 +7849,13 @@ static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id,
 }
 
 
-static int
-wpa_driver_nl80211_join_mesh(void *priv,
+static int nl80211_join_mesh(struct i802_bss *bss,
                             struct wpa_driver_mesh_join_params *params)
 {
-       struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
        struct nl_msg *msg;
        struct nlattr *container;
        int ret = -1;
-       u32 timeout;
 
        wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH);
@@ -7910,14 +7907,9 @@ wpa_driver_nl80211_join_mesh(void *priv,
        /*
         * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
         * the timer could disconnect stations even in that case.
-        *
-        * Set 0xffffffff instead of 0 because NL80211_MESHCONF_PLINK_TIMEOUT
-        * does not allow 0.
         */
-       timeout = params->conf.peer_link_timeout;
-       if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) || timeout == 0)
-               timeout = 0xffffffff;
-       if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, timeout)) {
+       if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
+                       params->conf.peer_link_timeout)) {
                wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
                goto fail;
        }
@@ -7941,6 +7933,37 @@ fail:
 }
 
 
+static int
+wpa_driver_nl80211_join_mesh(void *priv,
+                            struct wpa_driver_mesh_join_params *params)
+{
+       struct i802_bss *bss = priv;
+       int ret, timeout;
+
+       timeout = params->conf.peer_link_timeout;
+
+       /* Disable kernel inactivity timer */
+       if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM)
+               params->conf.peer_link_timeout = 0;
+
+       ret = nl80211_join_mesh(bss, params);
+       if (ret == -EINVAL && params->conf.peer_link_timeout == 0) {
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: Mesh join retry for peer_link_timeout");
+               /*
+                * Old kernel does not support setting
+                * NL80211_MESHCONF_PLINK_TIMEOUT to zero, so set 60 seconds
+                * into future from peer_link_timeout.
+                */
+               params->conf.peer_link_timeout = timeout + 60;
+               ret = nl80211_join_mesh(priv, params);
+       }
+
+       params->conf.peer_link_timeout = timeout;
+       return ret;
+}
+
+
 static int wpa_driver_nl80211_leave_mesh(void *priv)
 {
        struct i802_bss *bss = priv;