How to Build your Own Wireless Router (Part 3)

Renaud Cerrato
6 min readOct 22, 2018

--

Photo by John Barkiple on Unsplash

This post is the third part of the serie. The previous part covered the system configuration of a minimal 802.11n (2.4Ghz) access point, that part will enable 802.11ac (5Ghz).

Passive Scan

According to the documentation of the Airetos AEX-QCA9880-NX, the chipset is fully 802.11ac capable and we should now be able to move from the crowded 2.4 Ghz channels to the 5 Ghz heaven.

Let’s ask the device about the supported frequencies:

$ iw list
...
Frequencies:
* 2412 MHz [1] (20.0 dBm)
* 2417 MHz [2] (20.0 dBm)
* 2422 MHz [3] (20.0 dBm)
* 2427 MHz [4] (20.0 dBm)
* 2432 MHz [5] (20.0 dBm)
* 2437 MHz [6] (20.0 dBm)
* 2442 MHz [7] (20.0 dBm)
* 2447 MHz [8] (20.0 dBm)
* 2452 MHz [9] (20.0 dBm)
* 2457 MHz [10] (20.0 dBm)
* 2462 MHz [11] (20.0 dBm)
* 2467 MHz [12] (disabled)
* 2472 MHz [13] (disabled)
* 2484 MHz [14] (disabled)
...
Frequencies:
* 5180 MHz [36] (17.0 dBm) (no IR)
* 5200 MHz [40] (17.0 dBm) (no IR)
* 5220 MHz [44] (17.0 dBm) (no IR)
* 5240 MHz [48] (17.0 dBm) (no IR)
* 5260 MHz [52] (23.0 dBm) (no IR, radar detection)
* 5280 MHz [56] (23.0 dBm) (no IR, radar detection)
* 5300 MHz [60] (23.0 dBm) (no IR, radar detection)
* 5320 MHz [64] (23.0 dBm) (no IR, radar detection)
* 5500 MHz [100] (23.0 dBm) (no IR, radar detection)
* 5520 MHz [104] (23.0 dBm) (no IR, radar detection)
* 5540 MHz [108] (23.0 dBm) (no IR, radar detection)
* 5560 MHz [112] (23.0 dBm) (no IR, radar detection)
* 5580 MHz [116] (23.0 dBm) (no IR, radar detection)
* 5600 MHz [120] (23.0 dBm) (no IR, radar detection)
* 5620 MHz [124] (23.0 dBm) (no IR, radar detection)
* 5640 MHz [128] (23.0 dBm) (no IR, radar detection)
* 5660 MHz [132] (23.0 dBm) (no IR, radar detection)
* 5680 MHz [136] (23.0 dBm) (no IR, radar detection)
* 5700 MHz [140] (23.0 dBm) (no IR, radar detection)
* 5720 MHz [144] (23.0 dBm) (no IR, radar detection)
* 5745 MHz [149] (30.0 dBm) (no IR)
* 5765 MHz [153] (30.0 dBm) (no IR)
* 5785 MHz [157] (30.0 dBm) (no IR)
* 5805 MHz [161] (30.0 dBm) (no IR)
* 5825 MHz [165] (30.0 dBm) (no IR)
...

From the curated output above, we can see that the chipset supports channels 1 to 14 (2.4 Ghz) and channels 36 to 165 (5 Ghz) — but did you noticed the no IR flag?

The no IR flag stands for no-initiating-radiation (a.k.a passive scan) and that means you cannot use that mode of operation if that require you to initiate radiation first (and that includes beacons). In other words, you cannot run an access-point on those channels!

Regulatory compliance

The above situation is because of the Linux regulatory compliance, which regulates usage of the radio spectrum depending on a territory basis.

But, wait!

I’m living in the US and according to the link above, I should be able to emit on channels 36–48, so what’s going on? Let’s take a look at the regulatory domain currently in use:

$ iw reg get
country 00: DFS-UNSET
(2402 - 2472 @ 40), (N/A, 20), (N/A)
(2457 - 2482 @ 40), (N/A, 20), (N/A), NO-IR
(2474 - 2494 @ 20), (N/A, 20), (N/A), NO-OFDM, NO-IR
(5170 - 5250 @ 80), (N/A, 20), (N/A), NO-IR
(5250 - 5330 @ 80), (N/A, 20), (0 ms), DFS, NO-IR
(5490 - 5730 @ 160), (N/A, 20), (0 ms), DFS, NO-IR
(5735 - 5835 @ 80), (N/A, 20), (N/A), NO-IR
(57240 - 63720 @ 2160), (N/A, 0), (N/A)

The output above tell us that the current regulatory domain in use is worldwide (or unset), that mean it is currently using minimum values allowed in every country.

Unfortunately, trying to manually set the regulatory domain through sudo iw reg set US won’t help because the card has been shipped with the world regulatory domain burned into EEPROM:

$ dmesg | grep EEPROM
[ 12.123068] ath: EEPROM regdomain: 0x6c

Patch it!

Fortunately, the regulatory compliance is dealt at the driver level and can be easily patched. The original patch can be found in the Open-WRT source tree.

