Disable bss neighbor check/force 40 MHz channels in hostapd

Howto disable hostapd overlapping channel scanning or better howto force 40 Mhz channels even in dense wlan areas.

Current behavior

Hostapd does a check for overlapping channels with neighboring bss's before enabling 40 MHz channels as proposed by IEEE 802.11g. This however might result in switching to 20 MHz channels in dense wlan areas.

# hostapd -d /etc/hostapd/hostapd.conf
40 MHz affected channel range: [2407,2457] MHz
Neighboring BSS: 00:19:cb:a1:68:82 freq=2412 pri=0 sec=0
Neighboring BSS: 9c:c7:a6:ea:2f:7f freq=2412 pri=1 sec=0
Neighboring BSS: 88:25:2c:ac:0d:3c freq=2412 pri=1 sec=5
40 MHz pri/sec mismatch with BSS 88:25:2c:ac:0d:3c <2412,2432> (chan=1+) vs. <2442,2422>
20/40 MHz operation not permitted on channel pri=7 sec=3 based on overlapping BSSes

In fact I did scan my neighborhood and there are plenty of wlan-ap's that work with 40 Mhz channels.

Looks like hostapd works as intended by IEEE but other AP's don't give a f***.

If you want to keep it that way don't read any further.

But I thought, if they don't care why should I. At least the wlan should be as fast as my internet connection.

The patch

My setup is a linux box runing gentoo. It serves as internet gateway, router, nas, dlna server and ap.

There is no config option to disable the check in hostapd. So we need to change the source code. Gladly Gentoo is source based

At first I unpacked the sources and looked for the line where the check takes place. Found it in hostapd-2.1/src/ap/hw_features.c.

if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
    oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
else
    oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
wpa_scan_results_free(scan_res);

if (!oper40) {
    wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
        "channel pri=%d sec=%d based on overlapping BSSes",
        iface->conf->channel,
        iface->conf->channel +
        iface->conf->secondary_channel * 4);
    iface->conf->secondary_channel = 0;
}

I didn't want to change to much, so I just commented out the disabling of the secondary channel and created a patch.


--- hostapd-2.1.orig/src/ap/hw_features.c       2014-02-04 12:23:35.000000000 +0100
+++ hostapd-2.1/src/ap/hw_features.c    2014-02-14 07:52:08.727983248 +0100
@@ -477,7 +477,7 @@ static void ieee80211n_check_scan(struct
                           iface->conf->channel,
                           iface->conf->channel +
                           iface->conf->secondary_channel * 4);
-               iface->conf->secondary_channel = 0;
+               /* iface->conf->secondary_channel = 0; DILLIGAF */
        }

        res = ieee80211n_allowed_ht40_channel_pair(iface);

The injection

Now I needed emerge to apply the patch to hostapd.

Gentoo wiki provides this information.

Simply move your patch to /etc/portage/patches/net-wireless/hostapd.

Edit: As of hostapd version 2.6 the described way to inject the patch will not work anymore.
See below.

Create /etc/portage/bashrc to hook post_src_unpack().


post_src_unpack() {
    if type epatch_user >& /dev/null; then
        epatch_user
    fi
}


This way patches in /etc/portage/patches will be applied even if the ebuild does not call epatch_user (like hostapd ebuild).

Finally emerge hostapd and the binary will be compiled with the patch applied and 40 Mhz channels should work.

40 MHz affected channel range: [2407,2457] MHz
Neighboring BSS: 00:19:cb:a1:68:82 freq=2412 pri=0 sec=0
Neighboring BSS: 9c:c7:a6:ea:2f:7f freq=2412 pri=1 sec=0
Neighboring BSS: 88:25:2c:ac:0d:3c freq=2412 pri=1 sec=5
40 MHz pri/sec mismatch with BSS 88:25:2c:ac:0d:3c <2412,2432> (chan=1+) vs. <2442,2422>
20/40 MHz operation not permitted on channel pri=7 sec=3 based on overlapping BSSes
HT40: control channel: 7  secondary channel: 3
Completing interface initialization

Last words

This way is pretty much bruteforce but so far there seems no other way to achieve this. Maybe there will be a conf option in future.

