在 Linux 下创建 WiFi 热点 (Access Point),自古以来都不是一件容易的事情。

常见的解决方案有三种,hostapd、NetworkManager 和 systemd-networkd。

前两种方案用的比较多,而 systemd 近些年才在服务器中流行起来,文档和教程相对而言比较少。

一般而言,使用 NetworkManager 可以获得“开箱即用”的体验——但只能说勉强能用,存在的问题也很多。比如,5GHz 往往不能工作、不能指定频宽等等……

hostapd 则提供了许多配置项,但代价是配置非常复杂。好在有一些现成的配置文件和脚本可以参考,比如USB-WiFicreate_aplinux-wifi-hotspotlinux-router

使用 5GHz 频段

网上的教程一般只涉及 2.4GHz 的配置。一开始,我以为只需要把 802.11n 改成 802.11ac,再调整一下频段就可以了。然而,现实却狠狠地打了我的脸:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2月 26 14:45:16 armbian wpa_supplicant[1107]: nl80211: Added 802.11b mode based on 802.11g information
2月 26 14:45:16 armbian wpa_supplicant[1107]: nl80211: Mode IEEE 802.11g: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467[NO_IR] 2472 2484[NO_IR]
2月 26 14:45:16 armbian wpa_supplicant[1107]: nl80211: Mode IEEE 802.11a: 5180 5200[NO_IR] 5220 5240[NO_IR] 5260[NO_IR][RADAR] 5280[NO_IR][RADAR] 5300[NO_IR][RADAR] 5320[NO_IR][RADAR] 5500[NO_IR][RADAR] 5520[NO_IR][RADAR] 5540[NO_IR][RADAR] 5560[NO_IR][RADAR]
2月 26 14:45:16 armbian wpa_supplicant[1107]: nl80211: Mode IEEE 802.11b: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467[NO_IR] 2472 2484[NO_IR]
2月 26 14:45:16 armbian wpa_supplicant[1107]: Frequency 5280 (primary) not allowed for AP mode, flags: 0x117b NO-IR RADAR
2月 26 14:45:16 armbian wpa_supplicant[1107]: Primary frequency not allowed
2月 26 14:45:16 armbian wpa_supplicant[1107]: hostapd_logger: Configured channel (56) or frequency (5280) (secondary_channel=0) not found from the channel list of the current mode (2) IEEE 802.11a
2月 26 14:45:16 armbian wpa_supplicant[1107]: hostapd_logger: Hardware does not support configured channel
2月 26 14:45:16 armbian wpa_supplicant[1107]: Could not select hw_mode and channel. (-3)
2月 26 14:45:16 armbian wpa_supplicant[1107]: wlan0: interface state UNINITIALIZED->DISABLED
2月 26 14:45:16 armbian wpa_supplicant[1107]: wlan0: AP-DISABLED
2月 26 14:45:16 armbian wpa_supplicant[1107]: wlan0: Unable to setup interface.
2月 26 14:45:16 armbian wpa_supplicant[1107]: Failed to initialize AP interface
2月 26 14:45:16 armbian wpa_supplicant[1107]: hostapd_interface_deinit(0x55a8bcff50)
2月 26 14:45:16 armbian wpa_supplicant[1107]: wlan0: interface state DISABLED->DISABLED

