How does rrm work?

I patched the hostapd, to handle beacon responses. I will do a PR if everything is finished.


Further Mediatek seems not to work:

For hostapd, you'd (probably) have to upstream it first before OpenWRT will accept it i.e. contact and attach the patch to https://lists.infradead.org/mailman/listinfo/hostap. @hauke will probably be the reviewer once it's upstreamed and you open up a PR backporting the patch to OpenWrt.

Mediatek – https://github.com/openwrt/mt76/issues – headed in part @nbd.

Thanks a lot. I'm only exposing the values through ubus allowing me to collect them by another daemon to do fancy hearing map stuff. Sadly, I have to use the Nexus 5X of a friend to develop and test. Is there maybe some cheap device I could use for this?

Hi @PolynomialDivision
Yes, I saw what you did with the beacon responses - that was good stuff.

I think there is some improvement yet to make on this. The sleep 120 in my version blocks the restart on the init script when done from Luci which in turn causes a webpage timeout. It would be better to find some more elegant way to refresh things when radios come and go - maybe something using "procd_set_param watch hostapd". I'm not across how this works so will need to leave it to better programmers than me. Also, the sleep 120 deals with the normal CAC of 60 seconds for DFS channels but there are some channels (5600-5650MHz sub-band) where the CAC is 10 minutes.

Also, the change from_nr to _udp did fix the problem on the mdns browsers.

Finished.

Now, we only have to implement some process that listens to those reports and creates them. And then we can steer clients. :smiley:

1 Like

Can somebody try to steer a client?
First enable

ubus call hostapd.wlan0 bss_mgmt_enable '{"neighbor_report":True, "beacon_report":True, "bss_transition": True}'
ubus call hostapd.wlan1 bss_mgmt_enable '{"neighbor_report":True, "beacon_report":True, "bss_transition": True}'

Get Neighbor Reports

ubus call hostapd.wlan0 rrm_nr_get_own
ubus call hostapd.wlan1 rrm_nr_get_own

Now steer a client from wlan0 to wlan1 or or the other way around

ubus call hostapd.wlan0 wnm_disassoc_imminent '{"addr":"00:xx:xx:xx:xx:xx", "duration": 120, "neighbors":["[THE STRING OF THE NEIGHBOR REPORT FROM WLAN0 OR WLAN1]"]}'

I'm not sure if the client gets deauthed, or it switches the interface on it's own. I have to increase the debug level.

You can set the debug level of hostapd with

option log_level '0'

and check with

grep _level /var/run/hostapd-phy0.conf

Okay, I tried with a Xiaomi Mi 8 and it works

daemon.notice hostapd: wlan1: BSS-TM-RESP xx:xx:xx:xx:xx:xx status_code=0 bss_termination_delay=0 target_bssid=xx:xx:xx:xx:xx:xx

Can someone confirm this bug I reported?
https://bugzilla.kernel.org/show_bug.cgi?id=205813
I can crash my system with a TL-WN722N (ath9k) by sending several beacon requests...

Thanks, this script is working (modded it to include udp instead of nr). I can see a successful Neighbor Request and Neighbor Response on ath10k-ct-htt, hostapd-2.9 with openssl. The setup includes 2x Archer A7s Dumb APs with a WRT1900ACS router (disabled wireless functionality) – all three have OpenWrt built from the master branch.

Additional roaming settings were: 802.11r with FT-over-the-Air, 802.11v with BSS transition, 802.11k with list populated by your script.

This is my config in /etc/config/wireless:

config wifi-iface 'default_radio0'
	option device 'radio0'
	option network 'lan'
	option mode 'ap'
	option ssid 'OpenWrt'
	option encryption 'psk2+ccmp'
	option key 'XXXXXX'
	option dtim_period '3'
	option ieee80211r '1'
	option ft_psk_generate_local '1'
	option ft_over_ds '0'
	option ieee80211v '1'
	option bss_transition '1'
	option ieee80211k '1'

The following capture shows an exchange between an Archer A7v5 and an iPhone 11 Pro on iOS 13.3.

Screen Shot 2019-12-26 at 08.36.16

In the neighbor report I see four APs, (corresponding to 2x N SSIDs and 2x AC SSIDs).

Screen Shot 2019-12-26 at 08.40.15

However, I have an issue with your script whenever I reboot the APs. I have to keep restarting them (3x on each AP) to populate:

  1. ubus call hostapd.wlan0 rrm_nr_list
  2. ubus call umdns browse