The patch I created is for hostapd-2.1 (as of 02/14/2014 masked by ~amd64). It might be work with other versions too but you have to check it.

Also note it is only that easy because gentoo builds binaries from source and offers possibilities to hook into the build process. If you use other distributions you might need to do it yourself.

01/15/2016

Important update!

Short intro... I switched to a new kernel (4.1 from 3.10) and did a bit more observing than normal.

In the logs there suddenly appeared at lof of messages like these:

kernel: ath: phy0: Failed to stop TX DMA, queues=0x002!
kernel: ath: phy0: Failed to stop TX DMA, queues=0x00a!

(I use a wifi card with Atheros AR9380 chip together with ath9k driver.)

Well I checked kernel configuration but did not find any mistakes.

And then I was seeing this ... right before the messages appeared:

hostapd: wlp1s0: STA 38:59:f9:26:af:0b IEEE 802.11: Switching to 20 MHz operation

Ouch. Not only my hard enabled 40Mhz was switched off also the driver seems to have an issue when switching channel widths.

So I searched the source code and found another place where channel widths could be switched. It is a bss coexistence check.

I am not sure if I enabled/disabled something or it is the new kernel that caused this.

Anyway I changed the patch to circumvent the switch.
As I am using hostapd 2.4, there is only the patch for 2.4 right now.

As of 3/15/2016 there is a new patch for 2.5 too.

10/12/2016

Changes in Gentoo - EAPI 6

When you try to use the patch for hostapd-2.6 as described above, you will get a fatal error in the emerge process.

With version 2.6 of Hostapd, the EAPI version used in the ebuild changed from 4 to 6.

Prior version 6 of EAPI patches have been applied with call of epatch_user function from within the ebuild itself or, like described above, by hooking in the emerge process.
With version 6 of EAPI there is a new function eapply_user which is called by default in the src_prepare phase. See the description.

The problem is that the working directory at this point is a subdirectory of the extracted archiv. While the patch addresses files which are not in this subdirectory, it fails to apply.

A patch itself cannot by applied to files outside the current directory. So there is no way to change the patch itself to work again.
The only way I found is to hook into the emerge process and apply the patch.

At first one could simply change the bashrc from above to call eapply_user rather then epatch_user. But this will not work as eapply_user can only be called from a src_prepare hook. Also one needs to keep track of the current working directory, so the patch can applied. It is better to address only hostapd by the hook.
This can be achieved by creating the file /etc/portage/env/net-wireless/hostapd.

The file will only be sourced when hostapd is emerged. One could create a file that will only be sourced by hostapd-2.6 but I assume the all future hostapd ebuilds will also use EAPI version 6.
There is a global variable EAPI which can be used for checking the current used version. See description.

To apply the patch before it is applied by default, we can use the pre_src_prepare hook. Now we just have to make sure, it applied from within the right directory and everything should be just fine. See the supplied version of /etc/portage/env/net-wireless/hostapd.

Much text for a little change but it is necessary to know what happened behind the scenes.


#/etc/portage/env/net-wireless/hostapd
pre_src_prepare() {
    if [ "$EAPI" -eq 6 ]; then
        pwd="$(pwd)"
        cd "${WORKDIR}/${PF}"
        eapply_user
        cd "${pwd}"
    fi
}

10/17/2017

Bug in patch injection

Gentoo has released a revision release to address vulnerabilities in wpa/wpa2 (see #634438).
This results in a revision version (hostapd-2.6-r1). Somehow our patch fails to apply cause the injection uses the full version to change the work dir.
I fixed it and the file /etc/portage/env/net-wireless/hostapd should now look like this:


#!/usr/bin/env bash

pre_src_prepare() {
    if [ "$EAPI" -eq 6 ]; then
        pwd="$(pwd)"
        cd "${WORKDIR}/${P}"
        eapply_user
        cd "${pwd}"
    fi
}

06/04/2014

Patch for 2.2


diff -Naur hostapd-2.2.orig/src/ap/hw_features.c hostapd-2.2/src/ap/hw_features.c
--- hostapd-2.2.orig/src/ap/hw_features.c       2014-06-04 15:26:14.000000000 +0200
+++ hostapd-2.2/src/ap/hw_features.c    2014-06-16 14:58:26.740289954 +0200
@@ -539,7 +539,7 @@
                           iface->conf->channel,
                           iface->conf->channel +
                           iface->conf->secondary_channel * 4);