看起来是指定了网卡不支持的频段!使用 iw list 查看一下支持的频段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
❯ sudo iw list
......
Band 1:
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] (20.0 dBm) (no IR)
* 2472 MHz [13] (20.0 dBm)
* 2484 MHz [14] (20.0 dBm) (no IR)
......
Band 2:
Frequencies:
* 5180 MHz [36] (20.0 dBm)
* 5200 MHz [40] (20.0 dBm) (no IR)
* 5220 MHz [44] (20.0 dBm)
* 5240 MHz [48] (20.0 dBm) (no IR)
* 5260 MHz [52] (20.0 dBm) (no IR, radar detection)
* 5280 MHz [56] (20.0 dBm) (no IR, radar detection)
* 5300 MHz [60] (20.0 dBm) (no IR, radar detection)
* 5320 MHz [64] (20.0 dBm) (no IR, radar detection)
* 5500 MHz [100] (20.0 dBm) (no IR, radar detection)
* 5520 MHz [104] (20.0 dBm) (no IR, radar detection)
* 5540 MHz [108] (20.0 dBm) (no IR, radar detection)
* 5560 MHz [112] (20.0 dBm) (no IR, radar detection)
* 5580 MHz [116] (20.0 dBm) (no IR, radar detection)
* 5600 MHz [120] (20.0 dBm) (no IR, radar detection)
* 5620 MHz [124] (20.0 dBm) (no IR, radar detection)
* 5640 MHz [128] (20.0 dBm) (no IR, radar detection)
* 5660 MHz [132] (20.0 dBm) (no IR, radar detection)
* 5680 MHz [136] (20.0 dBm) (no IR, radar detection)
* 5700 MHz [140] (20.0 dBm) (no IR, radar detection)
* 5720 MHz [144] (20.0 dBm) (no IR, radar detection)
* 5745 MHz [149] (20.0 dBm)
* 5765 MHz [153] (20.0 dBm) (no IR)
* 5785 MHz [157] (20.0 dBm)
* 5805 MHz [161] (20.0 dBm) (no IR)
* 5825 MHz [165] (20.0 dBm) (no IR)

好家伙,几乎所有的 5GHz 信道都被标记了 no IR (no-initiating-radiation),也就是无法使用!

根据 Arch Linux wiki 的说法,每个国家都有着不同的限制,因此我们可以通过设置国家代码来规避这种限制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
❯ sudo iw reg get
global
country 00: DFS-UNSET
(2402 - 2472 @ 40), (6, 20), (N/A)
(2457 - 2482 @ 20), (6, 20), (N/A), AUTO-BW, PASSIVE-SCAN
(2474 - 2494 @ 20), (6, 20), (N/A), NO-OFDM, PASSIVE-SCAN
(5170 - 5250 @ 80), (6, 20), (N/A), AUTO-BW, PASSIVE-SCAN
(5250 - 5330 @ 80), (6, 20), (0 ms), DFS, AUTO-BW, PASSIVE-SCAN
(5490 - 5730 @ 160), (6, 20), (0 ms), DFS, PASSIVE-SCAN
(5735 - 5835 @ 80), (6, 20), (N/A), PASSIVE-SCAN
(57240 - 63720 @ 2160), (N/A, 0), (N/A)

❯ sudo iw reg set CN

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