First of all, be sure to enable the source repository from/etc/apt/sources.list :

$ cat /etc/apt/sources.list
...
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic main restricted
...

Then, prepare the build environment by installing the required dependencies:

$ sudo apt-get install build-essential fakeroot
$ sudo apt-get build-dep linux

Grab the source of your current kernel:

$ apt-get source linux

Since the original Open-WRT patch can’t be applied “as is” against the Ubuntu Kernel tree because of subtle differences in the build system, I had to fix it:

$ VERSION=$(uname -r)
$ cd linux-${VERSION%%-*}
$ wget -O - https://gist.github.com/renaudcerrato/02de8b2e8dc013bc71326defd2ef062c/raw/a2db325e520e6442c8c12f7599d64ac1b7596a3e/402-ath_regd_optional.patch | patch -p1 -b

Everything should now be ready for the build:

$ fakeroot debian/rules clean
$ fakeroot debian/rules binary-generic

If everything goes well, you can now install your patched Kernel over the previous one:

$ cd ..
$ sudo dpkg -i linux*.deb

Reboot, and voilà:

$ sudo iw reg set US
$ iw list
...
Frequencies:
* 5180 MHz [36] (17.0 dBm)
* 5200 MHz [40] (17.0 dBm)
* 5220 MHz [44] (17.0 dBm)
* 5240 MHz [48] (17.0 dBm)
* 5260 MHz [52] (23.0 dBm) (radar detection)
* 5280 MHz [56] (23.0 dBm) (radar detection)
* 5300 MHz [60] (23.0 dBm) (radar detection)
* 5320 MHz [64] (23.0 dBm) (radar detection)
* 5500 MHz [100] (23.0 dBm) (radar detection)
* 5520 MHz [104] (23.0 dBm) (radar detection)
* 5540 MHz [108] (23.0 dBm) (radar detection)
* 5560 MHz [112] (23.0 dBm) (radar detection)
* 5580 MHz [116] (23.0 dBm) (radar detection)
* 5600 MHz [120] (23.0 dBm) (radar detection)
* 5620 MHz [124] (23.0 dBm) (radar detection)
* 5640 MHz [128] (23.0 dBm) (radar detection)
* 5660 MHz [132] (23.0 dBm) (radar detection)
* 5680 MHz [136] (23.0 dBm) (radar detection)
* 5700 MHz [140] (23.0 dBm) (radar detection)
* 5720 MHz [144] (23.0 dBm) (radar detection)
* 5745 MHz [149] (30.0 dBm)
* 5765 MHz [153] (30.0 dBm)
* 5785 MHz [157] (30.0 dBm)
* 5805 MHz [161] (30.0 dBm)
* 5825 MHz [165] (30.0 dBm)
...

In order to avoid unattended upgrade, you may want to pin your Linux Kernel version.

Configuration

Your new hostapd configuration file should be almost straightforward now: hw_mode=a will enable the 5Ghz bands while ieee80211ac=1 enable 802.11ac (VHT). Using ieee80211d=1 along with country_code=US, we’ll advertise the regulatory domain we’re working on.

To get the most of your bandwidth, ht_capab and vht_capab should been set to reflect the capabilities of the hardware:

$ iw list
...
Band 1:
Capabilities: 0x19e3
RX LDPC
HT20/HT40
Static SM Power Save
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
...
Band 2:
VHT Capabilities (0x338001b2):
Max MPDU length: 11454
Supported Channel Width: neither 160 nor 80+80
RX LDPC
short GI (80 MHz)
TX STBC
RX antenna pattern consistency
TX antenna pattern consistency
...

According to the output above, here’s your final hostapd.conf:

$ cat /etc/hostapd/hostapd.conf
#### Interface configuration ####
interface=wlp5s0
bridge=br0
driver=nl80211
##### IEEE 802.11 related configuration #####
ssid=iCanHearYouHavingSex
hw_mode=a
channel=0
auth_algs=1
wmm_enabled=1
country_code=US
ieee80211d=1
ieee80211h=0
##### IEEE 802.11n related configuration #####
ieee80211n=1
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CK-40][LDPC][MAX-AMSDU-7935]
##### IEEE 802.11ac related configuration #####
ieee80211ac=1
vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP7][TX-ANTENNA-PATTERN][RX-ANTENNA-PATTERN]
vht_oper_chwidth=1
##### WPA/IEEE 802.11i configuration #####
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=YouCantGuess

hostpad.conf documentation can be found inline at /usr/share/doc/hostapd/examples/hostapd.conf

Conclusion

In this part, you learned about Linux regulatory compliance and how to workaround it by patching your Linux kernel before setting-up hostapd for 5GHz operations.

At this point, your wireless router is fully capable, and you should now be able to dive into most of the configuration files if you’re interested in more complex setups.

Feel free to suggest new articles for the serie and, in the meantime, I recommend to have a look at my companion article about adding virtual SSID to hostapd.

Thanks for reading!

--

--

Renaud Cerrato

Analog at birth but digital by design. Hardcore Android Developer. Linux devotee. Came back once from /dev/null.