-               iface->conf->secondary_channel = 0;
+               /* iface->conf->secondary_channel = 0; DILLIGAF */
                if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
                        /*
                         * TODO: Could consider scheduling another scan to check

Patch 2.2 works for 2.3 too.

01/15/2016

Patch for 2.4 (Changed see update above)


diff -upr hostapd-2.4.orig/src/ap/hw_features.c hostapd-2.4/src/ap/hw_features.c
--- hostapd-2.4.orig/src/ap/hw_features.c       2015-03-15 18:30:39.000000000 +0100
+++ hostapd-2.4/src/ap/hw_features.c    2016-01-15 16:15:37.271124328 +0100
@@ -310,7 +310,7 @@ static void ieee80211n_check_scan(struct
                           iface->conf->channel,
                           iface->conf->channel +
                           iface->conf->secondary_channel * 4);
-               iface->conf->secondary_channel = 0;
+               /* iface->conf->secondary_channel = 0; DILLIGAF */
                if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
                        /*
                         * TODO: Could consider scheduling another scan to check
diff -upr hostapd-2.4.orig/src/ap/ieee802_11_ht.c hostapd-2.4/src/ap/ieee802_11_ht.c
--- hostapd-2.4.orig/src/ap/ieee802_11_ht.c     2015-03-15 18:30:39.000000000 +0100
+++ hostapd-2.4/src/ap/ieee802_11_ht.c  2016-01-15 16:21:46.114132193 +0100
@@ -282,6 +282,7 @@ void hostapd_2040_coex_action(struct hos
        wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d",
                   is_ht_allowed, iface->num_sta_ht40_intolerant);

+    /* DILLIGAF
        if (!is_ht_allowed &&
            (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
                if (iface->conf->secondary_channel) {
@@ -306,6 +307,7 @@ void hostapd_2040_coex_action(struct hos
                                   delay_time);
                }
        }
+    */
 }

03/15/2016

Patch for 2.5 (Changed see update above)


diff -upr hostapd-2.5.orig/src/ap/hw_features.c hostapd-2.5/src/ap/hw_features.c
--- hostapd-2.5.orig/src/ap/hw_features.c       2015-09-27 21:02:05.000000000 +0200
+++ hostapd-2.5/src/ap/hw_features.c    2016-03-15 17:00:00.163082949 +0100
@@ -316,7 +316,7 @@ static void ieee80211n_check_scan(struct
                           iface->conf->channel,
                           iface->conf->channel +
                           iface->conf->secondary_channel * 4);
-               iface->conf->secondary_channel = 0;
+               /* iface->conf->secondary_channel = 0; DILLIGAF */
                if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
                        /*
                         * TODO: Could consider scheduling another scan to check
diff -upr hostapd-2.5.orig/src/ap/ieee802_11_ht.c hostapd-2.5/src/ap/ieee802_11_ht.c
--- hostapd-2.5.orig/src/ap/ieee802_11_ht.c     2015-09-27 21:02:05.000000000 +0200
+++ hostapd-2.5/src/ap/ieee802_11_ht.c  2016-03-15 17:04:06.571590399 +0100
@@ -282,6 +282,7 @@ void hostapd_2040_coex_action(struct hos
        wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d",
                   is_ht40_allowed, iface->num_sta_ht40_intolerant);

+    /* DILLIGAF
        if (!is_ht40_allowed &&
            (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
                if (iface->conf->secondary_channel) {
@@ -306,6 +307,7 @@ void hostapd_2040_coex_action(struct hos
                                   delay_time);
                }
        }
+    */
 }

10/12/2016

Patch for version 2.6


--- hostapd-2.6.orig/src/ap/hw_features.c       2016-10-02 20:51:11.000000000 +0200
+++ hostapd-2.6/src/ap/hw_features.c    2016-10-11 12:11:28.430817177 +0200
@@ -316,7 +316,7 @@
                           iface->conf->channel,
                           iface->conf->channel +
                           iface->conf->secondary_channel * 4);
