Wi-Fi roaming recipe

Note: This recipe was originally posted on July/2020 and updated on July/2022.

About Wi-Fi roaming, I'd like to share my experience. I hope it will be useful to all of you.

I've been "googling" a lot about wi-fi roaming. What I wanted was a seamless switch from one AP to another one.

802.11 extensions k, v and r are supposed to help, but as 2020, not every client implements them. Android and Windows use extension r when available. It does help. I've read that iOS devices seem to take better use, but I can't confirm since I don't own one.

There were people claiming that a good solution was to disable low transfer rates. This seems to be incorrect and could lead to a worse scenario.

A really good solution is to reduce transmission power on each AP. When signal becomes very weak, clients will search for a better AP and make the switch. But only in this very weak signal situation. This is why you need to reduce transmission power. You can use an app (such has Android Wifi Analyzer) to monitor signal strength while you walk around. Adjust power as needed.

Even with all this, some clients may still get attached to a low signal (but still useful) AP and refuse to switch. To help with that, I used the wifi-disconnect-low-signal script on all APs, which disconnects clients when signal is not good, forcing them to switch AP. It works great.

Now for the recipe: First, enable extension 802.11r. If it is not available, you might need to replace the wpad package for the complete one. For 19.07 this might require a new build. Second, adjust transmission power in each AP so that you get a lower limit of -70dBm at the furthest places. Then configure wifi-disconnect-low-signal SNR limits to 35 (connect) and -30 (stay). It is important to make sure that when the scripts disconnects a client, there will be a strong AP nearby. Otherwise, the client will be disconnect again, resulting in a bad experience. "Try and error" is needed until you get a good balance. For this, open two SSH sessions on each AP: on the first session run wifi-disconnect-low-signal in verbose mode (-v -v); on the second session watch OpenWrt system log (logread -f). Then slowly walk around, while monitoring it all. This way you could watch when you get disconnected from one AP and connected to another one, verifying if it occurred at the right time/place.

I used this for 2 years with great results. I've been able to walk around and still get a stable SSH connection and a stable phone VoIP conversation.

8 Likes

Very useful post thank you. I implemented wifi-disconnect-low-signal on my 2 APs and it works great for both my iphone and my windows tablet.

But my Android phone just cannot have 802.11r enabled. I have spent days trying to configure it (my phone is rooted), even go so far as to modifying the WCNSS_qcom_cfg.ini file in read-only system image to try and tweak the wifi setup. But it simply refuses to stay connected when it makes the jump to another AP. Good that I can put this piece of junk into the black list so at least other devices can still benefit from the setup....

Edit: I have since learned 802.11r fast transition (FT) isn't totally equivalent to the device not dropping connection when transitioning to another AP. Sure with FT you stay connected all the time, but even without FT this can be the case as well. The difference is a slight stuttering of data flow. With FT you virtually have no stuttering (something like a 20ms of data flow interruption which is barely noticable), whereas the interruption becomes something like ~200ms without FT. So no, you can't validate FT just because your phone's wifi icon stays on all the time during a transition.

Got 802.11r working even with my Android phone.

And still using this wifi-disconnect-low-signal script. It now works great for all of my devices. I'd say 90% of the time my Android phone (which happens to be my main device) now roams seamlessly between my two routers. Dunno why it occasionally still fails to roam (disconnects before reconnecting to the other router), but I am not complaining.

19.07.4 still does not have 802.11k and 802.11v incorporated, and this script to me is definitely the next best thing to make my wireless devices switch to the router with a stronger signal.

Edit: I have since learned 802.11r fast transition (FT) isn't totally equivalent to the device not dropping connection when transitioning to another AP. Sure with FT you stay connected all the time, but even without FT this can be the case as well. The difference is a slight stuttering of data flow. With FT you virtually have no stuttering (something like a 20ms of data flow interruption which is barely noticable), whereas the interruption becomes something like ~200ms without FT. So no, you can't validate FT just because your phone's wifi icon stays on all the time during a transition.

Thanks for this! :+1:

I am really new to openwrt and try to implement this script.. In logs i can see that it disconnects the device but the device is still connected. can anyone help me find what it is wrong?

this happens continuously. the device signal is below the threshold i have set up the script tried to disconnect the device but nothing happens

Same here. I've been trying solutions like this one, but still there :frowning:

Try this one:

function Device:disconnect_sta(sta)
   local endpoint = "hostapd." .. self.ifname
   conn:call(endpoint, "bss_transition_request", {
                addr = sta.addr,
                disassociation_imminent = false,
                disassociation_timer = 100,
                validity_period = 100,
                abriged = true,
   })
   inf("%s: disconnected %s", self.ifname, tostring(sta))
end

EDIT: this ubus command works 100% for me, but im not sure the lua script itself is even working

EDIT 2: It's working perfectly fine with the code I've posted. enjoy!