怎么回事?为什么国家代码的设置没有生效?就在我一筹莫展时,我无意间发现了这个issue
按照 issue 中的 workaround,将 regulatory.db链接到 /lib/firmware/regulatory.db-upstream后,出乎意料的可以工作了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
❯ dmesg | grep -i cfg80211
[ 13.255344] cfg80211: Loading compiled-in X.509 certificates for regulatory database
❯ sudo iw reg get
global
country US: DFS-FCC
(902 - 904 @ 2), (N/A, 30), (N/A)
(904 - 920 @ 16), (N/A, 30), (N/A)
(920 - 928 @ 8), (N/A, 30), (N/A)
(2400 - 2472 @ 40), (N/A, 30), (N/A)
(5150 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5350 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5470 - 5730 @ 160), (N/A, 24), (0 ms), DFS
(5730 - 5850 @ 80), (N/A, 30), (N/A), AUTO-BW
(5850 - 5895 @ 40), (N/A, 27), (N/A), NO-OUTDOOR, AUTO-BW, PASSIVE-SCAN
(5925 - 7125 @ 320), (N/A, 12), (N/A), NO-OUTDOOR, PASSIVE-SCAN
(57240 - 71000 @ 2160), (N/A, 40), (N/A)
❯ sudo iw list
......
Band 2:
Frequencies:
* 5180 MHz [36] (23.0 dBm)
* 5200 MHz [40] (23.0 dBm)
* 5220 MHz [44] (23.0 dBm)
* 5240 MHz [48] (23.0 dBm)
* 5260 MHz [52] (24.0 dBm) (radar detection)
* 5280 MHz [56] (24.0 dBm) (radar detection)
* 5300 MHz [60] (24.0 dBm) (radar detection)
* 5320 MHz [64] (24.0 dBm) (radar detection)
* 5500 MHz [100] (24.0 dBm) (radar detection)
* 5520 MHz [104] (24.0 dBm) (radar detection)
* 5540 MHz [108] (24.0 dBm) (radar detection)
* 5560 MHz [112] (24.0 dBm) (radar detection)
* 5580 MHz [116] (24.0 dBm) (radar detection)
* 5600 MHz [120] (24.0 dBm) (radar detection)
* 5620 MHz [124] (24.0 dBm) (radar detection)
* 5640 MHz [128] (24.0 dBm) (radar detection)
* 5660 MHz [132] (24.0 dBm) (radar detection)
* 5680 MHz [136] (24.0 dBm) (radar detection)
* 5700 MHz [140] (24.0 dBm) (radar detection)
* 5720 MHz [144] (24.0 dBm) (radar detection)
* 5745 MHz [149] (33.0 dBm)
* 5765 MHz [153] (33.0 dBm)
* 5785 MHz [157] (33.0 dBm)
* 5805 MHz [161] (33.0 dBm)
* 5825 MHz [165] (33.0 dBm)

开启 80MHz 频宽

一通操作猛如虎,一测速度二百五。

按照linux-router中的教程,只需要指定 ssid 和 password 就可以开启热点:

1
sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 --wifi5

这样虽然能开启热点,但尴尬的是它的频宽只有 20MHz,并且握手速度只有 54Mbps(还不如直接去用 802.11n 呢)

在中国,52-68 信道被划为 DFS 信道,而 96-144 信道则不允许使用。参考:List_of_WLAN_channels

使用 DFS 信道时,按照法规要求,启动时应先检测附近是否有雷达信号,在使用过程中如果检测到了雷达信号也必须进行规避。这会导致热点启动延迟,并带来诸多难以排查的奇怪问题。反正尽量别用就对了!

更重要的是,我的网卡在 DFS 信道上的发射功率远低于其他信道。因此,我们将使用其他信道。尝试指定 149 信道并启用 80MHz 频宽:

1
sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 -c 149 --country CN --wifi5 --req-vht --vht-ch-width 1