Because when the script staring, the radio may not started yet. So the umdns can't broadcast the local AP. I always restart the script after all radios have started.
If you add a sleep in the script to wait radios, LUCI may report timeout in the startup page as @muddyfeet said.

1 Like

Alright – worked around this by putting:

sleep 120
/etc/init.d/neighbor_report restart

in /etc/rc.local

Thus, preventing LUCI from timing out in the startup page.

EDIT:
I've attempted to do a proper fix by adding this:

procd_add_interface_trigger "interface.*" "wlan0" /etc/init.d/neighbor_report restart
procd_add_interface_trigger "interface.*" "wlan1" /etc/init.d/neighbor_report restart

But it doesn't work. Maybe moving the script to /etc/hotplug.d/iface and making it listen to ifup events work as per https://openwrt.org/docs/guide-user/base-system/hotplug#the_iface_folder?

@PolynomialDivision

I just tested, after quite a bit of trying:

A) Windows 7 Laptop - Lenovo T470 with a fairly recent Intel adapter - DOES NOT WORK - Reauths to the same adapter

B) Samsung S7 Edge running - DOES NOT WORK - Reauths to the same adapter

C) IPad Mini - OLD OLD model... Works, switches from wlan1 (5ghz) to wlan0 (2ghz) at will

Looks like its going to be time to upgrade my phone :wink:

1 Like

I discovered that devices sometimes roam, and somtimes not...
I upgraded my controller DAWN, to use disassoc_imm... function, instead of deauthing clients.
But I think, something is still broken. I have to look into this again, when I have time. And I call ubus methods on each interface. That's not good... :confused:

1 Like

Any idea how to interpret the data returned by the beacon reports? I have no idea how to pull some sort of RSSI out of there and force a roam via bss-tm to the best AP.

I got pretty much everything working, except for that.

I am using hostapd_cli for what its worth, but when i specify multiple neighbor= parameters the client will always just roam to the first one I provide. Even if its clearly a weaker signal.

I have done some Pull Request, that parses beacon reports:

Forgive me for being a bit of a newbie, but once I patch the build dir with this - how can it be integrated in to this script?

What do you mean by patch the build dir with this?

I patched openwrt/hostapd with your PR.

I'd like to just know if it does the job automatically once I set beacon_requests=1 or do I need to do something else like the umdns script in the previous posts in this thread.

EDIT:
Tested your patch and tested the command:

ubus call hostapd.wlan0 rrm_beacon_req '{"addr":"00:xx:xx:xx:xx:xx", "op_class":0, "channel":1,"duration":1,"mode":2,"bssid":"ff:ff:ff:ff:ff:ff", "ssid":""}

on QCA988X-ath10k-ct-htt, Archer A7v5, the following command works and logread gives me a hex string:

ubus call hostapd.wlan0 rrm_beacon_req '{"addr":"AA:BB:CC:XX:YY:ZZ", "op_class":1, "channel":48,"duration":100,"mode":0,"bssid":"ZZ:YY:XX:AA:BB:CC", "ssid":
"SSID"}'

It returns hex values like: 012a754b36

For ath10k-ct-htt, it was key that I set duration to 100 and mode to 0 for the report to be generated.

EDIT2:
My iPhone 11 Pro creates more detailed beacon reports and supports active/passive beacons. I don't want to post the hex output since using a Hex2ASCII converter shows my SSID and RegDomain settings.

I would like to know what happens when you issue a command "ubus call hostapd.wlan0 rrm_beacon_req" on the AP with the patch.

Does AP send an action frame to the client and client responds with neighbor AP list?

  1. Yes, the AP sends an action rame to the client to initiate the beacon report request. Currently you have to manually specify a client that you'll receive reports from.

  2. It responds with a hex string. Depending on the distance from the router, the hex string may or may not get cut off. When the SNR is low, the client produces a long hex string, which when converted to ASCII contains details on SSID and regdomain. However the rest of the message is garbled.

1 Like

If you look at my commit message:

But you have to subscribe to notifications! :wink: Then the hex string will be automatically formated into a json object that gives you all information you need.

I did that here:

And then you will receive blobmessages.

1 Like

An easyer way is to delete that if:

And do

 ubus monitor

or more specific

ubus monitor [ubus hostapd inferface]

Then u don't have to write a whole daemon that is subscribing to this notifications.


Edit:

Okay the link does not work.

Delete in my patch:

if (!hapd->ubus.obj.has_subscribers)
		return;

Edit:
@ParanoidZoid, @kaputorwon: Please indicate on Github, that you tested the PR.

1 Like