-               iface->conf->secondary_channel = 0;
+               /* iface->conf->secondary_channel = 0; DILLIGAF */
                if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
                        /*
                         * TODO: Could consider scheduling another scan to check
--- hostapd-2.6.orig/src/ap/ieee802_11_ht.c     2016-10-02 20:51:11.000000000 +0200
+++ hostapd-2.6/src/ap/ieee802_11_ht.c  2016-10-11 12:14:18.473952410 +0200
@@ -305,6 +305,7 @@
        wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d",
                   is_ht40_allowed, iface->num_sta_ht40_intolerant);

+/* DILLIGAF
        if (!is_ht40_allowed &&
            (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
                if (iface->conf->secondary_channel) {
@@ -329,6 +330,7 @@
                                   delay_time);
                }
        }
+*/
 }

Comments

Goeran, 11/18/2016:
@Stefan. Nice find ... I usally use hostapd_cli all_sta to see connected clients ... but it doesn't show the current bitrates
Stefan, 11/18/2016:
Hi Goeran,

I use the following with 150MBit connections in my hostapd.conf:

channel=11
ieee80211d=1
hw_mode=g
ieee80211n=1
ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40][RX-STBC1][MAX-AMSDU-3839]

You can check, if your clients connect with mor the 72MBit on the hostapd server with the following line:

for i in `ifconfig | grep wl | cut -d':' -f1`; do iw dev $i station dump; done

It will show at tx and rx bitrate the connection speed ;)
Goeran, 11/17/2016:
@Dirk Strange output from iw ... I don't use orange but iw should be the same.. I get something like this:
Interface wlp3s0
ifindex 4
wdev 0x100000001
addr 4c:5e:0c:15:52:04
ssid BNHome
type AP
wiphy 1
channel 13 (2472 MHz), width: 40 MHz, center1: 2462 MHz

Does an external wifi scanner detect 40Mhz ?

ht-cap sets/enables capabilities of your wifi hardware. Normaly you should see them with "iw phy"
Dirk, 11/17/2016:
h3consumption -p (gives an overview about the oranges settings).
...
...

wlan0 IEEE 802.11bgn ESSID:"XXX" Nickname:"<WIFI@REALTEK>"
Mode:Master Frequency:2.432 GHz Access Point: XX:XX:xX:XX:XX:XX
Bit Rate:150 Mb/s Sensitivity:0/0
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=86/100 Signal level=100/100 Noise level=0/100
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0


iw dev wlan0 info
gives

Interface wlan0
ifindex 4
type AP
wiphy 0

but clients (also a 150mbps capable wifi laptop and my galaxy s7 edge) connect only with 72.2 and 65 mbit...

What shout be in ht-cap section in hostapd.conf???

THX
Goeran, 11/17/2016:
@Dirk The message itself isn't patched out. So your 40Mhz should work ... just check with "iw dev <device> info"
Dirk, 11/17/2016:
Hello,

thank you for your great patch.

I am now trying it since hours.

My environment:
Orange PI PC Plus with Armbian 5.2 upgraded to 5.23.

Clear and fresh image.

Downloaded and de-tard hostapd

made manually changes (commenting out these 2 sections in the both files).

Compiling gives no error

but starting hostapd contains following messages:

wlan0: Event SCAN_RESULTS (3) received
nl80211: Received scan results (6 BSSes)
40 MHz affected channel range: [2397,2447] MHz
Found overlapping legacy BSS: xx:xx:xx:xx:xx:xx freq=2412
Overlapping 20 MHz BSS is found
20/40 MHz operation not permitted on channel pri=5 sec=1 based on overlapping BSSes
Completing interface initialization

Pleas help me...

my next try will be to test the 2.5 :(

Greetings

Dirk
Stefan, 10/13/2016:
Thank you for your eapi-6 patch and the 40mhz patch. This issue killed my working hostapd-2.5 :)
Jasper, 10/02/2016:
Thanks for sharing this!
Goeran, 08/04/2016:
@Alexey, a better solution for a distributor for sure. But everyone that applies a patch by himself wants to have 40 Mhz channels. So there is no need to have an extra option to enable it.
Alexey, 07/26/2016:
P.S. second patch is for wpa_supplicant
Add comment

* - required field

*

*


CAPTCHA image for SPAM prevention
If you can't read the word, click here.
*
*

impressum - disclaimer