不出意外的话,这时 hostapd 会输出一长串日志,告诉你启动失败了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
ctrl_interface_group=0
nl80211: TDLS supported
nl80211: TDLS external setup
nl80211: Supported cipher 00-0f-ac:1
nl80211: Supported cipher 00-0f-ac:5
nl80211: Supported cipher 00-0f-ac:2
nl80211: Supported cipher 00-0f-ac:4
nl80211: Supported cipher 00-0f-ac:10
nl80211: Supported cipher 00-0f-ac:8
nl80211: Supported cipher 00-0f-ac:9
nl80211: Supported cipher 00-0f-ac:6
nl80211: Supported cipher 00-0f-ac:13
nl80211: Supported cipher 00-0f-ac:11
nl80211: Supported cipher 00-0f-ac:12
nl80211: Using driver-based off-channel TX
nl80211: Driver-advertised extended capabilities (default) - hexdump(len=8): 00 00 00 00 00 00 00 40
nl80211: Driver-advertised extended capabilities mask (default) - hexdump(len=8): 00 00 00 00 00 00 00 40
nl80211: Use separate P2P group interface (driver advertised support)
nl80211: key_mgmt=0x1ff0f enc=0xfef auth=0x7 flags=0x240005105b1bfae0 rrm_flags=0x30 probe_resp_offloads=0x0 max_stations=0 max_remain_on_chan=5000 max_scan_ssids=4
nl80211: interface x2wlan0 in phy phy1
nl80211: Set mode ifindex 51 iftype 3 (AP)
nl80211: Setup AP(x2wlan0) - device_ap_sme=0 use_monitor=0
nl80211: Subscribe to mgmt frames with AP handle 0x55a682cb70
nl80211: Register frame type=0xb0 (WLAN_FC_STYPE_AUTH) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0x0 (WLAN_FC_STYPE_ASSOC_REQ) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0x20 (WLAN_FC_STYPE_REASSOC_REQ) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0xa0 (WLAN_FC_STYPE_DISASSOC) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0xc0 (WLAN_FC_STYPE_DEAUTH) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0x40 (WLAN_FC_STYPE_PROBE_REQ) nl_handle=0x55a682cb70 match= multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=04 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=0501 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=0503 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=0504 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=06 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=08 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=09 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=0a multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=11 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=12 multicast=0
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55a682cb70 match=7f multicast=0
rfkill: initial event: idx=2 type=1 op=0 soft=0 hard=0
nl80211: Add own interface ifindex 51 (ifidx_reason -1)
nl80211: if_indices[16]: 51(-1)
nl80211: Do not open EAPOL RX socket - using control port for RX
phy: phy1
BSS count 1, BSSID mask 00:00:00:00:00:00 (0 bits)
x2wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
Previous country code CN, new country code CN
nl80211: Regulatory information - country=CN (DFS-FCC)
nl80211: 2400-2483 @ 40 MHz 20 mBm
nl80211: 5150-5350 @ 80 MHz 20 mBm (DFS)
nl80211: 5725-5850 @ 80 MHz 33 mBm
nl80211: 57240-59400 @ 2160 MHz 28 mBm
nl80211: 59400-63720 @ 2160 MHz 44 mBm
nl80211: 63720-65880 @ 2160 MHz 28 mBm
nl80211: Added 802.11b mode based on 802.11g information
nl80211: Mode IEEE 802.11g: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484[DISABLED][NO_IR]
nl80211: Mode IEEE 802.11a: 5180[RADAR] 5200[RADAR] 5220[RADAR] 5240[RADAR] 5260[RADAR] 5280[RADAR] 5300[RADAR] 5320[RADAR] 5500[DISABLED][RADAR] 5520[DISABLED][RADAR] 5540[DISABLED][RADAR] 5560[DISABLED][RADAR]
nl80211: Mode IEEE 802.11b: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484[DISABLED][NO_IR]
Allowed channel: mode=1 chan=1 freq=2412 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=2 freq=2417 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=3 freq=2422 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=4 freq=2427 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=5 freq=2432 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=6 freq=2437 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=7 freq=2442 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=8 freq=2447 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=9 freq=2452 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=10 freq=2457 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=11 freq=2462 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=12 freq=2467 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=13 freq=2472 MHz max_tx_power=20 dBm
Allowed channel: mode=2 chan=149 freq=5745 MHz max_tx_power=33 dBm
Allowed channel: mode=2 chan=153 freq=5765 MHz max_tx_power=33 dBm
Allowed channel: mode=2 chan=157 freq=5785 MHz max_tx_power=33 dBm
Allowed channel: mode=2 chan=161 freq=5805 MHz max_tx_power=33 dBm
Allowed channel: mode=2 chan=165 freq=5825 MHz max_tx_power=33 dBm
Allowed channel: mode=0 chan=1 freq=2412 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=2 freq=2417 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=3 freq=2422 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=4 freq=2427 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=5 freq=2432 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=6 freq=2437 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=7 freq=2442 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=8 freq=2447 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=9 freq=2452 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=10 freq=2457 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=11 freq=2462 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=12 freq=2467 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=13 freq=2472 MHz max_tx_power=20 dBm
Completing interface initialization
Mode: IEEE 802.11a Channel: 149 Frequency: 5745 MHz
DFS chan_idx seems wrong; num-ch: 25 ch-no: -6 conf-ch-no: 149 11n: 0 sec-ch: 0 vht-oper-width: 1
Available channel: 36
Available channel: 40
Available channel: 44
Available channel: 48
Available channel: 52
Available channel: 56
Available channel: 60
Available channel: 64
Available channel: 100
Available channel: 104
Available channel: 108
Available channel: 112
Available channel: 116
Available channel: 120
Available channel: 124
Available channel: 128
Available channel: 132
Available channel: 136
Available channel: 140
Available channel: 144
Available channel: 149
Available channel: 153
Available channel: 157
Available channel: 161
Available channel: 165
Interface initialization failed
x2wlan0: interface state COUNTRY_UPDATE->DISABLED
x2wlan0: AP-DISABLED
x2wlan0: Unable to setup interface.
hostapd_interface_deinit_free(0x55a682aa30)
hostapd_interface_deinit_free: num_bss=1 conf->num_bss=1
hostapd_interface_deinit(0x55a682aa30)
x2wlan0: interface state DISABLED->DISABLED
hostapd_bss_deinit: deinit bss x2wlan0
x2wlan0: Deauthenticate all stations
nl80211: send_mlme - da=ff:ff:ff:ff:ff:ff noack=0 freq=0 no_cck=0 offchanok=0 wait_time=0 no_encrypt=0 fc=0xc0 (WLAN_FC_STYPE_DEAUTH) nlmode=3
nl80211: send_mlme - Use bss->freq=0
nl80211: send_mlme -> send_frame_cmd
nl80211: CMD_FRAME freq=0 wait=0 no_cck=0 no_ack=0 offchanok=0
CMD_FRAME - hexdump(len=26): c0 00 00 00 ff ff ff ff ff ff 0c 91 60 7f 02 1e 0c 91 60 7f 02 1e 00 00 03 00
nl80211: Frame command failed: ret=-22 (Invalid argument) (freq=0 wait=0)
x2wlan0: AP-DISABLED
hostapd_cleanup(hapd=0x55a682da10 (x2wlan0))
x2wlan0: CTRL-EVENT-TERMINATING
hostapd_free_hapd_data: Interface x2wlan0 wasn't started
hostapd_interface_deinit_free: driver=0x55746ee5a0 drv_priv=0x55a682ffd0 -> hapd_deinit
nl80211: deinit ifname=x2wlan0 disabled_11b_rates=0
nl80211: Remove monitor interface: refcount=0
nl80211: Remove beacon (ifindex=51)
netlink: Operstate: ifindex=51 linkmode=0 (kernel-control), operstate=6 (IF_OPER_UP)
nl80211: Set mode ifindex 51 iftype 2 (STATION)
nl80211: Failed to set interface 51 to mode 2: -16 (Device or resource busy)
nl80211: Try mode change after setting interface down
nl80211: Set mode ifindex 51 iftype 2 (STATION)
nl80211: Mode change succeeded while interface is down
nl80211: Teardown AP(x2wlan0) - device_ap_sme=0 use_monitor=0
nl80211: Unsubscribe mgmt frames handle 0x888888dd2e0a43f9 (AP teardown)
hostapd_interface_free(0x55a682aa30)
hostapd_interface_free: free hapd 0x55a682da10
hostapd_cleanup_iface(0x55a682aa30)
hostapd_cleanup_iface_partial(0x55a682aa30)
hostapd_cleanup_iface: free iface=0x55a682aa30

它告诉我们没有指定中心频率(vht_oper_centr_freq_seg0_idx):

1
DFS chan_idx seems wrong; num-ch: 25 ch-no: -6 conf-ch-no: 149 11n: 0 sec-ch: 0 vht-oper-width: 1

查看配置文件,可以看到我们确实没有指定 vht_oper_centr_freq_seg0_idx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
❯ sudo cat /dev/shm/lnxrouter_tmp/lnxrouter.wlan0.conf*/hostapd.conf
beacon_int=100
ssid=ssid
interface=x0wlan0
driver=nl80211
channel=149
ctrl_interface=/dev/shm/lnxrouter_tmp/lnxrouter.wlan0.conf.vRBiOQ/hostapd_ctrl
ctrl_interface_group=0
ignore_broadcast_ssid=0
ap_isolate=0
country_code=CN
ieee80211d=1
hw_mode=a
ieee80211ac=1
vht_oper_chwidth=1
wmm_enabled=1
wpa=2
wpa_passphrase=password
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
rsn_pairwise=CCMP

对于 80MHz 频宽,vht_oper_centr_freq_seg0_idx的值一般是 channel+6。
然而,lnxrouter 并没有提供指定 vht_oper_centr_freq_seg0_idx的选项,我采用了一个比较 dirty 的方法——直接修改 lnxrouter 的脚本文件: 眼瞎了,可以通过 --vht-seg0-ch 参数指定

再次执行脚本,hostapd 会出现新的报错:

1
2
3
DFS 0 channels required radar detection
80/80+80 MHz: no second channel offset
Could not set channel for kernel driver

这是由于我们没有设置合适的 ht_capabvht_capab 导致的。
参考hostapd-WiFi5.conf,添加合适的 capability 到 lnxrouter 中:

1
sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 -c 149 --country CN --ieee80211n --ieee80211ac --ht-capab "[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]" --vht-capab "[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][SU-BEAMFORMEE][HTC-VHT]" --vht-ch-width 1

Tips:
ht_capabvht_capab 的值取决于驱动程序,不同的驱动程序支持的参数可能不同。对于 rtw88 驱动,上述的 capability 应该可以正常工作。

Tips:
我并不清楚这些 capability 的作用,于是我让 GPT 解释了一下:

802.11n 功能:

  • HT40+HT40-:支持 40 MHz 信道宽度+- 表示 AP 使用 40 MHz 信道的上/下 20 MHz 部分。40 MHz 信道比 20 MHz 吞吐量更高。
  • SHORT-GI-20:启用 20 MHz 信道的短保护间隔(SGI)。保护间隔是符号间的静默时间,用于避免信号重叠。短保护间隔减少静默时间,提升信道效率。
  • SHORT-GI-40:同上,但适用于 40 MHz 信道,可减少开销并提升吞吐量。
  • GF(Greenfield 模式):启用 纯 802.11n 模式(不兼容传统非 HT 设备)。此模式通过放弃向后兼容性来提高效率(现代网络较少使用)。
  • MAX-AMSDU-7935
    设置 最大聚合 MAC 服务数据单元(AMSDU)大小,允许 AP 发送更大的数据包以减少开销。

802.11ac 功能:

  • SHORT-GI-80:启用 80 MHz 信道的短保护间隔,减少静默时间以提升吞吐量。
  • MAX-MPDU-11454:设置 最大 MPDU(MAC 协议数据单元)大小,更大的 MPDU 可提升效率。
  • TX-STBC-2BY1:启用 发射端空时块编码(STBC),通过多天线提升多径环境下的信号稳定性。
  • RX-STBC-1:启用 接收端 STBC(支持单空间流)。
  • SU-BEAMFORMEE:支持 单用户波束成形,AP 将信号定向传输至特定设备,提升信号质量与覆盖范围。
  • MU-BEAMFORMEE:支持 多用户波束成形,AP 可同时定向传输至多个设备。
  • HTC-VHT
    支持 802.11ac 的 高吞吐量控制信道模式

不出意外的话,此时热点已经工作在 80MHz 的频宽下,并且握手速度也应该达到 433/866Mbps。
1740635231637
1740641322796

后记

在 Linux 下创建 AP 确实不是一件容易的事。如果不是特殊需求,使用 OpenWrt 这种为无线专门优化过的发行版,可能会是更好的选择。